Index: /trunk/src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java	(revision 4326)
+++ /trunk/src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java	(revision 4327)
@@ -6,5 +6,4 @@
 import java.awt.AWTEvent;
 import java.awt.Cursor;
-import java.awt.EventQueue;
 import java.awt.Toolkit;
 import java.awt.event.AWTEventListener;
@@ -14,8 +13,11 @@
 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;
@@ -45,15 +47,17 @@
  * @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 {
@@ -101,4 +105,6 @@
             return;
 
+        drawTargetHighlight = Main.pref.getBoolean("draw.target-highlight", true);
+
         Main.map.mapView.addMouseListener(this);
         Main.map.mapView.addMouseMotionListener(this);
@@ -120,4 +126,5 @@
             System.out.println(ex);
         }
+        removeHighlighting();
     }
 
@@ -157,12 +164,82 @@
     @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();
+
+        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 {
+            // don't call buildDeleteCommands for DeleteMode.segment because it doesn't support
+            // silent operation and SplitWayAction will show dialogs. A lot.
+            Command delCmd = buildDeleteCommands(e, modifiers, true);
+            if(delCmd == null) {
+                Main.map.mapView.repaint();
+                return;
+            }
+
+            // 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
      *
+     * @param MouseEvent
+     * @param int modifiers
+     */
+    private void updateCursor(MouseEvent e, int modifiers) {
+        if (!Main.isDisplayingMapView())
+            return;
+        if(!Main.map.mapView.isActiveLayerVisible() || e == null)
+            return;
+
+        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
@@ -170,16 +247,17 @@
      * mouseevent. Instead we copy the previous event and only update the
      * modifiers.
-     *
-     * @param MouseEvent
-     * @param int modifiers
-     */
-    private void updateCursor(MouseEvent e, int modifiers) {
-        if (!Main.isDisplayingMapView())
-            return;
-        if(!Main.map.mapView.isActiveLayerVisible() || e == null)
-            return;
-
-        DeleteParameters parameters = getDeleteParameters(e, modifiers);
-        Main.map.mapView.setNewCursor(parameters.mode.cursor(), this);
+     */
+    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());
     }
 
@@ -204,4 +282,5 @@
 
         getCurrentDataSet().setSelected();
+        giveUserFeedback(e);
         Main.map.mapView.repaint();
     }
@@ -242,9 +321,5 @@
 
     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();
@@ -288,5 +363,5 @@
             return DeleteCommand.delete(getEditLayer(),Collections.singleton(parameters.nearestNode), false, silent);
         case node_with_references:
-            return DeleteCommand.deleteWithReferences(getEditLayer(),Collections.singleton(parameters.nearestNode));
+            return DeleteCommand.deleteWithReferences(getEditLayer(),Collections.singleton(parameters.nearestNode), silent);
         case segment:
             return DeleteCommand.deleteWaySegment(getEditLayer(), parameters.nearestSegment);
@@ -296,5 +371,5 @@
             return DeleteCommand.delete(getEditLayer(), Collections.singleton(parameters.nearestSegment.way), true, silent);
         case way_with_references:
-            return DeleteCommand.deleteWithReferences(getEditLayer(),Collections.singleton(parameters.nearestSegment.way),true);
+            return DeleteCommand.deleteWithReferences(getEditLayer(), Collections.singleton(parameters.nearestSegment.way), true);
         default:
             return null;
@@ -306,7 +381,9 @@
      */
     public void eventDispatched(AWTEvent e) {
+        if(e == null)
+            return;
         // 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: /trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java	(revision 4326)
+++ /trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java	(revision 4327)
@@ -9,10 +9,8 @@
 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;
@@ -66,7 +64,4 @@
     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>();
@@ -513,6 +508,6 @@
         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());
@@ -602,16 +597,4 @@
     }
 
-    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
Index: /trunk/src/org/openstreetmap/josm/actions/mapmode/ExtrudeAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/mapmode/ExtrudeAction.java	(revision 4326)
+++ /trunk/src/org/openstreetmap/josm/actions/mapmode/ExtrudeAction.java	(revision 4327)
@@ -185,4 +185,6 @@
             return;
 
