Index: applications/editors/josm/plugins/wmsplugin/src/wmsplugin/GeorefImage.java
===================================================================
--- applications/editors/josm/plugins/wmsplugin/src/wmsplugin/GeorefImage.java	(revision 18712)
+++ applications/editors/josm/plugins/wmsplugin/src/wmsplugin/GeorefImage.java	(revision 18761)
@@ -137,8 +137,8 @@
         boolean hasImage = in.readBoolean();
         if (hasImage)
-        	image = (BufferedImage) ImageIO.read(ImageIO.createImageInputStream(in));
+            image = (BufferedImage) ImageIO.read(ImageIO.createImageInputStream(in));
         else {
-        	in.readObject(); // read null from input stream
-        	image = null;
+            in.readObject(); // read null from input stream
+            image = null;
         }
     }
@@ -148,8 +148,8 @@
         out.writeObject(min);
         if(image == null) {
-        	out.writeBoolean(false);
+            out.writeBoolean(false);
             out.writeObject(null);
         } else {
-        	out.writeBoolean(true);
+            out.writeBoolean(true);
             ImageIO.write(image, "png", ImageIO.createImageOutputStream(out));
         }
Index: applications/editors/josm/plugins/wmsplugin/src/wmsplugin/Map_Rectifier_WMSmenuAction.java
===================================================================
--- applications/editors/josm/plugins/wmsplugin/src/wmsplugin/Map_Rectifier_WMSmenuAction.java	(revision 18712)
+++ applications/editors/josm/plugins/wmsplugin/src/wmsplugin/Map_Rectifier_WMSmenuAction.java	(revision 18761)
@@ -155,5 +155,5 @@
         // The loop is break;-ed if the users cancels
         outer: while(true) {
-        	diag.showDialog();
+            diag.showDialog();
             int answer = diag.getValue();
             // Break loop when the user cancels
Index: applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSAdjustAction.java
===================================================================
--- applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSAdjustAction.java	(revision 18712)
+++ applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSAdjustAction.java	(revision 18761)
@@ -32,6 +32,6 @@
 
 public class WMSAdjustAction extends MapMode implements MouseListener, MouseMotionListener{
-	static private final Logger logger = Logger.getLogger(WMSAdjustAction.class.getName());
-	
+    static private final Logger logger = Logger.getLogger(WMSAdjustAction.class.getName());
+    
     GeorefImage selectedImage;
     boolean mouseDown;
@@ -50,17 +50,17 @@
         super.enterMode();       
         if (!hasWMSLayersToAdjust()) {
-        	warnNoWMSLayers();
-        	return;
+            warnNoWMSLayers();
+            return;
         }
         List<WMSLayer> wmsLayers = Main.map.mapView.getLayersOfType(WMSLayer.class);
         if (wmsLayers.size() == 1) {
-        	adjustingLayer = wmsLayers.get(0);
+            adjustingLayer = wmsLayers.get(0);
         } else {
-        	adjustingLayer = (WMSLayer)askAdjustLayer(Main.map.mapView.getLayersOfType(WMSLayer.class));
+            adjustingLayer = (WMSLayer)askAdjustLayer(Main.map.mapView.getLayersOfType(WMSLayer.class));
         }
         if (adjustingLayer == null)
-        	return;
+            return;
         if (!adjustingLayer.isVisible()) {
-        	adjustingLayer.setVisible(true);
+            adjustingLayer.setVisible(true);
         }
         Main.map.mapView.addMouseListener(this);
@@ -175,8 +175,8 @@
    
        ExtendedDialog diag = new ExtendedDialog(
-    		   Main.parent, 
-    		   tr("Select WMS layer"), 
-    		   new String[] { tr("Start adjusting"),tr("Cancel") }
-    		   );
+               Main.parent, 
+               tr("Select WMS layer"), 
+               new String[] { tr("Start adjusting"),tr("Cancel") }
+               );
        diag.setContent(pnl);
        diag.setButtonIcons(new String[] { "mapmode/adjustwms", "cancel" });
@@ -195,5 +195,5 @@
    protected void warnNoWMSLayers() {
        JOptionPane.showMessageDialog(
-    		   Main.parent,
+               Main.parent,
                tr("There are currently no WMS layer to adjust."),
                tr("No layers to adjust"), 
@@ -208,12 +208,12 @@
     */
    protected boolean hasWMSLayersToAdjust() {
-	   if (Main.map == null) return false;
-	   if (Main.map.mapView == null) return false;
-	   return ! Main.map.mapView.getLayersOfType(WMSLayer.class).isEmpty();
-   }
-
-	@Override
-	protected void updateEnabledState() {
-		setEnabled(hasWMSLayersToAdjust());
-	}   
+       if (Main.map == null) return false;
+       if (Main.map.mapView == null) return false;
+       return ! Main.map.mapView.getLayersOfType(WMSLayer.class).isEmpty();
+   }
+
+    @Override
+    protected void updateEnabledState() {
+        setEnabled(hasWMSLayersToAdjust());
+    }   
 }
Index: applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSGrabber.java
===================================================================
--- applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSGrabber.java	(revision 18712)
+++ applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSGrabber.java	(revision 18761)
@@ -37,5 +37,5 @@
         return url != null && url.contains("{") && url.contains("}");
     }
