Index: images/cursor/modifier/joinnode.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: images\cursor\modifier\joinnode.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Index: images/cursor/modifier/joinway.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: images\cursor\modifier\joinway.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Index: src/org/openstreetmap/josm/actions/mapmode/DrawAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/DrawAction.java	(revision 1406)
+++ src/org/openstreetmap/josm/actions/mapmode/DrawAction.java	(working copy)
@@ -65,9 +65,13 @@
     private boolean ctrl;
     private boolean alt;
     private boolean shift;
-    private boolean mouseOnExistingNode;
+    private Node mouseOnExistingNode;
+    private Set<Way> mouseOnExistingWays = new HashSet<Way>();
+    private Set<OsmPrimitive> oldHighlights = new HashSet<OsmPrimitive>();
     private boolean drawHelperLine;
     private boolean wayIsFinished = false;
+    private boolean drawTargetHighlight;
+    private boolean drawTargetCursor;
     private Point mousePos;
     private Color selectedColor;
 
@@ -92,16 +96,98 @@
         return Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);
     }
 
+    /**
+     * Sets a special cursor to indicate that the next click will automatically join into
+     * an existing node or way (if feature is enabled)
+     *
+     * @param way If true, the cursor will indicate it is joined into a way; node otherwise
+     */
+    private void setJoinCursor(boolean way) {
+        if(!drawTargetCursor) {
+            resetCursor();
+            return;
+        }
+        try {
+            Main.map.mapView.setCursor(
+                    ImageProvider.getCursor("crosshair", (way ? "joinway" : "joinnode"))
+            );
+            return;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        resetCursor();
+    }
+
+    /**
+     * Resets the cursor to the default cursor for drawing mode (i.e. crosshair)
+     */
+    private void resetCursor() {
+        Main.map.mapView.setCursor(getCursor());
+    }
+
+    /**
+     * Takes the data from computeHelperLine to determine which ways/nodes should be highlighted
+     * (if feature enabled). Also sets the target cursor if appropriate.
+     */
+    private void addHighlighting() {
+        // if ctrl key is held ("no join"), don't highlight anything
+        if (ctrl) {
+            removeHighlighting();
+            resetCursor();
+            return;
+        }
+
+        if (mouseOnExistingNode != null) {
+            setJoinCursor(false);
+            // Clean old highlights
+            removeHighlighting();
+            if(drawTargetHighlight) {
+                oldHighlights.add(mouseOnExistingNode);
+                mouseOnExistingNode.highlighted = true;
+            }
+            return;
+        }
+
+        // Insert the node into all the nearby way segments
+        if(mouseOnExistingWays.size() == 0) {
+            removeHighlighting();
+            resetCursor();
+            return;
+        }
+
+        setJoinCursor(true);
+        // Clean old highlights
+        removeHighlighting();
+
+        if(!drawTargetHighlight) return;
+        oldHighlights.addAll(mouseOnExistingWays);
+        for(Way w : mouseOnExistingWays) {
+            w.highlighted = true;
+        }
+    }
+
+    /**
+     * Removes target highlighting from primitives
+     */
+    private void removeHighlighting() {
+        for(OsmPrimitive prim : oldHighlights) {
+            prim.highlighted = false;
+        }
+    }
+
     @Override public void enterMode() {
         super.enterMode();
         selectedColor = Main.pref.getColor(marktr("selected"), Color.red);
         drawHelperLine = Main.pref.getBoolean("draw.helper-line", true);
+        drawTargetHighlight = Main.pref.getBoolean("draw.target-highlight", true);
+        drawTargetCursor = Main.pref.getBoolean("draw.target-cursor", true);
         wayIsFinished = false;
-        
+
         Main.map.mapView.addMouseListener(this);
         Main.map.mapView.addMouseMotionListener(this);
         Main.map.mapView.addTemporaryLayer(this);
         DataSet.selListeners.add(this);
+
         try {
             Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK);
         } catch (SecurityException ex) {
@@ -109,12 +195,14 @@
         // would like to but haven't got mouse position yet:
         // computeHelperLine(false, false, false);
     }
+
     @Override public void exitMode() {
         super.exitMode();
         Main.map.mapView.removeMouseListener(this);
         Main.map.mapView.removeMouseMotionListener(this);
         Main.map.mapView.removeTemporaryLayer(this);
         DataSet.selListeners.remove(this);
+        removeHighlighting();
         try {
             Toolkit.getDefaultToolkit().removeAWTEventListener(this);
         } catch (SecurityException ex) {
@@ -146,7 +234,7 @@
         Main.ds.setSelected();
         mouseClicked(e);
     }
-    
+
     /**
      * If user clicked with the left button, add a node at the current mouse
      * position.
@@ -183,7 +271,7 @@
 
         if (!ctrl)
             n = Main.map.mapView.getNearestNode(mousePos);
-      
+
         if (n != null) {
             // user clicked on node
             if (shift || selection.isEmpty()) {
@@ -258,7 +346,7 @@
         if (!shift && selection.size() > 0 && !wayIsFinishedTemp) {
             Node selectedNode = null;
             Way selectedWay = null;
-            
+
             for (OsmPrimitive p : selection) {
                 if (p instanceof Node) {
                     if (selectedNode != null) {
@@ -276,7 +364,7 @@
                     selectedWay = (Way) p;
                 }
             }
-            
+
             // No nodes or ways have been selected, try again with no selection
             // This occurs when a relation has been selected
             if(selectedNode == null && selectedWay == null) {
@@ -291,7 +379,7 @@
                 if (selectedWay.isFirstLastNode(lastUsedNode)) {
                     n0 = lastUsedNode;
                 } else {
-                    // We have a way selected, but no suitable node to continue from. Start anew. 
+                    // We have a way selected, but no suitable node to continue from. Start anew.
                     tryAgain(e);
                     return;
                 }
@@ -325,7 +413,7 @@
                     return;
                 }
             }
-            
+
             // User clicked last node again, finish way
             if(n0 == n) {
                 lastUsedNode = null;
@@ -378,7 +466,7 @@
             extendedWay = true;
             Main.ds.setSelected(way);
         }
-      
+
         String title;
         if (!extendedWay) {
             if (!newNode) {
@@ -403,6 +491,7 @@
         Main.main.undoRedo.add(c);
         if(!wayIsFinished) lastUsedNode = n;
         computeHelperLine();
+        removeHighlighting();
         Main.map.mapView.repaint();
     }
 
@@ -419,6 +508,7 @@
         shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0;
         mousePos = e.getPoint();
 
+        addHighlighting();
         computeHelperLine();
     }
 
@@ -443,7 +533,8 @@
         Node selectedNode = null;
         Way selectedWay = null;
         Node currentMouseNode = null;
-        mouseOnExistingNode = false;
+        mouseOnExistingNode = null;
+        mouseOnExistingWays = new HashSet<Way>();
 
         Main.map.statusLine.setAngle(-1);
         Main.map.statusLine.setHeading(-1);
@@ -453,11 +544,19 @@
             currentMouseNode = Main.map.mapView.getNearestNode(mousePos);
         }
 
+        // We need this for highlighting and we'll only do so if we actually want to re-use
+        // *and* there is no node nearby (because nodes beat ways when re-using)
+        if(!ctrl && currentMouseNode == null) {
+            List<WaySegment> wss = Main.map.mapView.getNearestWaySegments(mousePos);
+            for(WaySegment ws : wss)
+                mouseOnExistingWays.add(ws.way);
+        }
+
         if (currentMouseNode != null) {
             // user clicked on node
             if (selection.isEmpty()) return;
             currentMouseEastNorth = currentMouseNode.eastNorth;
-            mouseOnExistingNode = true;
+            mouseOnExistingNode = currentMouseNode;
         } else {
             // no node found in clicked area
             currentMouseEastNorth = Main.map.mapView.getEastNorth(mousePos.x, mousePos.y);
@@ -510,8 +609,7 @@
         Main.map.statusLine.setDist(distance);
         updateStatusLine();
 
-        if (!drawHelperLine || wayIsFinished) return;
-
+        if ((!drawHelperLine || wayIsFinished) && !drawTargetHighlight) return;
         Main.map.mapView.repaint();
     }
 
@@ -639,10 +737,8 @@
     }
 
     public void paint(Graphics g, MapView mv) {
+        if (!drawHelperLine && !drawTargetHighlight) return;
 
-        // don't draw line if disabled in prefs
-        if (!drawHelperLine) return;
-
         // sanity checks
         if (Main.map.mapView == null) return;
         if (mousePos == null) return;
@@ -651,8 +747,7 @@
         if (shift) return;
 
         // don't draw line if we don't know where from or where to
-        if (currentBaseNode == null) return;
-        if (currentMouseEastNorth == null) return;
+        if (currentBaseNode == null || currentMouseEastNorth == null) return;
 
         // don't draw line if mouse is outside window
         if (!Main.map.mapView.getBounds().contains(mousePos)) return;
@@ -676,14 +771,13 @@
 
         g2.draw(b);
         g2.setStroke(new BasicStroke(1));
-
     }
 
     @Override public String getModeHelpText() {
         String rv;
 
         if (currentBaseNode != null && !shift) {
-            if (mouseOnExistingNode) {
+            if (mouseOnExistingNode != null) {
                 if (alt && /* FIXME: way exists */true)
                     rv = tr("Click to create a new way to the existing node.");
                 else
@@ -703,7 +797,7 @@
         //rv.append(tr("Click to add a new node. Ctrl: no node re-use/auto-insert. Shift: no auto-connect. Alt: new way"));
         return rv.toString();
     }