+        updateKeyModifiers(e);
+
         selectedSegment = Main.map.mapView.getNearestWaySegment(e.getPoint(), OsmPrimitive.isSelectablePredicate);
 
@@ -192,7 +194,7 @@
             // 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
@@ -202,5 +204,5 @@
                 mode = Mode.extrude;
                 getCurrentDataSet().setSelected(selectedSegment.way);
-                alwaysCreateNodes = ((e.getModifiers() & ActionEvent.SHIFT_MASK) != 0);
+                alwaysCreateNodes = shift;
             }
 
Index: /trunk/src/org/openstreetmap/josm/actions/mapmode/MapMode.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/mapmode/MapMode.java	(revision 4326)
+++ /trunk/src/org/openstreetmap/josm/actions/mapmode/MapMode.java	(revision 4327)
@@ -4,4 +4,5 @@
 import java.awt.Cursor;
 import java.awt.event.ActionEvent;
+import java.awt.event.InputEvent;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
@@ -25,4 +26,7 @@
 abstract public class MapMode extends JosmAction implements MouseListener, MouseMotionListener {
     protected final Cursor cursor;
+    protected boolean ctrl;
+    protected boolean alt;
+    protected boolean shift;
 
     /**
@@ -77,4 +81,18 @@
     }
 
+    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) {}
Index: /trunk/src/org/openstreetmap/josm/actions/mapmode/ParallelWayAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/mapmode/ParallelWayAction.java	(revision 4326)
+++ /trunk/src/org/openstreetmap/josm/actions/mapmode/ParallelWayAction.java	(revision 4327)
@@ -14,5 +14,4 @@
 import java.awt.Toolkit;
 import java.awt.event.AWTEventListener;
-import java.awt.event.ActionEvent;
 import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
@@ -109,8 +108,4 @@
     private final MapView mv;
 
-    private boolean ctrl;
-    private boolean alt;
-    private boolean shift;
-
     // Mouse tracking state
     private Point mousePressedPos;
@@ -233,7 +228,5 @@
     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;
@@ -394,7 +387,6 @@
             if (!isModifiersValidForDragMode())
                 return;
-            if (!initParallelWays(mousePressedPos, copyTags)) {
+            if (!initParallelWays(mousePressedPos, copyTags))
                 return;
-            }
             setMode(Mode.dragging);
         }
@@ -409,5 +401,5 @@
         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(),
@@ -431,5 +423,5 @@
         }
         pWays.changeOffset(d);
-        
+
         Main.map.statusLine.setDist(Math.abs(snappedRealD));
         Main.map.statusLine.repaint();
Index: /trunk/src/org/openstreetmap/josm/actions/mapmode/PlayHeadDragMode.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/mapmode/PlayHeadDragMode.java	(revision 4326)
+++ /trunk/src/org/openstreetmap/josm/actions/mapmode/PlayHeadDragMode.java	(revision 4327)
@@ -6,5 +6,4 @@
 import java.awt.Cursor;
 import java.awt.Point;
-import java.awt.event.ActionEvent;
 import java.awt.event.MouseEvent;
 
@@ -28,5 +27,5 @@
     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;
     }
@@ -68,5 +67,7 @@
         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) {
Index: /trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 4326)
+++ /trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 4327)
@@ -6,7 +6,10 @@
 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;
@@ -16,6 +19,8 @@
 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;
@@ -60,10 +65,42 @@
  * @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;
     /**
@@ -94,4 +131,11 @@
     private int initialMoveThreshold;
     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>();
 
     /**
@@ -109,4 +153,11 @@
         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);
+        }
     }
 
@@ -127,4 +178,137 @@
         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 needsRepaint = false;
+
+        Collection<OsmPrimitive> c = MapView.asColl(
+                mv.getNearestNodeOrWay(e.getPoint(), OsmPrimitive.isSelectablePredicate, true));
+
+        updateKeyModifiers(modifiers);
+        determineMapMode(!c.isEmpty());
+
+        if(drawTargetHighlight) {
+            needsRepaint = 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 needsRepaint;
+
+        for(OsmPrimitive x : c) {
+            // only highlight primitives that will change the selection
+            // when clicked. I.e. don't highlight selected elements unless
+            // we are in toggle mode.
+            if(ctrl || !x.isSelected()) {
+                x.setHighlighted(true);
+                oldHighlights.add(x);
+            }
+        }
+        return needsRepaint || !oldHighlights.isEmpty();
+    }
+
+    /**
+     * This is called whenever the keyboard modifier status changes
+     */
+    public void eventDispatched(AWTEvent e) {
+        if(oldEvent == null)
+            return;
+        // We don't have a mouse event, so we pass the old mouse event but the
+        // new modifiers.
+        giveUserFeedback(oldEvent, ((InputEvent) e).getModifiers());
     }
 
@@ -264,9 +448,21 @@
     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>();
@@ -339,6 +535,6 @@
             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) {
@@ -389,4 +585,22 @@
 
     /**
+     * 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.
@@ -400,14 +614,12 @@
     public void mousePressed(MouseEvent e) {
         // return early
-        if (!mv.isActiveLayerVisible() || !(Boolean) this.getValue("active") || e.getButton() != MouseEvent.BUTTON1) {
-            return;
-        }
+        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
@@ -422,7 +634,8 @@
                 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);
@@ -432,21 +645,7 @@
             // 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);
@@ -454,11 +653,13 @@
 
             selectPrims(cycleSetup(c, e), e, false, false);
-        } else {
-            mode = Mode.select;
-
+            break;
+        case select:
+        default:
             selectionManager.register(mv);
             selectionManager.mousePressed(e);
-        }
-
+            break;
+        }
+        giveUserFeedback(e);
+        mv.repaint();
         updateStatusLine();
     }
@@ -466,11 +667,9 @@
     @Override
     public void mouseReleased(MouseEvent e) {
-        if (!mv.isActiveLayerVisible()) {
-            return;
-        }
+        if (!mv.isActiveLayerVisible())
+            return;
 
         startingDraggingPos = null;
 
-        mv.setNewCursor(cursor, this);
         if (mode == Mode.select) {
             selectionManager.unregister(mv);
@@ -489,7 +688,7 @@
                 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) {
+                if (lastMousePos == null || lastMousePos.distanceSq(e.getPoint()) < 100) {
                     selectPrims(cyclePrims(cycleList, e), e, true, false);
 
@@ -500,5 +699,4 @@
                         // click and switch back to SelectMode
                         Main.worker.execute(new Runnable() {
-
                             public void run() {
                                 Main.map.selectDrawTool(true);
@@ -539,12 +737,11 @@
         }
 
-        // 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);
     }
@@ -554,6 +751,5 @@
      * 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>.
      */
@@ -562,6 +758,5 @@
 
         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();
@@ -630,12 +825,10 @@
 
     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())) {
-            return;
-        }
+        if ((shift && ctrl) || (ctrl && !released) || (!virtualWays.isEmpty()))
+            return;
 
         if (!released) {
@@ -666,15 +859,14 @@
     @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");
-        }
     }
 