-	
+    
     protected String baseURL;
     private final boolean urlWithPatterns;
@@ -71,5 +71,5 @@
             image.downloadingStarted = false;
         } catch(Exception e) {
-        	e.printStackTrace();
+            e.printStackTrace();
             throw new Exception(e.getMessage() + "\nImage couldn't be fetched: " + (url != null ? url.toString() : ""));
         }
@@ -112,9 +112,9 @@
                 + getProjection(baseURL, false)
                 + "&width=" + wi + "&height=" + ht;
-        	if (!(baseURL.endsWith("&") || baseURL.endsWith("?"))) {
-        		System.out.println(tr("Warning: The base URL ''{0}'' for a WMS service doesn't have a trailing '&' or a trailing '?'.", baseURL));
-        		System.out.println(tr("Warning: Fetching WMS tiles is likely to fail. Please check you preference settings."));
-        		System.out.println(tr("Warning: The complete URL is ''{0}''.", str));
-        	}
+            if (!(baseURL.endsWith("&") || baseURL.endsWith("?"))) {
+                System.out.println(tr("Warning: The base URL ''{0}'' for a WMS service doesn't have a trailing '&' or a trailing '?'.", baseURL));
+                System.out.println(tr("Warning: Fetching WMS tiles is likely to fail. Please check you preference settings."));
+                System.out.println(tr("Warning: The complete URL is ''{0}''.", str));
+            }
         }
         return new URL(str.replace(" ", "%20"));
