Index: applications/editors/josm/plugins/walkingpapers/.classpath
===================================================================
--- applications/editors/josm/plugins/walkingpapers/.classpath	(revision 16522)
+++ applications/editors/josm/plugins/walkingpapers/.classpath	(revision 16522)
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/JOSM"/>
+	<classpathentry kind="output" path="build"/>
+</classpath>
Index: applications/editors/josm/plugins/walkingpapers/.project
===================================================================
--- applications/editors/josm/plugins/walkingpapers/.project	(revision 16522)
+++ applications/editors/josm/plugins/walkingpapers/.project	(revision 16522)
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>slippymap</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
Index: applications/editors/josm/plugins/walkingpapers/.settings/org.eclipse.jdt.core.prefs
===================================================================
--- applications/editors/josm/plugins/walkingpapers/.settings/org.eclipse.jdt.core.prefs	(revision 16522)
+++ applications/editors/josm/plugins/walkingpapers/.settings/org.eclipse.jdt.core.prefs	(revision 16522)
@@ -0,0 +1,12 @@
+#Wed Jul 15 15:49:32 CEST 2009
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.5
Index: applications/editors/josm/plugins/walkingpapers/.settings/org.eclipse.jdt.ui.prefs
===================================================================
--- applications/editors/josm/plugins/walkingpapers/.settings/org.eclipse.jdt.ui.prefs	(revision 16522)
+++ applications/editors/josm/plugins/walkingpapers/.settings/org.eclipse.jdt.ui.prefs	(revision 16522)
@@ -0,0 +1,3 @@
+#Wed Jul 15 15:49:32 CEST 2009
+eclipse.preferences.version=1
+internal.default.compliance=default
Index: applications/editors/josm/plugins/walkingpapers/README
===================================================================
--- applications/editors/josm/plugins/walkingpapers/README	(revision 16522)
+++ applications/editors/josm/plugins/walkingpapers/README	(revision 16522)
@@ -0,0 +1,6 @@
+A plugin for displaying tiled, scanned maps from walking-papers.org.
+
+Written by Frederik Ramm <frederik@remote.org>, based on SlippyMap 
+plugin work by Lubomir Varga <lubomir.varga@freemap.sk> or <luvar@plaintext.sk>.
+
+Public Domain.
Index: applications/editors/josm/plugins/walkingpapers/build.xml
===================================================================
--- applications/editors/josm/plugins/walkingpapers/build.xml	(revision 16522)
+++ applications/editors/josm/plugins/walkingpapers/build.xml	(revision 16522)
@@ -0,0 +1,56 @@
+<project name="walkingpapers" default="dist" basedir=".">
+    <property name="josm"                   location="../../core/dist/josm-custom.jar"/>
+    <property name="plugin.dist.dir"        value="../../dist"/>
+    <property name="plugin.build.dir"       value="build"/>
+    <property name="plugin.jar"             value="${plugin.dist.dir}/${ant.project.name}.jar"/>
+    <property name="ant.build.javac.target" value="1.5"/>
+    <target name="init">
+        <mkdir dir="${plugin.build.dir}"/>
+    </target>
+    <target name="compile" depends="init">
+        <echo message="creating ${plugin.jar}"/>
+        <javac srcdir="src" classpath="${josm}" debug="true" destdir="${plugin.build.dir}">
+            <compilerarg value="-Xlint:deprecation"/>
+            <compilerarg value="-Xlint:unchecked"/>
+        </javac>
+    </target>
+    <target name="dist" depends="compile,revision">
+        <copy todir="${plugin.build.dir}/images">
+            <fileset dir="images"/>
+        </copy>
+        <jar destfile="${plugin.jar}" basedir="${plugin.build.dir}">
+            <manifest>
+                <attribute name="Author" value="Frederik Ramm"/>
+                <attribute name="Plugin-Class" value="org.openstreetmap.josm.plugins.walkingpapers.WalkingPapersPlugin"/>
+                <attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
+                <attribute name="Plugin-Description" value="Supports downloading tiled, scanned maps from walking-papers.org."/>
+                <attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/index.php/JOSM/Plugins/WalkingPapers"/>
+                <attribute name="Plugin-Mainversion" value="1465"/>
+                <attribute name="Plugin-Version" value="${version.entry.commit.revision}"/>
+            </manifest>
+        </jar>
+    </target>
+    <target name="revision">
+        <exec append="false" output="REVISION" executable="svn" failifexecutionfails="false">
+            <env key="LANG" value="C"/>
+            <arg value="info"/>
+            <arg value="--xml"/>
+            <arg value="."/>
+        </exec>
+        <xmlproperty file="REVISION" prefix="version" keepRoot="false" collapseAttributes="true"/>
+        <delete file="REVISION"/>
+    </target>
+    <target name="clean">
+        <delete dir="${plugin.build.dir}"/>
+        <delete file="${plugin.jar}"/>
+    </target>
+    <target name="install" depends="dist">
+        <property environment="env"/>
+        <condition property="josm.plugins.dir" value="${env.APPDATA}/JOSM/plugins" else="${user.home}/.josm/plugins">
+            <and>
+                <os family="windows"/>
+            </and>
+        </condition>
+        <copy file="${plugin.jar}" todir="${josm.plugins.dir}"/>
+    </target>
+</project>
Index: applications/editors/josm/plugins/walkingpapers/src/org/openstreetmap/josm/plugins/walkingpapers/WalkingPapersAddLayerAction.java
===================================================================
--- applications/editors/josm/plugins/walkingpapers/src/org/openstreetmap/josm/plugins/walkingpapers/WalkingPapersAddLayerAction.java	(revision 16522)
+++ applications/editors/josm/plugins/walkingpapers/src/org/openstreetmap/josm/plugins/walkingpapers/WalkingPapersAddLayerAction.java	(revision 16522)
@@ -0,0 +1,88 @@
+package org.openstreetmap.josm.plugins.walkingpapers;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+import java.awt.event.ActionEvent;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.net.URL;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
+import org.openstreetmap.josm.tools.OsmUrlToBounds;
+
+public class WalkingPapersAddLayerAction extends JosmAction {
+
+    public WalkingPapersAddLayerAction() {
+        super(tr("Scanned Map..."), "walkingpapers", 
+        	tr("Display a map that was previously scanned and uploaded to walking-papers.org"), null, false);
+    }
+
+    public void actionPerformed(ActionEvent e) {
+        String wpid = JOptionPane.showInputDialog(Main.parent, 
+        	tr("Image id from walking-papers.org"),
+        	Main.pref.get("walkingpapers.last-used-id"));
+
+        if (wpid == null || wpid.equals("")) return;
+
+        // screen-scrape details about this id from walking-papers.org
+        String wpUrl = "http://walking-papers.org/scan.php?id=" + wpid;
+
+        Pattern locationPattern = 
+        	Pattern.compile("<a id=\"print-location\" href=\"(http://www.openstreetmap.org/[^\"]+)\"");
+        Pattern hiddenFieldPattern = 
+        	Pattern.compile("<input name=\"(\\S+)\" type=\"hidden\" value=\"(.*)\" />");
+        Matcher m;
+        
+        Bounds b = null;
+        int minx = -1;
+        int maxx = -1;
+        int miny = -1;
+        int maxy = -1;
+        int minz = -1;
+        int maxz = -1;
+
+        try {
+        	BufferedReader r = new BufferedReader(new InputStreamReader(new URL(wpUrl).openStream(), "utf-8"));
+        	for (String line = r.readLine(); line != null; line = r.readLine()) {
+        		m = locationPattern.matcher(line);
+        		if (m.find()) {
+        			String escapedUrl = m.group(1);
+        			b = OsmUrlToBounds.parse(escapedUrl.replace("&amp;","&"));
+        		} else {
+        			m = hiddenFieldPattern.matcher(line);
+        			if (m.find()) {
+        				if ("maxrow".equals(m.group(1))) maxy = (int) Double.parseDouble(m.group(2));
+        				else if ("maxcolumn".equals(m.group(1))) maxx = (int) Double.parseDouble(m.group(2));
+        				else if ("minrow".equals(m.group(1))) miny = (int) Double.parseDouble(m.group(2));
+        				else if ("mincolumn".equals(m.group(1))) minx = (int) Double.parseDouble(m.group(2));
+        				else if ("minzoom".equals(m.group(1))) minz = Integer.parseInt(m.group(2));
+        				else if ("maxzoom".equals(m.group(1))) maxz = Integer.parseInt(m.group(2));
+        			}
+        		}
+        	}
+        	r.close();
+        	if ((b == null) || (minx < 0)) throw new Exception();
+        } catch (Exception ex) {
+            JOptionPane.showMessageDialog(Main.parent,tr("Could not read information from walking-papers.org for this id."));
+            return;
+        }
+        
+        // FIXME min/max values are not any good, they just indicate the centre tile x/y for the 
+        // minimum and the maximum zoom lvl but not how many tiles there are...
+        WalkingPapersLayer wpl = new WalkingPapersLayer(wpid, b, /* minx, maxx, miny, maxy, */ minz, maxz);
+        Main.main.addLayer(wpl);
+
+    }
+
+}
Index: applications/editors/josm/plugins/walkingpapers/src/org/openstreetmap/josm/plugins/walkingpapers/WalkingPapersKey.java
===================================================================
--- applications/editors/josm/plugins/walkingpapers/src/org/openstreetmap/josm/plugins/walkingpapers/WalkingPapersKey.java	(revision 16522)
+++ applications/editors/josm/plugins/walkingpapers/src/org/openstreetmap/josm/plugins/walkingpapers/WalkingPapersKey.java	(revision 16522)
@@ -0,0 +1,78 @@
+/**
+ * 
+ */
+package org.openstreetmap.josm.plugins.walkingpapers;
+
+/**
+ * <p>
+ * Key for map tile. Key have just X and Y value. It have overriden {@link #hashCode()},
+ * {@link #equals(Object)} and also {@link #toString()}.
+ * </p>
+ * 
+ * @author LuVar <lubomir.varga@freemap.sk>
+ * @author Dave Hansen <dave@sr71.net>
+ *
+ */
+public class WalkingPapersKey {
+	private final int x;
+	private final int y;
+	private final int level;
+	
+	/**
+	 * <p>
+	 * Constructs key for hashmaps for some tile describedy by X and Y position. X and Y are tiles
+	 * positions on discrete map.
+	 * </p>
+	 * 
+	 * @param x	x position in tiles table
+	 * @param y	y position in tiles table
+	 */
+	public final boolean valid;
+	public WalkingPapersKey(int level, int x, int y) {
+		this.x = x;
+		this.y = y;
+		this.level = level;
+		if (level <= 0 || x < 0 || y < 0) {
+			this.valid = false;
+			System.err.println("invalid WalkingPapersKey("+level+", "+x+", "+y+")");
+		} else {
+			this.valid = true;
+		}
+	}
+	
+	/**
+	 * <p>
+	 * Returns true ONLY if x and y are equals.
+	 * </p>
+	 * 
+	 * @see java.lang.Object#equals(java.lang.Object)
+	 */
+	@Override
+	public boolean equals(Object obj) {
+		if (obj instanceof WalkingPapersKey) {
+			WalkingPapersKey smk = (WalkingPapersKey) obj;
+			if((smk.x == this.x) && (smk.y == this.y) && (smk.level == this.level)) {
+				return true;
+			}
+		}
+		return false;
+	}
+	
+	/**
+	 * @return	return new Integer(this.x + this.y * 10000).hashCode();
+	 * @see java.lang.Object#hashCode()
+	 */
+	@Override
+	public int hashCode() {
+		return new Integer(this.x + this.y * 10000 + this.level * 100000).hashCode();
+	}
+	
+	/**
+	 * @see java.lang.Object#toString()
+	 */
+	@Override
+	public String toString() {
+		return "WalkingPapersKey(x=" + this.x + ",y=" + this.y + ",level=" + level + ")";
+	}
+	
+}
Index: applications/editors/josm/plugins/walkingpapers/src/org/openstreetmap/josm/plugins/walkingpapers/WalkingPapersLayer.java
===================================================================
--- applications/editors/josm/plugins/walkingpapers/src/org/openstreetmap/josm/plugins/walkingpapers/WalkingPapersLayer.java	(revision 16522)
+++ applications/editors/josm/plugins/walkingpapers/src/org/openstreetmap/josm/plugins/walkingpapers/WalkingPapersLayer.java	(revision 16522)
@@ -0,0 +1,410 @@
+package org.openstreetmap.josm.plugins.walkingpapers;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.image.ImageObserver;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.TreeSet;
+
+import javax.swing.Icon;
+import javax.swing.JMenuItem;
+import javax.swing.JSeparator;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
+import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.tools.ImageProvider;
+
+/**
+ * Class that displays a slippy map layer. Adapted from SlippyMap plugin for Walking Papers use.
+ * 
+ * @author Frederik Ramm <frederik@remote.org>
+ * @author LuVar <lubomir.varga@freemap.sk>
+ * @author Dave Hansen <dave@sr71.net>
+ * 
+ */
+public class WalkingPapersLayer extends Layer implements ImageObserver {
+	/**
+	 * Actual zoom lvl. Initial zoom lvl is set to
+	 * {@link WalkingPapersPreferences#getMinZoomLvl()}.
+	 */
+	private int currentZoomLevel;
+	private HashMap<WalkingPapersKey, WalkingPapersTile> tileStorage = null;
+
+	private Point[][] pixelpos = new Point[21][21];
+	private LatLon lastTopLeft;
+	private LatLon lastBotRight;
+	private int viewportMinX, viewportMaxX, viewportMinY, viewportMaxY;
+	private Image bufferImage;
+	private boolean needRedraw;
+	// FIXME need to find out bounds of Walking Papers scan: private int minx, maxx, miny, maxy, 
+	private int minzoom, maxzoom;
+	private String walkingPapersId;
+	
+	@SuppressWarnings("serial")
+	public WalkingPapersLayer(String id, Bounds b, /*int minx, int maxx, int miny, int maxy,*/ int minz, int maxz) {
+		super(tr("Walking Papers: " +id));
+		background = true;
+		walkingPapersId = id;
+
+		/*
+		this.minx = minx; this.maxx = maxx;
+		this.miny = miny; this.maxy = maxy;
+		*/
+		this.minzoom = minz; this.maxzoom = maxz;
+		currentZoomLevel = minz;
+		
+		clearTileStorage();
+		final Bounds copyOfB = b;
+		
+	    Layer.listeners.add(new LayerChangeListener() {
+	        public void activeLayerChange(Layer oldLayer, Layer newLayer) {
+	        	layerAdded(newLayer);
+	        }
+
+	        public void layerAdded(Layer newLayer) {
+	            /*Main.worker.execute(new Runnable() {
+	                public void run() {
+	                	*/
+	                    BoundingXYVisitor bbox = new BoundingXYVisitor();
+	                    bbox.visit(copyOfB);
+	                    Main.map.mapView.recalculateCenterScale(bbox);
+	             /*   }
+	            });*/
+	        	
+	        }
+
+	        public void layerRemoved(Layer oldLayer) {
+	        }
+	    });
+	}
+
+	/**
+	 * Zoom in, go closer to map.
+	 */
+	public void increaseZoomLevel() {
+		if (currentZoomLevel < maxzoom) {
+			currentZoomLevel++;
+			needRedraw = true;
+		}
+	}
+
+	/**
+	 * Zoom out from map.
+	 */
+	public void decreaseZoomLevel() {
+		if (currentZoomLevel > minzoom) {
+			currentZoomLevel--;
+			needRedraw = true;
+		}
+	}
+
+	public void clearTileStorage() {
+		tileStorage = new HashMap<WalkingPapersKey, WalkingPapersTile>();
+		checkTileStorage();
+	}
+
+	class TileTimeComp implements Comparator<WalkingPapersTile> {
+		public int compare(WalkingPapersTile s1, WalkingPapersTile s2) {
+			long t1 = s1.access_time();
+			long t2 = s2.access_time();
+			if (s1 == s2) return 0;
+			if (t1 == t2) {
+				t1 = s1.hashCode();
+				t2 = s2.hashCode();
+			}
+			if (t1 < t2) return -1;
+			return 1;
+		}
+	}
+
+	long lastCheck = 0;
+	/**
+	 * <p>
+	 * Check if tiles.size() is not more than max_nr_tiles. If yes, oldest tiles by timestamp
+	 * are fired out from cache.
+	 * </p>
+	 */
+	public void checkTileStorage() {
+		long now = System.currentTimeMillis();
+		if (now - lastCheck < 1000) return;
+		lastCheck = now;
+		TreeSet<WalkingPapersTile> tiles = new TreeSet<WalkingPapersTile>(new TileTimeComp());
+		tiles.addAll(tileStorage.values());
+		int max_nr_tiles = 100;
+		if (tiles.size() < max_nr_tiles) {
+			return;
+		}
+		int dropCount = tiles.size() - max_nr_tiles;;
+		for (WalkingPapersTile t : tiles) {
+			if (dropCount <= 0)
+				break;
+			t.dropImage();
+			dropCount--;
+		}
+	}
+
+	void loadSingleTile(WalkingPapersTile tile) {
+		tile.loadImage();
+		this.checkTileStorage();
+	}
+
+	/*
+	 * Attempt to approximate how much the image is
+	 * being scaled.  For instance, a 100x100 image
+	 * being scaled to 50x50 would return 0.25.
+	 */
+	Double getImageScaling(Image img, Point p0, Point p1) {
+		int realWidth = img.getWidth(this);
+		int realHeight = img.getHeight(this);
+		if (realWidth == -1 || realHeight == -1)
+				return null;
+		int drawWidth = p1.x - p0.x;
+		int drawHeight = p1.x - p0.x;
+
+		double drawArea = drawWidth * drawHeight;
+		double realArea = realWidth * realHeight;
+
+		return drawArea / realArea;
+	}
+
+	/**
+     */
+	@Override
+	public void paint(Graphics g, MapView mv) {
+		LatLon topLeft = mv.getLatLon(0, 0);
+		LatLon botRight = mv.getLatLon(mv.getWidth(), mv.getHeight());
+		Graphics oldg = g;
+
+		if (botRight.lon() == 0.0 || botRight.lat() == 0) {
+				// probably still initializing
+				return;
+		}
+		if (lastTopLeft != null && lastBotRight != null
+				&& topLeft.equalsEpsilon(lastTopLeft)
+				&& botRight.equalsEpsilon(lastBotRight) && bufferImage != null
+				&& mv.getWidth() == bufferImage.getWidth(null)
+				&& mv.getHeight() == bufferImage.getHeight(null) && !needRedraw) {
+
+			g.drawImage(bufferImage, 0, 0, null);
+			return;
+		}
+		
+		needRedraw = false;
+		lastTopLeft = topLeft;
+		lastBotRight = botRight;
+		bufferImage = mv.createImage(mv.getWidth(), mv.getHeight());
+		g = bufferImage.getGraphics();
+
+		viewportMinX = lonToTileX(topLeft.lon());
+		viewportMaxX = lonToTileX(botRight.lon());
+		viewportMinY = latToTileY(topLeft.lat());
+		viewportMaxY = latToTileY(botRight.lat());
+
+		if (viewportMinX > viewportMaxX) {
+			int tmp = viewportMinX;
+			viewportMinX = viewportMaxX;
+			viewportMaxX = tmp;
+		}
+		if (viewportMinY > viewportMaxY) {
+			int tmp = viewportMinY;
+			viewportMinY = viewportMaxY;
+			viewportMaxY = tmp;
+		}
+		
+		boolean protectServerFromOverload = false;
+		if ((viewportMaxX-viewportMinX) * (viewportMaxY-viewportMinY) > 100) {
+			System.out.println("more than 100 visible tiles - will not download new ones");
+			protectServerFromOverload = true;
+		}
+		if (viewportMaxX-viewportMinX > 18) return;
+		if (viewportMaxY-viewportMinY > 18) return;
+		
+
+		for (int x = viewportMinX - 1; x <= viewportMaxX + 1; x++) {
+			double lon = tileXToLon(x);
+			for (int y = viewportMinY - 1; y <= viewportMaxY + 1; y++) {
+				LatLon tmpLL = new LatLon(tileYToLat(y), lon);
+				pixelpos[x - viewportMinX + 1][y - viewportMinY + 1] = mv.getPoint(Main.proj
+						.latlon2eastNorth(tmpLL));
+			}
+		}
+
+		g.setColor(Color.DARK_GRAY);
+
+		Double imageScale = null;
+		int count = 0;
+
+		for (int x = viewportMinX-1; x <= viewportMaxX; x++) {
+
+			for (int y = viewportMinY-1; y <= viewportMaxY; y++) {
+				WalkingPapersKey key = new WalkingPapersKey(currentZoomLevel, x, y);
+				WalkingPapersTile tile;
+				tile = tileStorage.get(key);
+				if (!key.valid) continue;
+				if (tile == null) {
+					if (protectServerFromOverload) continue;
+					tile = new WalkingPapersTile(x, y, currentZoomLevel, this);
+					tileStorage.put(key, tile);
+					loadSingleTile(tile);
+					checkTileStorage();
+				}
+				Image img = tile.getImage();
+
+				if (img != null) {
+					Point p = pixelpos[x - viewportMinX + 1][y - viewportMinY + 1];
+					Point p2 = pixelpos[x - viewportMinX + 2][y - viewportMinY + 2];
+					g.drawImage(img, p.x, p.y, p2.x - p.x, p2.y - p.y, this);
+					if (imageScale == null)
+						imageScale = getImageScaling(img, p, p2);
+					count++;
+				}
+			}
+		}
+
+		oldg.drawImage(bufferImage, 0, 0, null);
+		
+		if (imageScale != null) {
+			// If each source image pixel is being stretched into > 3
+			// drawn pixels, zoom in... getting too pixelated
+			if (imageScale > 3) {
+				increaseZoomLevel();
+				this.paint(oldg, mv);
+			}
+
+			// If each source image pixel is being squished into > 0.32
+			// of a drawn pixels, zoom out.
+			else if (imageScale < 0.32) {
+				decreaseZoomLevel();
+				this.paint(oldg, mv);
+			}
+		}	
+	}// end of paint metod
+
+	WalkingPapersTile getTileForPixelpos(int px, int py) {
+		int tilex = viewportMaxX;
+		int tiley = viewportMaxY;
+		for (int x = viewportMinX; x <= viewportMaxX; x++) {
+			if (pixelpos[x - viewportMinX + 1][0].x > px) {
+				tilex = x - 1;
+				break;
+			}
+		}
+		
+		if (tilex == -1) return null;
+		
+		for (int y = viewportMinY; y <= viewportMaxY; y++) {
+			if (pixelpos[0][y - viewportMinY + 1].y > py) {
+				tiley = y - 1;
+				break;
+			}
+		}
+		
+		if (tiley == -1) return null;
+
+		WalkingPapersKey key = new WalkingPapersKey(currentZoomLevel, tilex, tiley);
+		if (!key.valid) {
+			System.err.println("getTileForPixelpos("+px+","+py+") made invalid key");
+			return null;
+		}
+		WalkingPapersTile tile = tileStorage.get(key);
+		if (tile == null)
+			tileStorage.put(key, tile = new WalkingPapersTile(tilex, tiley, currentZoomLevel, this));
+		checkTileStorage();
+		return tile;
+	}
+
+	@Override
+	public Icon getIcon() {
+		return ImageProvider.get("walkingpapers");
+	}
+
+	@Override
+	public Object getInfoComponent() {
+		return null;
+	}
+
+	@Override
+	public Component[] getMenuEntries() {
+		return new Component[] {
+				new JMenuItem(new LayerListDialog.ShowHideLayerAction(this)),
+				new JMenuItem(new LayerListDialog.DeleteLayerAction(this)),
+				new JSeparator(),
+				// color,
+				// new JMenuItem(new RenameLayerAction(associatedFile, this)),
+				new JSeparator(),
+				new JMenuItem(new LayerListPopup.InfoAction(this)) };
+	}
+
+	@Override
+	public String getToolTipText() {
+		return null;
+	}
+
+	@Override
+	public boolean isMergable(Layer other) {
+		return false;
+	}
+
+	@Override
+	public void mergeFrom(Layer from) {
+	}
+
+	@Override
+	public void visitBoundingBox(BoundingXYVisitor v) {
+	}
+
+	private int latToTileY(double lat) {
+		double l = lat / 180 * Math.PI;
+		double pf = Math.log(Math.tan(l) + (1 / Math.cos(l)));
+		return (int) (Math.pow(2.0, currentZoomLevel - 1) * (Math.PI - pf) / Math.PI);
+	}
+
+	private int lonToTileX(double lon) {
+		return (int) (Math.pow(2.0, currentZoomLevel - 3) * (lon + 180.0) / 45.0);
+	}
+
+	private double tileYToLat(int y) {
+		return Math.atan(Math.sinh(Math.PI
+				- (Math.PI * y / Math.pow(2.0, currentZoomLevel - 1))))
+				* 180 / Math.PI;
+	}
+
+	private double tileXToLon(int x) {
+		return x * 45.0 / Math.pow(2.0, currentZoomLevel - 3) - 180.0;
+	}
+
+	public boolean imageUpdate(Image img, int infoflags, int x, int y,
+			int width, int height) {
+		boolean done = ((infoflags & (ERROR | FRAMEBITS | ALLBITS)) != 0);
+		if ((infoflags & ERROR) != 0) return false;
+		// Repaint immediately if we are done, otherwise batch up
+		// repaint requests every 100 milliseconds
+		needRedraw = true;
+		Main.map.repaint(done ? 0 : 100);
+		return !done;
+	}
+
+	@Override
+	public void destroy() {
+		Main.pref.listener.remove(WalkingPapersLayer.this);
+	}
+	
+	public String getWalkingPapersId() {
+		return walkingPapersId;
+	}
+	
+
+	
+}
Index: applications/editors/josm/plugins/walkingpapers/src/org/openstreetmap/josm/plugins/walkingpapers/WalkingPapersPlugin.java
===================================================================
--- applications/editors/josm/plugins/walkingpapers/src/org/openstreetmap/josm/plugins/walkingpapers/WalkingPapersPlugin.java	(revision 16522)
+++ applications/editors/josm/plugins/walkingpapers/src/org/openstreetmap/josm/plugins/walkingpapers/WalkingPapersPlugin.java	(revision 16522)
@@ -0,0 +1,38 @@
+package org.openstreetmap.josm.plugins.walkingpapers;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.KeyEvent;
+
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.MainMenu;
+import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
+import org.openstreetmap.josm.plugins.Plugin;
+
+/**
+ * Main class for the walking papers plugin.
+ *
+ * @author Frederik Ramm <frederik@remote.org>
+ *
+ */
+public class WalkingPapersPlugin extends Plugin
+{
+	static JMenu walkingPapersMenu;
+	
+    public WalkingPapersPlugin()
+    {
+        MainMenu menu = Main.main.menu;
+        // Note to translators. Please do not translate "Walking Papers", because it is 
+        // the name of the project (www.walking-papers.org) and should retain this name
+        // in every language until and unless the project itself is i18nised.
+        walkingPapersMenu = menu.addMenu("Walking Papers", KeyEvent.VK_K, menu.defaultMenuPos);
+        walkingPapersMenu.add(new JMenuItem(new WalkingPapersAddLayerAction()));
+        
+        JOptionPane.showMessageDialog(Main.parent,tr("You are running the highly experimental Walking Papers plugin. Please report all problems."));
+    }
+
+}
Index: applications/editors/josm/plugins/walkingpapers/src/org/openstreetmap/josm/plugins/walkingpapers/WalkingPapersTile.java
===================================================================
--- applications/editors/josm/plugins/walkingpapers/src/org/openstreetmap/josm/plugins/walkingpapers/WalkingPapersTile.java	(revision 16522)
+++ applications/editors/josm/plugins/walkingpapers/src/org/openstreetmap/josm/plugins/walkingpapers/WalkingPapersTile.java	(revision 16522)
@@ -0,0 +1,78 @@
+package org.openstreetmap.josm.plugins.walkingpapers;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.Image;
+import java.awt.Toolkit;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+
+/**
+ * Class that contains information about one single slippy map tile.
+ * 
+ * @author Frederik Ramm <frederik@remote.org>
+ * @author LuVar <lubomir.varga@freemap.sk>
+ * @author Dave Hansen <dave@sr71.net>
+ * 
+ */
+public class WalkingPapersTile {
+    private Image tileImage;
+	long timestamp;
+
+    int x;
+    int y;
+    int z;
+    
+    WalkingPapersLayer parentLayer;
+
+
+    public WalkingPapersTile(int x, int y, int z, WalkingPapersLayer parent) {
+        this.x = x;
+        this.y = y;
+        this.z = z;
+        parentLayer = parent;
+		timestamp = System.currentTimeMillis();
+    }
+
+    public URL getImageUrl() {
+        try {
+            return new URL("http://paperwalking-uploads.s3.amazonaws.com/scans/" + parentLayer.getWalkingPapersId() + "/" + z + "/" + x + "/" + y + ".jpg");
+        } catch (MalformedURLException mfu) {
+        	mfu.printStackTrace();
+        }
+        return null;
+    }
+
+    public void loadImage() {
+        URL imageUrl = this.getImageUrl();
+        tileImage = Toolkit.getDefaultToolkit().createImage(imageUrl);
+		Toolkit.getDefaultToolkit().sync();
+   		timestamp = System.currentTimeMillis();
+    }
+
+    public Image getImage() {
+        timestamp = System.currentTimeMillis();
+        return tileImage;
+    }
+
+    public void dropImage() {
+		tileImage = null;
+		//  This should work in theory but doesn't seem to actually
+		//  reduce the X server memory usage
+		//tileImage.flush();
+    }
+
+    public long access_time() {
+        return timestamp;
+    }
+
+    public boolean equals(Object o) {
+        if (!(o instanceof WalkingPapersTile))
+            return false;
+        WalkingPapersTile other = (WalkingPapersTile) o;
+        return (this.x == other.x && this.y == other.y && this.z == other.z);
+    }
+}