Index: /trunk/src/org/openstreetmap/josm/data/osm/DataSet.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 4326)
+++ /trunk/src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 4327)
@@ -115,4 +115,8 @@
     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;
@@ -431,4 +435,25 @@
 
     /**
+     * returns an unmodifiable collection of *WaySegments* whose virtual
+     * nodes should be highlighted. WaySegments are used to avoid having
+     * to create a VirtualNode class that wouldn't have much purpose otherwise.
+     * 
+     * @return unmodifiable collection of WaySegments
+     */
+    public Collection<WaySegment> getHighlightedVirtualNodes() {
+        return Collections.unmodifiableCollection(highlightedVirtualNodes);
+    }
+
+    /**
+     * returns an unmodifiable collection of WaySegments that should be
+     * highlighted.
+     * 
+     * @return unmodifiable collection of WaySegments
+     */
+    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.
@@ -505,4 +530,32 @@
         selectionSnapshot = null;
         return true;
+    }
+
+    /**
+     * set what virtual nodes should be highlighted. Requires a Collection of
+     * *WaySegments* 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++;
     }
 
@@ -590,4 +643,18 @@
         }
         return changed;
+    }
+
+    /**
+     * 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>());
     }
 
Index: /trunk/src/org/openstreetmap/josm/data/osm/WaySegment.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/WaySegment.java	(revision 4326)
+++ /trunk/src/org/openstreetmap/josm/data/osm/WaySegment.java	(revision 4327)
@@ -30,4 +30,15 @@
     }
 
+    /**
+     * 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
Index: /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java	(revision 4326)
+++ /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java	(revision 4327)
@@ -35,13 +35,14 @@
 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;
 import org.openstreetmap.josm.gui.mappaint.BoxTextElemStyle;
+import org.openstreetmap.josm.gui.mappaint.NodeElemStyle;
+import org.openstreetmap.josm.gui.mappaint.TextElement;
 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.NodeElemStyle.Symbol;
-import org.openstreetmap.josm.gui.mappaint.TextElement;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Pair;
@@ -53,4 +54,5 @@
     private final boolean inactive;
     private final MapPaintSettings settings;
+    private final Collection<WaySegment> highlightWaySegments;
 
     private final boolean useStrokes;
@@ -64,4 +66,6 @@
     private final Color relationSelectedColor;
     private final Color nodeColor;
+    private final Color highlightColor;
+    private final Color highlightColorTransparent;
     private final Color backgroundColor;
 
@@ -81,9 +85,11 @@
     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;
@@ -96,4 +102,6 @@
         this.relationSelectedColor = PaintColors.RELATIONSELECTED.get();
         this.nodeColor = PaintColors.NODE.get();
+        this.highlightColor = PaintColors.HIGHLIGHT.get();
+        this.highlightColorTransparent = new Color(highlightColor.getRed(), highlightColor.getGreen(), highlightColor.getBlue(), 100);
         this.backgroundColor = PaintColors.getBackgroundColor();
 
@@ -131,6 +139,27 @@
         List<Node> wayNodes = way.getNodes();
         if (wayNodes.size() < 2) return;
-        
-        Iterator<Point> it = new OffsetIterator(way.getNodes(), offset);
+
+        // only highlight the segment if the way itself is not highlighted
+        if(!way.isHighlighted()) {
+            GeneralPath highlightSegs = null;
+            for(WaySegment ws : highlightWaySegments) {
+                if(ws.way != way || ws.lowerIndex < offset) {
+                    continue;
+                }
+                if(highlightSegs == null) {
+                    highlightSegs = new GeneralPath();
+                }
+
+                Point p1 = nc.getPoint(ws.getFirstNode());
+                Point p2 = nc.getPoint(ws.getSecondNode());
+                highlightSegs.moveTo(p1.x, p1.y);
+                highlightSegs.lineTo(p2.x, p2.y);
+            }
+
+            drawPathHighlight(highlightSegs, line);
+        }
+
+
+        Iterator<Point> it = new OffsetIterator(wayNodes, offset);
         while (it.hasNext()) {
             Point p = it.next();
@@ -209,4 +238,7 @@
             lastPoint = p;
         }
+        if(way.isHighlighted()) {
+            drawPathHighlight(path, line);
+        }
         displaySegments(path, orientationArrows, onewayArrows, onewayArrowsCasing, color, line, dashes, dashedColor);
     }
@@ -221,9 +253,9 @@
      */
     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