Index: applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSLayer.java
===================================================================
--- applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSLayer.java	(revision 18712)
+++ applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSLayer.java	(revision 18761)
@@ -41,390 +41,390 @@
 /**
  * This is a layer that grabs the current screen from an WMS server. The data
- * fetched this way is tiled and managerd to the disc to reduce server load.
+ * fetched this way is tiled and managed to the disc to reduce server load.
  */
 public class WMSLayer extends Layer {
-	protected static final Icon icon =
-		new ImageIcon(Toolkit.getDefaultToolkit().createImage(WMSPlugin.class.getResource("/images/wms_small.png")));
-
-	public int messageNum = 5; //limit for messages per layer
-	protected MapView mv;
-	protected String resolution;
-	protected boolean stopAfterPaint = false;
-	protected int ImageSize = 500;
-	protected int dax = 10;
-	protected int day = 10;
-	protected int minZoom = 3;
-	protected double dx = 0.0;
-	protected double dy = 0.0;
-	protected double pixelPerDegree;
-	protected GeorefImage[][] images = new GeorefImage[dax][day];
-	JCheckBoxMenuItem startstop = new JCheckBoxMenuItem(tr("Automatic downloading"), true);
-	protected JCheckBoxMenuItem alphaChannel = new JCheckBoxMenuItem(new ToggleAlphaAction());
-	protected String baseURL;
-	protected String cookies;
-	protected final int serializeFormatVersion = 5;
-
-	private ExecutorService executor = null;
-
-	/** set to true if this layer uses an invalid base url */
-	private boolean usesInvalidUrl = false;
-	/** set to true if the user confirmed to use an potentially invalid WMS base url */
-	private boolean isInvalidUrlConfirmed = false;
-
-	public WMSLayer() {
-		this(tr("Blank Layer"), null, null);
-		initializeImages();
-		mv = Main.map.mapView;
-	}
-
-	public WMSLayer(String name, String baseURL, String cookies) {
-		super(name);
-		alphaChannel.setSelected(Main.pref.getBoolean("wmsplugin.alpha_channel"));
-		setBackgroundLayer(true); /* set global background variable */
-		initializeImages();
-		this.baseURL = baseURL;
-		this.cookies = cookies;
-		WMSGrabber.getProjection(baseURL, true);
-		mv = Main.map.mapView;
-		resolution = mv.getDist100PixelText();
-		pixelPerDegree = getPPD();
-
-		executor = Executors.newFixedThreadPool(3);
-		if (baseURL != null && !baseURL.startsWith("html:") && !WMSGrabber.isUrlWithPatterns(baseURL)) {
-			if (!(baseURL.endsWith("&") || baseURL.endsWith("?"))) {
-				if (!confirmMalformedUrl(baseURL)) {
-					System.out.println(tr("Warning: WMS layer deactivated because of malformed base url ''{0}''", baseURL));
-					usesInvalidUrl = true;
-					setName(getName() + tr("(deactivated)"));
-					return;
-				} else {
-					isInvalidUrlConfirmed = true;
-				}
-			}
-		}
-	}
-
-	public double getDx(){
-		return dx;
-	}
-
-	public double getDy(){
-		return dy;
-	}
-
-	@Override
-	public void destroy() {
-		try {
-			executor.shutdownNow();
-			// Might not be initalized, so catch NullPointer as well
-		} catch(Exception x) {
-			x.printStackTrace();
-		}
-	}
-
-	public double getPPD(){
-		ProjectionBounds bounds = mv.getProjectionBounds();
-		return mv.getWidth() / (bounds.max.east() - bounds.min.east());
-	}
-
-	public void initializeImages() {
-		images = new GeorefImage[dax][day];
-		for(int x = 0; x<dax; ++x) {
-			for(int y = 0; y<day; ++y) {
-				images[x][y]= new GeorefImage(false);
-			}
-		}
-	}
-
-	@Override public Icon getIcon() {
-		return icon;
-	}
-
-	@Override public String getToolTipText() {
-		if(startstop.isSelected())
-			return tr("WMS layer ({0}), automatically downloading in zoom {1}", getName(), resolution);
-		else
-			return tr("WMS layer ({0}), downloading in zoom {1}", getName(), resolution);
-	}
-
-	@Override public boolean isMergable(Layer other) {
-		return false;
-	}
-
-	@Override public void mergeFrom(Layer from) {
-	}
-
-	private ProjectionBounds XYtoBounds (int x, int y) {
-		return new ProjectionBounds(
-				new EastNorth(      x * ImageSize / pixelPerDegree,       y * ImageSize / pixelPerDegree),
-				new EastNorth((x + 1) * ImageSize / pixelPerDegree, (y + 1) * ImageSize / pixelPerDegree));
-	}
-
-	private int modulo (int a, int b) {
-		return a % b >= 0 ? a%b : a%b+b;
-	}
-
-	@Override public void paint(Graphics2D g, final MapView mv, Bounds bounds) {
-		if(baseURL == null) return;
-		if (usesInvalidUrl && !isInvalidUrlConfirmed) return;
-
-		if( !startstop.isSelected() || (pixelPerDegree / getPPD() > minZoom) ){ //don't download when it's too outzoomed
-			for(int x = 0; x<dax; ++x) {
-				for(int y = 0; y<day; ++y) {
-					images[modulo(x,dax)][modulo(y,day)].paint(g, mv, dx, dy);
-				}
-			}
-		} else {
-			downloadAndPaintVisible(g, mv);
-		}
-	}
-
-	public void displace(double dx, double dy) {
-		this.dx += dx;
-		this.dy += dy;
-	}
-
-	protected boolean confirmMalformedUrl(String url) {
-		if (isInvalidUrlConfirmed)
-			return true;
-		String msg  = tr("<html>The base URL<br>"
-				        + "''{0}''<br>"
-				        + "for this WMS layer does neither end with a ''&'' nor with a ''?''.<br>"
-				        + "This is likely to lead to invalid WMS request. You should check your<br>"
-				        + "preference settings.<br>"
-				        + "Do you want to fetch WMS tiles anyway?",
-				        url);
-		String [] options = new String[] {
-			tr("Yes, fetch images"),
-			tr("No, abort")
-		};
-		int ret = JOptionPane.showOptionDialog(
-				Main.parent,
-				msg,
-				tr("Invalid URL?"),
-				JOptionPane.YES_NO_OPTION,
-				JOptionPane.WARNING_MESSAGE,
-				null,
-				options, options[1]
-		);
-		switch(ret) {
-		case JOptionPane.YES_OPTION: return true;
-		default: return false;
-		}
-	}
-	protected void downloadAndPaintVisible(Graphics g, final MapView mv){
-		if (usesInvalidUrl)
-			return;
-		ProjectionBounds bounds = mv.getProjectionBounds();
-		int bminx= (int)Math.floor (((bounds.min.east() - dx) * pixelPerDegree) / ImageSize );
-		int bminy= (int)Math.floor (((bounds.min.north() - dy) * pixelPerDegree) / ImageSize );
-		int bmaxx= (int)Math.ceil  (((bounds.max.east() - dx) * pixelPerDegree) / ImageSize );
-		int bmaxy= (int)Math.ceil  (((bounds.max.north() - dy) * pixelPerDegree) / ImageSize );
-
-		if((bmaxx - bminx > dax) || (bmaxy - bminy > day)){
-			JOptionPane.showMessageDialog(
-					Main.parent,
-					tr("The requested area is too big. Please zoom in a little, or change resolution"),
-					tr("Error"),
-					JOptionPane.ERROR_MESSAGE
-			);
-			return;
-		}
-
-		for(int x = bminx; x<bmaxx; ++x) {
-			for(int y = bminy; y<bmaxy; ++y){
-				GeorefImage img = images[modulo(x,dax)][modulo(y,day)];
-				g.drawRect(x, y, dax, bminy);
-				if(!img.paint(g, mv, dx, dy) && !img.downloadingStarted){
-					img.downloadingStarted = true;
-					img.image = null;
-					img.flushedResizedCachedInstance();
-					Grabber gr = WMSPlugin.getGrabber(XYtoBounds(x,y), img, mv, this);
-					gr.setPriority(1);
-					executor.submit(gr);
-				}
-			}
-		}
-	}
-
-	@Override public void visitBoundingBox(BoundingXYVisitor v) {
-		for(int x = 0; x<dax; ++x) {
-			for(int y = 0; y<day; ++y)
-				if(images[x][y].image!=null){
-					v.visit(images[x][y].min);
-					v.visit(images[x][y].max);
-				}
-		}
-	}
-
-	@Override public Object getInfoComponent() {
-		return getToolTipText();
-	}
-
-	@Override public Component[] getMenuEntries() {
-		return new Component[]{
-				new JMenuItem(LayerListDialog.getInstance().createShowHideLayerAction(this)),
-				new JMenuItem(LayerListDialog.getInstance().createDeleteLayerAction(this)),
-				new JSeparator(),
-				new JMenuItem(new LoadWmsAction()),
-				new JMenuItem(new SaveWmsAction()),
-				new JSeparator(),
-				startstop,
-				alphaChannel,
-				new JMenuItem(new ChangeResolutionAction()),
-				new JMenuItem(new ReloadErrorTilesAction()),
-				new JMenuItem(new DownloadAction()),
-				new JSeparator(),
-				new JMenuItem(new LayerListPopup.InfoAction(this))
-		};
-	}
-
-	public GeorefImage findImage(EastNorth eastNorth) {
-		for(int x = 0; x<dax; ++x) {
-			for(int y = 0; y<day; ++y)
-				if(images[x][y].image!=null && images[x][y].min!=null && images[x][y].max!=null)
-					if(images[x][y].contains(eastNorth, dx, dy))
-						return images[x][y];
-		}
-		return null;
-	}
-
-	public class DownloadAction extends AbstractAction {
-		public DownloadAction() {
-			super(tr("Download visible tiles"));
-		}
-		public void actionPerformed(ActionEvent ev) {
-			downloadAndPaintVisible(mv.getGraphics(), mv);
-		}
-	}
-
-	public class ChangeResolutionAction extends AbstractAction {
-		public ChangeResolutionAction() {
-			super(tr("Change resolution"));
-		}
-		public void actionPerformed(ActionEvent ev) {
-			initializeImages();
-			resolution = mv.getDist100PixelText();
-			pixelPerDegree = getPPD();
-			mv.repaint();
-		}
-	}
-
-	public class ReloadErrorTilesAction extends AbstractAction {
-		public ReloadErrorTilesAction() {
-			super(tr("Reload erroneous tiles"));
-		}
-		public void actionPerformed(ActionEvent ev) {
-			// Delete small files, because they're probably blank tiles.
-			// See https://josm.openstreetmap.de/ticket/2307
-			WMSPlugin.cache.customCleanUp(CacheFiles.CLEAN_SMALL_FILES, 2048);
-
-			for (int x = 0; x < dax; ++x) {
-				for (int y = 0; y < day; ++y) {
-					GeorefImage img = images[modulo(x,dax)][modulo(y,day)];
-					if(img.failed){
-						img.image = null;
-						img.flushedResizedCachedInstance();
-						img.downloadingStarted = false;
-						img.failed = false;
-						mv.repaint();
-					}
-				}
-			}
-		}
-	}
-
-	public class ToggleAlphaAction extends AbstractAction {
-		public ToggleAlphaAction() {
-			super(tr("Alpha channel"));
-		}
-		public void actionPerformed(ActionEvent ev) {
-			JCheckBoxMenuItem checkbox = (JCheckBoxMenuItem) ev.getSource();
-			boolean alphaChannel = checkbox.isSelected();
-			Main.pref.put("wmsplugin.alpha_channel", alphaChannel);
-
-			// clear all resized cached instances and repaint the layer
-			for (int x = 0; x < dax; ++x) {
-				for (int y = 0; y < day; ++y) {
-					GeorefImage img = images[modulo(x, dax)][modulo(y, day)];
-					img.flushedResizedCachedInstance();
-				}
-			}
-			mv.repaint();
-		}
-	}
-
-	public class SaveWmsAction extends AbstractAction {
-		public SaveWmsAction() {
-			super(tr("Save WMS layer to file"), ImageProvider.get("save"));
-		}
-		public void actionPerformed(ActionEvent ev) {
-			File f = SaveActionBase.createAndOpenSaveFileChooser(
-					tr("Save WMS layer"), ".wms");
-			try {
-				if (f != null) {
-					ObjectOutputStream oos = new ObjectOutputStream(
-							new FileOutputStream(f)
-					);
-					oos.writeInt(serializeFormatVersion);
-					oos.writeInt(dax);
-					oos.writeInt(day);
-					oos.writeInt(ImageSize);
-					oos.writeDouble(pixelPerDegree);
-					oos.writeObject(getName());
-					oos.writeObject(baseURL);
-					oos.writeObject(images);
-					oos.close();
-				}
-			} catch (Exception ex) {
-				ex.printStackTrace(System.out);
-			}
-		}
-	}
-
-	public class LoadWmsAction extends AbstractAction {
-		public LoadWmsAction() {
-			super(tr("Load WMS layer from file"), ImageProvider.get("load"));
-		}
-		public void actionPerformed(ActionEvent ev) {
-			JFileChooser fc = DiskAccessAction.createAndOpenFileChooser(true,
-					false, tr("Load WMS layer"), "wms");
-			if(fc == null) return;
-			File f = fc.getSelectedFile();
-			if (f == null) return;
-			try
-			{
-				FileInputStream fis = new FileInputStream(f);
-				ObjectInputStream ois = new ObjectInputStream(fis);
-				int sfv = ois.readInt();
-				if (sfv != serializeFormatVersion) {
-					JOptionPane.showMessageDialog(Main.parent,
-							tr("Unsupported WMS file version; found {0}, expected {1}", sfv, serializeFormatVersion),
-							tr("File Format Error"),
-							JOptionPane.ERROR_MESSAGE);
-					return;
-				}
-				startstop.setSelected(false);
-				dax = ois.readInt();
-				day = ois.readInt();
-				ImageSize = ois.readInt();
-				pixelPerDegree = ois.readDouble();
-				setName((String)ois.readObject());
-				baseURL = (String) ois.readObject();
-				images = (GeorefImage[][])ois.readObject();
-				ois.close();
-				fis.close();
-				mv.repaint();
-			}
-			catch (Exception ex) {
-				// FIXME be more specific
-				ex.printStackTrace(System.out);
-				JOptionPane.showMessageDialog(Main.parent,
-						tr("Error loading file"),
-						tr("Error"),
-						JOptionPane.ERROR_MESSAGE);
-				return;
-			}
-		}
-	}
+    protected static final Icon icon =
+        new ImageIcon(Toolkit.getDefaultToolkit().createImage(WMSPlugin.class.getResource("/images/wms_small.png")));
+
+    public int messageNum = 5; //limit for messages per layer
+    protected MapView mv;
+    protected String resolution;
+    protected boolean stopAfterPaint = false;
+    protected int ImageSize = 500;
+    protected int dax = 10;
+    protected int day = 10;
+    protected int minZoom = 3;
+    protected double dx = 0.0;
+    protected double dy = 0.0;
+    protected double pixelPerDegree;
+    protected GeorefImage[][] images = new GeorefImage[dax][day];
+    JCheckBoxMenuItem startstop = new JCheckBoxMenuItem(tr("Automatic downloading"), true);
+    protected JCheckBoxMenuItem alphaChannel = new JCheckBoxMenuItem(new ToggleAlphaAction());
+    protected String baseURL;
+    protected String cookies;
+    protected final int serializeFormatVersion = 5;
+
+    private ExecutorService executor = null;
+
+    /** set to true if this layer uses an invalid base url */
+    private boolean usesInvalidUrl = false;
+    /** set to true if the user confirmed to use an potentially invalid WMS base url */
+    private boolean isInvalidUrlConfirmed = false;
+
+    public WMSLayer() {
+        this(tr("Blank Layer"), null, null);
+        initializeImages();
+        mv = Main.map.mapView;
+    }
+
+    public WMSLayer(String name, String baseURL, String cookies) {
+        super(name);
+        alphaChannel.setSelected(Main.pref.getBoolean("wmsplugin.alpha_channel"));
+        setBackgroundLayer(true); /* set global background variable */
+        initializeImages();
+        this.baseURL = baseURL;
+        this.cookies = cookies;
+        WMSGrabber.getProjection(baseURL, true);
+        mv = Main.map.mapView;
+        resolution = mv.getDist100PixelText();
+        pixelPerDegree = getPPD();
+
+        executor = Executors.newFixedThreadPool(3);
+        if (baseURL != null && !baseURL.startsWith("html:") && !WMSGrabber.isUrlWithPatterns(baseURL)) {
+            if (!(baseURL.endsWith("&") || baseURL.endsWith("?"))) {
+                if (!confirmMalformedUrl(baseURL)) {
+                    System.out.println(tr("Warning: WMS layer deactivated because of malformed base url ''{0}''", baseURL));
+                    usesInvalidUrl = true;
+                    setName(getName() + tr("(deactivated)"));
+                    return;
+                } else {
+                    isInvalidUrlConfirmed = true;
+                }
+            }
+        }
+    }
+
+    public double getDx(){
+        return dx;
+    }
+
+    public double getDy(){
+        return dy;
+    }
+
+    @Override
+    public void destroy() {
+        try {
+            executor.shutdownNow();
+            // Might not be initalized, so catch NullPointer as well
+        } catch(Exception x) {
+            x.printStackTrace();
+        }
+    }
+
+    public double getPPD(){
+        ProjectionBounds bounds = mv.getProjectionBounds();
+        return mv.getWidth() / (bounds.max.east() - bounds.min.east());
+    }
+
+    public void initializeImages() {
+        images = new GeorefImage[dax][day];
+        for(int x = 0; x<dax; ++x) {
+            for(int y = 0; y<day; ++y) {
+                images[x][y]= new GeorefImage(false);
+            }
+        }
+    }
+
+    @Override public Icon getIcon() {
+        return icon;
+    }
+
+    @Override public String getToolTipText() {
+        if(startstop.isSelected())
+            return tr("WMS layer ({0}), automatically downloading in zoom {1}", getName(), resolution);
+        else
+            return tr("WMS layer ({0}), downloading in zoom {1}", getName(), resolution);
+    }
+
+    @Override public boolean isMergable(Layer other) {
+        return false;
+    }
+
+    @Override public void mergeFrom(Layer from) {
+    }
+
+    private ProjectionBounds XYtoBounds (int x, int y) {
+        return new ProjectionBounds(
+                new EastNorth(      x * ImageSize / pixelPerDegree,       y * ImageSize / pixelPerDegree),
+                new EastNorth((x + 1) * ImageSize / pixelPerDegree, (y + 1) * ImageSize / pixelPerDegree));
+    }
+
+    private int modulo (int a, int b) {
+        return a % b >= 0 ? a%b : a%b+b;
+    }
+
+    @Override public void paint(Graphics2D g, final MapView mv, Bounds bounds) {
+        if(baseURL == null) return;
+        if (usesInvalidUrl && !isInvalidUrlConfirmed) return;
+
+        if( !startstop.isSelected() || (pixelPerDegree / getPPD() > minZoom) ){ //don't download when it's too outzoomed
+            for(int x = 0; x<dax; ++x) {
+                for(int y = 0; y<day; ++y) {
+                    images[modulo(x,dax)][modulo(y,day)].paint(g, mv, dx, dy);
+                }
+            }
+        } else {
+            downloadAndPaintVisible(g, mv);
+        }
+    }
+
+    public void displace(double dx, double dy) {
+        this.dx += dx;
+        this.dy += dy;
+    }
+
+    protected boolean confirmMalformedUrl(String url) {
+        if (isInvalidUrlConfirmed)
+            return true;
+        String msg  = tr("<html>The base URL<br>"
+                        + "''{0}''<br>"
+                        + "for this WMS layer does neither end with a ''&'' nor with a ''?''.<br>"
+                        + "This is likely to lead to invalid WMS request. You should check your<br>"
+                        + "preference settings.<br>"
+                        + "Do you want to fetch WMS tiles anyway?",
+                        url);
+        String [] options = new String[] {
+            tr("Yes, fetch images"),
+            tr("No, abort")
+        };
+        int ret = JOptionPane.showOptionDialog(
+                Main.parent,
+                msg,
+                tr("Invalid URL?"),
+                JOptionPane.YES_NO_OPTION,
+                JOptionPane.WARNING_MESSAGE,
+                null,
+                options, options[1]
+        );
+        switch(ret) {
+        case JOptionPane.YES_OPTION: return true;
+        default: return false;
+        }
+    }
+    protected void downloadAndPaintVisible(Graphics g, final MapView mv){
+        if (usesInvalidUrl)
+            return;
+        ProjectionBounds bounds = mv.getProjectionBounds();
+        int bminx= (int)Math.floor (((bounds.min.east() - dx) * pixelPerDegree) / ImageSize );
+        int bminy= (int)Math.floor (((bounds.min.north() - dy) * pixelPerDegree) / ImageSize );
+        int bmaxx= (int)Math.ceil  (((bounds.max.east() - dx) * pixelPerDegree) / ImageSize );
+        int bmaxy= (int)Math.ceil  (((bounds.max.north() - dy) * pixelPerDegree) / ImageSize );
+
+        if((bmaxx - bminx > dax) || (bmaxy - bminy > day)){
+            JOptionPane.showMessageDialog(
+                    Main.parent,
+                    tr("The requested area is too big. Please zoom in a little, or change resolution"),
+                    tr("Error"),
+                    JOptionPane.ERROR_MESSAGE
+            );
+            return;
+        }
+
+        for(int x = bminx; x<bmaxx; ++x) {
+            for(int y = bminy; y<bmaxy; ++y){
+                GeorefImage img = images[modulo(x,dax)][modulo(y,day)];
+                g.drawRect(x, y, dax, bminy);
+                if(!img.paint(g, mv, dx, dy) && !img.downloadingStarted){
+                    img.downloadingStarted = true;
+                    img.image = null;
+                    img.flushedResizedCachedInstance();
+                    Grabber gr = WMSPlugin.getGrabber(XYtoBounds(x,y), img, mv, this);
+                    gr.setPriority(1);
+                    executor.submit(gr);
+                }
+            }
+        }
+    }
+
+    @Override public void visitBoundingBox(BoundingXYVisitor v) {
+        for(int x = 0; x<dax; ++x) {
+            for(int y = 0; y<day; ++y)
+                if(images[x][y].image!=null){
+                    v.visit(images[x][y].min);
+                    v.visit(images[x][y].max);
+                }
+        }
+    }
+
+    @Override public Object getInfoComponent() {
+        return getToolTipText();
+    }
+
+    @Override public Component[] getMenuEntries() {
+        return new Component[]{
+                new JMenuItem(LayerListDialog.getInstance().createShowHideLayerAction(this)),
+                new JMenuItem(LayerListDialog.getInstance().createDeleteLayerAction(this)),
+                new JSeparator(),
+                new JMenuItem(new LoadWmsAction()),
+                new JMenuItem(new SaveWmsAction()),
+                new JSeparator(),
+                startstop,
+                alphaChannel,
+                new JMenuItem(new ChangeResolutionAction()),
+                new JMenuItem(new ReloadErrorTilesAction()),
+                new JMenuItem(new DownloadAction()),
+                new JSeparator(),
+                new JMenuItem(new LayerListPopup.InfoAction(this))
+        };
+    }
+
+    public GeorefImage findImage(EastNorth eastNorth) {
+        for(int x = 0; x<dax; ++x) {
+            for(int y = 0; y<day; ++y)
+                if(images[x][y].image!=null && images[x][y].min!=null && images[x][y].max!=null)
+                    if(images[x][y].contains(eastNorth, dx, dy))
+                        return images[x][y];
+        }
+        return null;
+    }
+
+    public class DownloadAction extends AbstractAction {
+        public DownloadAction() {
+            super(tr("Download visible tiles"));
+        }
+        public void actionPerformed(ActionEvent ev) {
+            downloadAndPaintVisible(mv.getGraphics(), mv);
+        }
+    }
+
+    public class ChangeResolutionAction extends AbstractAction {
+        public ChangeResolutionAction() {
+            super(tr("Change resolution"));
+        }
+        public void actionPerformed(ActionEvent ev) {
+            initializeImages();
+            resolution = mv.getDist100PixelText();
+            pixelPerDegree = getPPD();
+            mv.repaint();
+        }
+    }
+
+    public class ReloadErrorTilesAction extends AbstractAction {
+        public ReloadErrorTilesAction() {
+            super(tr("Reload erroneous tiles"));
+        }
+        public void actionPerformed(ActionEvent ev) {
+            // Delete small files, because they're probably blank tiles.
+            // See https://josm.openstreetmap.de/ticket/2307
+            WMSPlugin.cache.customCleanUp(CacheFiles.CLEAN_SMALL_FILES, 2048);
+
+            for (int x = 0; x < dax; ++x) {
+                for (int y = 0; y < day; ++y) {
+                    GeorefImage img = images[modulo(x,dax)][modulo(y,day)];
+                    if(img.failed){
+                        img.image = null;
+                        img.flushedResizedCachedInstance();
+                        img.downloadingStarted = false;
+                        img.failed = false;
+                        mv.repaint();
+                    }
+                }
+            }
+        }
+    }
+
+    public class ToggleAlphaAction extends AbstractAction {
+        public ToggleAlphaAction() {
+            super(tr("Alpha channel"));
+        }
+        public void actionPerformed(ActionEvent ev) {
+            JCheckBoxMenuItem checkbox = (JCheckBoxMenuItem) ev.getSource();
+            boolean alphaChannel = checkbox.isSelected();
+            Main.pref.put("wmsplugin.alpha_channel", alphaChannel);
+
+            // clear all resized cached instances and repaint the layer
+            for (int x = 0; x < dax; ++x) {
+                for (int y = 0; y < day; ++y) {
+                    GeorefImage img = images[modulo(x, dax)][modulo(y, day)];
+                    img.flushedResizedCachedInstance();
+                }
+            }
+            mv.repaint();
+        }
+    }
+
+    public class SaveWmsAction extends AbstractAction {
+        public SaveWmsAction() {
+            super(tr("Save WMS layer to file"), ImageProvider.get("save"));
+        }
+        public void actionPerformed(ActionEvent ev) {
+            File f = SaveActionBase.createAndOpenSaveFileChooser(
+                    tr("Save WMS layer"), ".wms");
+            try {
+                if (f != null) {
+                    ObjectOutputStream oos = new ObjectOutputStream(
+                            new FileOutputStream(f)
+                    );
+                    oos.writeInt(serializeFormatVersion);
+                    oos.writeInt(dax);
+                    oos.writeInt(day);
+                    oos.writeInt(ImageSize);
+                    oos.writeDouble(pixelPerDegree);
+                    oos.writeObject(getName());
+                    oos.writeObject(baseURL);
+                    oos.writeObject(images);
+                    oos.close();
+                }
+            } catch (Exception ex) {
+                ex.printStackTrace(System.out);
+            }
+        }
+    }
+
+    public class LoadWmsAction extends AbstractAction {
+        public LoadWmsAction() {
+            super(tr("Load WMS layer from file"), ImageProvider.get("load"));
+        }
+        public void actionPerformed(ActionEvent ev) {
+            JFileChooser fc = DiskAccessAction.createAndOpenFileChooser(true,
+                    false, tr("Load WMS layer"), "wms");
+            if(fc == null) return;
+            File f = fc.getSelectedFile();
+            if (f == null) return;
+            try
+            {
+                FileInputStream fis = new FileInputStream(f);
+                ObjectInputStream ois = new ObjectInputStream(fis);
+                int sfv = ois.readInt();
+                if (sfv != serializeFormatVersion) {
+                    JOptionPane.showMessageDialog(Main.parent,
+                            tr("Unsupported WMS file version; found {0}, expected {1}", sfv, serializeFormatVersion),
+                            tr("File Format Error"),
+                            JOptionPane.ERROR_MESSAGE);
+                    return;
+                }
+                startstop.setSelected(false);
+                dax = ois.readInt();
+                day = ois.readInt();
+                ImageSize = ois.readInt();
+                pixelPerDegree = ois.readDouble();
+                setName((String)ois.readObject());
+                baseURL = (String) ois.readObject();
+                images = (GeorefImage[][])ois.readObject();
+                ois.close();
+                fis.close();
+                mv.repaint();
+            }
+            catch (Exception ex) {
+                // FIXME be more specific
+                ex.printStackTrace(System.out);
+                JOptionPane.showMessageDialog(Main.parent,
+                        tr("Error loading file"),
+                        tr("Error"),
+                        JOptionPane.ERROR_MESSAGE);
+                return;
+            }
+        }
+    }
 }
