Index: trunk/src/org/openstreetmap/josm/gui/layer/TMSLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/TMSLayer.java	(revision 3770)
+++ trunk/src/org/openstreetmap/josm/gui/layer/TMSLayer.java	(revision 3773)
@@ -17,5 +17,4 @@
 import java.awt.font.TextAttribute;
 import java.awt.geom.Rectangle2D;
-import java.awt.image.BufferedImage;
 import java.awt.image.ImageObserver;
 import java.io.IOException;
@@ -76,5 +75,5 @@
     public static final int MAX_ZOOM = 30;
     public static final int MIN_ZOOM = 2;
-    public static final int DEFAULT_MAX_ZOOM = 18;
+    public static final int DEFAULT_MAX_ZOOM = 20;
     public static final int DEFAULT_MIN_ZOOM = 2;
 
@@ -101,8 +100,10 @@
     public synchronized void tileLoadingFinished(Tile tile, boolean success)
     {
-        if (!success) {
-            BufferedImage img = new BufferedImage(tileSource.getTileSize(),tileSource.getTileSize(), BufferedImage.TYPE_INT_RGB);
-            drawErrorTile(img);
-            tile.setImage(img);
+        if (tile.hasError()) {
+            success = false;
+            tile.setImage(null);
+        }
+        if (sharpenLevel != 0 && success) {
+            tile.setImage(sharpenImage(tile.getImage()));
         }
         tile.setLoaded(true);
@@ -110,6 +111,6 @@
         Main.map.repaint(100);
         tileRequestsOutstanding.remove(tile);
-        if (sharpenLevel != 0 && success) {
-            tile.setImage(sharpenImage(tile.getImage()));
+        if (success) {
+            displayZoomLevel = tile.getZoom();
         }
         if (debug) {
@@ -135,4 +136,6 @@
      */
     public int currentZoomLevel;
+    public int bestZoomLevel;
+    public int displayZoomLevel = 0;
 
     private Tile clickedTile;
@@ -242,11 +245,7 @@
         }
 
-        currentZoomLevel = getBestZoom();
-        if (currentZoomLevel > getMaxZoomLvl()) {
-            currentZoomLevel = getMaxZoomLvl();
-        }
-        if (currentZoomLevel < getMinZoomLvl()) {
-            currentZoomLevel = getMinZoomLvl();
-        }
+        updateBestZoom();
+        currentZoomLevel = bestZoomLevel;
+
         clearTileCache();
         //tileloader = new OsmTileLoader(this);
@@ -269,4 +268,14 @@
         double ret = Math.log(getPPDeg()*360/tileSource.getTileSize())/Math.log(2);
         return (int)Math.round(ret);
+    }
+
+    private void updateBestZoom() {
+        bestZoomLevel = getBestZoom();
+        if (bestZoomLevel > getMaxZoomLvl()) {
+            bestZoomLevel = getMaxZoomLvl();
+        }
+        if (bestZoomLevel < getMinZoomLvl()) {
+            bestZoomLevel = getMinZoomLvl();
+        }
     }
 
@@ -508,4 +517,14 @@
     }
 
+    public boolean setZoomLevel(int zoom)
+    {
+        if (zoom > this.getMaxZoomLvl()) return false;
+        if (zoom < this.getMinZoomLvl()) return false;
+        currentZoomLevel = zoom;
+        lastImageScale = null;
+        zoomChanged();
+        return true;
+    }
+
     /**
      * Zoom out from map.
@@ -813,5 +832,5 @@
         for (Tile tile : ts.allTiles()) {
             Image img = getLoadedTileImage(tile);
-            if (img == null) {
+            if (img == null || tile.hasError()) {
                 if (debug) {
                     out("missed tile: " + tile);
@@ -875,4 +894,9 @@
         if (!tile.isLoaded() && PROP_DRAW_DEBUG.get()) {
             myDrawString(g, tr("image " + tileStatus), p.x + 2, texty);
+            texty += 1 + fontHeight;
+        }
+
+        if (tile.hasError() && (displayZoomLevel == 0 || !"no-tile".equals(tile.getValue("tile-info")))) {
+            myDrawString(g, tr("Error") + ": " + tr(tile.getErrorMessage()), p.x + 2, texty);
             texty += 1 + fontHeight;
         }
@@ -1168,5 +1192,5 @@
 
             g.setFont(ATTR_FONT);
-            String attributionText = tileSource.getAttributionText(currentZoomLevel,
+            String attributionText = tileSource.getAttributionText(displayZoomLevel,
                     getShiftedCoord(topLeft), getShiftedCoord(botRight));
             Rectangle2D stringBounds = g.getFontMetrics().getStringBounds(attributionText, g);
@@ -1200,5 +1224,5 @@
         }
         //g.drawString("currentZoomLevel=" + currentZoomLevel, 120, 120);
-        g.setColor(Color.black);
+        g.setColor(Color.lightGray);
         if (ts.insane()) {
             myDrawString(g, "zoom in to load any tiles", 120, 120);