@@ -238,5 +270,5 @@
             idx = 0;
         }
-        
+
         @Override
         public boolean hasNext() {
@@ -247,7 +279,7 @@
         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;
@@ -277,9 +309,9 @@
                 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;
@@ -292,6 +324,6 @@
                 int m = dx_next*(y_current0 - y_prev0) - dy_next*(x_current0 - x_prev0);
 
-                int cx_ = x_prev0 + (int) Math.round(m * dx_prev / det);
-                int cy_ = y_prev0 + (int) Math.round(m * dy_prev / det);
+                int cx_ = x_prev0 + Math.round(m * dx_prev / det);
+                int cy_ = y_prev0 + Math.round(m * dy_prev / det);
                 ++idx;
                 prev = current;
@@ -307,5 +339,5 @@
         }
     }
-    
+
     private void displaySegments(GeneralPath path, GeneralPath orientationArrows, GeneralPath onewayArrows, GeneralPath onewayArrowsCasing,
             Color color, BasicStroke line, BasicStroke dashes, Color dashedColor) {
@@ -337,4 +369,22 @@
         if(useStrokes) {
             g.setStroke(new BasicStroke());
+        }
+    }
+
+    /**
+     * highlights a given GeneralPath using the settings from BasicStroke to match the line's
+     * style. Width of the highlight is hard coded.
+     * @param path
+     * @param line
+     */
+    private void drawPathHighlight(GeneralPath path, BasicStroke line) {
+        if(path == null)
+            return;
+        g.setColor(highlightColorTransparent);
+        float w = (line.getLineWidth() + 4);
+        while(w >= line.getLineWidth()) {
+            g.setStroke(new BasicStroke(w, line.getEndCap(), line.getLineJoin(), line.getMiterLimit()));
+            g.draw(path);
+            w -= 4;
         }
     }
