Index: src/org/openstreetmap/josm/actions/DirectAllWaySegmentsReverseAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/DirectAllWaySegmentsReverseAction.java	(revision 0)
+++ src/org/openstreetmap/josm/actions/DirectAllWaySegmentsReverseAction.java	(revision 0)
@@ -0,0 +1,13 @@
+package org.openstreetmap.josm.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.KeyEvent;
+
+public class DirectAllWaySegmentsReverseAction extends DirectAllWaySegmentsAction {
+	public DirectAllWaySegmentsReverseAction() {
+		super(tr("Reverse way direction"), "segmentflip", tr("Try to direct all way segments so that they face the oposite direction to the current consensus."), KeyEvent.VK_A, KeyEvent.CTRL_DOWN_MASK | KeyEvent.ALT_DOWN_MASK, true);
+		reverseDirection = true;
+		
+	}
+}
Index: src/org/openstreetmap/josm/actions/ReverseSegmentAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/ReverseSegmentAction.java	(revision 219)
+++ src/org/openstreetmap/josm/actions/ReverseSegmentAction.java	(working copy)
@@ -25,7 +25,7 @@
 public final class ReverseSegmentAction extends JosmAction {
 
     public ReverseSegmentAction() {
-    	super(tr("Reverse Segments"), "segmentflip", tr("Revert the direction of all selected Segments."), KeyEvent.VK_R, KeyEvent.CTRL_MASK | KeyEvent.SHIFT_MASK, true);
+    	super(tr("Reverse segments"), "segmentflip", tr("Reverse the direction of all selected Segments."), KeyEvent.VK_R, KeyEvent.CTRL_MASK | KeyEvent.SHIFT_MASK, true);
     }
 
 	public void actionPerformed(ActionEvent e) {
Index: src/org/openstreetmap/josm/actions/DirectAllWaySegmentsAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/DirectAllWaySegmentsAction.java	(revision 0)
+++ src/org/openstreetmap/josm/actions/DirectAllWaySegmentsAction.java	(revision 0)
@@ -0,0 +1,169 @@
+package org.openstreetmap.josm.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.command.ChangeCommand;
+import org.openstreetmap.josm.command.Command;
+import org.openstreetmap.josm.command.SequenceCommand;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Segment;
+import org.openstreetmap.josm.data.osm.Way;
+
+public class DirectAllWaySegmentsAction extends JosmAction {
+	protected boolean reverseDirection = false;
+	
+	public DirectAllWaySegmentsAction() {
+		super(tr("Direct all way segments"), "reorder", tr("Try to direct all way segments so that they face the same direction."), KeyEvent.VK_S, KeyEvent.CTRL_DOWN_MASK | KeyEvent.ALT_DOWN_MASK, true);
+    }
+	
+	protected DirectAllWaySegmentsAction(String name, String iconName, String tooltip, int shortCut, int modifier, boolean register) { 
+		super(name, iconName, tooltip, shortCut, modifier, register);
+	}
+	
+	/**
+	 * This method first sorts all the segments in a way, then makes sure that all 
+	 * the segments are facing the same direction as the first one.
+	 */
+	public void actionPerformed(ActionEvent e) {
+		Collection<Way> ways = new LinkedList<Way>();
+		for (OsmPrimitive osm : Main.ds.getSelected())
+			if (osm instanceof Way)
+				ways.add((Way)osm);
+		if (ways.size() < 1) {
+			JOptionPane.showMessageDialog(Main.parent, tr("Please select at least one way."));
+			return;
+		}
+		if (ways.size() > 1) {
+			int answer = JOptionPane.showConfirmDialog(Main.parent, tr("You selected more than one way. Reorder the segments of " + ways.size() + " ways?"), tr("Reorder segments"), JOptionPane.OK_CANCEL_OPTION);
+			if (answer != JOptionPane.OK_OPTION)
+				return;
+		}
+		for (Way way : ways) {
+			if ( !way.isIncomplete() && way.segments.size() > 1 )
+			{			
+				final LinkedList<Segment> sel = new LinkedList<Segment>(sortSegments(new LinkedList<Segment>(way.segments)));   	
+	
+		    	Collection<Command> c = new LinkedList<Command>();
+	
+		    	boolean direction = false;
+		    	// work out the "average" direction of the way, we use this to direct the rest of the segments
+		    	int dirCounter = 0;
+		    	for(int i = 0; i < sel.size() - 1; i++)
+		    	{
+		    		Segment firstSegment = sel.get(i);
+		    		Segment secondSegment = sel.get(i+1);
+		    		if ( firstSegment.to == secondSegment.from || firstSegment.to == secondSegment.to ) // direction = true when 'from' is the first node in the Way
+		    			dirCounter++;
+		    		else
+		    			dirCounter--;
+		    	}
+		    	if ( dirCounter <= 0 )
+		    		direction = false;
+		    	else
+		    		direction = true;
+		    	
+		    	if ( reverseDirection )
+		    		direction = !direction;
+	    	
+	    		Node lastNode = null;
+
+	    		// we need to calculate what the first node in the way is, we work from there
+	    		Segment firstSegment = sel.getFirst();
+	    		Segment secondSegment = sel.get(1);
+	    		if ( firstSegment.to == secondSegment.from || firstSegment.to == secondSegment.to )
+	    			lastNode = firstSegment.from;
+	    		else
+	    			lastNode = firstSegment.to;
+	    		
+	    		// go through each segment and fip them correctly
+		    	for (Segment s : sel) {
+	    			Segment snew = new Segment(s);
+	    			boolean segDirection = s.from == lastNode;
+	    			// segDirection = true when the 'from' node occurs before the 'to' node in the Way 
+	    			if ( direction != segDirection )
+	    			{    			
+	    				// reverse the node's direction
+	    				Node n = snew.from;
+	    				snew.from = snew.to;
+	    				snew.to = n;
+	    				c.add(new ChangeCommand(s, snew));
+	    			}	
+	    			
+		    		if ( direction ) // if its facing forwards,
+		    			lastNode = snew.to; // our next node is the 'to' one
+		    		else
+		    			lastNode = snew.from; // otherwise its the 'from' one
+		    	}
+
+		    	LinkedList<Segment> segments = new LinkedList<Segment>();
+		    	
+		    	// Now we recreate the segment list, in the correct order of the direction
+	    		for (Segment s : sel) 
+	    			if ( !direction ) 
+	    				segments.addFirst(s);
+	    			else
+	    				segments.addLast(s);
+	    			
+	    		// Check if the new segment list is actually different to the old one
+	    		// before we go and add a change command for it
+	    		for(int i = 0; i < segments.size(); i++)
+	    			if ( way.segments.get(i) != segments.get(i) )
+	    			{
+				    	Way newWay2 = new Way(way);
+				    	newWay2.segments.clear();
+						newWay2.segments.addAll(segments);
+						c.add(new ChangeCommand(way, newWay2));
+						break;
+	    			}
+	
+	    		// Check we've got some change commands before we add a sequence command
+	    		if ( c.size() != 0 )
+	    			Main.main.editLayer().add(new SequenceCommand(tr("Direct all way segments"), c));
+			}
+		}
+		Main.map.repaint();
+	}
+
+	/**
+	 * This sort is based on the sort in ReorderAction, but it works iresepective
+	 * of the direction of the segments. This produces a sort that can be useful
+	 * even if the segments are facing the wrong direction.
+	 */
+	public static LinkedList<Segment> sortSegments(LinkedList<Segment> segments) {
+		LinkedList<Segment> sortedSegments = new LinkedList<Segment>();
+		while (!segments.isEmpty()) {
+			LinkedList<Segment> pivotList = new LinkedList<Segment>();
+			pivotList.add(segments.getFirst());
+			segments.removeFirst();
+			for (boolean found = true; found;) {
+				found = false;
+				for (Iterator<Segment> it = segments.iterator(); it.hasNext();) {
+					Segment ls = it.next();
+					if (ls.incomplete)
+						continue; // incomplete segments are never added to a new way
+					if (ls.from == pivotList.getLast().to || ls.to == pivotList.getLast().to || ls.from == pivotList.getLast().from || ls.to == pivotList.getLast().from) {
+						pivotList.addLast(ls);
+						it.remove();
+						found = true;
+					} else if (ls.to == pivotList.getFirst().from || ls.from == pivotList.getFirst().from || ls.to == pivotList.getFirst().to || ls.from == pivotList.getFirst().to) {
+						pivotList.addFirst(ls);
+						it.remove(); 
+						found = true;
+					}
+				}
+			}
+			sortedSegments.addAll(pivotList);
+		}
+	    return sortedSegments;
+    }
+}
Index: src/org/openstreetmap/josm/gui/MainMenu.java
===================================================================
--- src/org/openstreetmap/josm/gui/MainMenu.java	(revision 219)
+++ src/org/openstreetmap/josm/gui/MainMenu.java	(working copy)
@@ -12,6 +12,7 @@
 import org.openstreetmap.josm.actions.AlignInLineAction;
 import org.openstreetmap.josm.actions.AutoScaleAction;
 import org.openstreetmap.josm.actions.CombineWayAction;
+import org.openstreetmap.josm.actions.DirectAllWaySegmentsReverseAction;
 import org.openstreetmap.josm.actions.DownloadAction;
 import org.openstreetmap.josm.actions.DownloadIncompleteAction;
 import org.openstreetmap.josm.actions.ExitAction;
@@ -31,6 +32,7 @@
 import org.openstreetmap.josm.actions.UnselectAllAction;
 import org.openstreetmap.josm.actions.UploadAction;
 import org.openstreetmap.josm.actions.search.SearchAction;
+import org.openstreetmap.josm.actions.DirectAllWaySegmentsAction;
 
 /**
  * This is the JOSM main menu bar. It is overwritten to initialize itself and provide
@@ -56,6 +58,8 @@
 	public final Action alignInCircle = new AlignInCircleAction();
 	public final Action alignInLine = new AlignInLineAction();
 	public final Action reorder = new ReorderAction();
+	public final Action reorderWay = new DirectAllWaySegmentsAction();
+	public final Action reverseOrderWay = new DirectAllWaySegmentsReverseAction();
 	public final Action upload = new UploadAction();
 	public final Action save = new SaveAction();
 	public final Action saveAs = new SaveAsAction();
@@ -114,6 +118,9 @@
 		toolsMenu.add(reverseSegment);
 		toolsMenu.add(reorder);
 		toolsMenu.addSeparator();
+		toolsMenu.add(reorderWay);
+		toolsMenu.add(reverseOrderWay);
+		toolsMenu.addSeparator();
 		toolsMenu.add(splitWay);
 		toolsMenu.add(combineWay);
 		add(toolsMenu);
Index: src/org/openstreetmap/josm/gui/SelectionManager.java
===================================================================
--- src/org/openstreetmap/josm/gui/SelectionManager.java	(revision 219)
+++ src/org/openstreetmap/josm/gui/SelectionManager.java	(working copy)
@@ -162,7 +162,7 @@
 	 * If the correct button, from the "drawing rectangle" mode
 	 */
 	public void mousePressed(MouseEvent e) {
-		if (e.getButton() == MouseEvent.BUTTON1)
+		if (e.getButton() == MouseEvent.BUTTON1 || e.getButton() == MouseEvent.BUTTON3)
 			mousePosStart = mousePos = e.getPoint();
 	}
 
@@ -194,7 +194,7 @@
 	 * Check the state of the keys and buttons and set the selection accordingly.
 	 */
 	public void mouseReleased(MouseEvent e) {
-		if (e.getButton() != MouseEvent.BUTTON1)
+		if (e.getButton() != MouseEvent.BUTTON1 && e.getButton() != MouseEvent.BUTTON3)
 			return;
 		if (mousePos == null || mousePosStart == null)
 			return; // injected release from outside
@@ -206,7 +206,7 @@
 		mousePos = null;
 
 		boolean shift = (e.getModifiersEx() & MouseEvent.SHIFT_DOWN_MASK) != 0;
-		boolean alt = (e.getModifiersEx() & MouseEvent.ALT_DOWN_MASK) != 0;
+		boolean alt = (e.getModifiersEx() & MouseEvent.ALT_DOWN_MASK) != 0 || e.getButton() == MouseEvent.BUTTON3;
 		boolean ctrl = (e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) != 0;
 		if ((e.getModifiersEx() & MouseEvent.BUTTON3_DOWN_MASK) == 0)
 			selectionEndedListener.selectionEnded(r, alt, shift, ctrl);
Index: src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java	(revision 219)
+++ src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java	(working copy)
@@ -3,6 +3,8 @@
 import java.awt.Color;
 import java.awt.Graphics;
 import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.geom.Line2D;
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.DataSet;
@@ -67,7 +69,7 @@
 	 * White if selected (as always) or green otherwise.
 	 */
 	public void visit(Segment ls) {
-		drawSegment(ls, getPreferencesColor("segment", darkgreen));
+		drawSegment(ls, getPreferencesColor("segment", darkgreen), Main.pref.getBoolean("draw.segment.direction"));
 	}
 
 	/**
@@ -84,12 +86,14 @@
 			}
 		}
 
+		boolean showDirectionArrow = Main.pref.getBoolean("draw.segment.direction");
+		boolean showOrderNumber = Main.pref.getBoolean("draw.segment.order_number");
 		int orderNumber = 0;
 		for (Segment ls : w.segments) {
 			orderNumber++;
 			if (!ls.selected) // selected already in good color
-				drawSegment(ls, w.selected ? getPreferencesColor("selected", Color.WHITE) : wayColor);
-			if (!ls.incomplete && Main.pref.getBoolean("draw.segment.order_number"))
+				drawSegment(ls, w.selected ? getPreferencesColor("selected", Color.WHITE) : wayColor, showDirectionArrow);
+			if (!ls.incomplete && showOrderNumber)
 				drawOrderNumber(ls, orderNumber);
 		}
 	}
@@ -103,11 +107,15 @@
 		Point p2 = nc.getPoint(ls.to.eastNorth);
 		int x = (p1.x+p2.x)/2 - 4*strlen;
 		int y = (p1.y+p2.y)/2 + 4;
-		Color c = g.getColor();
-		g.setColor(Color.black);
-		g.fillRect(x-1,y-12,8*strlen+1,14);
-		g.setColor(c);
-		g.drawString(""+orderNumber,x,y);
+
+		Rectangle screen = g.getClipBounds();
+		if ( screen.contains(x,y) ) {
+			Color c = g.getColor();
+			g.setColor(getPreferencesColor("background", Color.BLACK));
+			g.fillRect(x-1,y-12,8*strlen+1,14);
+			g.setColor(c);
+			g.drawString(""+orderNumber,x,y);
+		}
     }
 
 	/**
@@ -119,13 +127,16 @@
 	public void drawNode(Node n, Color color) {
 		Point p = nc.getPoint(n.eastNorth);
 		g.setColor(color);
-		g.drawRect(p.x-1, p.y-1, 2, 2);
+		Rectangle screen = g.getClipBounds();
+
+		if ( screen.contains(p.x, p.y) )
+			g.drawRect(p.x-1, p.y-1,2,2);
 	}
 
 	/**
 	 * Draw a line with the given color.
 	 */
-	protected void drawSegment(Segment ls, Color col) {
+	protected void drawSegment(Segment ls, Color col, boolean showDirection) {
 		if (ls.incomplete)
 			return;
 		if (ls.selected)
@@ -133,12 +144,18 @@
 		g.setColor(col);
 		Point p1 = nc.getPoint(ls.from.eastNorth);
 		Point p2 = nc.getPoint(ls.to.eastNorth);
-		g.drawLine(p1.x, p1.y, p2.x, p2.y);
-
-		if (Main.pref.getBoolean("draw.segment.direction")) {
-			double t = Math.atan2(p2.y-p1.y, p2.x-p1.x) + Math.PI;
-	        g.drawLine(p2.x,p2.y, (int)(p2.x + 10*Math.cos(t-PHI)), (int)(p2.y + 10*Math.sin(t-PHI)));
-	        g.drawLine(p2.x,p2.y, (int)(p2.x + 10*Math.cos(t+PHI)), (int)(p2.y + 10*Math.sin(t+PHI)));
+		
+		Rectangle screen = g.getClipBounds();
+		Line2D line = new Line2D.Double(p1.x, p1.y, p2.x, p2.y);
+		if ( screen.contains(p1.x, p1.y, p2.x, p2.y) || screen.intersectsLine(line) )
+		{
+			g.drawLine(p1.x, p1.y, p2.x, p2.y);
+	
+			if (showDirection) {
+				double t = Math.atan2(p2.y-p1.y, p2.x-p1.x) + Math.PI;
+		        g.drawLine(p2.x,p2.y, (int)(p2.x + 10*Math.cos(t-PHI)), (int)(p2.y + 10*Math.sin(t-PHI)));
+		        g.drawLine(p2.x,p2.y, (int)(p2.x + 10*Math.cos(t+PHI)), (int)(p2.y + 10*Math.sin(t+PHI)));
+			}
 		}
 	}
 
