Index: trunk/src/org/openstreetmap/josm/actions/AutoScaleAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/AutoScaleAction.java	(revision 2757)
+++ trunk/src/org/openstreetmap/josm/actions/AutoScaleAction.java	(revision 2758)
@@ -28,5 +28,12 @@
 public class AutoScaleAction extends JosmAction {
 
-    public static final String[] MODES = { marktr("data"), marktr("layer"), marktr("selection"), marktr("conflict"), marktr("download") };
+    public static final String[] MODES = {
+        marktr("data"),
+        marktr("layer"),
+        marktr("selection"),
+        marktr("conflict"),
+        marktr("download"),
+        marktr("previous"),
+        marktr("next")};
 
     /**
@@ -81,4 +88,10 @@
             shortcut = KeyEvent.VK_5;
         }
+        if (mode.equals("previous")) {
+            shortcut = KeyEvent.VK_8;
+        }
+        if (mode.equals("next")) {
+            shortcut = KeyEvent.VK_9;
+        }
 
         return shortcut;
@@ -99,6 +112,10 @@
         } else if (mode.equals("conflict")) {
             putValue("help", ht("/Action/ZoomToConflict"));
-        }else if (mode.equals("download")) {
+        } else if (mode.equals("download")) {
             putValue("help", ht("/Action/ZoomToDownload"));
+        } else if (mode.equals("previous")) {
+            putValue("help", ht("/Action/ZoomPrevious"));
+        } else if (mode.equals("next")) {
+            putValue("help", ht("/Action/ZoomNext"));
         }
     }
@@ -106,7 +123,13 @@
     public void autoScale()  {
         if (Main.map != null) {
-            BoundingXYVisitor bbox = getBoundingBox();
-            if (bbox != null && bbox.getBounds() != null) {
-                Main.map.mapView.recalculateCenterScale(bbox);
+            if (mode.equals("previous")) {
+                Main.map.mapView.zoomPrevious();
+            } else if (mode.equals("next")) {
+                Main.map.mapView.zoomNext();
+            } else {
+                BoundingXYVisitor bbox = getBoundingBox();
+                if (bbox != null && bbox.getBounds() != null) {
+                    Main.map.mapView.recalculateCenterScale(bbox);
+                }
             }
         }
Index: trunk/src/org/openstreetmap/josm/gui/NavigatableComponent.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/NavigatableComponent.java	(revision 2757)
+++ trunk/src/org/openstreetmap/josm/gui/NavigatableComponent.java	(revision 2758)
@@ -8,4 +8,5 @@
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Date;
 import java.util.HashSet;
 import java.util.LinkedList;
@@ -205,6 +206,4 @@
      */
     private void zoomTo(EastNorth newCenter, double newScale) {
-        boolean rep = false;
-
         Bounds b = getProjection().getWorldBoundsLatLon();
         CachedLatLon cl = new CachedLatLon(newCenter);
@@ -219,11 +218,4 @@
             newCenter = new CachedLatLon(lat, lon).getEastNorth();
         }
-        if (!newCenter.equals(center)) {
-            EastNorth oldCenter = center;
-            center = newCenter;
-            rep = true;
-            firePropertyChange("center", oldCenter, newCenter);
-        }
-
         int width = getWidth()/2;
         int height = getHeight()/2;
@@ -250,14 +242,29 @@
             }
         }
+
+        if (!newCenter.equals(center) || (scale != newScale)) {
+            pushZoomUndo(center, scale);
+            zoomNoUndoTo(newCenter, newScale);
+        }
+    }
+
+    /**
+     * Zoom to the given coordinate without adding to the zoom undo buffer.
+     * @param newCenter The center x-value (easting) to zoom to.
+     * @param scale The scale to use.
+     */
+    private void zoomNoUndoTo(EastNorth newCenter, double newScale) {
+        if (!newCenter.equals(center)) {
+            EastNorth oldCenter = center;
+            center = newCenter;
+            firePropertyChange("center", oldCenter, newCenter);
+        }
         if (scale != newScale) {
             double oldScale = scale;
             scale = newScale;
-            rep = true;
             firePropertyChange("scale", oldScale, newScale);
         }
 
-        if(rep) {
-            repaint();
-        }
+        repaint();
     }
 
@@ -313,4 +320,51 @@
         zoomTo(new ProjectionBounds(getProjection().latlon2eastNorth(box.getMin()),
                 getProjection().latlon2eastNorth(box.getMax())));
+    }
+
+    private class ZoomData {
+        LatLon center;
+        double scale;
+
+        public ZoomData(EastNorth center, double scale) {
+            this.center = new CachedLatLon(center);
+            this.scale = scale;
+        }
+
+        public EastNorth getCenterEastNorth() {
+            return getProjection().latlon2eastNorth(center);
+        }
+
+        public double getScale() {
+            return scale;
+        }
+    }
+
+    private LinkedList<ZoomData> zoomUndoBuffer = new LinkedList<ZoomData>();
+    private LinkedList<ZoomData> zoomRedoBuffer = new LinkedList<ZoomData>();
+    private Date zoomTimestamp = new Date();
+
+    private void pushZoomUndo(EastNorth center, double scale) {
+        Date now = new Date();
+        if ((now.getTime() - zoomTimestamp.getTime()) > (Main.pref.getDouble("zoom.delay", 1.0) * 1000)) {
+            zoomUndoBuffer.push(new ZoomData(center, scale));
+            zoomRedoBuffer.clear();
+        }
+        zoomTimestamp = now;
+    }
+
+    public void zoomPrevious() {
+        if (!zoomUndoBuffer.isEmpty()) {
+            ZoomData zoom = zoomUndoBuffer.pop();
+            zoomRedoBuffer.push(new ZoomData(center, scale));
+            zoomNoUndoTo(zoom.getCenterEastNorth(), zoom.getScale());
+        }
+    }
+
+    public void zoomNext() {
+        if (!zoomRedoBuffer.isEmpty()) {
+            ZoomData zoom = zoomRedoBuffer.pop();
+            zoomUndoBuffer.push(new ZoomData(center, scale));
+            zoomNoUndoTo(zoom.getCenterEastNorth(), zoom.getScale());
+        }
     }
 