@@ -498,7 +548,10 @@
     public void drawNodeIcon(Node n, ImageIcon icon, float iconAlpha, boolean selected, boolean member) {
         Point p = nc.getPoint(n);
-        if ((p.x < 0) || (p.y < 0) || (p.x > nc.getWidth()) || (p.y > nc.getHeight())) return;
-
-        int w = icon.getIconWidth(), h=icon.getIconHeight();
+
+        final int w = icon.getIconWidth(), h=icon.getIconHeight();
+        if(n.isHighlighted()) {
+            drawPointHighlight(p, Math.max(w, h));
+        }
+
         if (iconAlpha != 1f) {
             g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, iconAlpha));
@@ -530,6 +583,9 @@
     public void drawNodeSymbol(Node n, Symbol s, Color fillColor, Color strokeColor) {
         Point p = nc.getPoint(n);
-        if ((p.x < 0) || (p.y < 0) || (p.x > nc.getWidth()) || (p.y > nc.getHeight())) return;
         int radius = s.size / 2;
+
+        if(n.isHighlighted()) {
+            drawPointHighlight(p, s.size);
+        }
 
         if (fillColor != null) {
@@ -612,6 +668,14 @@
      */
     public void drawNode(Node n, Color color, int size, boolean fill) {
+        if(size <= 0 && !n.isHighlighted())
+            return;
+
+        Point p = nc.getPoint(n);
+
+        if(n.isHighlighted()) {
+            drawPointHighlight(p, size);
+        }
+
         if (size > 1) {
-            Point p = nc.getPoint(n);
             if ((p.x < 0) || (p.y < 0) || (p.x > nc.getWidth()) || (p.y > nc.getHeight())) return;
             int radius = size / 2;
@@ -623,8 +687,22 @@
             }
             if (fill) {
-                g.fillRect(p.x - radius, p.y - radius, size + 1, size + 1);
+                g.fillRect(p.x-radius-1, p.y-radius-1, size + 1, size + 1);
             } else {
-                g.drawRect(p.x - radius, p.y - radius, size, size);
-            }
+                g.drawRect(p.x-radius-1, p.y-radius-1, size, size);
+            }
+        }
+    }
+
+    /**
+     * highlights a given point by drawing a rounded rectangle around it. Give the
+     * size of the object you want to be highlighted, width is added automatically.
+     */
+    private void drawPointHighlight(Point p, int size) {
+        g.setColor(highlightColorTransparent);
+        int s = size + 7;
+        while(s >= size) {
+            int r = (int) Math.floor(s/2);
+            g.fillRoundRect(p.x-r, p.y-r, s, s, r, r);
+            s -= 4;
         }
     }
@@ -633,6 +711,6 @@
         if (!isShowNames() || bs == null)
             return;
-        
-        Point p = nc.getPoint((Node) n);
+
+        Point p = nc.getPoint(n);
         TextElement text = bs.text;
         String s = text.labelCompositionStrategy.compose(n);