-    
+
     @Override public boolean layerIsSupported(Layer l) {
         return l instanceof OsmDataLayer;
     }
Index: src/org/openstreetmap/josm/data/osm/OsmPrimitive.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 1401)
+++ src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(working copy)
@@ -122,6 +122,12 @@
      * If set to true, this object is currently selected.
      */
     public volatile boolean selected = false;
+    
+    /**
+     * If set to true, this object is highlighted. Currently this is only used to
+     * show which ways/nodes will connect 
+     */
+    public volatile boolean highlighted = false;
 
     /**
      * Time of last modification to this object. This is not set by JOSM but
Index: src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java	(revision 1401)
+++ src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java	(working copy)
@@ -119,8 +119,7 @@
 
         if(osm.mappaintStyle == null && styles != null) {
             osm.mappaintStyle = styles.get(osm);
-            if(osm instanceof Way)
-                osm.isMappaintArea = styles.isArea(osm);
+            osm.isMappaintArea = styles.isArea(osm);
         }
         return osm.isMappaintArea;
     }
@@ -150,6 +149,8 @@
 
         if (nodeStyle != null && isZoomOk(nodeStyle) && showIcons > dist)
             drawNode(n, nodeStyle.icon, nodeStyle.annotate, n.selected);
+        else if (n.highlighted)
+            drawNode(n, highlightColor, selectedNodeSize, selectedNodeRadius, fillSelectedNode);
         else if (n.selected)
             drawNode(n, selectedColor, selectedNodeSize, selectedNodeRadius, fillSelectedNode);
         else if (n.tagged)
@@ -265,7 +266,10 @@
             int tmpWidth = (int) (100 /  (float) (circum / realWidth));
             if (tmpWidth > width) width = tmpWidth;
         }
-        if(w.selected)
+
+        if(w.highlighted)
+            color = highlightColor;
+        else if(w.selected)
             color = selectedColor;
 
         // draw overlays under the way
@@ -1135,7 +1139,7 @@
                 }
                 g2d.draw(currentPath);
             }
-            
+
             if(useStrokes > dist)
                 g2d.setStroke(new BasicStroke(1));
 
Index: src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java	(revision 1401)
+++ src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java	(working copy)
@@ -36,6 +36,7 @@
     public final static Color darkblue = new Color(0,0,128);
     public final static Color darkgreen = new Color(0,128,0);
     public final static Color teal = new Color(0,128,128);
+    public final static Color lightteal= new Color(0, 255, 186);
 
     /**
      * The environment to paint to.
@@ -61,6 +62,7 @@
     protected Color untaggedWayColor;
     protected Color incompleteColor;
     protected Color backgroundColor;
+    protected Color highlightColor;
     protected boolean showDirectionArrow;
     protected boolean showRelevantDirectionsOnly;
     protected boolean showHeadArrowOnly;
@@ -96,6 +98,7 @@
         untaggedWayColor = Main.pref.getColor(marktr("untagged way"), darkgreen);
         incompleteColor = Main.pref.getColor(marktr("incomplete way"), darkerblue);
         backgroundColor = Main.pref.getColor(marktr("background"), Color.BLACK);
+        highlightColor = Main.pref.getColor(marktr("highlight"), lightteal);
     }
 
     protected void getSettings(Boolean virtual) {
@@ -131,13 +134,13 @@
             System.out.println("Simplepaint Profiler");
 
         getSettings(virtual);
-        
-        if(profiler) 
+
+        if(profiler)
         {
             System.out.format("Prepare  : %4dms\n", (java.lang.System.currentTimeMillis()-profilerLast));
             profilerLast = java.lang.System.currentTimeMillis();
         }
-        
+
         // draw tagged ways first, then untagged ways. takes
         // time to iterate through list twice, OTOH does not
         // require changing the colour while painting...
@@ -244,6 +247,8 @@
 
         if (inactive)
             drawNode(n, inactiveColor, unselectedNodeSize, unselectedNodeRadius, fillUnselectedNode);
+        else if (n.highlighted)
+            drawNode(n, highlightColor, selectedNodeSize, selectedNodeRadius, fillSelectedNode);
         else if (n.selected)
             drawNode(n, selectedColor, selectedNodeSize, selectedNodeRadius, fillSelectedNode);
         else if(n.tagged)
@@ -300,6 +305,10 @@
 
         if (inactive) {
             wayColor = inactiveColor;
+        } else if(w.highlighted) {
+            wayColor = highlightColor;
+        } else if(w.selected) {
+            wayColor = selectedColor;
         } else if (!w.tagged) {
             wayColor = untaggedWayColor;
         } else {
@@ -311,7 +320,7 @@
             Point lastP = nc.getPoint(it.next().eastNorth);
             for (int orderNumber = 1; it.hasNext(); orderNumber++) {
                 Point p = nc.getPoint(it.next().eastNorth);
-                drawSegment(lastP, p, w.selected && !inactive ? selectedColor : wayColor, 
+                drawSegment(lastP, p, wayColor,
                     showOnlyHeadArrowOnly ? !it.hasNext() : showThisDirectionArrow);
                 if (showOrderNumber)
                     drawOrderNumber(lastP, p, orderNumber);