Index: applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSPlugin.java
===================================================================
--- applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSPlugin.java	(revision 18712)
+++ applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSPlugin.java	(revision 18761)
@@ -57,6 +57,6 @@
 
     protected void initExporterAndImporter() {
-    	ExtensionFileFilter.exporters.add(new WMSLayerExporter());
-    	ExtensionFileFilter.importers.add(new WMSLayerImporter());
+        ExtensionFileFilter.exporters.add(new WMSLayerExporter());
+        ExtensionFileFilter.importers.add(new WMSLayerImporter());
     }
 
Index: applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSPreferenceEditor.java
===================================================================
--- applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSPreferenceEditor.java	(revision 18712)
+++ applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSPreferenceEditor.java	(revision 18761)
@@ -59,5 +59,5 @@
         new String[]{tr("Menu Name (Default)"), tr("WMS URL (Default)")}, 0);
         final JTable listdef = new JTable(modeldef){
-        	@Override
+            @Override
             public boolean isCellEditable(int row,int column){return false;}
         };
@@ -85,8 +85,8 @@
                 p.add(value, GBC.eol().insets(5,0,0,0).fill(GBC.HORIZONTAL));
                 int answer = JOptionPane.showConfirmDialog(
-                		gui, p, 
-                		tr("Enter a menu name and WMS URL"), 
-                		JOptionPane.OK_CANCEL_OPTION,
-                		JOptionPane.QUESTION_MESSAGE);
+                        gui, p, 
+                        tr("Enter a menu name and WMS URL"), 
+                        JOptionPane.OK_CANCEL_OPTION,
+                        JOptionPane.QUESTION_MESSAGE);
                 if (answer == JOptionPane.OK_OPTION) {
                     model.addRow(new String[]{key.getText(), value.getText()});
@@ -117,33 +117,33 @@
                 if (lines.length == 0) {
                     JOptionPane.showMessageDialog(
-                    		gui, 
-                    		tr("Please select at least one row to copy."),
-                    		tr("Information"),
-                    		JOptionPane.INFORMATION_MESSAGE
-                    		);
+                            gui, 
+                            tr("Please select at least one row to copy."),
+                            tr("Information"),
+                            JOptionPane.INFORMATION_MESSAGE
+                            );
                     return;
                 }
                 
                 outer: for(int i = 0; i < lines.length; i++) {
-                	String c1 = modeldef.getValueAt(lines[i], 0).toString();
-                	String c2 = modeldef.getValueAt(lines[i], 1).toString();
-                	
-                	// Check if an entry with exactly the same values already
-                	// exists
-                	for(int j = 0; j < model.getRowCount(); j++) {
-                		if(c1.equals(model.getValueAt(j, 0).toString()) 
-                				&& c2.equals(model.getValueAt(j, 1).toString())) {
-                			// Select the already existing row so the user has
-                			// some feedback in case an entry exists
-                			list.getSelectionModel().setSelectionInterval(j, j);
-                			list.scrollRectToVisible(list.getCellRect(j, 0, true));
-                			continue outer;
-                		}
-                	}
-                	
-	                model.addRow(new String[] {c1, c2});
-	                int lastLine = model.getRowCount() - 1;
-	                list.getSelectionModel().setSelectionInterval(lastLine, lastLine);
-	                list.scrollRectToVisible(list.getCellRect(lastLine, 0, true));
+                    String c1 = modeldef.getValueAt(lines[i], 0).toString();
+                    String c2 = modeldef.getValueAt(lines[i], 1).toString();
+                    
+                    // Check if an entry with exactly the same values already
+                    // exists
+                    for(int j = 0; j < model.getRowCount(); j++) {
+                        if(c1.equals(model.getValueAt(j, 0).toString()) 
+                                && c2.equals(model.getValueAt(j, 1).toString())) {
+                            // Select the already existing row so the user has
+                            // some feedback in case an entry exists
+                            list.getSelectionModel().setSelectionInterval(j, j);
+                            list.scrollRectToVisible(list.getCellRect(j, 0, true));
+                            continue outer;
+                        }
+                    }
+                    
+                    model.addRow(new String[] {c1, c2});
+                    int lastLine = model.getRowCount() - 1;
+                    list.getSelectionModel().setSelectionInterval(lastLine, lastLine);
+                    list.scrollRectToVisible(list.getCellRect(lastLine, 0, true));
                 }
             }
@@ -182,5 +182,5 @@
         overlapPanel.add(spinNorth); 
          
-        p.add(overlapPanel);	
+        p.add(overlapPanel);    
     }
 