@@ -823,5 +901,4 @@
 
     public void drawRestriction(Relation r, NodeElemStyle icon) {
-
         Way fromWay = null;
         Way toWay = null;
@@ -998,16 +1075,27 @@
     }
 
-    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);
-                }
-            }
-            g.setColor(nodeColor);
-            g.draw(path);
-        }
+    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);
+        // 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);
     }
 
Index: /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/PaintColors.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/PaintColors.java	(revision 4326)
+++ /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/PaintColors.java	(revision 4327)
@@ -10,6 +10,6 @@
 import org.openstreetmap.josm.data.Preferences.ColorKey;
 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
+import org.openstreetmap.josm.gui.mappaint.StyleSource;
 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.MapPaintSylesUpdateListener;
-import org.openstreetmap.josm.gui.mappaint.StyleSource;
 
 public enum PaintColors implements ColorKey {
@@ -26,5 +26,5 @@
     INCOMPLETE_WAY(marktr("incomplete way"), new Color(0,0,96)), // darker blue
     BACKGROUND(marktr("background"), Color.BLACK),
-    HIGHLIGHT(marktr("highlight"), new Color(0, 255, 186)), // lighteal
+    HIGHLIGHT(marktr("highlight"), SELECTED.get()),
 
     UNTAGGED(marktr("untagged"),Color.GRAY),
Index: /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java	(revision 4326)
+++ /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java	(revision 4327)
@@ -5,4 +5,5 @@
 import java.awt.RenderingHints;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -16,4 +17,5 @@
 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;
@@ -220,5 +222,7 @@
                         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);
@@ -229,5 +233,5 @@
         sc.drawAll();
         sc = null;
-        painter.drawVirtualNodes(data.searchWays(bbox));
+        painter.drawVirtualNodes(data.searchWays(bbox), data.getHighlightedVirtualNodes());
 
         //long now = System.currentTimeMillis();
Index: /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/WireframeMapRenderer.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/WireframeMapRenderer.java	(revision 4326)
+++ /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/WireframeMapRenderer.java	(revision 4327)
@@ -25,4 +25,5 @@
 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;
@@ -168,5 +169,14 @@
             }
         }
-        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();
     }
 
@@ -228,16 +238,27 @@
     }
 
-    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);
-                }
-            }
-            g.setColor(nodeColor);
-            g.draw(path);
-        }
+    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);
+        // 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);
     }
 
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java	(revision 4326)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java	(revision 4327)
@@ -221,7 +221,5 @@
 
         Color myColor = color;
-        if(w.isHighlighted()) {
-            myColor = paintSettings.getHighlightColor();
-        } else if (selected) {
+        if (selected) {
             myColor = paintSettings.getSelectedColor(color.getAlpha());
         } else if (member) {
@@ -292,5 +290,5 @@
             '}';
     }
-    
+
     public String linejoinToString(int linejoin) {
         switch (linejoin) {
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java	(revision 4326)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java	(revision 4327)
@@ -111,5 +111,5 @@
             symbol = createSymbol(env);
         }
-        
+
         // optimization: if we neither have a symbol, nor an icon
         // we don't have to check for the remaining style properties and we don't
@@ -243,70 +243,59 @@
                 Color fillColor = symbol.fillColor;
                 if (fillColor != null) {
-                    if (n.isHighlighted()) {
-                        fillColor = settings.getHighlightColor();
-                    } else {
-                        if (painter.isInactiveMode() || n.isDisabled()) {
-                            fillColor = settings.getInactiveColor();
-                        } else if (selected) {
-                            fillColor = settings.getSelectedColor(fillColor.getAlpha());
-                        } else if (member) {
-                            fillColor = settings.getRelationSelectedColor(fillColor.getAlpha());
-                        }
+                    if (painter.isInactiveMode() || n.isDisabled()) {
+                        fillColor = settings.getInactiveColor();
+                    } else if (selected) {
+                        fillColor = settings.getSelectedColor(fillColor.getAlpha());
+                    } else if (member) {
+                        fillColor = settings.getRelationSelectedColor(fillColor.getAlpha());
                     }
                 }
                 Color strokeColor = symbol.strokeColor;
                 if (strokeColor != null) {
-                    if (n.isHighlighted()) {
-                        strokeColor = settings.getHighlightColor();
-                    } else {
-                        if (painter.isInactiveMode() || n.isDisabled()) {
-                            strokeColor = settings.getInactiveColor();
-                        } else if (selected) {
-                            strokeColor = settings.getSelectedColor(strokeColor.getAlpha());
-                        } else if (member) {
-                            strokeColor = settings.getRelationSelectedColor(strokeColor.getAlpha());
-                        }
+                    if (painter.isInactiveMode() || n.isDisabled()) {
+                        strokeColor = settings.getInactiveColor();
+                    } else if (selected) {
+                        strokeColor = settings.getSelectedColor(strokeColor.getAlpha());
+                    } else if (member) {
+                        strokeColor = settings.getRelationSelectedColor(strokeColor.getAlpha());
                     }
                 }
                 painter.drawNodeSymbol(n, symbol, fillColor, strokeColor);
             } else {
-                if (n.isHighlighted()) {
-                    painter.drawNode(n, settings.getHighlightColor(), settings.getSelectedNodeSize(), settings.isFillSelectedNode());
+                Color color;
+                boolean isConnection = n.isConnectionNode();
+
+                if (painter.isInactiveMode() || n.isDisabled()) {
+                    color = settings.getInactiveColor();
+                } else if (selected) {
+                    color = settings.getSelectedColor();
+                } else if (member) {
+                    color = settings.getRelationSelectedColor();
+                } else if (isConnection) {
+                    if (n.isTagged()) {
+                        color = settings.getTaggedConnectionColor();
+                    } else {
+                        color = settings.getConnectionColor();
+                    }
                 } else {
-                    Color color;
-                    boolean isConnection = n.isConnectionNode();
-
-                    if (painter.isInactiveMode() || n.isDisabled()) {
-                        color = settings.getInactiveColor();
-                    } else if (selected) {
-                        color = settings.getSelectedColor();
-                    } else if (member) {
-                        color = settings.getRelationSelectedColor();
-                    } else if (isConnection) {
-                        if (n.isTagged()) {
-                            color = settings.getTaggedConnectionColor();
-                        } else {
-                            color = settings.getConnectionColor();
-                        }
+                    if (n.isTagged()) {
+                        color = settings.getTaggedColor();
                     } else {
-                        if (n.isTagged()) {
-                            color = settings.getTaggedColor();
-                        } else {
-                            color = settings.getNodeColor();
-                        }
+                        color = settings.getNodeColor();
                     }
-
-                    final int size = Utils.max((selected ? settings.getSelectedNodeSize() : 0),
-                            (n.isTagged() ? settings.getTaggedNodeSize() : 0),
-                            (isConnection ? settings.getConnectionNodeSize() : 0),
-                            settings.getUnselectedNodeSize());
-
-                    final boolean fill = (selected && settings.isFillSelectedNode()) ||
-                            (n.isTagged() && settings.isFillTaggedNode()) ||
-                            (isConnection && settings.isFillConnectionNode()) ||
-                            settings.isFillUnselectedNode();
-
-                    painter.drawNode(n, color, size, fill);
                 }
+
+                final int size = Utils.max((selected ? settings.getSelectedNodeSize() : 0),
+                        (n.isTagged() ? settings.getTaggedNodeSize() : 0),
+                        (isConnection ? settings.getConnectionNodeSize() : 0),
+                        settings.getUnselectedNodeSize());
+
+                final boolean fill = (selected && settings.isFillSelectedNode()) ||
+                (n.isTagged() && settings.isFillTaggedNode()) ||
+                (isConnection && settings.isFillConnectionNode()) ||
+                settings.isFillUnselectedNode();
+
+                painter.drawNode(n, color, size, fill);
+
             }
         } else if (primitive instanceof Relation && icon != null) {
@@ -322,5 +311,5 @@
         return disabledIcon = new ImageIcon(GrayFilter.createDisabledImage(icon.getImage()));
     }
-    
+
     public Rectangle getBox() {
         if (icon != null) {
