[josm-plugins] 110/369: Imported Upstream version 0.0.svn20358

Bas Couwenberg sebastic at xs4all.nl
Sat Oct 18 12:03:32 UTC 2014


This is an automated email from the git hooks/post-receive script.

sebastic-guest pushed a commit to branch master
in repository josm-plugins.

commit eb75f53779d2392905b553b52fd0e3e43b059c7d
Author: Giovanni Mascellani <mascellani at poisson.phc.unipi.it>
Date:   Tue Mar 30 00:03:01 2010 +0200

    Imported Upstream version 0.0.svn20358
---
 DirectUpload/build.xml                             |  236 +++-
 DirectUpload/images/uploadtrace.png                |  Bin 0 -> 259 bytes
 .../plugins/DirectUpload/UploadDataGuiPlugin.java  |   24 +-
 agpifoj/.classpath                                 |    8 -
 agpifoj/.project                                   |   17 -
 agpifoj/CHANGELOG                                  |    1 -
 agpifoj/LICENSE                                    |  341 ------
 agpifoj/README                                     |   57 -
 agpifoj/build.xml                                  |   64 --
 agpifoj/images/agpifoj-open.png                    |  Bin 938 -> 0 bytes
 agpifoj/images/dialogs/agpifoj-mag-cursor.png      |  Bin 394 -> 0 bytes
 agpifoj/images/dialogs/agpifoj-marker-black.png    |  Bin 239 -> 0 bytes
 agpifoj/images/dialogs/agpifoj-marker-selected.png |  Bin 231 -> 0 bytes
 agpifoj/images/dialogs/agpifoj-marker.png          |  Bin 233 -> 0 bytes
 agpifoj/images/dialogs/agpifoj.png                 |  Bin 500 -> 0 bytes
 agpifoj/images/dialogs/gpx2img.png                 |  Bin 663 -> 0 bytes
 agpifoj/images/dialogs/gpx2imgManual.png           |  Bin 924 -> 0 bytes
 .../josm/plugins/agpifoj/AgpifojDialog.java        |  185 ---
 .../josm/plugins/agpifoj/AgpifojLayer.java         |  560 ----------
 .../josm/plugins/agpifoj/AgpifojPlugin.java        |  100 --
 .../plugins/agpifoj/CorrelateGpxWithImages.java    | 1175 --------------------
 .../josm/plugins/agpifoj/ImageDisplay.java         |  607 ----------
 cadastre-fr/build.xml                              |  110 +-
 cadastre-fr/images/cursor/modifier/move.png        |  Bin 0 -> 192 bytes
 cadastre-fr/src/cadastre_fr/CacheControl.java      |   27 +-
 cadastre-fr/src/cadastre_fr/CadastreGrabber.java   |   20 +-
 cadastre-fr/src/cadastre_fr/CadastreInterface.java |   99 +-
 cadastre-fr/src/cadastre_fr/CadastrePlugin.java    |  106 +-
 .../src/cadastre_fr/CadastrePreferenceSetting.java |  147 ++-
 .../src/cadastre_fr/CheckSourceUploadHook.java     |    8 +-
 .../src/cadastre_fr/DownloadSVGBuilding.java       |    4 +-
 cadastre-fr/src/cadastre_fr/DownloadSVGTask.java   |    2 +-
 cadastre-fr/src/cadastre_fr/GeorefImage.java       |  217 +++-
 cadastre-fr/src/cadastre_fr/ImageModifier.java     |   93 ++
 .../src/cadastre_fr/MenuActionGrabPlanImage.java   |  103 +-
 .../src/cadastre_fr/MenuActionLoadFromCache.java   |    6 +-
 .../src/cadastre_fr/MenuActionNewLocation.java     |   12 +-
 cadastre-fr/src/cadastre_fr/SimplifyWay.java       |   15 +-
 .../src/cadastre_fr/VectorImageModifier.java       |   23 +-
 cadastre-fr/src/cadastre_fr/WMSAdjustAction.java   |   68 +-
 cadastre-fr/src/cadastre_fr/WMSDownloadAction.java |    8 +-
 cadastre-fr/src/cadastre_fr/WMSLayer.java          |  106 +-
 colorscheme/build.xml                              |  240 +++-
 colorscheme/copyright.txt                          |    3 +-
 colorscheme/{LICENSE => gpl-2.0.txt}               |   14 +-
 colorscheme/gpl-3.0.txt                            |  674 +++++++++++
 .../josm/plugin/colorscheme/ColorSchemePlugin.java |    5 +-
 .../plugin/colorscheme/ColorSchemePreference.java  |    5 +-
 editgpx/.classpath                                 |    2 +-
 editgpx/build.xml                                  |  239 +++-
 .../josm-editgpx.launch                            |    2 +-
 .../josm/plugins/editgpx/EditGpxLayer.java         |  377 ++++---
 .../josm/plugins/editgpx/EditGpxMode.java          |    3 +-
 .../josm/plugins/editgpx/EditGpxPlugin.java        |   11 +-
 .../josm/plugins/editgpx/GPXLayerImportAction.java |    5 +-
 lakewalker/.classpath                              |   14 +-
 lakewalker/.settings/org.eclipse.jdt.ui.prefs      |   54 +
 lakewalker/build.xml                               |  237 +++-
 .../josm/plugins/lakewalker/BooleanConfigurer.java |  111 +-
 .../josm/plugins/lakewalker/DoubleConfigurer.java  |    9 +-
 .../josm/plugins/lakewalker/IntConfigurer.java     |   91 +-
 .../josm/plugins/lakewalker/Lakewalker.java        |   17 +-
 .../josm/plugins/lakewalker/LakewalkerAction.java  |    5 +-
 .../josm/plugins/lakewalker/LakewalkerApp.java     |   19 +-
 .../plugins/lakewalker/LakewalkerException.java    |   12 +-
 .../josm/plugins/lakewalker/LakewalkerPlugin.java  |   17 +-
 .../plugins/lakewalker/LakewalkerPreferences.java  |   18 +-
 .../josm/plugins/lakewalker/LakewalkerReader.java  |  128 ---
 .../josm/plugins/lakewalker/LakewalkerWMS.java     |   10 +-
 .../josm/plugins/lakewalker/StringConfigurer.java  |   18 +-
 .../plugins/lakewalker/StringEnumConfigurer.java   |   17 +-
 livegps/build.xml                                  |  241 +++-
 .../josm-livegps.launch                            |    2 +-
 livegps/src/livegps/AppendableGpxTrackSegment.java |   57 +
 livegps/src/livegps/ILiveGpsSuppressor.java        |   20 +
 livegps/src/livegps/LiveGpsAcquirer.java           |  461 ++++----
 livegps/src/livegps/LiveGpsData.java               |    1 -
 livegps/src/livegps/LiveGpsLayer.java              |  295 ++---
 livegps/src/livegps/LiveGpsLock.java               |   16 -
 livegps/src/livegps/LiveGpsPlugin.java             |  436 ++++----
 livegps/src/livegps/LiveGpsSuppressor.java         |  136 +++
 livegps/src/livegps/SingleSegmentGpxTrack.java     |   38 +
 measurement/build.xml                              |  236 +++-
 .../plugins/measurement/MeasurementDialog.java     |    2 +-
 .../josm/plugins/measurement/MeasurementLayer.java |    5 +-
 .../plugins/measurement/MeasurementPlugin.java     |   11 +-
 openvisible/build.xml                              |  244 +++-
 openvisible/copyright.txt                          |    5 +-
 surveyor/LICENSE => openvisible/gpl-2.0.txt        |   14 +-
 openvisible/gpl-3.0.txt                            |  674 +++++++++++
 .../josm/plugin/openvisible/OpenVisibleAction.java |    9 +-
 .../josm/plugin/openvisible/OpenVisiblePlugin.java |    5 +-
 routing/build.xml                                  |  267 +++--
 .../innovant/josm/plugin/routing/RoutingLayer.java |    4 +-
 .../josm/plugin/routing/RoutingPlugin.java         |   11 +-
 .../routing/gui/RoutingPreferenceDialog.java       |    5 +-
 slippymap/build.xml                                |  241 +++-
 .../josm/plugins/slippymap/SlippyMapLayer.java     |   37 +-
 .../josm/plugins/slippymap/SlippyMapPlugin.java    |    4 +-
 .../slippymap/SlippyMapPreferenceSetting.java      |    3 +-
 .../plugins/slippymap/SlippyMapPreferences.java    |   57 +-
 surveyor/build.xml                                 |  269 +++--
 surveyor/copyright.txt                             |    5 +-
 openvisible/LICENSE => surveyor/gpl-2.0.txt        |   14 +-
 surveyor/gpl-3.0.txt                               |  674 +++++++++++
 .../surveyor/AutoSaveEditLayerTimerTask.java       |    4 +-
 .../plugin/surveyor/AutoSaveGpsLayerTimerTask.java |    6 +-
 .../josm/plugin/surveyor/SurveyorLock.java         |    5 +
 .../josm/plugin/surveyor/SurveyorPlugin.java       |   11 +-
 .../plugin/surveyor/action/PlayAudioAction.java    |    4 +-
 .../josm/plugin/surveyor/action/SetNodeAction.java |   17 +-
 .../plugin/surveyor/action/SetWaypointAction.java  |   10 +-
 .../plugin/surveyor/action/gui/WaypointDialog.java |    2 +-
 svn-info.xml                                       |    8 +-
 utilsplugin/.classpath                             |    7 -
 utilsplugin/.project                               |   17 -
 utilsplugin/README                                 |   14 -
 utilsplugin/build.xml                              |   55 -
 utilsplugin/data/Join Areas Tests.osm              |  767 -------------
 utilsplugin/images/joinareas.png                   |  Bin 328 -> 0 bytes
 utilsplugin/images/joinnodeway.png                 |  Bin 452 -> 0 bytes
 utilsplugin/images/mergenodes.png                  |  Bin 314 -> 0 bytes
 utilsplugin/images/simplify.png                    |  Bin 968 -> 0 bytes
 utilsplugin/src/UtilsPlugin/JoinAreasAction.java   |  886 ---------------
 utilsplugin/src/UtilsPlugin/JumpToAction.java      |  179 ---
 utilsplugin/src/UtilsPlugin/SimplifyWayAction.java |  205 ----
 utilsplugin/src/UtilsPlugin/UtilsPlugin.java       |   29 -
 validator/.classpath                               |    8 -
 validator/.project                                 |   17 -
 .../.settings/org.eclipse.core.resources.prefs     |    3 -
 validator/.settings/org.eclipse.jdt.core.prefs     |  258 -----
 validator/.settings/org.eclipse.jdt.ui.prefs       |    4 -
 validator/CONTRIBUTION                             |    5 -
 validator/LICENSE                                  |  341 ------
 validator/README                                   |    2 -
 validator/build.xml                                |  163 ---
 validator/ignoretags.cfg                           |  362 ------
 validator/images/data/error.gif                    |  Bin 333 -> 0 bytes
 validator/images/data/other.gif                    |  Bin 121 -> 0 bytes
 validator/images/data/warning.gif                  |  Bin 324 -> 0 bytes
 validator/images/dialogs/fix.png                   |  Bin 30287 -> 0 bytes
 validator/images/dialogs/validator.png             |  Bin 890 -> 0 bytes
 validator/images/layer/validator.png               |  Bin 765 -> 0 bytes
 validator/images/preferences/validator.png         |  Bin 1388 -> 0 bytes
 validator/images/validator.png                     |  Bin 889 -> 0 bytes
 .../josm/plugins/validator/ErrorLayer.java         |  143 ---
 .../josm/plugins/validator/ErrorTreePanel.java     |  327 ------
 .../josm/plugins/validator/ErrorTreeRenderer.java  |   47 -
 .../josm/plugins/validator/GridLayer.java          |  204 ----
 .../josm/plugins/validator/OSMValidatorPlugin.java |  310 ------
 .../josm/plugins/validator/PreferenceEditor.java   |  131 ---
 .../josm/plugins/validator/Severity.java           |   67 --
 .../openstreetmap/josm/plugins/validator/Test.java |  228 ----
 .../josm/plugins/validator/TestError.java          |  400 -------
 .../josm/plugins/validator/ValidateAction.java     |  187 ----
 .../josm/plugins/validator/ValidateUploadHook.java |  127 ---
 .../josm/plugins/validator/ValidatorDialog.java    |  521 ---------
 .../josm/plugins/validator/ValidatorVisitor.java   |   10 -
 .../validator/tests/ChangePropertyKeyCommand.java  |   86 --
 .../josm/plugins/validator/tests/Coastlines.java   |  202 ----
 .../josm/plugins/validator/tests/CrossingWays.java |  220 ----
 .../plugins/validator/tests/DuplicateNode.java     |  154 ---
 .../josm/plugins/validator/tests/DuplicateWay.java |  153 ---
 .../validator/tests/DuplicatedWayNodes.java        |   70 --
 .../josm/plugins/validator/tests/NameMismatch.java |  109 --
 .../plugins/validator/tests/NodesWithSameName.java |   71 --
 .../plugins/validator/tests/OverlappingWays.java   |  173 ---
 .../validator/tests/SelfIntersectingWay.java       |   41 -
 .../plugins/validator/tests/SimilarNamedWays.java  |  173 ---
 .../josm/plugins/validator/tests/TagChecker.java   | 1029 -----------------
 .../josm/plugins/validator/tests/UnclosedWays.java |  127 ---
 .../plugins/validator/tests/UnconnectedWays.java   |  387 -------
 .../josm/plugins/validator/tests/UntaggedNode.java |  109 --
 .../josm/plugins/validator/tests/UntaggedWay.java  |  157 ---
 .../validator/tests/WronglyOrderedWays.java        |  115 --
 .../validator/util/AgregatePrimitivesVisitor.java  |   72 --
 .../josm/plugins/validator/util/Bag.java           |   93 --
 .../josm/plugins/validator/util/Entities.java      |  410 -------
 .../validator/util/MultipleNameVisitor.java        |  105 --
 .../josm/plugins/validator/util/NameVisitor.java   |   84 --
 .../josm/plugins/validator/util/Util.java          |  175 ---
 validator/tagchecker.cfg                           |   79 --
 wmsplugin/.settings/org.eclipse.jdt.ui.prefs       |   54 +
 wmsplugin/Makefile                                 |   29 +-
 wmsplugin/build.xml                                |  271 ++---
 wmsplugin/images/cursor/modifier/move.png          |  Bin 0 -> 192 bytes
 .../josm-wmsplugin.launch                          |    4 +-
 wmsplugin/sources.cfg                              |    2 +-
 wmsplugin/src/wmsplugin/GeorefImage.java           |  271 +++--
 wmsplugin/src/wmsplugin/Grabber.java               |   28 +-
 wmsplugin/src/wmsplugin/HTMLGrabber.java           |    3 -
 .../src/wmsplugin/Map_Rectifier_WMSmenuAction.java |   23 +-
 wmsplugin/src/wmsplugin/WMSAdjustAction.java       |   51 +-
 wmsplugin/src/wmsplugin/WMSGrabber.java            |   33 +-
 wmsplugin/src/wmsplugin/WMSInfo.java               |    2 +-
 wmsplugin/src/wmsplugin/WMSLayer.java              |  852 +++++++-------
 wmsplugin/src/wmsplugin/WMSPlugin.java             |    6 +-
 wmsplugin/src/wmsplugin/WMSPreferenceEditor.java   |   90 +-
 wmsplugin/webkit-image.cpp                         |  105 +-
 199 files changed, 7374 insertions(+), 16340 deletions(-)

diff --git a/DirectUpload/build.xml b/DirectUpload/build.xml
index cbfd294..196d3fa 100644
--- a/DirectUpload/build.xml
+++ b/DirectUpload/build.xml
@@ -1,56 +1,184 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+** This is the build file for the DirectUpload plugin
+**
+** Maintaining versions
+** ====================
+** see README.template
+**
+** Usage
+** =====
+** To build it run
+**
+**    > ant  dist
+**
+** To install the generated plugin locally (in your default plugin directory) run
+**
+**    > ant  install
+**
+** To build against the core in ../../core, create a correct manifest and deploy to
+** SVN, 
+**    set the properties commit.message and plugin.main.version
+** and run
+**    > ant  publish
+**
+**
+-->
 <project name="DirectUpload" 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="Subhodip Biswas"/>
-                <attribute name="Plugin-Class" value="org.openstreetmap.josm.plugins.DirectUpload.UploadDataGuiPlugin"/>
-                <attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
-                <attribute name="Plugin-Description" value="This plugin directly upload GPS Traces from current active layer in JOSM to openstreetmap.org."/>
-                <attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/index.php/User:Subhodip/GSoC_Doc#DirectUpload_Plugin_in_JOSM_:"/>
-                <attribute name="Plugin-Mainversion" value="2082"/>
-                <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>
+
+	<property name="commit.message" value="Changed constructor signature of plugin main class" />
+	<property name="plugin.main.version" value="2830" />
+
+	<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="Subhodip Biswas"/>
+				<attribute name="Plugin-Class" value="org.openstreetmap.josm.plugins.DirectUpload.UploadDataGuiPlugin"/>
+				<attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
+				<attribute name="Plugin-Description" value="This plugin directly upload GPS Traces from current active layer in JOSM to openstreetmap.org."/>
+				<attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/index.php/User:Subhodip/GSoC_Doc#DirectUpload_Plugin_in_JOSM_:"/>
+				<attribute name="Plugin-Mainversion" value="${plugin.main.version}"/>
+				<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>
+	<!--
+	 ************************** Publishing the plugin *********************************** 
+	-->
+	<!--
+	** extracts the JOSM release for the JOSM version in ../core and saves it in the 
+	** property ${coreversion.info.entry.revision}
+	**
+	-->
+	<target name="core-info">
+		<exec append="false" output="core.info.xml" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="info"/>
+			<arg value="--xml"/>
+			<arg value="../../core"/>
+		</exec>
+		<xmlproperty file="core.info.xml" prefix="coreversion" keepRoot="true" collapseAttributes="true"/>
+		<echo>Building against core revision ${coreversion.info.entry.revision}.</echo>
+		<echo>Plugin-Mainversion is set to ${plugin.main.version}.</echo>
+		<delete file="core.info.xml" />
+	</target>
+
+	<!--
+	** commits the source tree for this plugin
+	-->
+	<target name="commit-current">
+		<echo>Commiting the plugin source with message '${commit.message}' ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="commit"/>
+			<arg value="-m '${commit.message}'"/>
+			<arg value="."/>
+		</exec>
+	</target>
+
+	<!--
+	** updates (svn up) the source tree for this plugin
+	-->
+	<target name="update-current">
+		<echo>Updating plugin source ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="up"/>
+			<arg value="."/>
+		</exec>
+		<echo>Updating ${plugin.jar} ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="up"/>
+			<arg value="../dist/${plugin.jar}"/>
+		</exec>
+	</target>
+
+	<!--
+	** commits the plugin.jar 
+	-->
+	<target name="commit-dist">
+		<echo>
+***** Properties of published ${plugin.jar} *****
+Commit message    : '${commit.message}'					
+Plugin-Mainversion: ${plugin.main.version}
+JOSM build version: ${coreversion.info.entry.revision}
+Plugin-Version    : ${version.entry.commit.revision}
+***** / Properties of published ${plugin.jar} *****					
+					
+Now commiting ${plugin.jar} ...
+</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="-m '${commit.message}'"/>
+			<arg value="commit"/>
+			<arg value="${plugin.jar}"/>
+		</exec>
+	</target>
+
+	<!-- ** make sure svn is present as a command line tool ** -->
+	<target name="ensure-svn-present">
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false" failonerror="false" resultproperty="svn.exit.code">
+			<env key="LANG" value="C" />
+			<arg value="--version" />
+		</exec>
+		<fail message="Fatal: command 'svn --version' failed. Please make sure svn is installed on your system.">
+			<!-- return code not set at all? Most likely svn isn't installed -->
+			<condition>
+				<not>
+					<isset property="svn.exit.code" />
+				</not>
+			</condition>
+		</fail>
+		<fail message="Fatal: command 'svn --version' failed. Please make sure a working copy of svn is installed on your system.">
+			<!-- error code from SVN? Most likely svn is not what we are looking on this system -->
+			<condition>
+				<isfailure code="${svn.exit.code}" />
+			</condition>
+		</fail>
+	</target>
+
+	<target name="publish" depends="ensure-svn-present,core-info,commit-current,update-current,clean,dist,commit-dist">
+	</target>
 </project>
diff --git a/DirectUpload/images/uploadtrace.png b/DirectUpload/images/uploadtrace.png
new file mode 100644
index 0000000..ac15743
Binary files /dev/null and b/DirectUpload/images/uploadtrace.png differ
diff --git a/DirectUpload/src/org/openstreetmap/josm/plugins/DirectUpload/UploadDataGuiPlugin.java b/DirectUpload/src/org/openstreetmap/josm/plugins/DirectUpload/UploadDataGuiPlugin.java
index aa5dea7..7dfad2c 100644
--- a/DirectUpload/src/org/openstreetmap/josm/plugins/DirectUpload/UploadDataGuiPlugin.java
+++ b/DirectUpload/src/org/openstreetmap/josm/plugins/DirectUpload/UploadDataGuiPlugin.java
@@ -10,11 +10,12 @@ import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
+
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.JosmAction;
-import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.GpxLayer;
 import org.openstreetmap.josm.plugins.Plugin;
+import org.openstreetmap.josm.plugins.PluginInformation;
 import org.openstreetmap.josm.tools.Shortcut;
 /**
  *
@@ -23,13 +24,13 @@ import org.openstreetmap.josm.tools.Shortcut;
 public class UploadDataGuiPlugin extends Plugin{
     UploadAction openaction;
 
-    public UploadDataGuiPlugin() {
+    public UploadDataGuiPlugin(PluginInformation info) {
+    	super(info);
         openaction = new UploadAction();
         Main.main.menu.toolsMenu.add(openaction);
     }
 
-    class UploadAction extends JosmAction {
-
+    class UploadAction extends JosmAction{
         public UploadAction(){
             super(tr("Upload Traces"), "UploadAction", tr("Uploads traces to openstreetmap.org"),
             Shortcut.registerShortcut("tools:uploadtraces", tr("Tool: {0}", tr("Upload Traces")),
@@ -39,5 +40,18 @@ public class UploadDataGuiPlugin extends Plugin{
             UploadDataGui go = new UploadDataGui();
             go.setVisible(true);
         }
+
+        @Override
+		protected void updateEnabledState() {
+            if(Main.map == null
+                    || Main.map.mapView == null
+                    || Main.map.mapView.getActiveLayer() == null
+                    || !(Main.map.mapView.getActiveLayer() instanceof GpxLayer)) {                
+                setEnabled(false);
+            } else {
+            	setEnabled(true);
+            }
+
+		}		
     }
 }
\ No newline at end of file
diff --git a/agpifoj/.classpath b/agpifoj/.classpath
deleted file mode 100644
index 07c06bb..0000000
--- a/agpifoj/.classpath
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JDK 5"/>
-	<classpathentry combineaccessrules="false" kind="src" path="/JOSM"/>
-	<classpathentry kind="lib" path="/JOSM/lib/metadata-extractor-2.3.1-nosun.jar"/>
-	<classpathentry kind="output" path="bin"/>
-</classpath>
diff --git a/agpifoj/.project b/agpifoj/.project
deleted file mode 100644
index 9fa7bb2..0000000
--- a/agpifoj/.project
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>JOSM-agpifoj</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>
diff --git a/agpifoj/CHANGELOG b/agpifoj/CHANGELOG
deleted file mode 100644
index 3e0fe52..0000000
--- a/agpifoj/CHANGELOG
+++ /dev/null
@@ -1 +0,0 @@
-01-15-2008 : Release of a first beta.
\ No newline at end of file
diff --git a/agpifoj/LICENSE b/agpifoj/LICENSE
deleted file mode 100644
index fe31ef6..0000000
--- a/agpifoj/LICENSE
+++ /dev/null
@@ -1,341 +0,0 @@
-
-		    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-	51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-

-		    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-

-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-

-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-

-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-			    NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-

-	    How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year  name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/agpifoj/README b/agpifoj/README
deleted file mode 100644
index 987c280..0000000
--- a/agpifoj/README
+++ /dev/null
@@ -1,57 +0,0 @@
-AgPiFoj stands for 'Another geotag plug-in for Josm'.
-
-FEATURES
-
-- Access by a new menu item in the 'File' menu. This menu loads pictures and
-  makes a new layer from them in the map view.
-- Displays the images in a ToggleDialog (so it appears as a panel on the right
-  of the screen and can be shown/hidden with a click on a button of the left
-  toolbar. It can be set in a separate window by clicking the sticky button)
-- Loads geotag data from exif or correlate pictures with GPS tracks.
-- Displays the pictures as a little camera icon in the map view (this improves
-  the speed of loading large sets of pictures). The selected picture appears in
-  red.
-- Easy zoom in/out of the image with the mouse wheel. Hability to move the
-  image by clicking and/or dragging on it with mouse left button, or to select
-  the part of the image to zoom in by dragging the right button.
-- Displays the altitude and speed of the photo when available from the GPS
-  track.
-- Hability to synchronize a same set of photos with many GPS tracks (choose
-  item 'Correlate to GPX' in the contextual menu of the layer). If a  picture
-  set and a GPS track were badly time-synchronized, just load again the same
-  GPX track on the layer, by specifying a different offset and/or timezone.
-- Adds a viewport to the left toolbar : with all these plug-ins that add buttons
-  to that toolbar, some of them became inaccessible. This adds some little
-  arrows on top and bottom of the toolbar.
-
-NOTE
-For the user who used to use the 'Import images' option on GPS layers, the
-timezone is the opposite : it is greater than 0 when going to the east of
-Greenwich Meridian.
-
-INSTALL
-
-To install, put the agpifoj.jar in the JOSM plugin directory. Then in JOSM,
-select the menu Edit / Preferences and the plugins tab. Check the agpifoj
-plugin check-box, and restart JOSM. You'll seee the AgPiFoj menu item in
-the 'File' menu.
-
-BUILD
-
-The source code is in the agpifoj.jar : unzip it.
-Edit the build.xml to set the path to your josm-latest.jar as property.
-Run ant.
-The plugin jar file is in the dist directory.
-
-Tested on the latest JOSM version (build 521).
-
-CONTRIBUTION
-
-I got inspiration and some code from the Geotagged plugin (by Rob Neild)
-and the core JOSM source code (by Immanuel Scholz and others). This plugin is
-delivered under the GPL licence terms. It also uses the jpeg metadata
-extraction code is from Drew Noakes (bundled with Josm).
-
----
-
-Hope you'll find it useful.
diff --git a/agpifoj/build.xml b/agpifoj/build.xml
deleted file mode 100644
index 8a54e59..0000000
--- a/agpifoj/build.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<project name="AgPifoJ" 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}">
-            <fileset dir=".">
-                <include name="CHANGELOG"/>
-                <include name="LICENSE"/>
-                <include name="README"/>
-            </fileset>
-        </copy>
-        <copy todir="${plugin.build.dir}/images">
-            <fileset dir="images"/>
-        </copy>
-        <jar destfile="${plugin.jar}" basedir="${plugin.build.dir}">
-            <manifest>
-                <attribute name="Author" value="Christian Gallioz"/>
-                <attribute name="Plugin-Class" value="org.openstreetmap.josm.plugins.agpifoj.AgpifojPlugin"/>
-                <attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
-                <attribute name="Plugin-Description" value="Another geotag plugin for JOSM. Correlates pictures with GPS tracks or import EXIF geotagged pictures."/>
-                <attribute name="Plugin-Early" value="false"/>
-                <attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/index.php/JOSM/Plugins/AgPifoJ"/>
-                <attribute name="Plugin-Mainversion" value="2450"/>
-                <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>
diff --git a/agpifoj/images/agpifoj-open.png b/agpifoj/images/agpifoj-open.png
deleted file mode 100644
index 79ad9fe..0000000
Binary files a/agpifoj/images/agpifoj-open.png and /dev/null differ
diff --git a/agpifoj/images/dialogs/agpifoj-mag-cursor.png b/agpifoj/images/dialogs/agpifoj-mag-cursor.png
deleted file mode 100644
index 2d76611..0000000
Binary files a/agpifoj/images/dialogs/agpifoj-mag-cursor.png and /dev/null differ
diff --git a/agpifoj/images/dialogs/agpifoj-marker-black.png b/agpifoj/images/dialogs/agpifoj-marker-black.png
deleted file mode 100644
index c15a737..0000000
Binary files a/agpifoj/images/dialogs/agpifoj-marker-black.png and /dev/null differ
diff --git a/agpifoj/images/dialogs/agpifoj-marker-selected.png b/agpifoj/images/dialogs/agpifoj-marker-selected.png
deleted file mode 100644
index f365086..0000000
Binary files a/agpifoj/images/dialogs/agpifoj-marker-selected.png and /dev/null differ
diff --git a/agpifoj/images/dialogs/agpifoj-marker.png b/agpifoj/images/dialogs/agpifoj-marker.png
deleted file mode 100644
index 446f491..0000000
Binary files a/agpifoj/images/dialogs/agpifoj-marker.png and /dev/null differ
diff --git a/agpifoj/images/dialogs/agpifoj.png b/agpifoj/images/dialogs/agpifoj.png
deleted file mode 100644
index 6b683e8..0000000
Binary files a/agpifoj/images/dialogs/agpifoj.png and /dev/null differ
diff --git a/agpifoj/images/dialogs/gpx2img.png b/agpifoj/images/dialogs/gpx2img.png
deleted file mode 100644
index dfb92bd..0000000
Binary files a/agpifoj/images/dialogs/gpx2img.png and /dev/null differ
diff --git a/agpifoj/images/dialogs/gpx2imgManual.png b/agpifoj/images/dialogs/gpx2imgManual.png
deleted file mode 100644
index 880b59e..0000000
Binary files a/agpifoj/images/dialogs/gpx2imgManual.png and /dev/null differ
diff --git a/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/AgpifojDialog.java b/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/AgpifojDialog.java
deleted file mode 100644
index b46037c..0000000
--- a/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/AgpifojDialog.java
+++ /dev/null
@@ -1,185 +0,0 @@
-// License: GPL. Copyright 2007 by Christian Gallioz (aka khris78)
-// Parts of code from Geotagged plugin (by Rob Neild)
-// and the core JOSM source code (by Immanuel Scholz and others)
-
-package org.openstreetmap.josm.plugins.agpifoj;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.BorderLayout;
-import java.awt.Dimension;
-import java.awt.FlowLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.KeyEvent;
-
-import javax.swing.JButton;
-import javax.swing.JPanel;
-import javax.swing.JToggleButton;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.gui.dialogs.ToggleDialog;
-import org.openstreetmap.josm.plugins.agpifoj.AgpifojLayer.ImageEntry;
-import org.openstreetmap.josm.tools.ImageProvider;
-import org.openstreetmap.josm.tools.Shortcut;
-
-public class AgpifojDialog extends ToggleDialog implements ActionListener {
-
-    private static final String COMMAND_ZOOM = "zoom";
-    private static final String COMMAND_CENTERVIEW = "centre";
-    private static final String COMMAND_NEXT = "next";
-    private static final String COMMAND_REMOVE = "remove";
-    private static final String COMMAND_PREVIOUS = "previous";
-
-    private ImageDisplay imgDisplay = new ImageDisplay();
-    private boolean centerView = false;
-
-    // Only one instance of that class
-    static private AgpifojDialog INSTANCE = null;
-
-    public static AgpifojDialog getInstance() {
-        if (INSTANCE == null) {
-            INSTANCE = new AgpifojDialog();
-        }
-        return INSTANCE;
-    }
-
-    private AgpifojDialog() {
-        super(tr("AgPifoJ - Geotagged pictures"), "agpifoj", tr("Display geotagged photos"), Shortcut.registerShortcut("tools:geotagged", tr("Tool: {0}", tr("Display geotagged photos")), KeyEvent.VK_Y, Shortcut.GROUP_EDIT), 200);
-
-        if (INSTANCE != null) {
-            throw new IllegalStateException("Agpifoj dialog should not be instanciated twice !");
-        }
-
-        INSTANCE = this;
-
-        JPanel content = new JPanel();
-        content.setLayout(new BorderLayout());
-
-        content.add(imgDisplay, BorderLayout.CENTER);
-
-        JPanel buttons = new JPanel();
-        buttons.setLayout(new FlowLayout());
-
-        JButton button;
-
-        Dimension buttonDim = new Dimension(26,26);
-        button = new JButton();
-        button.setIcon(ImageProvider.get("dialogs", "previous"));
-        button.setActionCommand(COMMAND_PREVIOUS);
-        button.setToolTipText(tr("Previous"));
-        button.addActionListener(this);
-        button.setPreferredSize(buttonDim);
-        buttons.add(button);
-
-        button = new JButton();
-        button.setIcon(ImageProvider.get("dialogs", "delete"));
-        button.setActionCommand(COMMAND_REMOVE);
-        button.setToolTipText(tr("Remove photo from layer"));
-        button.addActionListener(this);
-        button.setPreferredSize(buttonDim);
-        buttons.add(button);
-
-        button = new JButton();
-        button.setIcon(ImageProvider.get("dialogs", "next"));
-        button.setActionCommand(COMMAND_NEXT);
-        button.setToolTipText(tr("Next"));
-        button.addActionListener(this);
-        button.setPreferredSize(buttonDim);
-        buttons.add(button);
-
-        JToggleButton tb = new JToggleButton();
-        tb.setIcon(ImageProvider.get("dialogs", "centreview"));
-        tb.setActionCommand(COMMAND_CENTERVIEW);
-        tb.setToolTipText(tr("Center view"));
-        tb.addActionListener(this);
-        tb.setPreferredSize(buttonDim);
-        buttons.add(tb);
-
-        button = new JButton();
-        button.setIcon(ImageProvider.get("dialogs", "zoom-best-fit"));
-        button.setActionCommand(COMMAND_ZOOM);
-        button.setToolTipText(tr("Zoom best fit and 1:1"));
-        button.addActionListener(this);
-        button.setPreferredSize(buttonDim);
-        buttons.add(button);
-
-        content.add(buttons, BorderLayout.SOUTH);
-
-        add(content, BorderLayout.CENTER);
-
-    }
-
-    public void actionPerformed(ActionEvent e) {
-        if (COMMAND_NEXT.equals(e.getActionCommand())) {
-            if (currentLayer != null) {
-                currentLayer.showNextPhoto();
-            }
-        } else if (COMMAND_PREVIOUS.equals(e.getActionCommand())) {
-            if (currentLayer != null) {
-                currentLayer.showPreviousPhoto();
-            }
-
-        } else if (COMMAND_CENTERVIEW.equals(e.getActionCommand())) {
-            centerView = ((JToggleButton) e.getSource()).isSelected();
-            if (centerView && currentEntry != null && currentEntry.pos != null) {
-                Main.map.mapView.zoomTo(currentEntry.pos);
-            }
-
-        } else if (COMMAND_ZOOM.equals(e.getActionCommand())) {
-            imgDisplay.zoomBestFitOrOne();
-
-        } else if (COMMAND_REMOVE.equals(e.getActionCommand())) {
-            if (currentLayer != null) {
-               currentLayer.removeCurrentPhoto();
-            }
-        }
-
-    }
-
-    public static void showImage(AgpifojLayer layer, ImageEntry entry) {
-        getInstance().displayImage(layer, entry);
-    }
-
-    private AgpifojLayer currentLayer = null;
-    private ImageEntry currentEntry = null;
-
-    public void displayImage(AgpifojLayer layer, ImageEntry entry) {
-        synchronized(this) {
-            if (currentLayer == layer && currentEntry == entry) {
-                repaint();
-                return;
-            }
-
-            if (centerView && Main.map != null && entry != null && entry.pos != null) {
-                Main.map.mapView.zoomTo(entry.pos);
-            }
-
-            currentLayer = layer;
-            currentEntry = entry;
-        }
-
-        if (entry != null) {
-            imgDisplay.setImage(entry.file);
-            StringBuffer osd = new StringBuffer(entry.file != null ? entry.file.getName() : "");
-            if (entry.elevation != null) {
-                osd.append(tr("\nAltitude: {0} m", entry.elevation.longValue()));
-            }
-            if (entry.speed != null) {
-                osd.append(tr("\n{0} km/h", Math.round(entry.speed)));
-            }
-            imgDisplay.setOsdText(osd.toString());
-        } else {
-            imgDisplay.setImage(null);
-            imgDisplay.setOsdText("");
-        }
-    }
-    
-    /**
-     * Returns whether an image is currently displayed
-     * @return If image is currently displayed
-     */
-    public boolean hasImage() {
-        return currentEntry != null;
-    }
-}
diff --git a/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/AgpifojLayer.java b/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/AgpifojLayer.java
deleted file mode 100644
index 789230c..0000000
--- a/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/AgpifojLayer.java
+++ /dev/null
@@ -1,560 +0,0 @@
-// License: GPL. Copyright 2007 by Christian Gallioz (aka khris78)
-// Parts of code from Geotagged plugin (by Rob Neild)
-// and the core JOSM source code (by Immanuel Scholz and others)
-
-package org.openstreetmap.josm.plugins.agpifoj;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-import static org.openstreetmap.josm.tools.I18n.trn;
-
-import java.awt.Component;
-import java.awt.Graphics2D;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.io.File;
-import java.io.IOException;
-import java.text.ParseException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.List;
-
-import javax.swing.Icon;
-import javax.swing.JMenuItem;
-import javax.swing.JOptionPane;
-import javax.swing.JSeparator;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.RenameLayerAction;
-import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.coor.CachedLatLon;
-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.PleaseWaitRunnable;
-import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
-import org.openstreetmap.josm.gui.layer.Layer;
-import org.openstreetmap.josm.tools.ExifReader;
-import org.openstreetmap.josm.tools.ImageProvider;
-
-import com.drew.imaging.jpeg.JpegMetadataReader;
-import com.drew.lang.Rational;
-import com.drew.metadata.Directory;
-import com.drew.metadata.Metadata;
-import com.drew.metadata.exif.GpsDirectory;
-
-public class AgpifojLayer extends Layer {
-
-    List<ImageEntry> data;
-
-    private Icon icon = ImageProvider.get("dialogs/agpifoj-marker");
-    private Icon selectedIcon = ImageProvider.get("dialogs/agpifoj-marker-selected");
-
-    private int currentPhoto = -1;
-
-    // These are used by the auto-guess function to store the result,
-    // so when the dialig is re-opened the users modifications don't
-    // get overwritten
-    public boolean hasTimeoffset = false;
-    public long timeoffset = 0;
-
-    /*
-     * Stores info about each image
-     */
-
-    static final class ImageEntry implements Comparable<ImageEntry> {
-        File file;
-        Date time;
-        LatLon exifCoor;
-        CachedLatLon pos;
-        /** Speed in kilometer per second */
-        Double speed;
-        /** Elevation (altitude) in meters */
-        Double elevation;
-
-        public void setCoor(LatLon latlon)
-        {
-            pos = new CachedLatLon(latlon);
-        }
-        public int compareTo(ImageEntry image) {
-            if (time != null && image.time != null) {
-                return time.compareTo(image.time);
-            } else if (time == null && image.time == null) {
-                return 0;
-            } else if (time == null) {
-                return -1;
-            } else {
-                return 1;
-            }
-        }
-    }
-
-    /** Loads a set of images, while displaying a dialog that indicates what the plugin is currently doing.
-     * In facts, this object is instantiated with a list of files. These files may be JPEG files or
-     * directories. In case of directories, they are scanned to find all the images they contain.
-     * Then all the images that have be found are loaded as ImageEntry instances.
-     */
-    private static final class Loader extends PleaseWaitRunnable {
-
-        private boolean cancelled = false;
-        private AgpifojLayer layer;
-        private final File[] selection;
-        private HashSet<String> loadedDirectories = new HashSet<String>();
-        private LinkedHashSet<String> errorMessages;
-
-        protected void rememberError(String message) {
-        	this.errorMessages.add(message);
-        }
-
-        public Loader(File[] selection) {
-            super(tr("Extracting GPS locations from EXIF"));
-            this.selection = selection;
-            errorMessages = new LinkedHashSet<String>();
-        }
-
-        @Override protected void realRun() throws IOException {
-
-            progressMonitor.subTask(tr("Starting directory scan"));
-            List<File> files = new ArrayList<File>();
-            try {
-                addRecursiveFiles(files, selection);
-            } catch(NullPointerException npe) {
-                rememberError(tr("One of the selected files was null"));
-            }
-
-            if (cancelled) {
-                return;
-            }
-            progressMonitor.subTask(tr("Read photos..."));
-            progressMonitor.setTicksCount(files.size());
-
-            progressMonitor.subTask(tr("Read photos..."));
-            progressMonitor.setTicksCount(files.size());
-
-            // read the image files
-            ArrayList<ImageEntry> data = new ArrayList<ImageEntry>(files.size());
-
-            for (File f : files) {
-
-                if (cancelled) {
-                    break;
-                }
-
-                progressMonitor.subTask(tr("Reading {0}...", f.getName()));
-                progressMonitor.worked(1);
-
-                ImageEntry e = new ImageEntry();
-
-                // Changed to silently cope with no time info in exif. One case
-                // of person having time that couldn't be parsed, but valid GPS info
-
-                try {
-                    e.time = ExifReader.readTime(f);
-                } catch (ParseException e1) {
-                    e.time = null;
-                }
-                e.file = f;
-                extractExif(e);
-                data.add(e);
-            }
-            layer = new AgpifojLayer(data);
-            files.clear();
-        }
-
-        private void addRecursiveFiles(List<File> files, File[] sel) {
-            boolean nullFile = false;
-
-            for (File f : sel) {
-
-                if(cancelled) {
-                    break;
-                }
-
-                if (f == null) {
-                    nullFile = true;
-
-                } else if (f.isDirectory()) {
-                    String canonical = null;
-                    try {
-                        canonical = f.getCanonicalPath();
-                    } catch (IOException e) {
-                        e.printStackTrace();
-                        rememberError(tr("Unable to get canonical path for directory {0}\n",
-                                           f.getAbsolutePath()));
-                    }
-
-                    if (canonical == null || loadedDirectories.contains(canonical)) {
-                        continue;
-                    } else {
-                        loadedDirectories.add(canonical);
-                    }
-
-                    File[] children = f.listFiles(AgpifojPlugin.JPEG_FILE_FILTER);
-                    if (children != null) {
-                        progressMonitor.subTask(tr("Scanning directory {0}", f.getPath()));
-                        try {
-                            addRecursiveFiles(files, children);
-                        } catch(NullPointerException npe) {
-                            npe.printStackTrace();
-
-                            rememberError(tr("Found null file in directory {0}\n", f.getPath()));
-                        }
-                    } else {
-                    	rememberError(tr("Error while getting files from directory {0}\n", f.getPath()));
-                    }
-
-                } else {
-                      files.add(f);
-                }
-            }
-
-            if (nullFile) {
-                throw new NullPointerException();
-            }
-        }
-
-        protected String formatErrorMessages() {
-        	StringBuffer sb = new StringBuffer();
-        	sb.append("<html>");
-    		if (errorMessages.size() == 1) {
-    			sb.append(errorMessages.iterator().next());
-    		} else {
-    			sb.append("<ul>");
-    			for (String msg: errorMessages) {
-    				sb.append("<li>").append(msg).append("</li>");
-    			}
-    			sb.append("/ul>");
-    		}
-    		sb.append("</html>");
-    		return sb.toString();
-        }
-
-        @Override protected void finish() {
-        	if (!errorMessages.isEmpty()) {
-        		JOptionPane.showMessageDialog(
-        				Main.parent,
-        				formatErrorMessages(),
-        				tr("Error"),
-        				JOptionPane.ERROR_MESSAGE
-        		);
-        	}
-            if (layer != null) {
-                Main.main.addLayer(layer);
-                layer.hook_up_mouse_events(); // Main.map.mapView should exist
-                                              // now. Can add mouse listener
-
-                if (! cancelled && layer.data.size() > 0) {
-                    boolean noGeotagFound = true;
-                    for (ImageEntry e : layer.data) {
-                        if (e.pos != null) {
-                            noGeotagFound = false;
-                        }
-                    }
-                    if (noGeotagFound) {
-                        new CorrelateGpxWithImages(layer).actionPerformed(null);
-                    }
-                }
-            }
-        }
-
-        @Override protected void cancel() {
-            cancelled = true;
-        }
-    }
-
-    public static void create(File[] files) {
-        Loader loader = new Loader(files);
-        Main.worker.execute(loader);
-    }
-
-    private AgpifojLayer(final List<ImageEntry> data) {
-
-        super(tr("Geotagged Images"));
-
-        Collections.sort(data);
-        this.data = data;
-    }
-
-    @Override
-    public Icon getIcon() {
-        return ImageProvider.get("dialogs/agpifoj");
-    }
-
-    @Override
-    public Object getInfoComponent() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Component[] getMenuEntries() {
-
-        JMenuItem correlateItem = new JMenuItem(tr("Correlate to GPX"), ImageProvider.get("dialogs/gpx2img"));
-        correlateItem.addActionListener(new CorrelateGpxWithImages(this));
-
-        return new Component[] {
-                new JMenuItem(LayerListDialog.getInstance().createShowHideLayerAction(this)),
-                new JMenuItem(LayerListDialog.getInstance().createDeleteLayerAction(this)),
-                new JMenuItem(new RenameLayerAction(null, this)),
-                new JSeparator(),
-                correlateItem
-                };
-    }
-
-    @Override
-    public String getToolTipText() {
-        int i = 0;
-        for (ImageEntry e : data)
-            if (e.pos != null)
-                i++;
-        return data.size() + " " + trn("image", "images", data.size())
-                + " loaded. " + tr("{0} were found to be gps tagged.", i);
-    }
-
-    @Override
-    public boolean isMergable(Layer other) {
-        return other instanceof AgpifojLayer;
-    }
-
-    @Override
-    public void mergeFrom(Layer from) {
-        AgpifojLayer l = (AgpifojLayer) from;
-
-        ImageEntry selected = null;
-        if (l.currentPhoto >= 0) {
-            selected = l.data.get(l.currentPhoto);
-        }
-
-        data.addAll(l.data);
-        Collections.sort(data);
-
-        // Supress the double photos.
-        if (data.size() > 1) {
-            ImageEntry cur;
-            ImageEntry prev = data.get(data.size() - 1);
-            for (int i = data.size() - 2; i >= 0; i--) {
-                cur = data.get(i);
-                if (cur.file.equals(prev.file)) {
-                    data.remove(i);
-                } else {
-                    prev = cur;
-                }
-            }
-        }
-
-        if (selected != null) {
-            for (int i = 0; i < data.size() ; i++) {
-                if (data.get(i) == selected) {
-                    currentPhoto = i;
-                    AgpifojDialog.showImage(AgpifojLayer.this, data.get(i));
-                    break;
-                }
-            }
-        }
-
-        setName(l.getName());
-
-    }
-
-    @Override
-    public void paint(Graphics2D g, MapView mv, Bounds bounds) {
-
-        int iconWidth = icon.getIconWidth() / 2;
-        int iconHeight = icon.getIconHeight() / 2;
-
-        for (ImageEntry e : data) {
-            if (e.pos != null) {
-                Point p = mv.getPoint(e.pos);
-
-                Rectangle r = new Rectangle(p.x - iconWidth,
-                                            p.y - iconHeight,
-                                            icon.getIconWidth(),
-                                            icon.getIconHeight());
-                icon.paintIcon(mv, g, r.x, r.y);
-            }
-        }
-
-        // Draw the selection on top of the other pictures.
-        if (currentPhoto >= 0 && currentPhoto < data.size()) {
-            ImageEntry e = data.get(currentPhoto);
-
-            if (e.pos != null) {
-                Point p = mv.getPoint(e.pos);
-
-                Rectangle r = new Rectangle(p.x - selectedIcon.getIconWidth() / 2,
-                                            p.y - selectedIcon.getIconHeight() / 2,
-                                            selectedIcon.getIconWidth(),
-                                            selectedIcon.getIconHeight());
-                selectedIcon.paintIcon(mv, g, r.x, r.y);
-            }
-        }
-    }
-
-    @Override
-    public void visitBoundingBox(BoundingXYVisitor v) {
-        for (ImageEntry e : data)
-            v.visit(e.pos);
-    }
-
-    /*
-     * Extract gps from image exif
-     *
-     * If successful, fills in the LatLon and EastNorth attributes of passed in
-     * image;
-     */
-
-    private static void extractExif(ImageEntry e) {
-
-        try {
-            int deg;
-            float min, sec;
-            double lon, lat;
-
-            Metadata metadata = JpegMetadataReader.readMetadata(e.file);
-            Directory dir = metadata.getDirectory(GpsDirectory.class);
-
-            // longitude
-
-            Rational[] components = dir
-                    .getRationalArray(GpsDirectory.TAG_GPS_LONGITUDE);
-
-            deg = components[0].intValue();
-            min = components[1].floatValue();
-            sec = components[2].floatValue();
-
-            lon = (deg + (min / 60) + (sec / 3600));
-
-            if (dir.getString(GpsDirectory.TAG_GPS_LONGITUDE_REF).charAt(0) == 'W')
-                lon = -lon;
-
-            // latitude
-
-            components = dir.getRationalArray(GpsDirectory.TAG_GPS_LATITUDE);
-
-            deg = components[0].intValue();
-            min = components[1].floatValue();
-            sec = components[2].floatValue();
-
-            lat = (deg + (min / 60) + (sec / 3600));
-
-            if (dir.getString(GpsDirectory.TAG_GPS_LATITUDE_REF).charAt(0) == 'S')
-                lat = -lat;
-
-            // Store values
-
-            e.setCoor(new LatLon(lat, lon));
-            e.exifCoor = e.pos;
-
-        } catch (Exception p) {
-            e.pos = null;
-        }
-    }
-
-    public void showNextPhoto() {
-        if (data != null && data.size() > 0) {
-            currentPhoto++;
-            if (currentPhoto >= data.size()) {
-                currentPhoto = data.size() - 1;
-            }
-            AgpifojDialog.showImage(this, data.get(currentPhoto));
-        } else {
-            currentPhoto = -1;
-        }
-        Main.main.map.repaint();
-    }
-
-    public void showPreviousPhoto() {
-        if (data != null && data.size() > 0) {
-            currentPhoto--;
-            if (currentPhoto < 0) {
-                currentPhoto = 0;
-            }
-            AgpifojDialog.showImage(this, data.get(currentPhoto));
-        } else {
-            currentPhoto = -1;
-        }
-        Main.main.map.repaint();
-    }
-
-    public void removeCurrentPhoto() {
-        if (data != null && data.size() > 0 && currentPhoto >= 0 && currentPhoto < data.size()) {
-            data.remove(currentPhoto);
-            if (currentPhoto >= data.size()) {
-                currentPhoto = data.size() - 1;
-            }
-            if (currentPhoto >= 0) {
-                AgpifojDialog.showImage(this, data.get(currentPhoto));
-            } else {
-                AgpifojDialog.showImage(this, null);
-            }
-        }
-        Main.main.map.repaint();
-    }
-
-    private MouseAdapter mouseAdapter = null;
-
-    private void hook_up_mouse_events() {
-        mouseAdapter = new MouseAdapter() {
-            @Override public void mousePressed(MouseEvent e) {
-
-                if (e.getButton() != MouseEvent.BUTTON1) {
-                    return;
-                }
-                if (isVisible())
-                    Main.map.mapView.repaint();
-            }
-
-            @Override public void mouseReleased(MouseEvent ev) {
-                if (ev.getButton() != MouseEvent.BUTTON1) {
-                    return;
-                }
-                if (!isVisible()) {
-                    return;
-                }
-                for (int i = data.size() - 1; i >= 0; --i) {
-                    ImageEntry e = data.get(i);
-                    if (e.pos == null)
-                        continue;
-                    Point p = Main.map.mapView.getPoint(e.pos);
-                    Rectangle r = new Rectangle(p.x - icon.getIconWidth() / 2,
-                                                p.y - icon.getIconHeight() / 2,
-                                                icon.getIconWidth(),
-                                                icon.getIconHeight());
-                    if (r.contains(ev.getPoint())) {
-                        currentPhoto = i;
-                        AgpifojDialog.showImage(AgpifojLayer.this, e);
-                        Main.main.map.repaint();
-                        break;
-                    }
-                }
-                Main.map.mapView.repaint();
-            }
-        };
-        Main.map.mapView.addMouseListener(mouseAdapter);
-        Layer.listeners.add(new LayerChangeListener() {
-            public void activeLayerChange(Layer oldLayer, Layer newLayer) {
-                if (newLayer == AgpifojLayer.this && currentPhoto >= 0) {
-                    Main.main.map.repaint();
-                    AgpifojDialog.showImage(AgpifojLayer.this, data.get(currentPhoto));
-                }
-            }
-
-            public void layerAdded(Layer newLayer) {
-            }
-
-            public void layerRemoved(Layer oldLayer) {
-                if (oldLayer == AgpifojLayer.this) {
-                    Main.map.mapView.removeMouseListener(mouseAdapter);
-                    currentPhoto = -1;
-                    data.clear();
-                    data = null;
-                }
-            }
-        });
-    }
-
-}
diff --git a/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/AgpifojPlugin.java b/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/AgpifojPlugin.java
deleted file mode 100644
index 9d17ac1..0000000
--- a/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/AgpifojPlugin.java
+++ /dev/null
@@ -1,100 +0,0 @@
-// License: GPL. Copyright 2007 by Christian Gallioz (aka khris78)
-// Parts of code from Geotagged plugin (by Rob Neild)
-// and the core JOSM source code (by Immanuel Scholz and others)
-
-package org.openstreetmap.josm.plugins.agpifoj;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.event.ActionEvent;
-import java.io.File;
-
-import javax.swing.JFileChooser;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.JosmAction;
-import org.openstreetmap.josm.gui.IconToggleButton;
-import org.openstreetmap.josm.gui.MainMenu;
-import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.gui.layer.Layer;
-import org.openstreetmap.josm.plugins.Plugin;
-
-public class AgpifojPlugin extends Plugin {
-
-    static class JpegFileFilter extends javax.swing.filechooser.FileFilter
-                                        implements java.io.FileFilter {
-
-        @Override public boolean accept(File f) {
-            if (f.isDirectory()) {
-                return true;
-            } else {
-                String name = f.getName().toLowerCase();
-                return name.endsWith(".jpg") || name.endsWith(".jpeg");
-            }
-        }
-
-        @Override public String getDescription() {
-            return tr("JPEG images (*.jpg)");
-        }
-    };
-
-    static final JpegFileFilter JPEG_FILE_FILTER = new JpegFileFilter();
-
-    private class Action extends JosmAction {
-
-        public Action() {
-            super(tr("Open images with AgPifoJ..."),
-                  "agpifoj-open",
-                  tr("Load set of images as a new layer."),
-                  null, false);
-        }
-
-        public void actionPerformed(ActionEvent e) {
-
-            JFileChooser fc = new JFileChooser(Main.pref.get("tagimages.lastdirectory"));
-            fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
-            fc.setMultiSelectionEnabled(true);
-            fc.setAcceptAllFileFilterUsed(false);
-            fc.setFileFilter(JPEG_FILE_FILTER);
-
-            int result = fc.showOpenDialog(Main.parent);
-
-            File[] sel = fc.getSelectedFiles();
-            if (sel == null || sel.length == 0 || result != JFileChooser.APPROVE_OPTION) {
-                return;
-            }
-
-            Main.pref.put("tagimages.lastdirectory", fc.getCurrentDirectory().getPath());
-
-            AgpifojLayer.create(sel);
-        }
-    }
-
-    public AgpifojPlugin() {
-        MainMenu.add(Main.main.menu.fileMenu, new Action());
-    }
-
-    /**
-     * Called after Main.mapFrame is initialized. (After the first data is loaded).
-     * You can use this callback to tweak the newFrame to your needs, as example install
-     * an alternative Painter.
-     */
-    @Override
-    public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
-        if (newFrame != null) {
-            AgpifojDialog dialog = AgpifojDialog.getInstance();
-            IconToggleButton b = newFrame.addToggleDialog(dialog);
-
-            boolean found = false;
-            for (Layer layer : newFrame.mapView.getAllLayers()) {
-                if (layer instanceof AgpifojLayer) {
-                    found = true;
-                    break;
-                }
-            }
-            b.setSelected(found);
-        } else {
-            AgpifojDialog.getInstance().displayImage(null, null);
-        }
-    }
-}
diff --git a/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/CorrelateGpxWithImages.java b/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/CorrelateGpxWithImages.java
deleted file mode 100644
index 602b989..0000000
--- a/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/CorrelateGpxWithImages.java
+++ /dev/null
@@ -1,1175 +0,0 @@
-// License: GPL. Copyright 2007 by Christian Gallioz (aka khris78)
-// Parts of code from Geotagged plugin (by Rob Neild)
-// and the core JOSM source code (by Immanuel Scholz and others)
-
-package org.openstreetmap.josm.plugins.agpifoj;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.BorderLayout;
-import java.awt.Cursor;
-import java.awt.Dimension;
-import java.awt.FlowLayout;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.List;
-import java.util.TimeZone;
-import java.util.Vector;
-import java.util.zip.GZIPInputStream;
-
-import javax.swing.AbstractListModel;
-import javax.swing.ButtonGroup;
-import javax.swing.JButton;
-import javax.swing.JComboBox;
-import javax.swing.JFileChooser;
-import javax.swing.JLabel;
-import javax.swing.JList;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JRadioButton;
-import javax.swing.JScrollPane;
-import javax.swing.JSlider;
-import javax.swing.JTextField;
-import javax.swing.ListSelectionModel;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-import javax.swing.event.ListSelectionEvent;
-import javax.swing.event.ListSelectionListener;
-import javax.swing.filechooser.FileFilter;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.data.gpx.GpxData;
-import org.openstreetmap.josm.data.gpx.GpxTrack;
-import org.openstreetmap.josm.data.gpx.WayPoint;
-import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
-import org.openstreetmap.josm.gui.ExtendedDialog;
-import org.openstreetmap.josm.gui.layer.GpxLayer;
-import org.openstreetmap.josm.gui.layer.Layer;
-import org.openstreetmap.josm.io.GpxReader;
-import org.openstreetmap.josm.plugins.agpifoj.AgpifojLayer.ImageEntry;
-import org.openstreetmap.josm.tools.ExifReader;
-import org.openstreetmap.josm.tools.GBC;
-import org.openstreetmap.josm.tools.ImageProvider;
-import org.openstreetmap.josm.tools.PrimaryDateParser;
-import org.xml.sax.SAXException;
-
-
-/** This class displays the window to select the GPX file and the offset (timezone + delta).
- * Then it correlates the images of the layer with that GPX file.
- */
-public class CorrelateGpxWithImages implements ActionListener {
-
-    private static List<GpxData> loadedGpxData = new ArrayList<GpxData>();
-
-    public static class CorrelateParameters {
-        GpxData gpxData;
-        float timezone;
-        long offset;
-    }
-
-    AgpifojLayer yLayer = null;
-
-    private static class GpxDataWrapper {
-        String name;
-        GpxData data;
-        File file;
-
-        public GpxDataWrapper(String name, GpxData data, File file) {
-            this.name = name;
-            this.data = data;
-            this.file = file;
-        }
-
-        @Override
-		public String toString() {
-            return name;
-        }
-    }
-
-    Vector gpxLst = new Vector();
-    JPanel panel = null;
-    JComboBox cbGpx = null;
-    JTextField tfTimezone = null;
-    JTextField tfOffset = null;
-    JRadioButton rbAllImg = null;
-    JRadioButton rbUntaggedImg = null;
-    JRadioButton rbNoExifImg = null;
-
-    /** This class is called when the user doesn't find the GPX file he needs in the files that have
-     * been loaded yet. It displays a FileChooser dialog to select the GPX file to be loaded.
-     */
-    private class LoadGpxDataActionListener implements ActionListener {
-
-        public void actionPerformed(ActionEvent arg0) {
-            JFileChooser fc = new JFileChooser(Main.pref.get("lastDirectory"));
-            fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
-            fc.setAcceptAllFileFilterUsed(false);
-            fc.setMultiSelectionEnabled(false);
-            fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
-            fc.setFileFilter(new FileFilter(){
-                @Override public boolean accept(File f) {
-                    return (f.isDirectory()
-                            || f .getName().toLowerCase().endsWith(".gpx")
-                            || f.getName().toLowerCase().endsWith(".gpx.gz"));
-                }
-                @Override public String getDescription() {
-                    return tr("GPX Files (*.gpx *.gpx.gz)");
-                }
-            });
-            fc.showOpenDialog(Main.parent);
-            File sel = fc.getSelectedFile();
-            if (sel == null)
-                return;
-
-            try {
-                panel.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
-
-                Main.pref.put("lastDirectory", sel.getPath());
-
-                for (int i = gpxLst.size() - 1 ; i >= 0 ; i--) {
-                    if (gpxLst.get(i) instanceof GpxDataWrapper) {
-                        GpxDataWrapper wrapper = (GpxDataWrapper) gpxLst.get(i);
-                        if (sel.equals(wrapper.file)) {
-                            cbGpx.setSelectedIndex(i);
-                            if (!sel.getName().equals(wrapper.name)) {
-                                JOptionPane.showMessageDialog(
-                                		Main.parent,
-                                        tr("File {0} is loaded yet under the name \"{1}\"", sel.getName(), wrapper.name),
-                                        tr("Error"),
-                                        JOptionPane.ERROR_MESSAGE
-                                        );
-                            }
-                            return;
-                        }
-                    }
-                }
-                GpxData data = null;
-                try {
-                    InputStream iStream;
-                    if (sel.getName().toLowerCase().endsWith(".gpx.gz")) {
-                        iStream = new GZIPInputStream(new FileInputStream(sel));
-                    } else {
-                        iStream = new FileInputStream(sel);
-                    }
-                    data = new GpxReader(iStream, sel).data;
-                    data.storageFile = sel;
-
-                } catch (SAXException x) {
-                    x.printStackTrace();
-                    JOptionPane.showMessageDialog(
-                    		Main.parent,
-                    		tr("Error while parsing {0}",sel.getName())+": "+x.getMessage(),
-                    		tr("Error"),
-                    		JOptionPane.ERROR_MESSAGE
-                    		);
-                    return;
-                } catch (IOException x) {
-                    x.printStackTrace();
-                    JOptionPane.showMessageDialog(
-                    		Main.parent,
-                    		tr("Could not read \"{0}\"",sel.getName())+"\n"+x.getMessage(),
-                    		tr("Error"),
-                    		JOptionPane.ERROR_MESSAGE
-                    		);
-                    return;
-                }
-
-                loadedGpxData.add(data);
-                if (gpxLst.get(0) instanceof String) {
-                    gpxLst.remove(0);
-                }
-                gpxLst.add(new GpxDataWrapper(sel.getName(), data, sel));
-                cbGpx.setSelectedIndex(cbGpx.getItemCount() - 1);
-            } finally {
-                panel.setCursor(Cursor.getDefaultCursor());
-            }
-        }
-    }
-
-    /** This action listener is called when the user has a photo of the time of his GPS receiver. It
-     * displays the list of photos of the layer, and upon selection displays the selected photo.
-     * From that photo, the user can key in the time of the GPS.
-     * Then values of timezone and delta are set.
-     * @author chris
-     *
-     */
-    private class SetOffsetActionListener implements ActionListener {
-        JPanel panel;
-        JLabel lbExifTime;
-        JTextField tfGpsTime;
-        JComboBox cbTimezones;
-        ImageDisplay imgDisp;
-        JList imgList;
-
-        public void actionPerformed(ActionEvent arg0) {
-            SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
-
-            panel = new JPanel();
-            panel.setLayout(new BorderLayout());
-            panel.add(new JLabel(tr("<html>Take a photo of your GPS receiver while it displays the time.<br>"
-                                    + "Display that photo here.<br>"
-                                    + "And then, simply capture the time you read on the photo and select a timezone<hr></html>")),
-                                    BorderLayout.NORTH);
-
-            imgDisp = new ImageDisplay();
-            imgDisp.setPreferredSize(new Dimension(300, 225));
-            panel.add(imgDisp, BorderLayout.CENTER);
-
-            JPanel panelTf = new JPanel();
-            panelTf.setLayout(new GridBagLayout());
-
-            GridBagConstraints gc = new GridBagConstraints();
-            gc.gridx = gc.gridy = 0;
-            gc.gridwidth = gc.gridheight = 1;
-            gc.weightx = gc.weighty = 0.0;
-            gc.fill = GridBagConstraints.NONE;
-            gc.anchor = GridBagConstraints.WEST;
-            panelTf.add(new JLabel(tr("Photo time (from exif):")), gc);
-
-            lbExifTime = new JLabel();
-            gc.gridx = 1;
-            gc.weightx = 1.0;
-            gc.fill = GridBagConstraints.HORIZONTAL;
-            gc.gridwidth = 2;
-            panelTf.add(lbExifTime, gc);
-
-            gc.gridx = 0;
-            gc.gridy = 1;
-            gc.gridwidth = gc.gridheight = 1;
-            gc.weightx = gc.weighty = 0.0;
-            gc.fill = GridBagConstraints.NONE;
-            gc.anchor = GridBagConstraints.WEST;
-            panelTf.add(new JLabel(tr("Gps time (read from the above photo): ")), gc);
-
-            tfGpsTime = new JTextField();
-            tfGpsTime.setEnabled(false);
-            tfGpsTime.setMinimumSize(new Dimension(150, tfGpsTime.getMinimumSize().height));
-            gc.gridx = 1;
-            gc.weightx = 1.0;
-            gc.fill = GridBagConstraints.HORIZONTAL;
-            panelTf.add(tfGpsTime, gc);
-
-            gc.gridx = 2;
-            gc.weightx = 0.2;
-            panelTf.add(new JLabel(tr(" [dd/mm/yyyy hh:mm:ss]")), gc);
-
-            gc.gridx = 0;
-            gc.gridy = 2;
-            gc.gridwidth = gc.gridheight = 1;
-            gc.weightx = gc.weighty = 0.0;
-            gc.fill = GridBagConstraints.NONE;
-            gc.anchor = GridBagConstraints.WEST;
-            panelTf.add(new JLabel(tr("I'm in the timezone of: ")), gc);
-
-            Vector vtTimezones = new Vector<String>();
-            String[] tmp = TimeZone.getAvailableIDs();
-
-            for (String tzStr : tmp) {
-                TimeZone tz = TimeZone.getTimeZone(tzStr);
-
-                String tzDesc = new StringBuffer(tzStr).append(" (")
-                                        .append(formatTimezone(tz.getRawOffset() / 3600000.0))
-                                        .append(')').toString();
-                vtTimezones.add(tzDesc);
-            }
-
-            Collections.sort(vtTimezones);
-
-            cbTimezones = new JComboBox(vtTimezones);
-
-            String tzId = Main.pref.get("tagimages.timezoneid", "");
-            TimeZone defaultTz;
-            if (tzId.length() == 0) {
-                defaultTz = TimeZone.getDefault();
-            } else {
-                defaultTz = TimeZone.getTimeZone(tzId);
-            }
-
-            cbTimezones.setSelectedItem(new StringBuffer(defaultTz.getID()).append(" (")
-                    .append(formatTimezone(defaultTz.getRawOffset() / 3600000.0))
-                    .append(')').toString());
-
-            gc.gridx = 1;
-            gc.weightx = 1.0;
-            gc.gridwidth = 2;
-            gc.fill = GridBagConstraints.HORIZONTAL;
-            panelTf.add(cbTimezones, gc);
-
-            panel.add(panelTf, BorderLayout.SOUTH);
-
-            JPanel panelLst = new JPanel();
-            panelLst.setLayout(new BorderLayout());
-
-            imgList = new JList(new AbstractListModel() {
-                public Object getElementAt(int i) {
-                    return yLayer.data.get(i).file.getName();
-                }
-
-                public int getSize() {
-                    return yLayer.data.size();
-                }
-            });
-            imgList.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-            imgList.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
-
-                public void valueChanged(ListSelectionEvent arg0) {
-                    int index = imgList.getSelectedIndex();
-                    imgDisp.setImage(yLayer.data.get(index).file);
-                    Date date = yLayer.data.get(index).time;
-                    if (date != null) {
-                        lbExifTime.setText(new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(date));
-                        tfGpsTime.setText(new SimpleDateFormat("dd/MM/yyyy ").format(date));
-                        tfGpsTime.setCaretPosition(tfGpsTime.getText().length());
-                        tfGpsTime.setEnabled(true);
-                    } else {
-                        lbExifTime.setText(tr("No date"));
-                        tfGpsTime.setText("");
-                        tfGpsTime.setEnabled(false);
-                    }
-                }
-
-            });
-            panelLst.add(new JScrollPane(imgList), BorderLayout.CENTER);
-
-            JButton openButton = new JButton(tr("Open an other photo"));
-            openButton.addActionListener(new ActionListener() {
-
-                public void actionPerformed(ActionEvent arg0) {
-                    JFileChooser fc = new JFileChooser(Main.pref.get("tagimages.lastdirectory"));
-                    fc.setAcceptAllFileFilterUsed(false);
-                    fc.setMultiSelectionEnabled(false);
-                    fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
-                    fc.setFileFilter(AgpifojPlugin.JPEG_FILE_FILTER);
-                    fc.showOpenDialog(Main.parent);
-                    File sel = fc.getSelectedFile();
-                    if (sel == null) {
-                        return;
-                    }
-
-                    imgDisp.setImage(sel);
-
-                    Date date = null;
-                    try {
-                        date = ExifReader.readTime(sel);
-                    } catch (Exception e) {
-                    }
-                    if (date != null) {
-                        lbExifTime.setText(new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(date));
-                        tfGpsTime.setText(new SimpleDateFormat("dd/MM/yyyy ").format(date));
-                        tfGpsTime.setEnabled(true);
-                    } else {
-                        lbExifTime.setText(tr("No date"));
-                        tfGpsTime.setText("");
-                        tfGpsTime.setEnabled(false);
-                    }
-                }
-            });
-            panelLst.add(openButton, BorderLayout.PAGE_END);
-
-            panel.add(panelLst, BorderLayout.LINE_START);
-
-            boolean isOk = false;
-            while (! isOk) {
-                int answer = JOptionPane.showConfirmDialog(
-                		Main.parent, panel,
-                		tr("Synchronize time from a photo of the GPS receiver"),
-                		JOptionPane.OK_CANCEL_OPTION,
-                		JOptionPane.QUESTION_MESSAGE
-                		);
-                if (answer == JOptionPane.CANCEL_OPTION) {
-                    return;
-                }
-
-                long delta;
-
-                try {
-                    delta = dateFormat.parse(lbExifTime.getText()).getTime()
-                            - dateFormat.parse(tfGpsTime.getText()).getTime();
-                } catch(ParseException e) {
-                    JOptionPane.showMessageDialog(Main.parent, tr("Error while parsing the date.\n"
-                            + "Please use the requested format"),
-                            tr("Invalid date"), JOptionPane.ERROR_MESSAGE );
-                    continue;
-                }
-
-                String selectedTz = (String) cbTimezones.getSelectedItem();
-                int pos = selectedTz.lastIndexOf('(');
-                tzId = selectedTz.substring(0, pos - 1);
-                String tzValue = selectedTz.substring(pos + 1, selectedTz.length() - 1);
-
-                Main.pref.put("tagimages.timezoneid", tzId);
-                tfOffset.setText(Long.toString(delta / 1000));
-                tfTimezone.setText(tzValue);
-
-                isOk = true;
-
-            }
-
-        }
-    }
-
-    public CorrelateGpxWithImages(AgpifojLayer layer) {
-        this.yLayer = layer;
-    }
-
-    public void actionPerformed(ActionEvent arg0) {
-        // Construct the list of loaded GPX tracks
-        Collection<Layer> layerLst = Main.main.map.mapView.getAllLayers();
-        Iterator<Layer> iterLayer = layerLst.iterator();
-        while (iterLayer.hasNext()) {
-            Layer cur = iterLayer.next();
-            if (cur instanceof GpxLayer) {
-                gpxLst.add(new GpxDataWrapper(((GpxLayer) cur).getName(),
-                                              ((GpxLayer) cur).data,
-                                              ((GpxLayer) cur).data.storageFile));
-            }
-        }
-        for (GpxData data : loadedGpxData) {
-            gpxLst.add(new GpxDataWrapper(data.storageFile.getName(),
-                                          data,
-                                          data.storageFile));
-        }
-
-        if (gpxLst.size() == 0) {
-            gpxLst.add(tr("<No GPX track loaded yet>"));
-        }
-
-        JPanel panelCb = new JPanel();
-        panelCb.setLayout(new FlowLayout());
-
-        panelCb.add(new JLabel(tr("GPX track: ")));
-
-        cbGpx = new JComboBox(gpxLst);
-        panelCb.add(cbGpx);
-
-        JButton buttonOpen = new JButton(tr("Open another GPX trace"));
-        buttonOpen.setIcon(ImageProvider.get("agpifoj-open"));
-        buttonOpen.addActionListener(new LoadGpxDataActionListener());
-
-        panelCb.add(buttonOpen);
-
-        JPanel panelTf = new JPanel();
-        panelTf.setLayout(new GridBagLayout());
-
-        GridBagConstraints gc = new GridBagConstraints();
-        gc.anchor = GridBagConstraints.WEST;
-
-        gc.gridx = gc.gridy = 0;
-        gc.gridwidth = gc.gridheight = 1;
-        gc.fill = GridBagConstraints.NONE;
-        gc.weightx = gc.weighty = 0.0;
-        panelTf.add(new JLabel(tr("Timezone: ")), gc);
-
-        float gpstimezone = Float.parseFloat(Main.pref.get("tagimages.doublegpstimezone", "0.0"));
-        if (gpstimezone == 0.0) {
-            gpstimezone = - Long.parseLong(Main.pref.get("tagimages.gpstimezone", "0"));
-        }
-        tfTimezone = new JTextField();
-        tfTimezone.setText(formatTimezone(gpstimezone));
-
-        gc.gridx = 1;
-        gc.gridy = 0;
-        gc.gridwidth = gc.gridheight = 1;
-        gc.fill = GridBagConstraints.HORIZONTAL;
-        gc.weightx = 1.0;
-        gc.weighty = 0.0;
-        panelTf.add(tfTimezone, gc);
-
-        gc.gridx = 0;
-        gc.gridy = 1;
-        gc.gridwidth = gc.gridheight = 1;
-        gc.fill = GridBagConstraints.NONE;
-        gc.weightx = gc.weighty = 0.0;
-        panelTf.add(new JLabel(tr("Offset:")), gc);
-
-        long delta = Long.parseLong(Main.pref.get("tagimages.delta", "0")) / 1000;
-        tfOffset = new JTextField();
-        tfOffset.setText(Long.toString(delta));
-        gc.gridx = gc.gridy = 1;
-        gc.gridwidth = gc.gridheight = 1;
-        gc.fill = GridBagConstraints.HORIZONTAL;
-        gc.weightx = 1.0;
-        gc.weighty = 0.0;
-        panelTf.add(tfOffset, gc);
-
-        JButton buttonViewGpsPhoto = new JButton(tr("<html>I can take a picture of my GPS receiver.<br>"
-                                                    + "Can this help?</html>"));
-        buttonViewGpsPhoto.addActionListener(new SetOffsetActionListener());
-        gc.gridx = 2;
-        gc.gridy = 0;
-        gc.gridwidth = 1;
-        gc.gridheight = 2;
-        gc.fill = GridBagConstraints.BOTH;
-        gc.weightx = 0.5;
-        gc.weighty = 1.0;
-        panelTf.add(buttonViewGpsPhoto, gc);
-
-        gc.gridx = 0;
-        gc.gridy = 2;
-        gc.gridwidth = gc.gridheight = 1;
-        gc.fill = GridBagConstraints.NONE;
-        gc.weightx = gc.weighty = 0.0;
-        panelTf.add(new JLabel(tr("Update position for: ")), gc);
-
-        gc.gridx = 1;
-        gc.gridy = 2;
-        gc.gridwidth = 2;
-        gc.gridheight = 1;
-        gc.fill = GridBagConstraints.HORIZONTAL;
-        gc.weightx = 1.0;
-        gc.weighty = 0.0;
-        rbAllImg = new JRadioButton(tr("All images"));
-        panelTf.add(rbAllImg, gc);
-
-        gc.gridx = 1;
-        gc.gridy = 3;
-        gc.gridwidth = 2;
-        gc.gridheight = 1;
-        gc.fill = GridBagConstraints.HORIZONTAL;
-        gc.weightx = 1.0;
-        gc.weighty = 0.0;
-        rbNoExifImg = new JRadioButton(tr("Images with no exif position"));
-        panelTf.add(rbNoExifImg, gc);
-
-        gc.gridx = 1;
-        gc.gridy = 4;
-        gc.gridwidth = 2;
-        gc.gridheight = 1;
-        gc.fill = GridBagConstraints.HORIZONTAL;
-        gc.weightx = 1.0;
-        gc.weighty = 0.0;
-        rbUntaggedImg = new JRadioButton(tr("Not yet tagged images"));
-        panelTf.add(rbUntaggedImg, gc);
-
-        ButtonGroup group = new ButtonGroup();
-        group.add(rbAllImg);
-        group.add(rbNoExifImg);
-        group.add(rbUntaggedImg);
-
-        rbUntaggedImg.setSelected(true);
-
-        panel = new JPanel();
-        panel.setLayout(new BorderLayout());
-
-        panel.add(panelCb, BorderLayout.PAGE_START);
-        panel.add(panelTf, BorderLayout.CENTER);
-
-        boolean isOk = false;
-        GpxDataWrapper selectedGpx = null;
-        while (! isOk) {
-        	ExtendedDialog dialog = new ExtendedDialog(
-        			Main.parent,
-                tr("Correlate images with GPX track"),
-                new String[] { tr("Correlate"), tr("Auto-Guess"), tr("Cancel") }
-        			);
-
-        	dialog.setContent(panel);
-        	dialog.setButtonIcons(new String[] { "ok.png", "dialogs/gpx2imgManual.png", "cancel.png" });
-        	dialog.showDialog();
-        	int answer = dialog.getValue();
-            if(answer != 1 && answer != 2)
-                return;
-
-            // Check the selected values
-            Object item = cbGpx.getSelectedItem();
-
-            if (item == null || ! (item instanceof GpxDataWrapper)) {
-                JOptionPane.showMessageDialog(Main.parent, tr("You should select a GPX track"),
-                                              tr("No selected GPX track"), JOptionPane.ERROR_MESSAGE );
-                continue;
-            }
-            selectedGpx = ((GpxDataWrapper) item);
-
-            if (answer == 2) {
-                autoGuess(selectedGpx.data);
-                return;
-            }
-
-            Float timezoneValue = parseTimezone(tfTimezone.getText().trim());
-            if (timezoneValue == null) {
-                JOptionPane.showMessageDialog(Main.parent, tr("Error while parsing timezone.\nExpected format: {0}", "+H:MM"),
-                        tr("Invalid timezone"), JOptionPane.ERROR_MESSAGE);
-                continue;
-            }
-            gpstimezone = timezoneValue.floatValue();
-
-            String deltaText = tfOffset.getText().trim();
-            if (deltaText.length() > 0) {
-                try {
-                    if(deltaText.startsWith("+"))
-                        deltaText = deltaText.substring(1);
-                    delta = Long.parseLong(deltaText);
-                } catch(NumberFormatException nfe) {
-                    JOptionPane.showMessageDialog(Main.parent, tr("Error while parsing offset.\nExpected format: {0}", "number"),
-                            tr("Invalid offset"), JOptionPane.ERROR_MESSAGE);
-                    continue;
-                }
-            } else {
-                delta = 0;
-            }
-
-            Main.pref.put("tagimages.doublegpstimezone", Double.toString(gpstimezone));
-            Main.pref.put("tagimages.gpstimezone", Long.toString(- ((long) gpstimezone)));
-            Main.pref.put("tagimages.delta", Long.toString(delta * 1000));
-
-            isOk = true;
-        }
-
-        // Construct a list of images that have a date, and sort them on the date.
-        ArrayList<ImageEntry> dateImgLst = getSortedImgList(rbAllImg.isSelected(), rbNoExifImg.isSelected());
-
-        int matched = matchGpxTrack(dateImgLst, selectedGpx.data, (long) (gpstimezone * 3600) + delta);
-
-        // Search whether an other layer has yet defined some bounding box.
-        // If none, we'll zoom to the bounding box of the layer with the photos.
-        boolean boundingBoxedLayerFound = false;
-        for (Layer l: Main.map.mapView.getAllLayers()) {
-            if (l != yLayer) {
-                BoundingXYVisitor bbox = new BoundingXYVisitor();
-                l.visitBoundingBox(bbox);
-                if (bbox.getBounds() != null) {
-                    boundingBoxedLayerFound = true;
-                    break;
-                }
-            }
-        }
-        if (! boundingBoxedLayerFound) {
-            BoundingXYVisitor bbox = new BoundingXYVisitor();
-            yLayer.visitBoundingBox(bbox);
-            Main.map.mapView.recalculateCenterScale(bbox);
-        }
-
-        Main.map.repaint();
-
-        JOptionPane.showMessageDialog(Main.parent, tr("Found {0} matches of {1} in GPX track {2}", matched, dateImgLst.size(), selectedGpx.name),
-                tr("GPX Track loaded"),
-                ((dateImgLst.size() > 0 && matched == 0) ? JOptionPane.WARNING_MESSAGE
-                                                         : JOptionPane.INFORMATION_MESSAGE));
-
-    }
-
-    // These variables all belong to "auto guess" but need to be accessible
-    // from the slider change listener
-    private int dayOffset;
-    private JLabel lblMatches;
-    private JLabel lblOffset;
-    private JLabel lblTimezone;
-    private JLabel lblMinutes;
-    private JLabel lblSeconds;
-    private JSlider sldTimezone;
-    private JSlider sldMinutes;
-    private JSlider sldSeconds;
-    private GpxData autoGpx;
-    private ArrayList<ImageEntry> autoImgs;
-    private long firstGPXDate = -1;
-    private long firstExifDate = -1;
-
-    /**
-     * Tries to automatically match opened photos to a given GPX track. Changes are applied
-     * immediately. Presents dialog with sliders for manual adjust.
-     * @param GpxData The GPX track to match against
-     */
-    private void autoGuess(GpxData gpx) {
-        autoGpx = gpx;
-        autoImgs = getSortedImgList(true, false);
-        PrimaryDateParser dateParser = new PrimaryDateParser();
-
-        // no images found, exit
-        if(autoImgs.size() <= 0) {
-            JOptionPane.showMessageDialog(Main.parent,
-                tr("The selected photos don't contain time information."),
-                tr("Photos don't contain time information"), JOptionPane.WARNING_MESSAGE);
-            return;
-        }
-
-        AgpifojDialog dialog = AgpifojDialog.getInstance();
-        dialog.showDialog();
-        // Will show first photo if none is selected yet
-        if(!dialog.hasImage())
-            yLayer.showNextPhoto();
-        // FIXME: If the dialog is minimized it will not be maximized. ToggleDialog is
-        // in need of a complete re-write to allow this in a reasonable way.
-
-        // Init variables
-        firstExifDate = autoImgs.get(0).time.getTime()/1000;
-
-
-        // Finds first GPX point
-        outer: for (GpxTrack trk : gpx.tracks) {
-            for (Collection<WayPoint> segment : trk.trackSegs) {
-                for (WayPoint curWp : segment) {
-                    String curDateWpStr = (String) curWp.attr.get("time");
-                    if (curDateWpStr == null) continue;
-
-                    try {
-                        firstGPXDate = dateParser.parse(curDateWpStr).getTime()/1000;
-                        break outer;
-                    } catch(Exception e) {}
-                }
-            }
-        }
-
-        // No GPX timestamps found, exit
-        if(firstGPXDate < 0) {
-            JOptionPane.showMessageDialog(Main.parent,
-                tr("The selected GPX track doesn't contain timestamps. Please select another one."),
-                tr("GPX Track has no time information"), JOptionPane.WARNING_MESSAGE);
-            return;
-        }
-
-        // seconds
-        long diff = (yLayer.hasTimeoffset)
-            ? yLayer.timeoffset
-            : firstExifDate - firstGPXDate;
-        yLayer.timeoffset = diff;
-        yLayer.hasTimeoffset = true;
-
-        double diffInH = (double)diff/(60*60);    // hours
-
-        // Find day difference
-        dayOffset = (int)Math.round(diffInH / 24); // days
-        double timezone = diff - dayOffset*24*60*60;  // seconds
-
-        // In hours, rounded to two decimal places
-        timezone = (double)Math.round(timezone*100/(60*60)) / 100;
-
-        // Due to imprecise clocks we might get a "+3:28" timezone, which should obviously be 3:30 with
-        // -2 minutes offset. This determines the real timezone and finds offset.
-        double fixTimezone = (double)Math.round(timezone * 2)/2; // hours, rounded to one decimal place
-        int offset = (int)Math.round(diff - fixTimezone*60*60) - dayOffset*24*60*60; // seconds
-
-        /*System.out.println("phto " + firstExifDate);
-        System.out.println("gpx  " + firstGPXDate);
-        System.out.println("diff " + diff);
-        System.out.println("difh " + diffInH);
-        System.out.println("days " + dayOffset);
-        System.out.println("time " + timezone);
-        System.out.println("fix  " + fixTimezone);
-        System.out.println("offt " + offset);*/
-
-        // This is called whenever one of the sliders is moved.
-        // It updates the labels and also calls the "match photos" code
-        class sliderListener implements ChangeListener {
-            public void stateChanged(ChangeEvent e) {
-                // parse slider position into real timezone
-                double tz = Math.abs(sldTimezone.getValue());
-                String zone = tz % 2 == 0
-                    ? (int)Math.floor(tz/2) + ":00"
-                    : (int)Math.floor(tz/2) + ":30";
-                if(sldTimezone.getValue() < 0) zone = "-" + zone;
-
-                lblTimezone.setText(tr("Timezone: {0}", zone));
-                lblMinutes.setText(tr("Minutes: {0}", sldMinutes.getValue()));
-                lblSeconds.setText(tr("Seconds: {0}", sldSeconds.getValue()));
-
-                float gpstimezone = parseTimezone(zone).floatValue();
-
-                // Reset previous position
-                for(ImageEntry x : autoImgs) {
-                    x.pos = null;
-                }
-
-                long timediff = (long) (gpstimezone * 3600)
-                        + dayOffset*24*60*60
-                        + sldMinutes.getValue()*60
-                        + sldSeconds.getValue();
-
-                int matched = matchGpxTrack(autoImgs, autoGpx, timediff);
-
-                lblMatches.setText(
-                    tr("Matched {0} of {1} photos to GPX track.", matched, autoImgs.size())
-                    + ((Math.abs(dayOffset) == 0)
-                        ? ""
-                        : " " + tr("(Time difference of {0} days)", Math.abs(dayOffset))
-                      )
-                );
-
-                int offset = (int)(firstGPXDate+timediff-firstExifDate);
-                int o = Math.abs(offset);
-                lblOffset.setText(
-                    tr("Offset between track and photos: {0}m {1}s",
-                          (offset < 0 ? "-" : "") + Long.toString(Math.round(o/60)),
-                          Long.toString(Math.round(o%60))
-                    )
-                );
-
-                yLayer.timeoffset = timediff;
-                Main.main.map.repaint();
-            }
-        }
-
-        // Info Labels
-        lblMatches = new JLabel();
-        lblOffset = new JLabel();
-
-        // Timezone Slider
-        // The slider allows to switch timezon from -12:00 to 12:00 in 30 minutes
-        // steps. Therefore the range is -24 to 24.
-        lblTimezone = new JLabel();
-        sldTimezone = new JSlider(-24, 24, 0);
-        sldTimezone.setPaintLabels(true);
-        Hashtable<Integer,JLabel> labelTable = new Hashtable<Integer, JLabel>();
-        labelTable.put(-24, new JLabel("-12:00"));
-        labelTable.put(-12, new JLabel( "-6:00"));
-        labelTable.put(  0, new JLabel(  "0:00"));
-        labelTable.put( 12, new JLabel(  "6:00"));
-        labelTable.put( 24, new JLabel( "12:00"));
-        sldTimezone.setLabelTable(labelTable);
-
-        // Minutes Slider
-        lblMinutes = new JLabel();
-        sldMinutes = new JSlider(-15, 15, 0);
-        sldMinutes.setPaintLabels(true);
-        sldMinutes.setMajorTickSpacing(5);
-
-        // Seconds slider
-        lblSeconds = new JLabel();
-        sldSeconds = new JSlider(-60, 60, 0);
-        sldSeconds.setPaintLabels(true);
-        sldSeconds.setMajorTickSpacing(30);
-
-        // Put everything together
-        JPanel p = new JPanel(new GridBagLayout());
-        p.setPreferredSize(new Dimension(400, 230));
-        p.add(lblMatches, GBC.eol().fill());
-        p.add(lblOffset, GBC.eol().fill().insets(0, 0, 0, 10));
-        p.add(lblTimezone, GBC.eol().fill());
-        p.add(sldTimezone, GBC.eol().fill().insets(0, 0, 0, 10));
-        p.add(lblMinutes, GBC.eol().fill());
-        p.add(sldMinutes, GBC.eol().fill().insets(0, 0, 0, 10));
-        p.add(lblSeconds, GBC.eol().fill());
-        p.add(sldSeconds, GBC.eol().fill());
-
-        // If there's an error in the calculation the found values
-        // will be off range for the sliders. Catch this error
-        // and inform the user about it.
-        try {
-            sldTimezone.setValue((int)(fixTimezone*2));
-            sldMinutes.setValue(offset/60);
-            sldSeconds.setValue(offset%60);
-        } catch(Exception e) {
-            JOptionPane.showMessageDialog(Main.parent,
-                tr("An error occurred while trying to match the photos to the GPX track."
-                    +" You can adjust the sliders to manually match the photos."),
-                tr("Matching photos to track failed"),
-                JOptionPane.WARNING_MESSAGE);
-        }
-
-        // Call the sliderListener once manually so labels get adjusted
-        new sliderListener().stateChanged(null);
-        // Listeners added here, otherwise it tries to match three times
-        // (when setting the default values)
-        sldTimezone.addChangeListener(new sliderListener());
-        sldMinutes.addChangeListener(new sliderListener());
-        sldSeconds.addChangeListener(new sliderListener());
-
-        // There is no way to cancel this dialog, all changes get applied
-        // immediately. Therefore "Close" is marked with an "OK" icon.
-        // Settings are only saved temporarily to the layer.
-        ExtendedDialog d = new ExtendedDialog(Main.parent,
-            tr("Adjust timezone and offset"),
-            new String[] { tr("Close"),  tr("Default Values") }
-        );
-
-        d.setContent(p);
-        d.setButtonIcons(new String[] { "ok.png", "dialogs/refresh.png"});
-        d.showDialog();
-        int answer = d.getValue();
-        // User wants default values; discard old result and re-open dialog
-        if(answer == 2) {
-            yLayer.hasTimeoffset = false;
-            autoGuess(gpx);
-        }
-    }
-
-    /**
-     * Returns a list of images that fulfill the given criteria.
-     * Default setting is to return untagged images, but may be overwritten.
-     * @param boolean all -- returns all available images
-     * @param boolean noexif -- returns untagged images without EXIF-GPS coords
-     * @return ArrayList<ImageEntry> matching images
-     */
-    private ArrayList<ImageEntry> getSortedImgList(boolean all, boolean noexif) {
-        ArrayList<ImageEntry> dateImgLst = new ArrayList<ImageEntry>(yLayer.data.size());
-        if (all) {
-            for (ImageEntry e : yLayer.data) {
-                if (e.time != null) {
-                    // Reset previous position
-                    e.pos = null;
-                    dateImgLst.add(e);
-                }
-            }
-
-        } else if (noexif) {
-            for (ImageEntry e : yLayer.data) {
-                if (e.time != null && e.exifCoor == null) {
-                    dateImgLst.add(e);
-                }
-            }
-
-        } else {
-            for (ImageEntry e : yLayer.data) {
-                if (e.time != null && e.pos == null) {
-                    dateImgLst.add(e);
-                }
-            }
-        }
-
-        Collections.sort(dateImgLst, new Comparator<ImageEntry>() {
-            public int compare(ImageEntry arg0, ImageEntry arg1) {
-                return arg0.time.compareTo(arg1.time);
-            }
-        });
-
-        return dateImgLst;
-    }
-
-    private int matchGpxTrack(ArrayList<ImageEntry> dateImgLst, GpxData selectedGpx, long offset) {
-        int ret = 0;
-
-        PrimaryDateParser dateParser = new PrimaryDateParser();
-
-        for (GpxTrack trk : selectedGpx.tracks) {
-            for (Collection<WayPoint> segment : trk.trackSegs) {
-
-                long prevDateWp = 0;
-                WayPoint prevWp = null;
-
-                for (WayPoint curWp : segment) {
-
-                    String curDateWpStr = (String) curWp.attr.get("time");
-                    if (curDateWpStr != null) {
-
-                        try {
-                            long curDateWp = dateParser.parse(curDateWpStr).getTime()/1000 + offset;
-                            ret += matchPoints(dateImgLst, prevWp, prevDateWp, curWp, curDateWp);
-
-                            prevWp = curWp;
-                            prevDateWp = curDateWp;
-
-                        } catch(ParseException e) {
-                            System.err.println("Error while parsing date \"" + curDateWpStr + '"');
-                            e.printStackTrace();
-                            prevWp = null;
-                            prevDateWp = 0;
-                        }
-                    } else {
-                        prevWp = null;
-                        prevDateWp = 0;
-                    }
-                }
-            }
-        }
-        return ret;
-    }
-
-    private int matchPoints(ArrayList<ImageEntry> dateImgLst, WayPoint prevWp, long prevDateWp,
-                                                                   WayPoint curWp, long curDateWp) {
-        // Time between the track point and the previous one, 5 sec if first point, i.e. photos take
-        // 5 sec before the first track point can be assumed to be take at the starting position
-        long interval = prevDateWp > 0 ? ((int)Math.abs(curDateWp - prevDateWp)) : 5;
-        int ret = 0;
-
-        // i is the index of the timewise last photo that has the same or earlier EXIF time
-        int i = getLastIndexOfListBefore(dateImgLst, curDateWp);
-
-        // no photos match
-        if (i < 0)
-            return 0;
-
-        Double speed = null;
-        Double prevElevation = null;
-        Double curElevation = null;
-
-        if (prevWp != null) {
-            double distance = prevWp.getCoor().greatCircleDistance(curWp.getCoor());
-            // This is in km/h, 3.6 * m/s
-            if (curDateWp > prevDateWp)
-                speed = 3.6 * distance / (curDateWp - prevDateWp);
-            try {
-                prevElevation = new Double((String) prevWp.attr.get("ele"));
-            } catch(Exception e) {}
-        }
-
-        try {
-            curElevation = new Double((String) curWp.attr.get("ele"));
-        } catch (Exception e) {}
-
-        // First trackpoint, then interval is set to five seconds, i.e. photos up to five seconds
-        // before the first point will be geotagged with the starting point
-        if(prevDateWp == 0 || curDateWp <= prevDateWp) {
-            while(i >= 0 && (dateImgLst.get(i).time.getTime()/1000) <= curDateWp
-                        && (dateImgLst.get(i).time.getTime()/1000) >= (curDateWp - interval)) {
-                if(dateImgLst.get(i).pos == null) {
-                    dateImgLst.get(i).setCoor(curWp.getCoor());
-                    dateImgLst.get(i).speed = speed;
-                    dateImgLst.get(i).elevation = curElevation;
-                    ret++;
-                }
-                i--;
-            }
-            return ret;
-        }
-
-        // This code gives a simple linear interpolation of the coordinates between current and
-        // previous track point assuming a constant speed in between
-        long imgDate;
-        while(i >= 0 && (imgDate = dateImgLst.get(i).time.getTime()/1000) >= prevDateWp) {
-
-            if(dateImgLst.get(i).pos == null) {
-                // The values of timeDiff are between 0 and 1, it is not seconds but a dimensionless
-                // variable
-                double timeDiff = (double)(imgDate - prevDateWp) / interval;
-                dateImgLst.get(i).setCoor(prevWp.getCoor().interpolate(curWp.getCoor(), timeDiff));
-                dateImgLst.get(i).speed = speed;
-
-                if (curElevation != null && prevElevation != null)
-                    dateImgLst.get(i).elevation = prevElevation + (curElevation - prevElevation) * timeDiff;
-
-                ret++;
-            }
-            i--;
-        }
-        return ret;
-    }
-
-    private int getLastIndexOfListBefore(ArrayList<ImageEntry> dateImgLst, long searchedDate) {
-        int lstSize= dateImgLst.size();
-
-        // No photos or the first photo taken is later than the search period
-        if(lstSize == 0 || searchedDate < dateImgLst.get(0).time.getTime()/1000)
-            return -1;
-
-        // The search period is later than the last photo
-        if (searchedDate > dateImgLst.get(lstSize - 1).time.getTime() / 1000)
-            return lstSize-1;
-
-        // The searched index is somewhere in the middle, do a binary search from the beginning
-        int curIndex= 0;
-        int startIndex= 0;
-        int endIndex= lstSize-1;
-        while (endIndex - startIndex > 1) {
-            curIndex= (int) Math.round((double)(endIndex + startIndex)/2);
-            if (searchedDate > dateImgLst.get(curIndex).time.getTime()/1000)
-                startIndex= curIndex;
-            else
-                endIndex= curIndex;
-        }
-        if (searchedDate < dateImgLst.get(endIndex).time.getTime()/1000)
-            return startIndex;
-
-        // This final loop is to check if photos with the exact same EXIF time follows
-        while ((endIndex < (lstSize-1)) && (dateImgLst.get(endIndex).time.getTime()
-                                                == dateImgLst.get(endIndex + 1).time.getTime()))
-            endIndex++;
-        return endIndex;
-    }
-
-
-    private String formatTimezone(double timezone) {
-        StringBuffer ret = new StringBuffer();
-
-        if (timezone < 0) {
-            ret.append('-');
-            timezone = -timezone;
-        } else {
-            ret.append('+');
-        }
-        ret.append((long) timezone).append(':');
-        int minutes = (int) ((timezone % 1) * 60);
-        if (minutes < 10) {
-            ret.append('0');
-        }
-        ret.append(minutes);
-
-        return ret.toString();
-    }
-
-    private Float parseTimezone(String timezone) {
-        if (timezone.length() == 0) {
-            return new Float(0);
-        }
-
-        char sgnTimezone = '+';
-        StringBuffer hTimezone = new StringBuffer();
-        StringBuffer mTimezone = new StringBuffer();
-        int state = 1; // 1=start/sign, 2=hours, 3=minutes.
-        for (int i = 0; i < timezone.length(); i++) {
-            char c = timezone.charAt(i);
-            switch (c) {
-            case ' ' :
-                if (state != 2 || hTimezone.length() != 0) {
-                    return null;
-                }
-                break;
-            case '+' :
-            case '-' :
-                if (state == 1) {
-                    sgnTimezone = c;
-                    state = 2;
-                } else {
-                    return null;
-                }
-                break;
-            case ':' :
-            case '.' :
-                if (state == 2) {
-                    state = 3;
-                } else {
-                    return null;
-                }
-                break;
-            case '0' : case '1' : case '2' : case '3' : case '4' :
-            case '5' : case '6' : case '7' : case '8' : case '9' :
-                switch(state) {
-                case 1 :
-                case 2 :
-                    state = 2;
-                    hTimezone.append(c);
-                    break;
-                case 3 :
-                    mTimezone.append(c);
-                    break;
-                default :
-                    return null;
-                }
-                break;
-            default :
-                return null;
-            }
-        }
-
-        int h = 0;
-        int m = 0;
-        try {
-            h = Integer.parseInt(hTimezone.toString());
-            if (mTimezone.length() > 0) {
-                m = Integer.parseInt(mTimezone.toString());
-            }
-        } catch (NumberFormatException nfe) {
-            // Invalid timezone
-            return null;
-        }
-
-        if (h > 12 || m > 59 ) {
-            return null;
-        } else {
-            return new Float((h + m / 60.0) * (sgnTimezone == '-' ? -1 : 1));
-        }
-    }
-}
diff --git a/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/ImageDisplay.java b/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/ImageDisplay.java
deleted file mode 100644
index 0bb96f0..0000000
--- a/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/ImageDisplay.java
+++ /dev/null
@@ -1,607 +0,0 @@
-// License: GPL. Copyright 2007 by Christian Gallioz (aka khris78)
-
-package org.openstreetmap.josm.plugins.agpifoj;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.Color;
-import java.awt.Dimension;
-import java.awt.FontMetrics;
-import java.awt.Graphics;
-import java.awt.Image;
-import java.awt.MediaTracker;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.Toolkit;
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseListener;
-import java.awt.event.MouseMotionListener;
-import java.awt.event.MouseWheelEvent;
-import java.awt.event.MouseWheelListener;
-import java.awt.geom.Rectangle2D;
-import java.io.File;
-
-import javax.swing.JComponent;
-
-public class ImageDisplay extends JComponent {
-
-    /** The file that is currently displayed */
-    private File file = null;
-
-    /** The image currently displayed */
-    private Image image = null;
-
-    /** The image currently displayed */
-    private boolean errorLoading = false;
-
-    /** The rectangle (in image coordinates) of the image that is visible. This rectangle is calculated
-     * each time the zoom is modified */
-    private Rectangle visibleRect = null;
-
-    /** When a selection is done, the rectangle of the selection (in image coordinates) */
-    private Rectangle selectedRect = null;
-
-    /** The tracker to load the images */
-    private MediaTracker tracker = new MediaTracker(this);
-
-    private String osdText = null;
-
-    /** The thread that reads the images. */
-    private class LoadImageRunnable implements Runnable {
-
-        File file = null;
-
-        public LoadImageRunnable(File file) {
-            this.file = file;
-        }
-
-        public void run() {
-            Image img = Toolkit.getDefaultToolkit().createImage(file.getPath());
-            tracker.addImage(img, 1);
-
-            // Wait for the end of loading
-            while (! tracker.checkID(1, true)) {
-                if (this.file != ImageDisplay.this.file) {
-                    // The file has changed
-                    tracker.removeImage(img);
-                    return;
-                }
-                try {
-                    Thread.sleep(5);
-                } catch (InterruptedException e) {
-                }
-            }
-
-            boolean error = tracker.isErrorID(1);
-            if (img != null && (img.getWidth(null) == 0 || img.getHeight(null) == 0)) {
-                error = true;
-            }
-
-            synchronized(ImageDisplay.this) {
-                if (this.file != ImageDisplay.this.file) {
-                    // The file has changed
-                    tracker.removeImage(img);
-                    return;
-                }
-                ImageDisplay.this.image = img;
-                visibleRect = new Rectangle(0, 0, img.getWidth(null), img.getHeight(null));
-                selectedRect = null;
-                errorLoading = error;
-            }
-            tracker.removeImage(img);
-            ImageDisplay.this.repaint();
-        }
-    }
-
-    private class ImgDisplayMouseListener implements MouseListener, MouseWheelListener, MouseMotionListener {
-
-        boolean mouseIsDragging = false;
-        long lastTimeForMousePoint = 0l;
-        Point mousePointInImg = null;
-
-        /** Zoom in and out, trying to preserve the point of the image that was under the mouse cursor
-         * at the same place */
-        public void mouseWheelMoved(MouseWheelEvent e) {
-            File file;
-            Image image;
-            Rectangle visibleRect;
-
-            synchronized (ImageDisplay.this) {
-                file = ImageDisplay.this.file;
-                image = ImageDisplay.this.image;
-                visibleRect = ImageDisplay.this.visibleRect;
-            }
-
-            mouseIsDragging = false;
-            selectedRect = null;
-
-            if (image == null) {
-                return;
-            }
-
-            // Calculate the mouse cursor position in image coordinates, so that we can center the zoom
-            // on that mouse position. 
-            // To avoid issues when the user tries to zoom in on the image borders, this point is not calculated 
-            // again if there was less than 1.5seconds since the last event.
-            System.out.println(e);
-            if (e.getWhen() - lastTimeForMousePoint > 1500 || mousePointInImg == null) {
-            	lastTimeForMousePoint = e.getWhen();
-                mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY());
-            }
-
-            // Applicate the zoom to the visible rectangle in image coordinates
-            if (e.getWheelRotation() > 0) {
-                visibleRect.width = visibleRect.width * 3 / 2;
-                visibleRect.height = visibleRect.height * 3 / 2;
-            } else {
-                visibleRect.width = visibleRect.width * 2 / 3;
-                visibleRect.height = visibleRect.height * 2 / 3;
-            }
-
-            // Check that the zoom doesn't exceed 2:1
-            if (visibleRect.width < getSize().width / 2) {
-                visibleRect.width = getSize().width / 2;
-            }
-            if (visibleRect.height < getSize().height / 2) {
-                visibleRect.height = getSize().height / 2;
-            }
-
-            // Set the same ratio for the visible rectangle and the display area
-            int hFact = visibleRect.height * getSize().width;
-            int wFact = visibleRect.width * getSize().height;
-            if (hFact > wFact) {
-                visibleRect.width = hFact / getSize().height;
-            } else {
-                visibleRect.height = wFact / getSize().width;
-            }
-
-            // The size of the visible rectangle is limited by the image size.
-            checkVisibleRectSize(image, visibleRect);
-
-            // Set the position of the visible rectangle, so that the mouse cursor doesn't move on the image.
-            Rectangle drawRect = calculateDrawImageRectangle(visibleRect);
-            visibleRect.x = mousePointInImg.x + ((drawRect.x - e.getX()) * visibleRect.width) / drawRect.width;
-            visibleRect.y = mousePointInImg.y + ((drawRect.y - e.getY()) * visibleRect.height) / drawRect.height;
-
-            // The position is also limited by the image size
-            checkVisibleRectPos(image, visibleRect);
-
-            synchronized(ImageDisplay.this) {
-                if (ImageDisplay.this.file == file) {
-                    ImageDisplay.this.visibleRect = visibleRect;
-                }
-            }
-            ImageDisplay.this.repaint();
-        }
-
-        /** Center the display on the point that has been clicked */
-        public void mouseClicked(MouseEvent e) {
-            // Move the center to the clicked point.
-            File file;
-            Image image;
-            Rectangle visibleRect;
-
-            synchronized (ImageDisplay.this) {
-                file = ImageDisplay.this.file;
-                image = ImageDisplay.this.image;
-                visibleRect = ImageDisplay.this.visibleRect;
-            }
-
-            if (image == null) {
-                return;
-            }
-
-            if (e.getButton() != 1) {
-                return;
-            }
-
-            // Calculate the translation to set the clicked point the center of the view.
-            Point click = comp2imgCoord(visibleRect, e.getX(), e.getY());
-            Point center = getCenterImgCoord(visibleRect);
-
-            visibleRect.x += click.x - center.x;
-            visibleRect.y += click.y - center.y;
-
-            checkVisibleRectPos(image, visibleRect);
-
-            synchronized(ImageDisplay.this) {
-                if (ImageDisplay.this.file == file) {
-                    ImageDisplay.this.visibleRect = visibleRect;
-                }
-            }
-            ImageDisplay.this.repaint();
-        }
-
-        /** Initialize the dragging, either with button 1 (simple dragging) or button 3 (selection of
-         * a picture part) */
-        public void mousePressed(MouseEvent e) {
-            if (image == null) {
-                mouseIsDragging = false;
-                selectedRect = null;
-                return;
-            }
-
-            File file;
-            Image image;
-            Rectangle visibleRect;
-
-            synchronized (ImageDisplay.this) {
-                file = ImageDisplay.this.file;
-                image = ImageDisplay.this.image;
-                visibleRect = ImageDisplay.this.visibleRect;
-            }
-
-            if (image == null) {
-                return;
-            }
-
-            if (e.getButton() == 1) {
-                mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY());
-                mouseIsDragging = true;
-                selectedRect = null;
-            } else if (e.getButton() == 3) {
-                mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY());
-                checkPointInVisibleRect(mousePointInImg, visibleRect);
-                mouseIsDragging = false;
-                selectedRect = new Rectangle(mousePointInImg.x, mousePointInImg.y, 0, 0);
-                ImageDisplay.this.repaint();
-            } else {
-                mouseIsDragging = false;
-                selectedRect = null;
-            }
-        }
-
-        public void mouseDragged(MouseEvent e) {
-            if (! mouseIsDragging && selectedRect == null) {
-                return;
-            }
-
-            File file;
-            Image image;
-            Rectangle visibleRect;
-
-            synchronized (ImageDisplay.this) {
-                file = ImageDisplay.this.file;
-                image = ImageDisplay.this.image;
-                visibleRect = ImageDisplay.this.visibleRect;
-            }
-
-            if (image == null) {
-                mouseIsDragging = false;
-                selectedRect = null;
-                return;
-            }
-
-            if (mouseIsDragging) {
-                Point p = comp2imgCoord(visibleRect, e.getX(), e.getY());
-                visibleRect.x += mousePointInImg.x - p.x;
-                visibleRect.y += mousePointInImg.y - p.y;
-                checkVisibleRectPos(image, visibleRect);
-                synchronized(ImageDisplay.this) {
-                    if (ImageDisplay.this.file == file) {
-                        ImageDisplay.this.visibleRect = visibleRect;
-                    }
-                }
-                ImageDisplay.this.repaint();
-
-            } else if (selectedRect != null) {
-                Point p = comp2imgCoord(visibleRect, e.getX(), e.getY());
-                checkPointInVisibleRect(p, visibleRect);
-                Rectangle rect = new Rectangle(
-                        (p.x < mousePointInImg.x ? p.x : mousePointInImg.x),
-                        (p.y < mousePointInImg.y ? p.y : mousePointInImg.y),
-                        (p.x < mousePointInImg.x ? mousePointInImg.x - p.x : p.x - mousePointInImg.x),
-                        (p.y < mousePointInImg.y ? mousePointInImg.y - p.y : p.y - mousePointInImg.y));
-                checkVisibleRectSize(image, rect);
-                checkVisibleRectPos(image, rect);
-                ImageDisplay.this.selectedRect = rect;
-                ImageDisplay.this.repaint();
-            }
-
-        }
-
-        public void mouseReleased(MouseEvent e) {
-            if (! mouseIsDragging && selectedRect == null) {
-                return;
-            }
-
-            File file;
-            Image image;
-            Rectangle visibleRect;
-
-            synchronized (ImageDisplay.this) {
-                file = ImageDisplay.this.file;
-                image = ImageDisplay.this.image;
-                visibleRect = ImageDisplay.this.visibleRect;
-            }
-
-            if (image == null) {
-                mouseIsDragging = false;
-                selectedRect = null;
-                return;
-            }
-
-            if (mouseIsDragging) {
-                mouseIsDragging = false;
-
-            } else if (selectedRect != null) {
-                int oldWidth = selectedRect.width;
-                int oldHeight = selectedRect.height;
-
-                // Check that the zoom doesn't exceed 2:1
-                if (selectedRect.width < getSize().width / 2) {
-                    selectedRect.width = getSize().width / 2;
-                }
-                if (selectedRect.height < getSize().height / 2) {
-                    selectedRect.height = getSize().height / 2;
-                }
-
-                // Set the same ratio for the visible rectangle and the display area
-                int hFact = selectedRect.height * getSize().width;
-                int wFact = selectedRect.width * getSize().height;
-                if (hFact > wFact) {
-                    selectedRect.width = hFact / getSize().height;
-                } else {
-                    selectedRect.height = wFact / getSize().width;
-                }
-
-                // Keep the center of the selection
-                if (selectedRect.width != oldWidth) {
-                    selectedRect.x -= (selectedRect.width - oldWidth) / 2;
-                }
-                if (selectedRect.height != oldHeight) {
-                    selectedRect.y -= (selectedRect.height - oldHeight) / 2;
-                }
-
-                checkVisibleRectSize(image, selectedRect);
-                checkVisibleRectPos(image, selectedRect);
-
-                synchronized (ImageDisplay.this) {
-                    if (file == ImageDisplay.this.file) {
-                        ImageDisplay.this.visibleRect = selectedRect;
-                    }
-                }
-                selectedRect = null;
-                ImageDisplay.this.repaint();
-            }
-        }
-
-        public void mouseEntered(MouseEvent e) {
-        }
-
-        public void mouseExited(MouseEvent e) {
-        }
-
-        public void mouseMoved(MouseEvent e) {
-        }
-
-        private void checkPointInVisibleRect(Point p, Rectangle visibleRect) {
-            if (p.x < visibleRect.x) {
-                p.x = visibleRect.x;
-            }
-            if (p.x > visibleRect.x + visibleRect.width) {
-                p.x = visibleRect.x + visibleRect.width;
-            }
-            if (p.y < visibleRect.y) {
-                p.y = visibleRect.y;
-            }
-            if (p.y > visibleRect.y + visibleRect.height) {
-                p.y = visibleRect.y + visibleRect.height;
-            }
-        }
-    }
-
-    public ImageDisplay() {
-        ImgDisplayMouseListener mouseListener = new ImgDisplayMouseListener();
-        addMouseListener(mouseListener);
-        addMouseWheelListener(mouseListener);
-        addMouseMotionListener(mouseListener);
-    }
-
-    public void setImage(File file) {
-        synchronized(this) {
-            this.file = file;
-            image = null;
-            selectedRect = null;
-            errorLoading = false;
-        }
-        repaint();
-        if (file != null) {
-            new Thread(new LoadImageRunnable(file)).start();
-        }
-    }
-
-    public void setOsdText(String text) {
-        this.osdText = text;
-    }
-
-    public void paintComponent(Graphics g) {
-        Image image;
-        File file;
-        Rectangle visibleRect;
-        boolean errorLoading;
-
-        synchronized(this) {
-            image = this.image;
-            file = this.file;
-            visibleRect = this.visibleRect;
-            errorLoading = this.errorLoading;
-        }
-
-        if (file == null) {
-            g.setColor(Color.black);
-            String noImageStr = tr("No image");
-            Rectangle2D noImageSize = g.getFontMetrics(g.getFont()).getStringBounds(noImageStr, g);
-            Dimension size = getSize();
-            g.drawString(noImageStr,
-                         (int) ((size.width - noImageSize.getWidth()) / 2),
-                         (int) ((size.height - noImageSize.getHeight()) / 2));
-        } else if (image == null) {
-            g.setColor(Color.black);
-            String loadingStr;
-            if (! errorLoading) {;
-                loadingStr = tr("Loading {0}", file.getName());
-            } else {
-                loadingStr = tr("Error on file {0}", file.getName());
-            }
-            Rectangle2D noImageSize = g.getFontMetrics(g.getFont()).getStringBounds(loadingStr, g);
-            Dimension size = getSize();
-            g.drawString(loadingStr,
-                         (int) ((size.width - noImageSize.getWidth()) / 2),
-                         (int) ((size.height - noImageSize.getHeight()) / 2));
-        } else {
-            Rectangle target = calculateDrawImageRectangle(visibleRect);
-            g.drawImage(image,
-                        target.x, target.y, target.x + target.width, target.y + target.height,
-                        visibleRect.x, visibleRect.y, visibleRect.x + visibleRect.width, visibleRect.y + visibleRect.height,
-                        null);
-            if (selectedRect != null) {
-                Point topLeft = img2compCoord(visibleRect, selectedRect.x, selectedRect.y);
-                Point bottomRight = img2compCoord(visibleRect,
-                                                  selectedRect.x + selectedRect.width,
-                                                  selectedRect.y + selectedRect.height);
-                g.setColor(new Color(128, 128, 128, 180));
-                g.fillRect(target.x, target.y, target.width, topLeft.y - target.y);
-                g.fillRect(target.x, target.y, topLeft.x - target.x, target.height);
-                g.fillRect(bottomRight.x, target.y, target.x + target.width - bottomRight.x, target.height);
-                g.fillRect(target.x, bottomRight.y, target.width, target.y + target.height - bottomRight.y);
-                g.setColor(Color.black);
-                g.drawRect(topLeft.x, topLeft.y, bottomRight.x - topLeft.x, bottomRight.y - topLeft.y);
-            }
-            if (errorLoading) {
-                String loadingStr = tr("Error on file {0}", file.getName());
-                Rectangle2D noImageSize = g.getFontMetrics(g.getFont()).getStringBounds(loadingStr, g);
-                Dimension size = getSize();
-                g.drawString(loadingStr,
-                             (int) ((size.width - noImageSize.getWidth()) / 2),
-                             (int) ((size.height - noImageSize.getHeight()) / 2));
-            }
-            if (osdText != null) {
-                FontMetrics metrics = g.getFontMetrics(g.getFont());
-                int ascent = metrics.getAscent();
-                Color bkground = new Color(255, 255, 255, 128);
-                int lastPos = 0;
-                int pos = osdText.indexOf("\n");
-                int x = 3;
-                int y = 3;
-                String line;
-                while (pos > 0) {
-                    line = osdText.substring(lastPos, pos);
-                    Rectangle2D lineSize = metrics.getStringBounds(line, g);
-                    g.setColor(bkground);
-                    g.fillRect(x, y, (int) lineSize.getWidth(), (int) lineSize.getHeight());
-                    g.setColor(Color.black);
-                    g.drawString(line, x, y + ascent);
-                    y += (int) lineSize.getHeight();
-                    lastPos = pos + 1;
-                    pos = osdText.indexOf("\n", lastPos);
-                }
-
-                line = osdText.substring(lastPos);
-                Rectangle2D lineSize = g.getFontMetrics(g.getFont()).getStringBounds(line, g);
-                g.setColor(bkground);
-                g.fillRect(x, y, (int) lineSize.getWidth(), (int) lineSize.getHeight());
-                g.setColor(Color.black);
-                g.drawString(line, x, y + ascent);
-            }
-        }
-    }
-
-    private final Point img2compCoord(Rectangle visibleRect, int xImg, int yImg) {
-        Rectangle drawRect = calculateDrawImageRectangle(visibleRect);
-        return new Point(drawRect.x + ((xImg - visibleRect.x) * drawRect.width) / visibleRect.width,
-                         drawRect.y + ((yImg - visibleRect.y) * drawRect.height) / visibleRect.height);
-    }
-
-    private final Point comp2imgCoord(Rectangle visibleRect, int xComp, int yComp) {
-        Rectangle drawRect = calculateDrawImageRectangle(visibleRect);
-        return new Point(visibleRect.x + ((xComp - drawRect.x) * visibleRect.width) / drawRect.width,
-                         visibleRect.y + ((yComp - drawRect.y) * visibleRect.height) / drawRect.height);
-    }
-
-   private final Point getCenterImgCoord(Rectangle visibleRect) {
-        return new Point(visibleRect.x + visibleRect.width / 2,
-                                 visibleRect.y + visibleRect.height / 2);
-    }
-
-    private Rectangle calculateDrawImageRectangle(Rectangle visibleRect) {
-        Dimension size = getSize();
-        int x, y, w, h;
-        x = 0;
-        y = 0;
-        w = size.width;
-        h = size.height;
-
-        int wFact = w * visibleRect.height;
-        int hFact = h * visibleRect.width;
-        if (wFact != hFact) {
-            if (wFact > hFact) {
-                w = hFact / visibleRect.height;
-                x = (size.width - w) / 2;
-            } else {
-                h = wFact / visibleRect.width;
-                y = (size.height - h) / 2;
-            }
-        }
-        return new Rectangle(x, y, w, h);
-    }
-
-    public void zoomBestFitOrOne() {
-        File file;
-        Image image;
-        Rectangle visibleRect;
-
-        synchronized (this) {
-            file = ImageDisplay.this.file;
-            image = ImageDisplay.this.image;
-            visibleRect = ImageDisplay.this.visibleRect;
-        }
-
-        if (image == null) {
-            return;
-        }
-
-        if (visibleRect.width != image.getWidth(null) || visibleRect.height != image.getHeight(null)) {
-            // The display is not at best fit. => Zoom to best fit
-            visibleRect = new Rectangle(0, 0, image.getWidth(null), image.getHeight(null));
-
-        } else {
-            // The display is at best fit => zoom to 1:1
-            Point center = getCenterImgCoord(visibleRect);
-            visibleRect = new Rectangle(center.x - getWidth() / 2, center.y - getHeight() / 2,
-                                        getWidth(), getHeight());
-            checkVisibleRectPos(image, visibleRect);
-        }
-
-        synchronized(this) {
-            if (file == this.file) {
-                this.visibleRect = visibleRect;
-            }
-        }
-        repaint();
-    }
-
-    private final void checkVisibleRectPos(Image image, Rectangle visibleRect) {
-        if (visibleRect.x < 0) {
-            visibleRect.x = 0;
-        }
-        if (visibleRect.y < 0) {
-            visibleRect.y = 0;
-        }
-        if (visibleRect.x + visibleRect.width > image.getWidth(null)) {
-            visibleRect.x = image.getWidth(null) - visibleRect.width;
-        }
-        if (visibleRect.y + visibleRect.height > image.getHeight(null)) {
-            visibleRect.y = image.getHeight(null) - visibleRect.height;
-        }
-    }
-
-    private void checkVisibleRectSize(Image image, Rectangle visibleRect) {
-        if (visibleRect.width > image.getWidth(null)) {
-            visibleRect.width = image.getWidth(null);
-        }
-        if (visibleRect.height > image.getHeight(null)) {
-            visibleRect.height = image.getHeight(null);
-        }
-    }
-}
\ No newline at end of file
diff --git a/cadastre-fr/build.xml b/cadastre-fr/build.xml
index 78ae672..ec7cc5c 100644
--- a/cadastre-fr/build.xml
+++ b/cadastre-fr/build.xml
@@ -1,9 +1,40 @@
+<!--
+** This is a template build file for the cadastre-fr plugin.
+**
+** Maintaining versions
+** ====================
+** see README.template
+**
+** Usage
+** =====
+** To build it run
+**
+**    > ant  dist
+**
+** To install the generated plugin locally (in your default plugin directory) run
+**
+**    > ant  install
+**
+** To build against the core in ../../core, create a correct manifest and deploy to
+** SVN, 
+**    set the properties commit.message and plugin.main.version
+** and run
+**    > ant  publish
+**
+**
+-->
 <project name="cadastre-fr" 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"/>
+	
+	
+
+	<property name="commit.message" value="Changed constructor for Plugin" />
+	<property name="plugin.main.version" value="2830" />
+	
     <target name="init">
         <mkdir dir="${plugin.build.dir}"/>
     </target>
@@ -25,7 +56,7 @@
                 <attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
                 <attribute name="Plugin-Description" value="A special handler for the French land registry WMS server."/>
                 <attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/wiki/FR:JOSM/Fr:Plugin/Cadastre"/>
-                <attribute name="Plugin-Mainversion" value="2509"/>
+                <attribute name="Plugin-Mainversion" value="${plugin.main.version}"/>
                 <attribute name="Plugin-Stage" value="60"/>
                 <attribute name="Plugin-Version" value="${version.entry.commit.revision}"/>
             </manifest>
@@ -54,4 +85,81 @@
         </condition>
         <copy file="${plugin.jar}" todir="${josm.plugins.dir}"/>
     </target>
+	
+	<!--
+		 ************************** Publishing the plugin *********************************** 
+		-->
+			<!--
+			  ** extracts the JOSM release for the JOSM version in ../core and saves it in the 
+			  ** property ${coreversion.info.entry.revision}
+			  **
+			-->
+			<target name="core-info">
+		        <exec append="false" output="core.info.xml" executable="svn" failifexecutionfails="false">
+		                    <env key="LANG" value="C"/>
+		                    <arg value="info"/>
+		                    <arg value="--xml"/>
+		                    <arg value="../../core"/>
+		        </exec>
+		        <xmlproperty file="core.info.xml" prefix="coreversion" keepRoot="true" collapseAttributes="true"/>
+				<echo>Building against core revision ${coreversion.info.entry.revision}.</echo>			
+				<echo>Plugin-Mainversion is set to ${plugin.main.version}.</echo>
+				<delete file="core.info.xml" />
+			</target>
+
+			<!--
+			 ** commits the source tree for this plugin
+			-->
+			<target name="commit-current">
+				<echo>Commiting the plugin source with message '${commit.message}' ...</echo>
+			    <exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			                    <env key="LANG" value="C"/>
+			                    <arg value="commit"/>
+			                    <arg value="-m '${commit.message}'"/>
+			                    <arg value="."/>
+			    </exec>	    
+			</target>
+
+			<!--
+			** updates (svn up) the source tree for this plugin
+			-->
+			<target name="update-current">
+				<echo>Updating plugin source ...</echo>
+			    <exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			                    <env key="LANG" value="C"/>
+			                    <arg value="up"/>
+			                    <arg value="."/>
+			    </exec>	    
+				<echo>Updating ${plugin.jar} ...</echo>
+			    <exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			                    <env key="LANG" value="C"/>
+			                    <arg value="up"/>
+			                    <arg value="../dist/${plugin.jar}"/>
+			    </exec>	    
+			</target>
+			
+			<!--
+			 ** commits the plugin.jar 
+			 -->
+			<target name="commit-dist">
+					<echo>
+	***** Properties of published ${plugin.jar} *****
+	Commit message    : '${commit.message}'					
+	Plugin-Mainversion: ${plugin.main.version}
+	JOSM build version: ${coreversion.info.entry.revision}
+	Plugin-Version    : ${version.entry.commit.revision}
+	***** / Properties of published ${plugin.jar} *****					
+						
+	Now commiting ${plugin.jar} ...
+	</echo>					
+				    <exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+				                    <env key="LANG" value="C"/>
+					    			<arg value="-m '${commit.message}'"/>
+				    				<arg value="commit"/>	                			
+	            			        <arg value="${plugin.jar}"/>
+				    </exec>	    
+		   	</target>
+					
+			<target name="publish" depends="core-info,commit-current,update-current,clean,dist,commit-dist">
+			</target>
 </project>
diff --git a/cadastre-fr/images/cursor/modifier/move.png b/cadastre-fr/images/cursor/modifier/move.png
new file mode 100644
index 0000000..54a0b84
Binary files /dev/null and b/cadastre-fr/images/cursor/modifier/move.png differ
diff --git a/cadastre-fr/src/cadastre_fr/CacheControl.java b/cadastre-fr/src/cadastre_fr/CacheControl.java
index 9ace78e..1268bd5 100644
--- a/cadastre-fr/src/cadastre_fr/CacheControl.java
+++ b/cadastre-fr/src/cadastre_fr/CacheControl.java
@@ -48,6 +48,13 @@ public class CacheControl implements Runnable {
     private ArrayList<GeorefImage> imagesToSave = new ArrayList<GeorefImage>();
     private Lock imagesLock = new ReentrantLock();
 
+    public boolean isCachePipeEmpty() {
+        imagesLock.lock();
+        boolean ret = imagesToSave.isEmpty();
+        imagesLock.unlock();
+        return ret;
+    }
+    
     public CacheControl(WMSLayer wmsLayer) {
         cacheEnabled = Main.pref.getBoolean("cadastrewms.enableCaching", true);
         this.wmsLayer = wmsLayer;
@@ -170,11 +177,10 @@ public class CacheControl implements Runnable {
     public synchronized void run() {
         for (;;) {
             imagesLock.lock();
-            // copy locally the images to save for better performance
-            ArrayList<GeorefImage> images = new ArrayList<GeorefImage>(imagesToSave);
-            imagesToSave.clear();
+            //ArrayList<GeorefImage> images = new ArrayList<GeorefImage>(imagesToSave);
+            int size = imagesToSave.size();
             imagesLock.unlock();
-            if (images != null && !images.isEmpty()) {
+            if (size > 0) {
                 String extension = String.valueOf((wmsLayer.getLambertZone() + 1));
                 if (Main.proj instanceof LambertCC9Zones)
                     extension = cLambertCC9Z + extension;
@@ -185,22 +191,27 @@ public class CacheControl implements Runnable {
                     if (file.exists()) {
                         ObjectOutputStreamAppend oos = new ObjectOutputStreamAppend(
                                 new BufferedOutputStream(new FileOutputStream(file, true)));
-                        for (GeorefImage img : images) {
-                            oos.writeObject(img);
+                        for (int i=0; i < size; i++) {
+                            oos.writeObject(imagesToSave.get(i));
                         }
                         oos.close();
                     } else {
                         ObjectOutputStream oos = new ObjectOutputStream(
                                 new BufferedOutputStream(new FileOutputStream(file)));
                         wmsLayer.write(oos);
-                        for (GeorefImage img : images) {
-                            oos.writeObject(img);
+                        for (int i=0; i < size; i++) {
+                            oos.writeObject(imagesToSave.get(i));
                         }
                         oos.close();
                     }
                 } catch (IOException e) {
                     e.printStackTrace(System.out);
                 }
+                imagesLock.lock();
+                for (int i=0; i < size; i++) {
+                    imagesToSave.remove(0);
+                }
+                imagesLock.unlock();
             }
             try {wait();} catch (InterruptedException e) {
                 e.printStackTrace(System.out);
diff --git a/cadastre-fr/src/cadastre_fr/CadastreGrabber.java b/cadastre-fr/src/cadastre_fr/CadastreGrabber.java
index aad2577..4c4b726 100644
--- a/cadastre-fr/src/cadastre_fr/CadastreGrabber.java
+++ b/cadastre-fr/src/cadastre_fr/CadastreGrabber.java
@@ -19,8 +19,6 @@ import org.openstreetmap.josm.io.ProgressInputStream;
 
 public class CadastreGrabber {
 
-    public final static double epsilon = 1e-11;
-
     private CadastreInterface wmsInterface = new CadastreInterface();
 
     public GeorefImage grab(WMSLayer wmsLayer, EastNorth lambertMin, EastNorth lambertMax) throws IOException, OsmTransferException {
@@ -45,14 +43,14 @@ public class CadastreGrabber {
 
     private URL getURLRaster(WMSLayer wmsLayer, EastNorth lambertMin, EastNorth lambertMax) throws MalformedURLException {
         // GET /scpc/wms?version=1.1&request=GetMap&layers=CDIF:PMC at QH4480001701&format=image/png&bbox=-1186,0,13555,8830&width=576&height=345&exception=application/vnd.ogc.se_inimage&styles= HTTP/1.1
-        final int cRasterX = 1000; // keep width constant and adjust width to original image proportions
+        final int cRasterX = CadastrePlugin.imageWidth; // keep width constant and adjust width to original image proportions
         String str = new String(wmsInterface.baseURL+"/scpc/wms?version=1.1&request=GetMap");
         str += "&layers=CDIF:PMC@";
         str += wmsLayer.getCodeCommune();
         str += "&format=image/png";
         str += "&bbox=";
         str += wmsLayer.eastNorth2raster(lambertMin, lambertMax);
-        //str += "&width=800&height=800"; // maximum allowed by wms server
+        //str += "&width=1000&height=800"; // maximum allowed by wms server
         str += "&width="+cRasterX+"&height="; // maximum allowed by wms server (576/345, 800/378, 1000/634)
         str += (int)(cRasterX*(wmsLayer.communeBBox.max.getY() - wmsLayer.communeBBox.min.getY())/(wmsLayer.communeBBox.max.getX() - wmsLayer.communeBBox.min.getX()));
         str += "&exception=application/vnd.ogc.se_inimage&styles=";
@@ -61,24 +59,16 @@ public class CadastreGrabber {
 
     private URL getURLVector(EastNorth lambertMin, EastNorth lambertMax) throws MalformedURLException {
         String str = new String(wmsInterface.baseURL+"/scpc/wms?version=1.1&request=GetMap");
-        str += "&layers=CDIF:LS3,CDIF:LS2,CDIF:LS1,CDIF:PARCELLE,CDIF:NUMERO";
-        str += ",CDIF:PT3,CDIF:PT2,CDIF:PT1,CDIF:LIEUDIT";
-        str += ",CDIF:SUBSECTION";
-        str += ",CDIF:SECTION";
-        str += ",CDIF:COMMUNE";
+        str += "&layers="+CadastrePlugin.grabLayers;
         str += "&format=image/png";
         //str += "&format=image/jpeg";
         str += "&bbox="+lambertMin.east()+",";
         str += lambertMin.north() + ",";
         str += lambertMax.east() + ",";
         str += lambertMax.north();
-        //str += "&width=800&height=600"; // maximum allowed by wms server
-        str += "&width=1000&height=800"; // maximum allowed by wms server
+        str += "&width="+CadastrePlugin.imageWidth+"&height="+CadastrePlugin.imageHeight;
         //str += "&exception=application/vnd.ogc.se_inimage"; // used by normal client but not required
-        str += "&styles=LS3_90,LS2_90,LS1_90,PARCELLE_90,NUMERO_90,PT3_90,PT2_90,PT1_90,LIEUDIT_90";
-        str += ",SUBSECTION_90";
-        str += ",SECTION_90";
-        str += ",COMMUNE_90";
+        str += "&styles="+CadastrePlugin.grabStyles;
         System.out.println("URL="+str);
         return new URL(str.replace(" ", "%20"));
     }
diff --git a/cadastre-fr/src/cadastre_fr/CadastreInterface.java b/cadastre-fr/src/cadastre_fr/CadastreInterface.java
index b030d7e..58c261c 100644
--- a/cadastre-fr/src/cadastre_fr/CadastreInterface.java
+++ b/cadastre-fr/src/cadastre_fr/CadastreInterface.java
@@ -11,6 +11,7 @@ import java.io.OutputStream;
 import java.net.HttpURLConnection;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.util.Date;
 import java.util.Vector;
 
 import javax.swing.JComboBox;
@@ -42,6 +43,7 @@ public class CadastreInterface {
         }
     }
     private Vector<PlanImage> listOfFeuilles = new Vector<PlanImage>();
+    private long cookieTimestamp;
 
     final String baseURL = "http://www.cadastre.gouv.fr";
     final String cImageFormat = "Cette commune est au format ";
@@ -50,63 +52,79 @@ public class CadastreInterface {
     final String c0ptionListStart = "<option value=\"";
     final String cOptionListEnd = "</option>";
     final String cBBoxCommunStart = "new GeoBox(";
-    final String cBBoxCommunEnd = ")";
+    final String cBBoxCommunEnd = ")";    
 
     final String cInterfaceVector = "afficherCarteCommune.do";
     final String cInterfaceRasterTA = "afficherCarteTa.do";
     final String cInterfaceRasterFeuille = "afficherCarteFeuille.do";
     final String cImageLinkStart = "title=\"image\"><a href=\"#\" onClick=\"popup('afficherCarteFeuille.do?f=";
     final String cImageNameStart = ">Feuille ";
+    
+    final static long cCookieExpiration = 30 * 60 * 1000; // 30 minutes expressed in milliseconds
+
+    final  int cRetriesGetCookie = 10; // 10 times every 3 seconds means 30 seconds trying to get a cookie
 
     public boolean retrieveInterface(WMSLayer wmsLayer) throws DuplicateLayerException {
         if (wmsLayer.getName().equals(""))
             return false;
+        if (wmsLayer.getName().equals(lastWMSLayerName))
+            return true;
         // open the session with the French Cadastre web front end
         downloadCancelled = false;
         try {
-            if (cookie == null || !wmsLayer.getName().equals(lastWMSLayerName)) {
+            if (cookie == null || isCookieExpired())
                 getCookie();
-                getInterface(wmsLayer);
-                this.lastWMSLayerName = wmsLayer.getName();
+            if (cookie != null && interfaceRef == null) {
+                    getInterface(wmsLayer);
+                    this.lastWMSLayerName = wmsLayer.getName();
+            } else {
+                JOptionPane.showMessageDialog(Main.parent,
+                        tr("Cannot open a new client session.\nServer in maintenance or temporary overloaded."));
+                return false;
             }
             openInterface();
         } catch (IOException e) {
-            /*JOptionPane.showMessageDialog(Main.parent,
+            JOptionPane.showMessageDialog(Main.parent,
                     tr("Town/city {0} not found or not available\n" +
-                            "or action canceled", wmsLayer.getLocation()));*/
-            JOptionPane pane = new JOptionPane(
-                    tr("Town/city {0} not found or not available\n" +
-                            "or action canceled", wmsLayer.getLocation()),
-                            JOptionPane.INFORMATION_MESSAGE);
-            // this below is a temporary workaround to fix the "always on top" issue
-            JDialog dialog = pane.createDialog(Main.parent, tr("Select commune"));
-            CadastrePlugin.prepareDialog(dialog);
-            dialog.setVisible(true);
-            // till here
+                            "or action canceled", wmsLayer.getLocation()));
             return false;
         }
         return true;
     }
 
+    /**
+     * 
+     * @return true if a cookie is delivered by WMS and false is WMS is not opening a client session
+     *         (too many clients or in maintenance)
+     * @throws IOException
+     */
     private void getCookie() throws IOException {
+        boolean cookied = false;
+        int retries = cRetriesGetCookie;
         try {
-            // first, get the cookie from Cadastre to allow next downloads
-            searchFormURL = new URL(baseURL + "/scpc/rechercherPlan.do");
-            urlConn = (HttpURLConnection)searchFormURL.openConnection();
-            urlConn.setRequestMethod("GET");
-            urlConn.connect();
-            if (urlConn.getResponseCode() != HttpURLConnection.HTTP_OK) {
-                throw new IOException("Cannot get Cadastre cookie.");
-            }
-            System.out.println("GET "+searchFormURL);
-            BufferedReader in = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
-            while(in.readLine() != null) {}  // read the buffer otherwise we sent POST too early
-            String headerName=null;
-            for (int i=1; (headerName = urlConn.getHeaderFieldKey(i))!=null; i++) {
-                if (headerName.equals("Set-Cookie")) {
-                    cookie = urlConn.getHeaderField(i);
-                    cookie = cookie.substring(0, cookie.indexOf(";"));
-                    System.out.println("Cookie="+cookie);
+            searchFormURL = new URL(baseURL + "/scpc/accueil.do");
+            while (cookied == false && retries > 0) {
+                urlConn = (HttpURLConnection)searchFormURL.openConnection();
+                urlConn.setRequestMethod("GET");
+                urlConn.connect();
+                if (urlConn.getResponseCode() == HttpURLConnection.HTTP_OK) {
+                    System.out.println("GET "+searchFormURL);
+                    BufferedReader in = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
+                    while(in.readLine() != null) {}  // read the buffer otherwise we sent POST too early
+                    String headerName=null;
+                    for (int i=1; (headerName = urlConn.getHeaderFieldKey(i))!=null; i++) {
+                        if (headerName.equals("Set-Cookie")) {
+                            cookie = urlConn.getHeaderField(i);
+                            cookie = cookie.substring(0, cookie.indexOf(";"));
+                            cookieTimestamp = new Date().getTime();
+                            System.out.println("received cookie=" + cookie + " at " + new Date(cookieTimestamp));
+                            cookied = true;
+                        }
+                    }
+                } else {
+                    System.out.println("Request to home page failed. Http error:"+urlConn.getResponseCode()+". Try again "+retries+" times");
+                    CadastrePlugin.safeSleep(3000);
+                    retries --;
                 }
             }
         } catch (MalformedURLException e) {
@@ -117,11 +135,21 @@ public class CadastreInterface {
 
     public void resetCookie() {
         lastWMSLayerName = null;
+        cookie = null;
+    }
+    
+    public boolean isCookieExpired() {
+        long now = new Date().getTime();
+        if ((now - cookieTimestamp) > cCookieExpiration) {
+            System.out.println("cookie received at "+new Date(cookieTimestamp)+" expired (now is "+new Date(now)+")");
+            return true;
+        }
+        return false;
     }
 
-    public void resetCookieIfNewLayer(String newWMSLayerName) {
+    public void resetInterfaceRefIfNewLayer(String newWMSLayerName) {
         if (!newWMSLayerName.equals(lastWMSLayerName)) {
-            resetCookie();
+            interfaceRef = null;
         }
     }
 
@@ -153,7 +181,6 @@ public class CadastreInterface {
                     // commune known but raster format. Select "Feuille" (non-georeferenced image) from list.
                     int res = selectFeuilleDialog();
                     if (res != -1) {
-                        // TODO
                         wmsLayer.setCodeCommune(listOfFeuilles.elementAt(res).name);
                         checkLayerDuplicates(wmsLayer);
                         interfaceRef = buildRasterFeuilleInterfaceRef(wmsLayer.getCodeCommune());
@@ -230,6 +257,8 @@ public class CadastreInterface {
             }
             content += "&codeDepartement=";
             content += "&nbResultatParPage=10";
+            content += "&x=0&y=0";
+            searchFormURL = new URL(baseURL + "/scpc/rechercherPlan.do");
             urlConn = (HttpURLConnection)searchFormURL.openConnection();
             urlConn.setRequestMethod("POST");
             urlConn.setDoOutput(true);
diff --git a/cadastre-fr/src/cadastre_fr/CadastrePlugin.java b/cadastre-fr/src/cadastre_fr/CadastrePlugin.java
index 635f3fc..8383902 100644
--- a/cadastre-fr/src/cadastre_fr/CadastrePlugin.java
+++ b/cadastre-fr/src/cadastre_fr/CadastrePlugin.java
@@ -22,8 +22,10 @@ import org.openstreetmap.josm.actions.UploadAction;
 import org.openstreetmap.josm.gui.MainMenu;
 import org.openstreetmap.josm.gui.MapFrame;
 import org.openstreetmap.josm.gui.IconToggleButton;
+import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
 import org.openstreetmap.josm.plugins.Plugin;
+import org.openstreetmap.josm.plugins.PluginInformation;
 import org.openstreetmap.josm.data.projection.*;
 
 /**
@@ -86,9 +88,26 @@ import org.openstreetmap.josm.data.projection.*;
  *                   support of subprojections in preferences for zones setting and UTM20N
  *                 - removed autosourcing of empty new nodes
  * 1.6 28-Nov-2009 - Fix minor issues if Grab is called without layer (possible since projection rework)
+ * 1.7 12-Dec-2009 - Change URL's changes for cookie and downgrade imgs resolution due to WMS changes
+ * 1.8 xxx         - filter the mouse button 1 during georeferencing
+ *                 - retry if getting a new cookie failed (10 times during 30 seconds)
+ *                 - cookie expiration automatically detected and renewed (after 30 minutes)
+ *                 - proper WMS layer cleanup at destruction (workaround for memory leak)
+ *                 - new cache format (v3) storing original image and cropped image bbox + angle
+ *                 - new cache format (v4) storing original image size for later rotation 
+ *                 - cache files read compatible with previous formats
+ *                 - raster image rotation issues fixed, now using shift+ctrl key instead of ctrl
+ *                 - raster image adjustment using default system menu modifier (ctrl for windows) for Mac support
+ *                 - image resolution configurable (high, medium, low) like the online interface
+ *                 - layer selection configurable for vectorized images
+ *                 - from Erik Amzallag:
+ *                 -     possibility to modify the auto-sourcing text just before upload 
+ *                 - from Cl�ment M�nier:
+ *                 -     new option allowing an auto-selection of the first cadastre layer for grab
+ *                 -     non-modal JDialog in MenuActionGrabPlanImage  
  */
 public class CadastrePlugin extends Plugin {
-    static String VERSION = "1.6";
+    static String VERSION = "1.8";
 
     static JMenu cadastreJMenu;
 
@@ -112,6 +131,10 @@ public class CadastrePlugin extends Plugin {
 
     public static boolean drawBoundaries = false;
 
+    public static int imageWidth, imageHeight;
+    
+    public static String grabLayers, grabStyles = null;
+
     static private boolean menuEnabled = false;
 
     /**
@@ -119,8 +142,9 @@ public class CadastrePlugin extends Plugin {
      *
      * @throws Exception
      */
-    public CadastrePlugin() throws Exception {
-        System.out.println("Pluging \"cadastre-fr\" started...");
+    public CadastrePlugin(PluginInformation info) throws Exception {
+    	super(info);
+        System.out.println("Pluging cadastre-fr v"+VERSION+" started...");
         if (Main.pref.get("cadastrewms.cacheDir").equals(""))
             cacheDir = Main.pref.getPreferencesDir()+"plugins/cadastrewms/";
         else {
@@ -158,7 +182,7 @@ public class CadastrePlugin extends Plugin {
                 }
             });
 
-            JMenuItem menuResetCookie = new JMenuItem(new MenuActionResetCookie());
+            //JMenuItem menuResetCookie = new JMenuItem(new MenuActionResetCookie());
             //JMenuItem menuLambertZone = new JMenuItem(new MenuActionLambertZone());
             JMenuItem menuLoadFromCache = new JMenuItem(new MenuActionLoadFromCache());
             // temporary disabled:
@@ -169,7 +193,7 @@ public class CadastrePlugin extends Plugin {
             cadastreJMenu.add(menuActionGrabPlanImage);
             cadastreJMenu.add(menuSettings);
             cadastreJMenu.add(menuSource);
-            cadastreJMenu.add(menuResetCookie);
+            //cadastreJMenu.add(menuResetCookie); not required any more
             //cadastreJMenu.add(menuLambertZone);
             cadastreJMenu.add(menuLoadFromCache);
             // all SVG features disabled until official WMS is released
@@ -191,6 +215,57 @@ public class CadastrePlugin extends Plugin {
             backgroundTransparent = false;
             transparency = 1.0f;
         }
+        String currentResolution = Main.pref.get("cadastrewms.resolution", "high");
+        if (currentResolution.equals("high")) {
+            imageWidth = 1000; imageHeight = 800;
+        } else if (currentResolution.equals("medium")){
+            imageWidth = 800; imageHeight = 600;
+        } else { 
+            imageWidth = 600; imageHeight = 400;
+        }
+        grabLayers = "";
+        grabStyles = "";
+        if (Main.pref.getBoolean("cadastrewms.layerWater", true)) {
+            grabLayers += "CDIF:LS3,";
+            grabStyles += "LS3_90,";
+        }
+        if (Main.pref.getBoolean("cadastrewms.layerBuilding", true)) {
+            grabLayers += "CDIF:LS2,";
+            grabStyles += "LS2_90,";
+        }
+        if (Main.pref.getBoolean("cadastrewms.layerSymbol", true)) {
+            grabLayers += "CDIF:LS1,";
+            grabStyles += "LS1_90,";
+        }
+        if (Main.pref.getBoolean("cadastrewms.layerParcel", true)) {
+            grabLayers += "CDIF:PARCELLE,";
+            grabStyles += "PARCELLE_90,";
+        }
+        if (Main.pref.getBoolean("cadastrewms.layerNumero", true)) {
+            grabLayers += "CDIF:NUMERO,";
+            grabStyles += "NUMERO_90,";
+        }
+        if (Main.pref.getBoolean("cadastrewms.layerLabel", true)) {
+            grabLayers += "CDIF:PT3,CDIF:PT2,CDIF:PT1,";
+            grabStyles += "PT3_90,PT2_90,PT1_90,";
+        }
+        if (Main.pref.getBoolean("cadastrewms.layerLieudit", true)) {
+            grabLayers += "CDIF:LIEUDIT,";
+            grabStyles += "LIEUDIT_90,";
+        }
+        if (Main.pref.getBoolean("cadastrewms.layerSection", true)) {
+            grabLayers += "CDIF:SUBSECTION,CDIF:SECTION,";
+            grabStyles += "SUBSECTION_90,SECTION_90,";
+        }
+        if (Main.pref.getBoolean("cadastrewms.layerCommune", true)) {
+            grabLayers += "CDIF:COMMUNE,";
+            grabStyles += "COMMUNE_90,";
+        }
+        if (grabLayers.length() > 0) { // remove the last ','
+            grabLayers = grabLayers.substring(0, grabLayers.length()-1);
+            grabStyles = grabStyles.substring(0, grabStyles.length()-1);
+        }
+        
         // overwrite F11 shortcut used from the beginning by this plugin and recently used
         // for full-screen switch in JOSM core
         int i = 0;
@@ -282,6 +357,26 @@ public class CadastrePlugin extends Plugin {
         dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
     }
     
+    /**
+     * Adds the WMSLayer following this rule:<br/>
+     * - if a WMSLayer exists place this new layer just before this layer<br/>
+     * - Otherwise place it at the bottom
+     * @param wmsLayer the wmsLayer to add
+     */
+    public static void addWMSLayer(WMSLayer wmsLayer) {
+        if (Main.map != null && Main.map.mapView != null) {
+            int wmsNewLayerPos = Main.map.mapView.getAllLayers().size();
+            for(Layer l : Main.map.mapView.getLayersOfType(WMSLayer.class)) {
+                int wmsPos = Main.map.mapView.getLayerPos(l);
+                if (wmsPos < wmsNewLayerPos) wmsNewLayerPos = wmsPos;
+            }
+            Main.main.addLayer(wmsLayer);
+            // Move the layer to its new position
+            Main.map.mapView.moveLayer(wmsLayer, wmsNewLayerPos);
+        } else
+            Main.main.addLayer(wmsLayer);
+    }
+    
     private static String checkSourceMillesime() {
         java.util.Calendar calendar = java.util.Calendar.getInstance();
         int currentYear = calendar.get(java.util.Calendar.YEAR);
@@ -299,4 +394,5 @@ public class CadastrePlugin extends Plugin {
         }
         return src;
     }
+    
 }
diff --git a/cadastre-fr/src/cadastre_fr/CadastrePreferenceSetting.java b/cadastre-fr/src/cadastre_fr/CadastrePreferenceSetting.java
index 972e7d0..157c9be 100644
--- a/cadastre-fr/src/cadastre_fr/CadastrePreferenceSetting.java
+++ b/cadastre-fr/src/cadastre_fr/CadastrePreferenceSetting.java
@@ -8,8 +8,8 @@ import java.awt.event.ActionListener;
 import javax.swing.*;
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.gui.preferences.PreferenceDialog;
 import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
+import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.I18n;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -35,6 +35,8 @@ public class CadastrePreferenceSetting implements PreferenceSetting {
 
     private JCheckBox drawBoundaries = new JCheckBox(tr("Draw boundaries of downloaded data."));
 
+    private JComboBox imageInterpolationMethod = new JComboBox();
+
     private JCheckBox disableImageCropping = new JCheckBox(tr("Disable image cropping during georeferencing."));
     
     private JRadioButton grabMultiplier1 = new JRadioButton("", true);
@@ -47,9 +49,29 @@ public class CadastrePreferenceSetting implements PreferenceSetting {
     
     private JRadioButton crosspiece1 = new JRadioButton("off");
     
-    private JRadioButton crosspiece2 = new JRadioButton("50m");
+    private JRadioButton crosspiece2 = new JRadioButton("25m");
+
+    private JRadioButton crosspiece3 = new JRadioButton("50m");
+
+    private JRadioButton crosspiece4 = new JRadioButton("100m");
+
+    private JCheckBox autoFirstLayer = new JCheckBox(tr("Automaticly select first WMS layer when grabing if multiple layers exist."));
+    
+    private JRadioButton grabRes1 = new JRadioButton("high");
 
-    private JRadioButton crosspiece3 = new JRadioButton("100m");
+    private JRadioButton grabRes2 = new JRadioButton("medium");
+
+    private JRadioButton grabRes3 = new JRadioButton("low");
+
+    private JCheckBox layerLS3 = new JCheckBox(tr("water"));
+    private JCheckBox layerLS2 = new JCheckBox(tr("building"));
+    private JCheckBox layerLS1 = new JCheckBox(tr("symbol"));
+    private JCheckBox layerParcel = new JCheckBox(tr("parcel"));
+    private JCheckBox layerLabel = new JCheckBox(tr("parcel number"));
+    private JCheckBox layerNumero = new JCheckBox(tr("address"));
+    private JCheckBox layerLieudit = new JCheckBox(tr("locality"));
+    private JCheckBox layerSection = new JCheckBox(tr("section"));
+    private JCheckBox layerCommune = new JCheckBox(tr("commune"));
 
     static final int DEFAULT_SQUARE_SIZE = 100;
     private JTextField grabMultiplier4Size = new JTextField(5);
@@ -65,7 +87,7 @@ public class CadastrePreferenceSetting implements PreferenceSetting {
 
     static final int DEFAULT_CROSSPIECES = 0;
     
-    public void addGui(final PreferenceDialog gui) {
+    public void addGui(final PreferenceTabbedPane gui) {
 
         String description = tr("A special handler of the French cadastre wms at www.cadastre.gouv.fr" + "<BR><BR>"
                 + "Please read the Terms and Conditions of Use here (in French): <br>"
@@ -117,6 +139,51 @@ public class CadastrePreferenceSetting implements PreferenceSetting {
         drawBoundaries.setToolTipText(tr("Draw a rectangle around downloaded data from WMS server."));
         cadastrewms.add(drawBoundaries, GBC.eop().insets(0, 0, 0, 5));
 
+        // option to select the single grabbed image resolution
+        JLabel jLabelRes = new JLabel(tr("Image resolution:"));
+        cadastrewms.add(jLabelRes, GBC.std().insets(0, 5, 10, 0));
+        ButtonGroup bgResolution = new ButtonGroup();
+        ActionListener resActionListener = new ActionListener() {
+            public void actionPerformed(ActionEvent actionEvent) {
+              AbstractButton button = (AbstractButton) actionEvent.getSource();
+              grabMultiplier4Size.setEnabled(button == grabMultiplier4);
+            }
+          };
+        grabRes1.addActionListener( resActionListener);
+        grabRes1.setToolTipText(tr("High resolution (1000x800)"));
+        grabRes2.addActionListener( resActionListener);
+        grabRes2.setToolTipText(tr("Medium resolution (800x600)"));
+        grabRes3.addActionListener( resActionListener);
+        grabRes3.setToolTipText(tr("Low resolution (600x400)"));
+        bgResolution.add(grabRes1);
+        bgResolution.add(grabRes2);
+        bgResolution.add(grabRes3);
+        String currentResolution = Main.pref.get("cadastrewms.resolution", "high");
+        if (currentResolution.equals("high"))
+            grabRes1.setSelected(true);
+        if (currentResolution.equals("medium"))
+            grabRes2.setSelected(true);
+        if (currentResolution.equals("low"))
+            grabRes3.setSelected(true);
+        cadastrewms.add(grabRes1, GBC.std().insets(5, 0, 5, 0));
+        cadastrewms.add(grabRes2, GBC.std().insets(5, 0, 5, 0));
+        cadastrewms.add(grabRes3, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 5, 0, 5));
+        
+        // option to select image zooming interpolation method
+        JLabel jLabelImageZoomInterpolation = new JLabel(tr("Image filter interpolation:"));
+        cadastrewms.add(jLabelImageZoomInterpolation, GBC.std().insets(0, 0, 10, 0));
+        imageInterpolationMethod.addItem(tr("Nearest-Neighbor (fastest) [ Default ]"));
+        imageInterpolationMethod.addItem(tr("Bilinear (fast)"));
+        imageInterpolationMethod.addItem(tr("Bicubic (slow)"));
+        String savedImageInterpolationMethod = Main.pref.get("cadastrewms.imageInterpolation", "standard");
+        if (savedImageInterpolationMethod.equals("bilinear")) 
+            imageInterpolationMethod.setSelectedIndex(1);
+        else if (savedImageInterpolationMethod.equals("bicubic")) 
+            imageInterpolationMethod.setSelectedIndex(2);
+        else
+            imageInterpolationMethod.setSelectedIndex(0);
+        cadastrewms.add(imageInterpolationMethod, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 5, 200, 5));
+
         // separator
         cadastrewms.add(new JSeparator(SwingConstants.HORIZONTAL), GBC.eol().fill(GBC.HORIZONTAL));
         
@@ -133,6 +200,7 @@ public class CadastrePreferenceSetting implements PreferenceSetting {
         grabMultiplier1.setIcon(ImageProvider.get("preferences", "unsel_box_1"));
         grabMultiplier1.setSelectedIcon(ImageProvider.get("preferences", "sel_box_1"));
         grabMultiplier1.addActionListener( multiplierActionListener);
+        grabMultiplier1.setToolTipText(tr("Grab one image full screen"));
         grabMultiplier2.setIcon(ImageProvider.get("preferences", "unsel_box_2"));
         grabMultiplier2.setSelectedIcon(ImageProvider.get("preferences", "sel_box_2"));
         grabMultiplier2.addActionListener( multiplierActionListener);
@@ -168,14 +236,45 @@ public class CadastrePreferenceSetting implements PreferenceSetting {
         grabMultiplier4Size.setEnabled(currentScale.equals(Scale.SQUARE_100M.value));
         cadastrewms.add(grabMultiplier4Size, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 5, 0, 5));
 
+        // WMS layers selection
+        JLabel jLabelLayers = new JLabel(tr("Layers:"));
+        cadastrewms.add(jLabelLayers, GBC.std().insets(0, 5, 10, 0));
+        layerLS3.setSelected(Main.pref.getBoolean("cadastrewms.layerWater", true));
+        layerLS3.setToolTipText(tr("See, rivers, swimming pools."));
+        cadastrewms.add(layerLS3, GBC.std().insets(5, 0, 5, 0));
+        layerLS2.setSelected(Main.pref.getBoolean("cadastrewms.layerBuilding", true));
+        layerLS2.setToolTipText(tr("Buildings, covers, underground constructions."));
+        cadastrewms.add(layerLS2, GBC.std().insets(5, 0, 5, 0));
+        layerLS1.setSelected(Main.pref.getBoolean("cadastrewms.layerSymbol", true));
+        layerLS1.setToolTipText(tr("Symbols like cristian cross."));
+        cadastrewms.add(layerLS1, GBC.std().insets(5, 0, 5, 0));
+        layerParcel.setSelected(Main.pref.getBoolean("cadastrewms.layerParcel", true));
+        layerParcel.setToolTipText(tr("Parcels."));
+        cadastrewms.add(layerParcel, GBC.eop().insets(5, 0, 5, 0));
+        layerLabel.setSelected(Main.pref.getBoolean("cadastrewms.layerLabel", true));
+        layerLabel.setToolTipText(tr("Parcels numbers, street names."));
+        cadastrewms.add(layerLabel, GBC.std().insets(70, 0, 5, 0));
+        layerNumero.setSelected(Main.pref.getBoolean("cadastrewms.layerNumero", true));
+        layerNumero.setToolTipText(tr("Address, houses numbers."));
+        cadastrewms.add(layerNumero, GBC.std().insets(5, 0, 5, 0));
+        layerLieudit.setSelected(Main.pref.getBoolean("cadastrewms.layerLieudit", true));
+        layerLieudit.setToolTipText(tr("Locality, hamlet, place."));
+        cadastrewms.add(layerLieudit, GBC.std().insets(5, 0, 5, 0));
+        layerSection.setSelected(Main.pref.getBoolean("cadastrewms.layerSection", true));
+        layerSection.setToolTipText(tr("Cadastral sections and subsections."));
+        cadastrewms.add(layerSection, GBC.std().insets(5, 0, 5, 0));
+        layerCommune.setSelected(Main.pref.getBoolean("cadastrewms.layerCommune", true));
+        layerCommune.setToolTipText(tr("Municipality administrative borders."));
+        cadastrewms.add(layerCommune, GBC.eop().insets(5, 0, 5, 0));
+        
         // separator
         cadastrewms.add(new JSeparator(SwingConstants.HORIZONTAL), GBC.eol().fill(GBC.HORIZONTAL));
 
-        // for raster images (not vectorized), image grab divider (from 1 to 10)
+        // for raster images (not vectorized), image grab divider (from 1 to 12)
         String savedRasterDivider = Main.pref.get("cadastrewms.rasterDivider", DEFAULT_RASTER_DIVIDER);
         JLabel jLabelRasterDivider = new JLabel(tr("Raster images grab multiplier:"));
         rasterDivider.setText(savedRasterDivider);
-        rasterDivider.setToolTipText("Raster image grab division, from 1 to 10; 10 is very high definition");
+        rasterDivider.setToolTipText("Raster image grab division, from 1 to 12; 12 is very high definition");
         cadastrewms.add(jLabelRasterDivider, GBC.std().insets(0, 5, 10, 0));
         cadastrewms.add(rasterDivider, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 5, 200, 5));
         // option to disable image cropping during raster image georeferencing
@@ -190,12 +289,15 @@ public class CadastrePreferenceSetting implements PreferenceSetting {
         if (crosspieces == 0) crosspiece1.setSelected(true);
         if (crosspieces == 1) crosspiece2.setSelected(true);
         if (crosspieces == 2) crosspiece3.setSelected(true);
+        if (crosspieces == 3) crosspiece4.setSelected(true);
         bgCrosspieces.add(crosspiece1);
         bgCrosspieces.add(crosspiece2);
         bgCrosspieces.add(crosspiece3);
+        bgCrosspieces.add(crosspiece4);
         cadastrewms.add(crosspiece1, GBC.std().insets(5, 0, 5, 0));
         cadastrewms.add(crosspiece2, GBC.std().insets(5, 0, 5, 0));
-        cadastrewms.add(crosspiece3, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 5, 0, 5));
+        cadastrewms.add(crosspiece3, GBC.std().insets(5, 0, 5, 0));
+        cadastrewms.add(crosspiece4, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 5, 0, 5));
 
         // separator
         cadastrewms.add(new JSeparator(SwingConstants.HORIZONTAL), GBC.eol().fill(GBC.HORIZONTAL));
@@ -217,7 +319,11 @@ public class CadastrePreferenceSetting implements PreferenceSetting {
         cacheSize.setToolTipText(tr("Oldest files are automatically deleted when this size is exceeded"));
         cadastrewms.add(jLabelCacheSize, GBC.std().insets(20, 0, 0, 0));
         cadastrewms.add(cacheSize, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 5, 200, 5));
-        
+        // separator
+        cadastrewms.add(new JSeparator(SwingConstants.HORIZONTAL), GBC.eol().fill(GBC.HORIZONTAL));
+        autoFirstLayer.setSelected(Main.pref.getBoolean("cadastrewms.autoFirstLayer", false));
+        autoFirstLayer.setToolTipText(tr("Automatically selects the first WMS layer if multiple layers exist when grabbing."));
+        cadastrewms.add(autoFirstLayer, GBC.eop().insets(0, 0, 0, 0));
         cadastrewms.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.VERTICAL));
 
     }
@@ -230,6 +336,18 @@ public class CadastrePreferenceSetting implements PreferenceSetting {
         Main.pref.put("cadastrewms.backgroundTransparent", transparency.isSelected());
         Main.pref.put("cadastrewms.brightness", Float.toString((float)sliderTrans.getValue()/10));
         Main.pref.put("cadastrewms.drawBoundaries", drawBoundaries.isSelected());
+        if (grabRes1.isSelected())
+            Main.pref.put("cadastrewms.resolution", "high");
+        else if (grabRes2.isSelected())
+            Main.pref.put("cadastrewms.resolution", "medium");
+        else if (grabRes3.isSelected())
+            Main.pref.put("cadastrewms.resolution", "low");
+        if (imageInterpolationMethod.getSelectedIndex() == 2)
+            Main.pref.put("cadastrewms.imageInterpolation", "bicubic");
+        else if (imageInterpolationMethod.getSelectedIndex() == 1)
+            Main.pref.put("cadastrewms.imageInterpolation", "bilinear");
+        else 
+            Main.pref.put("cadastrewms.imageInterpolation", "standard");
         if (grabMultiplier1.isSelected())
             Main.pref.put("cadastrewms.scale", Scale.X1.toString());
         else if (grabMultiplier2.isSelected())
@@ -245,9 +363,18 @@ public class CadastrePreferenceSetting implements PreferenceSetting {
             } catch (NumberFormatException e) { // ignore the last input
             }
         }
+        Main.pref.put("cadastrewms.layerWater", layerLS3.isSelected());
+        Main.pref.put("cadastrewms.layerBuilding", layerLS2.isSelected());
+        Main.pref.put("cadastrewms.layerSymbol", layerLS1.isSelected());
+        Main.pref.put("cadastrewms.layerParcel", layerParcel.isSelected());
+        Main.pref.put("cadastrewms.layerLabel", layerLabel.isSelected());
+        Main.pref.put("cadastrewms.layerNumero", layerNumero.isSelected());
+        Main.pref.put("cadastrewms.layerLieudit", layerLieudit.isSelected());
+        Main.pref.put("cadastrewms.layerSection", layerSection.isSelected());
+        Main.pref.put("cadastrewms.layerCommune", layerCommune.isSelected());
         try {
             int i = Integer.parseInt(rasterDivider.getText());
-            if (i > 0 && i < 11)
+            if (i > 0 && i < 13)
                 Main.pref.put("cadastrewms.rasterDivider", String.valueOf(i));
         } catch (NumberFormatException e) { // ignore the last input
         }
@@ -255,6 +382,7 @@ public class CadastrePreferenceSetting implements PreferenceSetting {
         if (crosspiece1.isSelected()) Main.pref.put("cadastrewms.crosspieces", "0");
         else if (crosspiece2.isSelected()) Main.pref.put("cadastrewms.crosspieces", "1");
         else if (crosspiece3.isSelected()) Main.pref.put("cadastrewms.crosspieces", "2");
+        else if (crosspiece4.isSelected()) Main.pref.put("cadastrewms.crosspieces", "3");
         Main.pref.put("cadastrewms.enableCaching", enableCache.isSelected());
 
         // spread data into objects instead of restarting the application
@@ -263,6 +391,7 @@ public class CadastrePreferenceSetting implements PreferenceSetting {
             Main.pref.put("cadastrewms.cacheSize", String.valueOf(CacheControl.cacheSize));
         } catch (NumberFormatException e) { // ignore the last input
         }
+        Main.pref.put("cadastrewms.autoFirstLayer", autoFirstLayer.isSelected());
         CacheControl.cacheEnabled = enableCache.isSelected();
         CadastrePlugin.refreshConfiguration();
         CadastrePlugin.refreshMenu();
diff --git a/cadastre-fr/src/cadastre_fr/CheckSourceUploadHook.java b/cadastre-fr/src/cadastre_fr/CheckSourceUploadHook.java
index 712a5b5..c2a125c 100644
--- a/cadastre-fr/src/cadastre_fr/CheckSourceUploadHook.java
+++ b/cadastre-fr/src/cadastre_fr/CheckSourceUploadHook.java
@@ -12,6 +12,7 @@ import javax.swing.JList;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
+import javax.swing.JTextField;
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.upload.UploadHook;
@@ -77,7 +78,9 @@ public class CheckSourceUploadHook implements UploadHook
         if (!sel.isEmpty()) {
             JPanel p = new JPanel(new GridBagLayout());
             OsmPrimitivRenderer renderer = new OsmPrimitivRenderer();
-            p.add(new JLabel(tr("Auto-tag source added:")), GBC.eol());
+            p.add(new JLabel(tr("Add \"source=...\" to elements?")), GBC.eol());
+            JTextField tf = new JTextField(CadastrePlugin.source);
+            p.add(tf, GBC.eol());
             JList l = new JList(sel.toArray());
             l.setCellRenderer(renderer);
             l.setVisibleRowCount(l.getModel().getSize() < 6 ? l.getModel().getSize() : 10);
@@ -85,8 +88,9 @@ public class CheckSourceUploadHook implements UploadHook
             boolean bContinue = JOptionPane.showConfirmDialog(Main.parent, p, tr("Add \"source=...\" to elements?"),
                    JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION;
             if (bContinue)
-                Main.main.undoRedo.add(new ChangePropertyCommand(sel, "source", CadastrePlugin.source));
+                Main.main.undoRedo.add(new ChangePropertyCommand(sel, "source", tf.getText()));
         }
 
     }
 }
+
diff --git a/cadastre-fr/src/cadastre_fr/DownloadSVGBuilding.java b/cadastre-fr/src/cadastre_fr/DownloadSVGBuilding.java
index ab36189..f2ce93b 100644
--- a/cadastre-fr/src/cadastre_fr/DownloadSVGBuilding.java
+++ b/cadastre-fr/src/cadastre_fr/DownloadSVGBuilding.java
@@ -191,7 +191,7 @@ public class DownloadSVGBuilding extends PleaseWaitRunnable {
     private Node checkNearestNode(Node nodeToAdd, Collection<Node> nodes) {
         double epsilon = 0.05; // smallest distance considering duplicate node
         for (Node n : nodes) {
-            if (!n.isDeleted() && !n.incomplete) {
+            if (!n.isDeleted() && !n.isIncomplete()) {
                 double dist = n.getEastNorth().distance(nodeToAdd.getEastNorth());
                 if (dist < epsilon) {
                     return n;
@@ -220,7 +220,7 @@ public class DownloadSVGBuilding extends PleaseWaitRunnable {
         str += bbox.min.north() + ",";
         str += bbox.max.east() + ",";
         str += bbox.max.north();
-        str += "&width=800&height=600"; // maximum allowed by wms server
+        str += "&width="+CadastrePlugin.imageWidth+"&height="+CadastrePlugin.imageHeight;
         str += "&exception=application/vnd.ogc.se_inimage";
         str += "&styles=";
         str += "LS2_90";
diff --git a/cadastre-fr/src/cadastre_fr/DownloadSVGTask.java b/cadastre-fr/src/cadastre_fr/DownloadSVGTask.java
index bba3fcb..bae5381 100644
--- a/cadastre-fr/src/cadastre_fr/DownloadSVGTask.java
+++ b/cadastre-fr/src/cadastre_fr/DownloadSVGTask.java
@@ -176,7 +176,7 @@ public class DownloadSVGTask extends PleaseWaitRunnable {
         str += bbox.min.north() + ",";
         str += bbox.max.east() + ",";
         str += bbox.max.north();
-        str += "&width=800&height=600"; // maximum allowed by wms server
+        str += "&width="+CadastrePlugin.imageWidth+"&height="+CadastrePlugin.imageHeight;
         str += "&styles=";
         str += "COMMUNE_90";
         System.out.println("URL="+str);
diff --git a/cadastre-fr/src/cadastre_fr/GeorefImage.java b/cadastre-fr/src/cadastre_fr/GeorefImage.java
index a24918f..c67fe1a 100644
--- a/cadastre-fr/src/cadastre_fr/GeorefImage.java
+++ b/cadastre-fr/src/cadastre_fr/GeorefImage.java
@@ -8,9 +8,10 @@ import java.awt.Graphics2D;
 import java.awt.GraphicsConfiguration;
 import java.awt.GraphicsDevice;
 import java.awt.GraphicsEnvironment;
+import java.awt.Image;
 import java.awt.Point;
-import java.awt.Transparency;
 import java.awt.image.BufferedImage;
+import java.awt.image.ImageObserver;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
@@ -21,11 +22,22 @@ import javax.imageio.ImageIO;
 import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.gui.NavigatableComponent;
 
-public class GeorefImage implements Serializable {
+public class GeorefImage implements Serializable, ImageObserver {
     private static final long serialVersionUID = 1L;
 
+    // bbox of the georeferenced image (the nice horizontal and vertical box)
     public EastNorth min;
     public EastNorth max;
+    // bbox of the georeferenced original image (raster only) (inclined if rotated and before cropping)
+    // P[0] is bottom,left then next are clockwise. 
+    public EastNorth[] orgRaster = new EastNorth[4];
+    // bbox of the georeferenced original image (raster only) after cropping 
+    public EastNorth[] orgCroppedRaster = new EastNorth[4];
+    // angle with georeferenced original image after rotation (raster images only)(in radian)
+    public double angle = 0;
+    public int imageOriginalHeight = 0;
+    public int imageOriginalWidth = 0;
+
     public BufferedImage image;
 
     private double pixelPerEast;
@@ -33,8 +45,19 @@ public class GeorefImage implements Serializable {
 
     public GeorefImage(BufferedImage img, EastNorth min, EastNorth max) {
         image = img;
+        
         this.min = min;
         this.max = max;
+        this.orgRaster[0] = min;
+        this.orgRaster[1] = new EastNorth(min.east(), max.north());
+        this.orgRaster[2] = max;
+        this.orgRaster[3] = new EastNorth(max.east(), min.north());
+        this.orgCroppedRaster[0] = min;
+        this.orgCroppedRaster[1] = new EastNorth(min.east(), max.north());
+        this.orgCroppedRaster[2] = max;
+        this.orgCroppedRaster[3] = new EastNorth(max.east(), min.north());
+        this.imageOriginalHeight = img.getHeight();
+        this.imageOriginalWidth = img.getWidth();
         updatePixelPer();
     }
 
@@ -44,12 +67,20 @@ public class GeorefImage implements Serializable {
         return gd.getDefaultConfiguration();
     }
 
-    private void getNewBounding(EastNorth min, EastNorth max, EastNorth c, EastNorth d) {
+    /**
+     * Recalculate the new bounding box of the image based on the four points provided as parameters. 
+     * The new bbox defined in [min.max] will retain the extreme values of both boxes. 
+     * @param p1 one of the bounding box corner
+     * @param p2 one of the bounding box corner
+     * @param p3 one of the bounding box corner
+     * @param p4 one of the bounding box corner
+     */
+    private EastNorthBound computeNewBounding(EastNorth p1, EastNorth p2, EastNorth p3, EastNorth p4) {
         EastNorth pt[] = new EastNorth[4];
-        pt[0] = min;
-        pt[1] = max;
-        pt[2] = c;
-        pt[3] = d;
+        pt[0] = p1;
+        pt[1] = p2;
+        pt[2] = p3;
+        pt[3] = p4;
         double smallestEast = Double.MAX_VALUE;
         double smallestNorth = Double.MAX_VALUE;
         double highestEast = Double.MIN_VALUE;
@@ -60,8 +91,8 @@ public class GeorefImage implements Serializable {
             highestEast = Math.max(pt[i].east(), highestEast);
             highestNorth = Math.max(pt[i].north(), highestNorth);
         }
-        min.setLocation(smallestEast, smallestNorth);
-        max.setLocation(highestEast, highestNorth);
+        return new EastNorthBound(new EastNorth(smallestEast, smallestNorth),
+                new EastNorth(highestEast, highestNorth));
     }
 
     public boolean contains(EastNorth en) {
@@ -82,8 +113,31 @@ public class GeorefImage implements Serializable {
         if (backgroundTransparent && transparency < 1.0f)
             g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, transparency));
         if (drawBoundaries) {
-            g.setColor(Color.green);
-            g.drawRect(minPt.x, maxPt.y, maxPt.x - minPt.x, minPt.y - maxPt.y);
+            if (orgCroppedRaster == null) {
+                // this is the old cache format where only [min,max] bbox is stored
+                g.setColor(Color.green);
+                g.drawRect(minPt.x, maxPt.y, maxPt.x - minPt.x, minPt.y - maxPt.y);
+            } else {
+                Point[] croppedPoint = new Point[5];
+                for (int i=0; i<4; i++)
+                    croppedPoint[i] = nc.getPoint(orgCroppedRaster[i]);
+                croppedPoint[4] = croppedPoint[0];
+                for (int i=0; i<4; i++) {
+                    g.setColor(Color.green);
+                    g.drawLine(croppedPoint[i].x, croppedPoint[i].y, croppedPoint[i+1].x, croppedPoint[i+1].y);
+                }
+                /* 
+                //Uncomment this section to display the original image size (before cropping)
+                Point[] orgPoint = new Point[5];
+                for (int i=0; i<4; i++)
+                    orgPoint[i] = nc.getPoint(orgRaster[i]);
+                orgPoint[4] = orgPoint[0];
+                for (int i=0; i<4; i++) {
+                  g.setColor(Color.red);
+                  g.drawLine(orgPoint[i].x, orgPoint[i].y, orgPoint[i+1].x, orgPoint[i+1].y);
+                }
+                */
+            }
         }
         g.drawImage(image, minPt.x, maxPt.y, maxPt.x, minPt.y, // dest
                 0, 0, image.getWidth(), image.getHeight(), // src
@@ -134,21 +188,55 @@ public class GeorefImage implements Serializable {
      * Save only primitives to keep cache independent of software changes.
      */
     private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
-        max = new EastNorth(in.readDouble(), in.readDouble());
-        min = new EastNorth(in.readDouble(), in.readDouble());
+        if (WMSLayer.currentFormat >= 2) {
+            max = new EastNorth(in.readDouble(), in.readDouble());
+            min = new EastNorth(in.readDouble(), in.readDouble());
+        }
+        orgRaster = null;
+        orgCroppedRaster = null;
+        if (WMSLayer.currentFormat >= 3) {
+            orgRaster = new EastNorth[4];
+            orgCroppedRaster = new EastNorth[4];
+            angle = in.readDouble();
+            orgRaster[0] = new EastNorth(in.readDouble(), in.readDouble());
+            orgRaster[1] = new EastNorth(in.readDouble(), in.readDouble());
+            orgRaster[2] = new EastNorth(in.readDouble(), in.readDouble());
+            orgRaster[3] = new EastNorth(in.readDouble(), in.readDouble());
+            orgCroppedRaster[0] = new EastNorth(in.readDouble(), in.readDouble());
+            orgCroppedRaster[1] = new EastNorth(in.readDouble(), in.readDouble());
+            orgCroppedRaster[2] = new EastNorth(in.readDouble(), in.readDouble());
+            orgCroppedRaster[3] = new EastNorth(in.readDouble(), in.readDouble());
+        }
+        if (WMSLayer.currentFormat >= 4) {
+            imageOriginalHeight = in.readInt();
+            imageOriginalWidth =  in.readInt();
+        }        
         image = (BufferedImage) ImageIO.read(ImageIO.createImageInputStream(in));
         updatePixelPer();
     }
 
     /**
      * Method required by BufferedImage serialization.
-     * Cache uses only primitives to stay independent of software changes.
+     * Use only primitives for stability in time (not influenced by josm-core changes).
      */
     private void writeObject(ObjectOutputStream out) throws IOException {
-        out.writeDouble(max.getX());
-        out.writeDouble(max.getY());
-        out.writeDouble(min.getX());
-        out.writeDouble(min.getY());
+        out.writeDouble(max.getX()); out.writeDouble(max.getY());
+        out.writeDouble(min.getX()); out.writeDouble(min.getY());
+        if (orgRaster == null) { // just in case we save an old format layer already cached
+            orgRaster = new EastNorth[4];
+            orgCroppedRaster = new EastNorth[4];
+        }
+        out.writeDouble(angle);
+        out.writeDouble(orgRaster[0].getX()); out.writeDouble(orgRaster[0].getY());
+        out.writeDouble(orgRaster[1].getX()); out.writeDouble(orgRaster[1].getY());
+        out.writeDouble(orgRaster[2].getX()); out.writeDouble(orgRaster[2].getY());
+        out.writeDouble(orgRaster[3].getX()); out.writeDouble(orgRaster[3].getY());
+        out.writeDouble(orgCroppedRaster[0].getX()); out.writeDouble(orgCroppedRaster[0].getY());
+        out.writeDouble(orgCroppedRaster[1].getX()); out.writeDouble(orgCroppedRaster[1].getY());
+        out.writeDouble(orgCroppedRaster[2].getX()); out.writeDouble(orgCroppedRaster[2].getY());
+        out.writeDouble(orgCroppedRaster[3].getX()); out.writeDouble(orgCroppedRaster[3].getY());
+        out.writeInt(imageOriginalHeight);
+        out.writeInt(imageOriginalWidth);
         ImageIO.write(image, "png", ImageIO.createImageOutputStream(out));
     }
 
@@ -181,6 +269,10 @@ public class GeorefImage implements Serializable {
     public void shear(double dx, double dy) {
         min = new EastNorth(min.east() + dx, min.north() + dy);
         max = new EastNorth(max.east() + dx, max.north() + dy);
+        for (int i=0; i<4; i++) {
+            orgRaster[i] = new EastNorth(orgRaster[i].east() + dx, orgRaster[i].north() + dy);
+            orgCroppedRaster[i] = new EastNorth(orgCroppedRaster[i].east() + dx, orgCroppedRaster[i].north() + dy);
+        }
     }
     
     /**
@@ -191,43 +283,80 @@ public class GeorefImage implements Serializable {
     public void scale(EastNorth anchor, double proportion) {
         min = anchor.interpolate(min, proportion);
         max = anchor.interpolate(max, proportion);
+        for (int i=0; i<4; i++) {
+            orgRaster[i] = anchor.interpolate(orgRaster[i], proportion);
+            orgCroppedRaster[i] = anchor.interpolate(orgCroppedRaster[i], proportion);
+        }
         updatePixelPer();
     }
 
     /**
      * Rotate this image and its min/max coordinates around anchor point
      * @param anchor anchor of rotation
-     * @param angle angle of rotation (in radians)
-     */
-    public void rotate(EastNorth anchor, double angle) {
-        EastNorth min2 = new EastNorth(min.east(), max.north());
-        EastNorth max2 = new EastNorth(max.east(), min.north());
-        min = min.rotate(anchor, angle);
-        max = max.rotate(anchor, angle);
-        min2 = min2.rotate(anchor, angle);
-        max2 = max2.rotate(anchor, angle);
-        getNewBounding(min, max, min2, max2);
-        image = tilt(image, angle);
-    }
-
-    /**
-     * Rotate by copying original buffered image into a new one with new dimensions 
-     * @param image
-     * @param angle
-     * @return
+     * @param old_ang previous angle of image before rotation (0 the first time)(in radian)
+     * @param delta_ang angle of rotation (in radian)
      */
-    public static BufferedImage tilt(BufferedImage image, double angle) {
-        double sin = Math.abs(Math.sin(angle)), cos = Math.abs(Math.cos(angle));
-        int w = image.getWidth(), h = image.getHeight();
-        int neww = (int)Math.floor(w*cos+h*sin), newh = (int)Math.floor(h*cos+w*sin);
+    public void rotate(EastNorth anchor, double delta_ang) {
+        if (orgRaster == null || orgCroppedRaster == null)
+            return;
+        // rotate the bounding boxes coordinates first
+        for (int i=0; i<4; i++) {
+            orgRaster[i] = orgRaster[i].rotate(anchor, delta_ang);
+            orgCroppedRaster[i] = orgCroppedRaster[i].rotate(anchor, delta_ang);
+        }
+        // rotate the image now
+        double sin = Math.abs(Math.sin(angle+delta_ang)), cos = Math.abs(Math.cos(angle+delta_ang));
+        int w = imageOriginalWidth, h = imageOriginalHeight;
+        int neww = (int)Math.floor(w*cos+h*sin);
+        int newh = (int)Math.floor(h*cos+w*sin);
         GraphicsConfiguration gc = getDefaultConfiguration();
-        BufferedImage result = gc.createCompatibleImage(neww, newh, Transparency.TRANSLUCENT);
+        BufferedImage result = gc.createCompatibleImage(neww, newh, image.getTransparency());
         Graphics2D g = result.createGraphics();
-        g.translate((neww-w)/2, (newh-h)/2);
-        g.rotate(angle, w/2, h/2);
+        g.translate((neww-image.getWidth())/2, (newh-image.getHeight())/2);
+        g.rotate(delta_ang, image.getWidth()/2, image.getHeight()/2);
         g.drawRenderedImage(image, null);
         g.dispose();
-        return result;
+        image = result;
+        EastNorthBound enb = computeNewBounding(orgCroppedRaster[0], orgCroppedRaster[1], orgCroppedRaster[2], orgCroppedRaster[3]);
+        min = enb.min;
+        max = enb.max;
+        angle+=delta_ang;
+    }
+    
+    /**
+     * Crop the image based on new bbox coordinates adj1 and adj2 (for raster images only).
+     * @param adj1 is the new corner bottom, left
+     * @param adj2 is the new corner top, right
+     */
+    public void crop(EastNorth adj1, EastNorth adj2) {
+        // s1 and s2 have 0,0 at top, left where all EastNorth coord. have 0,0 at bottom, left
+        int sx1 = (int)((adj1.getX() - min.getX())*getPixelPerEast());
+        int sy1 = (int)((max.getY() - adj2.getY())*getPixelPerNorth());
+        int sx2 = (int)((adj2.getX() - min.getX())*getPixelPerEast());
+        int sy2 = (int)((max.getY() - adj1.getY())*getPixelPerNorth());
+        int newWidth = Math.abs(sx2 - sx1);
+        int newHeight = Math.abs(sy2 - sy1);
+        BufferedImage new_img = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
+        Graphics g = new_img.getGraphics();
+        g.drawImage(image, 0, 0, newWidth-1, newHeight-1,
+                sx1, sy1, sx2, sy2,
+                this);
+        image = new_img;
+        this.min = adj1;
+        this.max = adj2;
+        this.orgCroppedRaster[0] = min;
+        this.orgCroppedRaster[1] = new EastNorth(min.east(), max.north());
+        this.orgCroppedRaster[2] = max;
+        this.orgCroppedRaster[3] = new EastNorth(max.east(), min.north());
+        this.imageOriginalWidth = newWidth;
+        this.imageOriginalHeight = newHeight;
+        updatePixelPer();
+    }
+
+    @Override
+    public boolean imageUpdate(Image img, int infoflags, int x, int y,
+            int width, int height) {
+        return false;
     }
 
 }
diff --git a/cadastre-fr/src/cadastre_fr/ImageModifier.java b/cadastre-fr/src/cadastre_fr/ImageModifier.java
index a0c86c7..82b7700 100644
--- a/cadastre-fr/src/cadastre_fr/ImageModifier.java
+++ b/cadastre-fr/src/cadastre_fr/ImageModifier.java
@@ -1,7 +1,12 @@
 // License: GPL. v2 and later. Copyright 2008-2009 by Pieren <pieren3 at gmail.com> and others
+// Some of the procedures below are imported from image4j.sourceforge.net, license LGPL.
 package cadastre_fr;
 
+import java.awt.Transparency;
 import java.awt.image.BufferedImage;
+import java.awt.image.ColorConvertOp;
+import java.awt.image.DataBuffer;
+import java.awt.image.IndexColorModel;
 
 public abstract class ImageModifier {
     /**
@@ -13,4 +18,92 @@ public abstract class ImageModifier {
 
     public BufferedImage bufferedImage;
 
+    protected BufferedImage convert1(BufferedImage src) {
+        IndexColorModel icm = new IndexColorModel(
+            1, 2, new byte[] { (byte) 0, (byte) 0xFF },
+            new byte[] { (byte) 0, (byte) 0xFF },
+            new byte[] { (byte) 0, (byte) 0xFF }
+        );
+        
+        BufferedImage dest = new BufferedImage(
+            src.getWidth(), src.getHeight(),
+            BufferedImage.TYPE_BYTE_BINARY,
+            icm
+            );
+        
+        ColorConvertOp cco = new ColorConvertOp(
+            src.getColorModel().getColorSpace(),
+            dest.getColorModel().getColorSpace(),
+            null
+            );
+        
+        cco.filter(src, dest);
+        
+        return dest;
+      }
+
+    /**
+     * Converts the source image to 4-bit colour
+     * using the default 16-colour palette:
+     * <ul>
+     *  <li>black</li><li>dark red</li><li>dark green</li>
+     *  <li>dark yellow</li><li>dark blue</li><li>dark magenta</li>
+     *  <li>dark cyan</li><li>dark grey</li><li>light grey</li>
+     *  <li>red</li><li>green</li><li>yellow</li><li>blue</li>
+     *  <li>magenta</li><li>cyan</li><li>white</li>
+     * </ul>
+     * No transparency.
+     * @param src the source image to convert
+     * @return a copy of the source image with a 4-bit colour depth, with the default colour pallette
+     */
+    protected BufferedImage convert4(BufferedImage src) {
+        int[] cmap = new int[] {
+          0x000000, 0x800000, 0x008000, 0x808000,
+          0x000080, 0x800080, 0x008080, 0x808080,
+          0xC0C0C0, 0xFF0000, 0x00FF00, 0xFFFF00,
+          0x0000FF, 0xFF00FF, 0x00FFFF, 0xFFFFFF
+        };
+        return convert4(src, cmap);
+      }
+        
+      /**
+       * Converts the source image to 4-bit colour
+       * using the given colour map.  No transparency.
+       * @param src the source image to convert
+       * @param cmap the colour map, which should contain no more than 16 entries
+       * The entries are in the form RRGGBB (hex).
+       * @return a copy of the source image with a 4-bit colour depth, with the custom colour pallette
+       */
+    protected BufferedImage convert4(BufferedImage src, int[] cmap) {
+        IndexColorModel icm = new IndexColorModel(
+            4, cmap.length, cmap, 0, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE
+            );
+        BufferedImage dest = new BufferedImage(
+            src.getWidth(), src.getHeight(),
+            BufferedImage.TYPE_BYTE_BINARY,
+            icm
+            );
+        ColorConvertOp cco = new ColorConvertOp(
+            src.getColorModel().getColorSpace(),
+            dest.getColorModel().getColorSpace(),
+            null
+            );
+        cco.filter(src, dest);
+        
+        return dest;
+      }
+      
+    protected BufferedImage convert8(BufferedImage src) {
+        BufferedImage dest = new BufferedImage(
+            src.getWidth(), src.getHeight(),
+            BufferedImage.TYPE_BYTE_INDEXED
+            );
+        ColorConvertOp cco = new ColorConvertOp(
+            src.getColorModel().getColorSpace(),
+            dest.getColorModel().getColorSpace(),
+            null
+            );
+        cco.filter(src, dest);
+        return dest;
+      }
 }
diff --git a/cadastre-fr/src/cadastre_fr/MenuActionGrabPlanImage.java b/cadastre-fr/src/cadastre_fr/MenuActionGrabPlanImage.java
index 506d555..447f4fb 100644
--- a/cadastre-fr/src/cadastre_fr/MenuActionGrabPlanImage.java
+++ b/cadastre-fr/src/cadastre_fr/MenuActionGrabPlanImage.java
@@ -7,8 +7,11 @@ import java.awt.GridBagLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
 import java.util.ArrayList;
 
+import javax.swing.JDialog;
 import javax.swing.JLabel;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
@@ -36,9 +39,12 @@ public class MenuActionGrabPlanImage extends JosmAction implements Runnable, Mou
     private int cGetCorners = 1;
     private int cGetLambertCrosspieces = 2;
     private EastNorth ea1;
+    private EastNorth ea2;
     private long mouseClickedTime = 0;
     private EastNorth georefpoint1;
     private EastNorth georefpoint2;
+    private boolean ignoreMouseClick = false;
+    
     /**
      * The time which needs to pass between two clicks during georeferencing, in milliseconds
      */
@@ -123,6 +129,9 @@ public class MenuActionGrabPlanImage extends JosmAction implements Runnable, Mou
         }
         else
             mouseClickedTime = System.currentTimeMillis();
+        if (e.getButton() != MouseEvent.BUTTON1)
+            return;
+        if (ignoreMouseClick) return; // In case we are currently just allowing zooming to read lambert coordinates
         countMouseClicked++;
         EastNorth ea = Main.proj.latlon2eastNorth(Main.map.mapView.getLatLon(e.getX(), e.getY()));
         System.out.println("clic:"+countMouseClicked+" ,"+ea+", mode:"+mode);
@@ -143,17 +152,11 @@ public class MenuActionGrabPlanImage extends JosmAction implements Runnable, Mou
         } else if (mode == cGetLambertCrosspieces) {
             if (countMouseClicked == 1) {
                 ea1 = ea;
-                if (inputLambertPosition())
-                    continueGeoreferencing();
+                inputLambertPosition(); // This will automatically asks for second point and continue the georeferencing
             }
             if (countMouseClicked == 2) {
-                if (inputLambertPosition()) {
-                    Main.map.mapView.removeMouseListener(this);
-                    affineTransform(ea1, ea, georefpoint1, georefpoint2);
-                    wmsLayer.saveNewCache();
-                    Main.map.mapView.repaint();
-                    actionCompleted();
-                }
+                ea2 = ea;
+                inputLambertPosition(); // This will automatically ends the georeferencing
             }
         }
     }
@@ -235,6 +238,17 @@ public class MenuActionGrabPlanImage extends JosmAction implements Runnable, Mou
 	    }
 	    return true;
     }
+    
+    /**
+     * Ends the georeferencing by computing the affine transformation
+     */
+    private void endGeoreferencing() {
+        Main.map.mapView.removeMouseListener(this);
+        affineTransform(ea1, ea2, georefpoint1, georefpoint2);
+        wmsLayer.saveNewCache();
+        Main.map.mapView.repaint();
+        actionCompleted();
+    }
 
     /**
      *
@@ -258,9 +272,11 @@ public class MenuActionGrabPlanImage extends JosmAction implements Runnable, Mou
         return true;
     }
 
-    private boolean inputLambertPosition() {
-        JLabel labelEnterPosition = new JLabel(tr("Enter cadastre east,north position"));
-        JLabel labelWarning = new JLabel(tr("(Warning: verify north with arrow !!)"));
+    private void inputLambertPosition() {
+        JLabel labelEnterPosition = new JLabel(
+                tr("Enter cadastre east,north position"));
+        JLabel labelWarning = new JLabel(
+                tr("(Warning: verify north with arrow !!)"));
         JPanel p = new JPanel(new GridBagLayout());
         JLabel labelEast = new JLabel(tr("East"));
         JLabel labelNorth = new JLabel(tr("North"));
@@ -272,30 +288,49 @@ public class MenuActionGrabPlanImage extends JosmAction implements Runnable, Mou
         p.add(inputEast, GBC.eol().fill(GBC.HORIZONTAL).insets(10, 5, 0, 5));
         p.add(labelNorth, GBC.std().insets(0, 0, 10, 0));
         p.add(inputNorth, GBC.eol().fill(GBC.HORIZONTAL).insets(10, 5, 0, 5));
-        JOptionPane pane = new JOptionPane(p, JOptionPane.INFORMATION_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null);
+        final JOptionPane pane = new JOptionPane(p,
+                JOptionPane.INFORMATION_MESSAGE, JOptionPane.OK_CANCEL_OPTION,
+                null);
         String number;
-        if (countMouseClicked == 1) number = "first";
-        else number = "second";
-        pane.createDialog(Main.parent, tr("Set {0} Lambert coordinates",number)).setVisible(true);
-        if (!Integer.valueOf(JOptionPane.OK_OPTION).equals(pane.getValue())) {
-            if (canceledOrRestartCurrAction("georeferencing"))
-                startGeoreferencing();
-            return false;
-        }
-        if (inputEast.getText().length() != 0 && inputNorth.getText().length() != 0) {
-            try {
-                double e = Double.parseDouble(inputEast.getText());
-                double n = Double.parseDouble(inputNorth.getText());
-                if (countMouseClicked == 1)
-                    georefpoint1 = new EastNorth(e, n);
-                else
-                    georefpoint2 = new EastNorth(e, n);
-                return true;
-            } catch (NumberFormatException e) {
-                return false;
+        if (countMouseClicked == 1)
+            number = "first";
+        else
+            number = "second";
+        JDialog dialog = pane.createDialog(Main.parent, tr(
+                "Set {0} Lambert coordinates", number));
+        dialog.setModal(false);
+        ignoreMouseClick = true; // To avoid mouseClicked from being called
+                                 // during coordinates reading
+        dialog.setAlwaysOnTop(true);
+        dialog.setVisible(true);
+        pane.addPropertyChangeListener(new PropertyChangeListener() {
+            public void propertyChange(PropertyChangeEvent evt) {
+                if (JOptionPane.VALUE_PROPERTY.equals(evt.getPropertyName())) {
+                    ignoreMouseClick = false;
+                    if (!Integer.valueOf(JOptionPane.OK_OPTION).equals(
+                            pane.getValue())) {
+                        if (canceledOrRestartCurrAction("georeferencing"))
+                            startGeoreferencing();
+                    }
+                    if (inputEast.getText().length() != 0
+                            && inputNorth.getText().length() != 0) {
+                        try {
+                            double e = Double.parseDouble(inputEast.getText());
+                            double n = Double.parseDouble(inputNorth.getText());
+                            if (countMouseClicked == 1) {
+                                georefpoint1 = new EastNorth(e, n);
+                                continueGeoreferencing();
+                            } else {
+                                georefpoint2 = new EastNorth(e, n);
+                                endGeoreferencing();
+                            }
+                        } catch (NumberFormatException e) {
+                            return;
+                        }
+                    }
+                }
             }
-        }
-        return false;
+        });
     }
 
     /**
diff --git a/cadastre-fr/src/cadastre_fr/MenuActionLoadFromCache.java b/cadastre-fr/src/cadastre_fr/MenuActionLoadFromCache.java
index 81ec64b..c98b8cb 100644
--- a/cadastre-fr/src/cadastre_fr/MenuActionLoadFromCache.java
+++ b/cadastre-fr/src/cadastre_fr/MenuActionLoadFromCache.java
@@ -74,9 +74,9 @@ public class MenuActionLoadFromCache extends JosmAction {
                     }
                     // create layer and load cache
                     WMSLayer wmsLayer = new WMSLayer("", "", Integer.parseInt(ext)-1);
-                    if (wmsLayer.getCacheControl().loadCache(file, layoutZone))
-                        Main.main.addLayer(wmsLayer);
-                    
+                    if (wmsLayer.getCacheControl().loadCache(file, layoutZone)) {
+                        CadastrePlugin.addWMSLayer(wmsLayer);
+                    }                    
                 }
             }
         }
diff --git a/cadastre-fr/src/cadastre_fr/MenuActionNewLocation.java b/cadastre-fr/src/cadastre_fr/MenuActionNewLocation.java
index 1d40d5e..9a26700 100644
--- a/cadastre-fr/src/cadastre_fr/MenuActionNewLocation.java
+++ b/cadastre-fr/src/cadastre_fr/MenuActionNewLocation.java
@@ -38,7 +38,7 @@ public class MenuActionNewLocation extends JosmAction {
         String location = "";
         String codeDepartement = "";
         String codeCommune = "";
-        boolean resetCookie = false;
+        boolean changeInterface = false;
         JLabel labelSectionNewLocation = new JLabel(tr("Add a new layer"));
         JPanel p = new JPanel(new GridBagLayout());
         JLabel labelLocation = new JLabel(tr("Location"));
@@ -65,7 +65,7 @@ public class MenuActionNewLocation extends JosmAction {
         WMSLayer wmsLayer = null;
         if (!inputTown.getText().equals("")) {
             location = inputTown.getText().toUpperCase();
-            resetCookie = true;
+            changeInterface = true;
             Main.pref.put("cadastrewms.location", location);
             Main.pref.put("cadastrewms.codeCommune", codeCommune);
             if (Main.map != null) {
@@ -84,15 +84,15 @@ public class MenuActionNewLocation extends JosmAction {
             else if (Main.proj instanceof UTM_20N_France_DOM)
                 zone = ((UTM_20N_France_DOM)Main.proj).getCurrentGeodesic();
             wmsLayer = new WMSLayer(location, codeCommune, zone);
-            Main.main.addLayer(wmsLayer);
+            CadastrePlugin.addWMSLayer(wmsLayer);
             System.out.println("Add new layer with Location:" + inputTown.getText());
         } else if (existingLayers != null && existingLayers.size() > 0 && Main.map.mapView.getActiveLayer() instanceof WMSLayer) {
             wmsLayer = (WMSLayer)Main.map.mapView.getActiveLayer();
-            resetCookie = true;
+            changeInterface = true;
         }
 
-        if (resetCookie)
-            CadastrePlugin.cadastreGrabber.getWmsInterface().resetCookieIfNewLayer(wmsLayer.getName());
+        if (changeInterface)
+            CadastrePlugin.cadastreGrabber.getWmsInterface().resetInterfaceRefIfNewLayer(wmsLayer.getName());
         return wmsLayer;
     }
 
diff --git a/cadastre-fr/src/cadastre_fr/SimplifyWay.java b/cadastre-fr/src/cadastre_fr/SimplifyWay.java
index d6a8b35..525126f 100644
--- a/cadastre-fr/src/cadastre_fr/SimplifyWay.java
+++ b/cadastre-fr/src/cadastre_fr/SimplifyWay.java
@@ -16,8 +16,8 @@ import org.openstreetmap.josm.command.DeleteCommand;
 import org.openstreetmap.josm.command.SequenceCommand;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.data.osm.visitor.CollectBackReferencesVisitor;
 import static org.openstreetmap.josm.tools.I18n.trn;
 
  
@@ -32,15 +32,18 @@ public class SimplifyWay {
         Way wnew = new Way(w);
 
         int toI = wnew.getNodesCount() - 1;
+        List<OsmPrimitive> parents = new ArrayList<OsmPrimitive>();
         for (int i = wnew.getNodesCount() - 1; i >= 0; i--) {
-            CollectBackReferencesVisitor backRefsV = new CollectBackReferencesVisitor(dataSet, false);
-            backRefsV.visit(wnew.getNode(i));
+            //CollectBackReferencesVisitor backRefsV = new CollectBackReferencesVisitor(dataSet, false);
+            //backRefsV.visit(wnew.getNode(i));
+           parents.addAll(w.getNode(i).getReferrers());
             boolean used = false;
-            if (backRefsV.getData().size() == 1) {
+            if (parents.size() == 1) {
                 used = Collections.frequency(w.getNodes(), wnew.getNode(i)) > 1;
             } else {
-                backRefsV.getData().remove(w);
-                used = !backRefsV.getData().isEmpty();
+                //backRefsV.getData().remove(w);
+                parents.remove(w);
+                used = !parents.isEmpty();
             }
             if (!used)
                 used = wnew.getNode(i).isTagged();
diff --git a/cadastre-fr/src/cadastre_fr/VectorImageModifier.java b/cadastre-fr/src/cadastre_fr/VectorImageModifier.java
index befd3bc..81249f7 100644
--- a/cadastre-fr/src/cadastre_fr/VectorImageModifier.java
+++ b/cadastre-fr/src/cadastre_fr/VectorImageModifier.java
@@ -15,12 +15,8 @@ public class VectorImageModifier extends ImageModifier {
     
     public static int cadastreBackgroundTransp = 1; // original white but transparent
 
-    private boolean withBackground = false;
-
     private int backgroundPixel = 0;
 
-    private int backgroundSampleX, backgroundSampleY;
-
     public VectorImageModifier(BufferedImage bi) {
         bufferedImage = bi;
         if (Main.pref.getBoolean("cadastrewms.backgroundTransparent"))
@@ -29,6 +25,7 @@ public class VectorImageModifier extends ImageModifier {
             replaceBackground();
         if (Main.pref.getBoolean("cadastrewms.invertGrey"))
             invertGrey();
+        //bufferedImage = convert8(convert1(bufferedImage));
     }
 
     /**
@@ -43,13 +40,11 @@ public class VectorImageModifier extends ImageModifier {
                 int pixel = bufferedImage.getRGB(x, y);
                 if (pixel == cadastreBackground) {
                     bufferedImage.setRGB(x, y, josmBackgroundColor);
-                    if (!withBackground)
-                        withBackground = true;
-                    backgroundSampleX = x;
-                    backgroundSampleY = y;
                 }
             }
         }
+        // The cadastre has now a new background (for invertGrey())
+        cadastreBackground = josmBackgroundColor;
     }
 
     /**
@@ -80,8 +75,11 @@ public class VectorImageModifier extends ImageModifier {
         int g = col.getGreen();
         int b = col.getBlue();
         if ((b == r) && (b == g)) {
-            pixel = (0x00 << 32) + ((byte) (255 - r) << 16) + ((byte) (255 - r) << 8) + ((byte) (255 - r));
+            pixel = ((byte) col.getAlpha() << 24) + ((byte) (255 - r) << 16) + ((byte) (255 - r) << 8) + ((byte) (255 - r));
         }
+        // Maybe we should try to find a better formula to avoid discontinuity when text is drawn on a colored item
+        // (building, ...). One could use the conversion to and from HSB to only change the brightness not the color.
+        // Note: the color palette does not have the inverse colors so it may be very weird!
         return pixel;
     }
 
@@ -92,10 +90,7 @@ public class VectorImageModifier extends ImageModifier {
             IndexColorModel icm = (IndexColorModel) colorModel;
             WritableRaster raster = bufferedImage.getRaster();
             // pixel is offset in ICM's palette
-            if (withBackground)
-                backgroundPixel = raster.getSample(backgroundSampleX, backgroundSampleY, 0);
-            else
-                backgroundPixel = 1; // default Cadastre background sample
+            backgroundPixel = 1; // default Cadastre background sample
             int size = icm.getMapSize();
             byte[] reds = new byte[size];
             byte[] greens = new byte[size];
@@ -103,6 +98,8 @@ public class VectorImageModifier extends ImageModifier {
             icm.getReds(reds);
             icm.getGreens(greens);
             icm.getBlues(blues);
+            // The cadastre background has now an alpha to 0 (for invertGrey())
+            cadastreBackground = 0x00ffffff;
             IndexColorModel icm2 = new IndexColorModel(colorModel.getPixelSize(), size, reds, greens, blues,
                     backgroundPixel);
             bufferedImage = new BufferedImage(icm2, raster, bufferedImage.isAlphaPremultiplied(), null);
diff --git a/cadastre-fr/src/cadastre_fr/WMSAdjustAction.java b/cadastre-fr/src/cadastre_fr/WMSAdjustAction.java
index 95cb1d8..28d265a 100644
--- a/cadastre-fr/src/cadastre_fr/WMSAdjustAction.java
+++ b/cadastre-fr/src/cadastre_fr/WMSAdjustAction.java
@@ -3,7 +3,10 @@ package cadastre_fr;
 
 import static org.openstreetmap.josm.tools.I18n.tr;
 
+import java.awt.Color;
 import java.awt.Cursor;
+import java.awt.Graphics2D;
+import java.awt.Toolkit;
 import java.awt.event.ActionEvent;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
@@ -14,6 +17,7 @@ import javax.swing.JOptionPane;
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.MapView;
 import org.openstreetmap.josm.actions.mapmode.MapMode;
 import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -28,7 +32,8 @@ public class WMSAdjustAction extends MapMode implements
     private boolean rasterMoved;
     private EastNorth prevEastNorth;
     enum Mode { moveXY, moveZ, rotate}
-    private Mode mode = null;
+    private static Mode mode = null;
+    private static EastNorth[] croppedRaster = new EastNorth[5];;
 
     public WMSAdjustAction(MapFrame mapFrame) {
         super(tr("Adjust WMS"), "adjustxywms",
@@ -58,9 +63,12 @@ public class WMSAdjustAction extends MapMode implements
                 Main.map.mapView.addMouseListener(this);
                 Main.map.mapView.addMouseMotionListener(this);
                 rasterMoved = false;
+                selectedLayer.adjustModeEnabled = true;
             } else {
                 JOptionPane.showMessageDialog(Main.parent,tr("This mode works only if active layer is\n"
                         +"a cadastre \"plan image\" (raster image)"));
+                exitMode();
+                Main.map.selectMapMode((MapMode)Main.map.getDefaultButtonAction());
             }
         }
     }
@@ -79,19 +87,22 @@ public class WMSAdjustAction extends MapMode implements
             }
         }
         modifiedLayers.clear();
-        selectedLayer = null;
+        if (selectedLayer != null) {
+            selectedLayer.adjustModeEnabled = false;
+            selectedLayer = null;
+        }
     }
 
     @Override
     public void mousePressed(MouseEvent e) {
         if (e.getButton() != MouseEvent.BUTTON1)
             return;
-        boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;
+        boolean ctrl = (e.getModifiers() & Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()) != 0;
         // boolean alt = (e.getModifiers() & ActionEvent.ALT_MASK) != 0;
         boolean shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0;
-        if (shift)
+        if (shift && !ctrl)
             mode = Mode.moveZ;
-        else if (ctrl)
+        else if (shift && ctrl)
             mode = Mode.rotate;
         else
             mode = Mode.moveXY;
@@ -102,17 +113,30 @@ public class WMSAdjustAction extends MapMode implements
 
     @Override public void mouseDragged(MouseEvent e) {
         EastNorth newEastNorth = Main.map.mapView.getEastNorth(e.getX(),e.getY());
-        if (mode == Mode.moveXY) {
-            displace(prevEastNorth, newEastNorth);
-        } else if (mode == Mode.moveZ) {
-            resize(newEastNorth);
-        } else if (mode == Mode.rotate) {
-            rotate(prevEastNorth, newEastNorth);
+        if (mode == Mode.rotate) {
+            rotateFrameOnly(prevEastNorth, newEastNorth);
+        } else {
+            if (mode == Mode.moveXY) {
+                displace(prevEastNorth, newEastNorth);
+            } else if (mode == Mode.moveZ) {
+                resize(newEastNorth);
+            } 
+            prevEastNorth = newEastNorth;
         }
         if (!modifiedLayers.contains(selectedLayer))
             modifiedLayers.add(selectedLayer);
         Main.map.mapView.repaint();
-        prevEastNorth = newEastNorth;
+    }
+    
+    public static void paintAdjustFrames(Graphics2D g, final MapView mv) {
+        if (mode == Mode.rotate && croppedRaster != null) {
+            g.setColor(Color.red);
+            for (int i=0; i<4; i++)
+                g.drawLine(mv.getPoint(croppedRaster[i]).x,
+                        mv.getPoint(croppedRaster[i]).y,
+                        mv.getPoint(croppedRaster[i+1]).x,
+                        mv.getPoint(croppedRaster[i+1]).y);
+        }
     }
 
     private void displace(EastNorth start, EastNorth end) {
@@ -134,8 +158,28 @@ public class WMSAdjustAction extends MapMode implements
         selectedLayer.rotate(pivot, rotationAngle);
     }
 
+    private void rotateFrameOnly(EastNorth start, EastNorth end) {
+        if (start != null && end != null) {
+            EastNorth pivot = selectedLayer.getRasterCenter();
+            double startAngle = Math.atan2(start.east()-pivot.east(), start.north()-pivot.north());
+            double endAngle = Math.atan2(end.east()-pivot.east(), end.north()-pivot.north());
+            double rotationAngle = endAngle - startAngle;
+            if (selectedLayer.images.get(0).orgCroppedRaster != null) {
+                for (int i=0; i<4; i++) {
+                    croppedRaster[i] = selectedLayer.images.get(0).orgCroppedRaster[i].rotate(pivot, rotationAngle);
+                }
+                croppedRaster[4] = croppedRaster[0];
+            }
+        }
+    }
+
     @Override public void mouseReleased(MouseEvent e) {
         //Main.map.mapView.repaint();
+        if (mode == Mode.rotate) {
+            EastNorth newEastNorth = Main.map.mapView.getEastNorth(e.getX(),e.getY());
+            rotate(prevEastNorth, newEastNorth);
+            Main.map.mapView.repaint();
+        }
         Main.map.mapView.setCursor(Cursor.getDefaultCursor());
         prevEastNorth = null;
         mode = null;
diff --git a/cadastre-fr/src/cadastre_fr/WMSDownloadAction.java b/cadastre-fr/src/cadastre_fr/WMSDownloadAction.java
index 082f76d..f6af8eb 100644
--- a/cadastre-fr/src/cadastre_fr/WMSDownloadAction.java
+++ b/cadastre-fr/src/cadastre_fr/WMSDownloadAction.java
@@ -40,8 +40,12 @@ public class WMSDownloadAction extends JosmAction {
                 return existingWMSlayers.get(0);
             if (existingWMSlayers.size() == 0)
                 return new MenuActionNewLocation().addNewLayer(existingWMSlayers);
-            JOptionPane.showMessageDialog(Main.parent,
-                    tr("More than one WMS layer present\nSelect one of them first, then retry"));
+            if (Main.pref.getBoolean("cadastrewms.autoFirstLayer", false)) {
+                return existingWMSlayers.get(0);
+            } else {
+                JOptionPane.showMessageDialog(Main.parent,
+                        tr("More than one WMS layer present\nSelect one of them first, then retry"));
+            }
         } else {
             return new MenuActionNewLocation().addNewLayer(existingWMSlayers);
         }
diff --git a/cadastre-fr/src/cadastre_fr/WMSLayer.java b/cadastre-fr/src/cadastre_fr/WMSLayer.java
index 5a9972c..7db4c44 100644
--- a/cadastre-fr/src/cadastre_fr/WMSLayer.java
+++ b/cadastre-fr/src/cadastre_fr/WMSLayer.java
@@ -9,6 +9,7 @@ import java.awt.Graphics;
 import java.awt.Graphics2D;
 import java.awt.Image;
 import java.awt.Point;
+import java.awt.RenderingHints;
 import java.awt.Toolkit;
 import java.awt.image.BufferedImage;
 import java.awt.image.ImageObserver;
@@ -50,7 +51,14 @@ public class WMSLayer extends Layer implements ImageObserver {
 
     protected Vector<GeorefImage> images = new Vector<GeorefImage>();
 
-    protected final int serializeFormatVersion = 2;
+    /**
+     * v1 to v2 = not supported
+     * v2 to v3 = add 4 more EastNorth coordinates in GeorefImages
+     * v3 to v4 = add original raster image width and height
+     */
+    protected final int serializeFormatVersion = 4;
+    
+    public static int currentFormat;
 
     private ArrayList<EastNorthBound> dividedBbox = new ArrayList<EastNorthBound>();
 
@@ -68,11 +76,14 @@ public class WMSLayer extends Layer implements ImageObserver {
 
     public double X0, Y0, angle, fX, fY;
 
+    // bbox of the georeferenced raster image (the nice horizontal and vertical box)
     private EastNorth rasterMin;
     private EastNorth rasterMax;
     private double rasterRatio;
 
     private JMenuItem saveAsPng;
+    
+    public boolean adjustModeEnabled;
 
     public WMSLayer() {
         this(tr("Blank Layer"), "", -1);
@@ -87,6 +98,20 @@ public class WMSLayer extends Layer implements ImageObserver {
         CadastrePlugin.pluginUsed = true;
     }
 
+    public void destroy() {
+        // if the layer is currently saving the images in the cache, wait until it's finished
+        if (cacheControl != null) {
+            while (!cacheControl.isCachePipeEmpty()) {
+                System.out.println("Try to close a WMSLayer which is currently saving in cache : wait 1 sec.");
+                CadastrePlugin.safeSleep(1000);
+            }
+        }
+        super.destroy();
+        images = null;
+        dividedBbox = null;
+        System.out.println("Layer "+location+" destroyed");
+    }
+    
     private static String buildName(String location, String codeCommune) {
         String ret = new String(location.toUpperCase());
         if (codeCommune != null && !codeCommune.equals(""))
@@ -210,13 +235,26 @@ public class WMSLayer extends Layer implements ImageObserver {
     @Override
     public void paint(Graphics2D g, final MapView mv, Bounds bounds) {
         synchronized(this){
+            Object savedInterpolation = g.getRenderingHint(RenderingHints.KEY_INTERPOLATION);
+            if (savedInterpolation == null) savedInterpolation = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR;
+            String interpolation = Main.pref.get("cadastrewms.imageInterpolation", "standard");
+            if (interpolation.equals("bilinear"))
+                g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
+            else if (interpolation.equals("bicubic"))
+                g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
+            else
+                g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
             for (GeorefImage img : images)
                 img.paint(g, mv, CadastrePlugin.backgroundTransparent,
                         CadastrePlugin.transparency, CadastrePlugin.drawBoundaries);
+            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, savedInterpolation);
         }
         if (this.isRaster) {
             paintCrosspieces(g, mv);
         }
+        if (this.adjustModeEnabled) {
+            WMSAdjustAction.paintAdjustFrames(g, mv);
+        }            
     }
 
     @Override
@@ -356,8 +394,8 @@ public class WMSLayer extends Layer implements ImageObserver {
         double rasterSizeY = communeBBox.max.getY() - communeBBox.min.getY();
         double ratio = rasterSizeY/rasterSizeX;
         // keep same ratio on screen as WMS bbox (stored in communeBBox)
-        rasterMin = new EastNorth(eaMin.getX(), rasterCenter.getY()-(eaMax.getX()-eaMin.getX())*ratio/2);
-        rasterMax = new EastNorth(eaMax.getX(), rasterCenter.getY()+(eaMax.getX()-eaMin.getX())*ratio/2);
+        rasterMin = new EastNorth(eaMin.getX(), rasterCenter.getY()-(eaMax.getX()-eaMin.getX())*ratio/2); 
+        rasterMax = new EastNorth(eaMax.getX(), rasterCenter.getY()+(eaMax.getX()-eaMin.getX())*ratio/2); 
         rasterRatio = (rasterMax.getX()-rasterMin.getX())/rasterSizeX;
     }
 
@@ -394,10 +432,10 @@ public class WMSLayer extends Layer implements ImageObserver {
      * @throws ClassNotFoundException
      */
     public boolean read(ObjectInputStream ois, int currentLambertZone) throws IOException, ClassNotFoundException {
-        int sfv = ois.readInt();
-        if (sfv != this.serializeFormatVersion) {
+        currentFormat = ois.readInt();;
+        if (currentFormat < 2) {
             JOptionPane.showMessageDialog(Main.parent, tr("Unsupported cache file version; found {0}, expected {1}\nCreate a new one.",
-                    sfv, this.serializeFormatVersion), tr("Cache Format Error"), JOptionPane.ERROR_MESSAGE);
+                    currentFormat, this.serializeFormatVersion), tr("Cache Format Error"), JOptionPane.ERROR_MESSAGE);
             return false;
         }
         this.setLocation((String) ois.readObject());
@@ -497,24 +535,12 @@ public class WMSLayer extends Layer implements ImageObserver {
         // adj2 is corner top, right
         EastNorth adj2 = new EastNorth(en1.east() > en2.east() ? en1.east() : en2.east(),
                 en1.north() > en2.north() ? en1.north() : en2.north());
-        // s1 and s2 have 0,0 at top, left where all EastNorth coord. have 0,0 at bottom, left
-        int sx1 = (int)((adj1.getX() - images.get(0).min.getX())*images.get(0).getPixelPerEast());
-        int sy1 = (int)((images.get(0).max.getY() - adj2.getY())*images.get(0).getPixelPerNorth());
-        int sx2 = (int)((adj2.getX() - images.get(0).min.getX())*images.get(0).getPixelPerEast());
-        int sy2 = (int)((images.get(0).max.getY() - adj1.getY())*images.get(0).getPixelPerNorth());
-        int newWidth = Math.abs(sx2 - sx1);
-        int newHeight = Math.abs(sy2 - sy1);
-        BufferedImage new_img = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
-        Graphics g = new_img.getGraphics();
-        g.drawImage(images.get(0).image, 0, 0, newWidth-1, newHeight-1,
-                sx1, sy1, sx2, sy2,
-                this);
-        images.set(0, new GeorefImage(new_img, adj1, adj2));
-        // important: update the layer georefs !
+        images.get(0).crop(adj1, adj2);
+        // update the layer georefs
         rasterMin = adj1;
         rasterMax = adj2;
+        setCommuneBBox(new EastNorthBound(new EastNorth(0,0), new EastNorth(images.get(0).image.getWidth()-1,images.get(0).image.getHeight()-1)));
         rasterRatio = (rasterMax.getX()-rasterMin.getX())/(communeBBox.max.getX() - communeBBox.min.getX());
-        setCommuneBBox(new EastNorthBound(new EastNorth(0,0), new EastNorth(newWidth-1,newHeight-1)));
     }
 
     public EastNorthBound getCommuneBBox() {
@@ -523,8 +549,6 @@ public class WMSLayer extends Layer implements ImageObserver {
 
     public void setCommuneBBox(EastNorthBound entireCommune) {
         this.communeBBox = entireCommune;
-//        if (Main.proj instanceof LambertCC9Zones)
-//            setLambertCC9Zone(communeBBox.min.north());
     }
 
     /**
@@ -538,32 +562,6 @@ public class WMSLayer extends Layer implements ImageObserver {
         return lambertZone;
     }
 
-//    public void setLambertCC9Zone(double north) {
-//        int lambertZone = LambertCC9Zones.north2ZoneNumber(north);
-//        this.lambertZone = lambertZone;
-//        if (((LambertCC9Zones)Main.proj).getLayoutZone() != lambertZone) {
-//            String currentZone = MenuActionLambertZone.lambert9zones[((LambertCC9Zones)Main.proj).getLayoutZone()+1];
-//            String destZone = MenuActionLambertZone.lambert9zones[lambertZone+1];
-//            if (Main.map.mapView.getAllLayers().size() == 1) {
-//                /* Enable this code below when JOSM will have a proper support of dynamic projection change
-//                 *
-//                System.out.println("close all layers and change current Lambert zone from "+LambertCC9Zones.layoutZone+" to "+lambertZone);
-//                Bounds b = null;
-//                if (Main.map != null && Main.map.mapView != null)
-//                    b = Main.map.mapView.getRealBounds();
-//                LambertCC9Zones.layoutZone = lambertZone;
-//                Main.map.mapView.zoomTo(b);
-//                */
-//            } else {
-//                JOptionPane.showMessageDialog(Main.parent, tr("Current layer is in Lambert CC9 Zone \"{0}\"\n"+
-//                        "where the commune is in Lambert CC9 Zone \"{1}\".\n"+
-//                        "Upload your changes, close all layers and change\n"+
-//                        "manually the Lambert zone from the Cadastre menu"
-//                        , currentZone, destZone));
-//            }
-//        }
-//    }
-
     public EastNorth getRasterCenter() {
         return new EastNorth((images.get(0).max.east()+images.get(0).min.east())/2,
                 (images.get(0).max.north()+images.get(0).min.north())/2);
@@ -571,24 +569,30 @@ public class WMSLayer extends Layer implements ImageObserver {
 
     public void displace(double dx, double dy) {
         this.rasterMin = new EastNorth(rasterMin.east() + dx, rasterMin.north() + dy);
+        this.rasterMax = new EastNorth(rasterMax.east() + dx, rasterMax.north() + dy);
         images.get(0).shear(dx, dy);
     }
 
     public void resize(EastNorth rasterCenter, double proportion) {
         this.rasterMin = rasterMin.interpolate(rasterCenter, proportion);
+        this.rasterMax = rasterMax.interpolate(rasterCenter, proportion);
         images.get(0).scale(rasterCenter, proportion);
     }
 
     public void rotate(EastNorth rasterCenter, double angle) {
         this.rasterMin = rasterMin.rotate(rasterCenter, angle);
+        this.rasterMax = rasterMax.rotate(rasterCenter, angle);
+//        double proportion = dst1.distance(dst2)/org1.distance(org2);
         images.get(0).rotate(rasterCenter, angle);
+        this.angle += angle; 
     }
 
     private void paintCrosspieces(Graphics g, MapView mv) {
         String crosspieces = Main.pref.get("cadastrewms.crosspieces", "0");
         if (!crosspieces.equals("0")) {
-            int modulo = 50;
-            if (crosspieces.equals("2")) modulo = 100;
+            int modulo = 25;
+            if (crosspieces.equals("2")) modulo = 50;
+            if (crosspieces.equals("3")) modulo = 100;
             EastNorthBound currentView = new EastNorthBound(mv.getEastNorth(0, mv.getHeight()),
                     mv.getEastNorth(mv.getWidth(), 0));
             int minX = ((int)currentView.min.east()/modulo+1)*modulo;
diff --git a/colorscheme/build.xml b/colorscheme/build.xml
index 3cde739..c06e3b9 100644
--- a/colorscheme/build.xml
+++ b/colorscheme/build.xml
@@ -1,57 +1,187 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+** This is the build file for the colorscheme plugin
+**
+** Maintaining versions
+** ====================
+** see README.template
+**
+** Usage
+** =====
+** To build it run
+**
+**    > ant  dist
+**
+** To install the generated plugin locally (in your default plugin directory) run
+**
+**    > ant  install
+**
+** To build against the core in ../../core, create a correct manifest and deploy to
+** SVN, 
+**    set the properties commit.message and plugin.main.version
+** and run
+**    > ant  publish
+**
+**
+-->
 <project name="colorscheme" 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}">
-            <fileset dir="src">
-                <include name="*.xml"/>
-            </fileset>
-        </copy>
-        <jar destfile="${plugin.jar}" basedir="${plugin.build.dir}">
-            <manifest>
-                <attribute name="Author" value="Christof Dallermassl"/>
-                <attribute name="Plugin-Class" value="at.dallermassl.josm.plugin.colorscheme.ColorSchemePlugin" />
-                <attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
-                <attribute name="Plugin-Description" value="Allows the user to create different color schemes and to switch between them. Just change the colors and create a new scheme. Used to switch to a white background with matching colors for better visibility in bright sunlight. See dialog in JOSM's preferences and 'Map Settings' (strange but true :-)" />
-                <attribute name="Plugin-Mainversion" value="1742"/>
-                <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>
+
+
+	<property name="commit.message" value="Uses new constructor for Plugin" />
+	<property name="plugin.main.version" value="2830" />
+
+	<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}">
+			<fileset dir="src">
+				<include name="*.xml"/>
+			</fileset>
+		</copy>
+		<jar destfile="${plugin.jar}" basedir="${plugin.build.dir}">
+			<manifest>
+				<attribute name="Author" value="Christof Dallermassl"/>
+				<attribute name="Plugin-Class" value="at.dallermassl.josm.plugin.colorscheme.ColorSchemePlugin" />
+				<attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
+				<attribute name="Plugin-Description" value="Allows the user to create different color schemes and to switch between them. Just change the colors and create a new scheme. Used to switch to a white background with matching colors for better visibility in bright sunlight. See dialog in JOSM's preferences and 'Map Settings' (strange but true :-)" />
+				<attribute name="Plugin-Mainversion" value="${plugin.main.version}"/>
+				<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>
+
+	<!--
+	 ************************** Publishing the plugin *********************************** 
+	-->
+	<!--
+	** extracts the JOSM release for the JOSM version in ../core and saves it in the 
+	** property ${coreversion.info.entry.revision}
+	**
+	-->
+	<target name="core-info">
+		<exec append="false" output="core.info.xml" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="info"/>
+			<arg value="--xml"/>
+			<arg value="../../core"/>
+		</exec>
+		<xmlproperty file="core.info.xml" prefix="coreversion" keepRoot="true" collapseAttributes="true"/>
+		<echo>Building against core revision ${coreversion.info.entry.revision}.</echo>
+		<echo>Plugin-Mainversion is set to ${plugin.main.version}.</echo>
+		<delete file="core.info.xml" />
+	</target>
+
+	<!--
+	** commits the source tree for this plugin
+	-->
+	<target name="commit-current">
+		<echo>Commiting the plugin source with message '${commit.message}' ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="commit"/>
+			<arg value="-m '${commit.message}'"/>
+			<arg value="."/>
+		</exec>
+	</target>
+
+	<!--
+	** updates (svn up) the source tree for this plugin
+	-->
+	<target name="update-current">
+		<echo>Updating plugin source ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="up"/>
+			<arg value="."/>
+		</exec>
+		<echo>Updating ${plugin.jar} ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="up"/>
+			<arg value="../dist/${plugin.jar}"/>
+		</exec>
+	</target>
+
+	<!--
+	** commits the plugin.jar 
+	-->
+	<target name="commit-dist">
+		<echo>
+***** Properties of published ${plugin.jar} *****
+Commit message    : '${commit.message}'					
+Plugin-Mainversion: ${plugin.main.version}
+JOSM build version: ${coreversion.info.entry.revision}
+Plugin-Version    : ${version.entry.commit.revision}
+***** / Properties of published ${plugin.jar} *****					
+					
+Now commiting ${plugin.jar} ...
+</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="-m '${commit.message}'"/>
+			<arg value="commit"/>
+			<arg value="${plugin.jar}"/>
+		</exec>
+	</target>
+
+	<!-- ** make sure svn is present as a command line tool ** -->
+	<target name="ensure-svn-present">
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false" failonerror="false" resultproperty="svn.exit.code">
+			<env key="LANG" value="C" />
+			<arg value="--version" />
+		</exec>
+		<fail message="Fatal: command 'svn --version' failed. Please make sure svn is installed on your system.">
+			<!-- return code not set at all? Most likely svn isn't installed -->
+			<condition>
+				<not>
+					<isset property="svn.exit.code" />
+				</not>
+			</condition>
+		</fail>
+		<fail message="Fatal: command 'svn --version' failed. Please make sure a working copy of svn is installed on your system.">
+			<!-- error code from SVN? Most likely svn is not what we are looking on this system -->
+			<condition>
+				<isfailure code="${svn.exit.code}" />
+			</condition>
+		</fail>
+	</target>
+
+	<target name="publish" depends="ensure-svn-present,core-info,commit-current,update-current,clean,dist,commit-dist">
+	</target>
 </project>
diff --git a/colorscheme/copyright.txt b/colorscheme/copyright.txt
index 871ae08..f79259b 100644
--- a/colorscheme/copyright.txt
+++ b/colorscheme/copyright.txt
@@ -3,4 +3,5 @@ Plugin colorscheme
 This plugin is copyrighted 2008-2009 
 by Christof Dallermassl <christof at dallermassl.at>.
 
-It is distributed under GPL-v2 license (see file  LICENSE in this directory).
+It is distributed under GPL-v3 or later license 
+(see file gpl-3.0.txt in this directory).
diff --git a/colorscheme/LICENSE b/colorscheme/gpl-2.0.txt
similarity index 98%
rename from colorscheme/LICENSE
rename to colorscheme/gpl-2.0.txt
index 37b7a4d..d511905 100644
--- a/colorscheme/LICENSE
+++ b/colorscheme/gpl-2.0.txt
@@ -1,12 +1,12 @@
-      GNU GENERAL PUBLIC LICENSE
-           Version 2, June 1991
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
 
  Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
-          Preamble
+			    Preamble
 
   The licenses for most software are designed to take away your
 freedom to share and change it.  By contrast, the GNU General Public
@@ -56,7 +56,7 @@ patent must be licensed for everyone's free use or not licensed at all.
   The precise terms and conditions for copying, distribution and
 modification follow.
 
-        GNU GENERAL PUBLIC LICENSE
+		    GNU GENERAL PUBLIC LICENSE
    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 
   0. This License applies to any program or other work which contains
@@ -255,7 +255,7 @@ make exceptions for this.  Our decision will be guided by the two goals
 of preserving the free status of all derivatives of our free software and
 of promoting the sharing and reuse of software generally.
 
-          NO WARRANTY
+			    NO WARRANTY
 
   11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
 FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
@@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
 PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGES.
 
-         END OF TERMS AND CONDITIONS
+		     END OF TERMS AND CONDITIONS
 
-      How to Apply These Terms to Your New Programs
+	    How to Apply These Terms to Your New Programs
 
   If you develop a new program, and you want it to be of the greatest
 possible use to the public, the best way to achieve this is to make it
diff --git a/colorscheme/gpl-3.0.txt b/colorscheme/gpl-3.0.txt
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/colorscheme/gpl-3.0.txt
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/colorscheme/src/at/dallermassl/josm/plugin/colorscheme/ColorSchemePlugin.java b/colorscheme/src/at/dallermassl/josm/plugin/colorscheme/ColorSchemePlugin.java
index 6bd746b..106cb48 100644
--- a/colorscheme/src/at/dallermassl/josm/plugin/colorscheme/ColorSchemePlugin.java
+++ b/colorscheme/src/at/dallermassl/josm/plugin/colorscheme/ColorSchemePlugin.java
@@ -6,6 +6,7 @@ package at.dallermassl.josm.plugin.colorscheme;
 
 import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
 import org.openstreetmap.josm.plugins.Plugin;
+import org.openstreetmap.josm.plugins.PluginInformation;
 
 /**
  * ColorScheme Plugin for JOSM.
@@ -17,8 +18,8 @@ public class ColorSchemePlugin extends Plugin {
     /**
      * Default Constructor
      */
-    public ColorSchemePlugin() {
-
+    public ColorSchemePlugin(PluginInformation info) {
+    	super(info);
     }
 
     @Override
diff --git a/colorscheme/src/at/dallermassl/josm/plugin/colorscheme/ColorSchemePreference.java b/colorscheme/src/at/dallermassl/josm/plugin/colorscheme/ColorSchemePreference.java
index 75a65c7..bcb784d 100644
--- a/colorscheme/src/at/dallermassl/josm/plugin/colorscheme/ColorSchemePreference.java
+++ b/colorscheme/src/at/dallermassl/josm/plugin/colorscheme/ColorSchemePreference.java
@@ -29,6 +29,7 @@ import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.gui.preferences.ColorPreference;
 import org.openstreetmap.josm.gui.preferences.PreferenceDialog;
 import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
+import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
 import org.openstreetmap.josm.tools.GBC;
 
 public class ColorSchemePreference implements PreferenceSetting {
@@ -50,7 +51,7 @@ public class ColorSchemePreference implements PreferenceSetting {
     /* (non-Javadoc)
      * @see org.openstreetmap.josm.gui.preferences.PreferenceSetting#addGui(org.openstreetmap.josm.gui.preferences.PreferenceDialog)
      */
-    public void addGui(final PreferenceDialog gui) {
+    public void addGui(final PreferenceTabbedPane gui) {
         Map<String, String> colorMap = Main.pref.getAllPrefix(PREF_KEY_COLOR_PREFIX);
         colorKeys = new ArrayList<String>(colorMap.keySet());
         Collections.sort(colorKeys);
@@ -176,7 +177,7 @@ public class ColorSchemePreference implements PreferenceSetting {
         return colorMap;
     }
 
-    public ColorPreference getColorPreference(PreferenceDialog gui) {
+    public ColorPreference getColorPreference(PreferenceTabbedPane gui) {
         if(colorPreference == null) {
             for(PreferenceSetting setting : gui.getSettings()) {
                 if(setting instanceof ColorPreference) {
diff --git a/editgpx/.classpath b/editgpx/.classpath
index 7d87ead..4a8596f 100644
--- a/editgpx/.classpath
+++ b/editgpx/.classpath
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
 	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="src" path="src-common"/>
+	<classpathentry excluding="src/" including="images/" kind="src" path=""/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JDK 5"/>
 	<classpathentry combineaccessrules="false" kind="src" path="/JOSM"/>
 	<classpathentry kind="output" path="bin"/>
diff --git a/editgpx/build.xml b/editgpx/build.xml
index b991a6e..efb0741 100644
--- a/editgpx/build.xml
+++ b/editgpx/build.xml
@@ -1,56 +1,187 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+** This is the build file for the editgpx plugin
+**
+** Maintaining versions
+** ====================
+** see README.template
+**
+** Usage
+** =====
+** To build it run
+**
+**    > ant  dist
+**
+** To install the generated plugin locally (in your default plugin directory) run
+**
+**    > ant  install
+**
+** To build against the core in ../../core, create a correct manifest and deploy to
+** SVN, 
+**    set the properties commit.message and plugin.main.version
+** and run
+**    > ant  publish
+**
+**
+-->
 <project name="editgpx" 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="Martin Garbe" />
-                <attribute name="Plugin-Class" value="org.openstreetmap.josm.plugins.editgpx.EditGpxPlugin" />
-                <attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
-                <attribute name="Plugin-Description" value="Allows the user to anonymize timestamps and delete parts of huge GPX tracks very fast." />
-                <attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/wiki/JOSM/Plugins/EditGpx" />
-                <attribute name="Plugin-Mainversion" value="2450" />
-                <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>
+
+
+	<property name="commit.message" value="Changed constructor signature of plugin main class" />
+	<property name="plugin.main.version" value="2907" />
+
+
+	<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="Martin Garbe" />
+				<attribute name="Plugin-Class" value="org.openstreetmap.josm.plugins.editgpx.EditGpxPlugin" />
+				<attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
+				<attribute name="Plugin-Description" value="Allows the user to anonymize timestamps and delete parts of huge GPX tracks very fast." />
+				<attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/wiki/JOSM/Plugins/EditGpx" />
+				<attribute name="Plugin-Mainversion" value="${plugin.main.version}" />
+				<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>
+
+	<!--
+	 ************************** Publishing the plugin *********************************** 
+	-->
+	<!--
+	** extracts the JOSM release for the JOSM version in ../core and saves it in the 
+	** property ${coreversion.info.entry.revision}
+	**
+	-->
+	<target name="core-info">
+		<exec append="false" output="core.info.xml" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="info"/>
+			<arg value="--xml"/>
+			<arg value="../../core"/>
+		</exec>
+		<xmlproperty file="core.info.xml" prefix="coreversion" keepRoot="true" collapseAttributes="true"/>
+		<echo>Building against core revision ${coreversion.info.entry.revision}.</echo>
+		<echo>Plugin-Mainversion is set to ${plugin.main.version}.</echo>
+		<delete file="core.info.xml" />
+	</target>
+
+	<!--
+	** commits the source tree for this plugin
+	-->
+	<target name="commit-current">
+		<echo>Commiting the plugin source with message '${commit.message}' ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="commit"/>
+			<arg value="-m '${commit.message}'"/>
+			<arg value="."/>
+		</exec>
+	</target>
+
+	<!--
+	** updates (svn up) the source tree for this plugin
+	-->
+	<target name="update-current">
+		<echo>Updating plugin source ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="up"/>
+			<arg value="."/>
+		</exec>
+		<echo>Updating ${plugin.jar} ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="up"/>
+			<arg value="../dist/${plugin.jar}"/>
+		</exec>
+	</target>
+
+	<!--
+	** commits the plugin.jar 
+	-->
+	<target name="commit-dist">
+		<echo>
+***** Properties of published ${plugin.jar} *****
+Commit message    : '${commit.message}'					
+Plugin-Mainversion: ${plugin.main.version}
+JOSM build version: ${coreversion.info.entry.revision}
+Plugin-Version    : ${version.entry.commit.revision}
+***** / Properties of published ${plugin.jar} *****					
+					
+Now commiting ${plugin.jar} ...
+</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="-m '${commit.message}'"/>
+			<arg value="commit"/>
+			<arg value="${plugin.jar}"/>
+		</exec>
+	</target>
+
+	<!-- ** make sure svn is present as a command line tool ** -->
+	<target name="ensure-svn-present">
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false" failonerror="false" resultproperty="svn.exit.code">
+			<env key="LANG" value="C" />
+			<arg value="--version" />
+		</exec>
+		<fail message="Fatal: command 'svn --version' failed. Please make sure svn is installed on your system.">
+			<!-- return code not set at all? Most likely svn isn't installed -->
+			<condition>
+				<not>
+					<isset property="svn.exit.code" />
+				</not>
+			</condition>
+		</fail>
+		<fail message="Fatal: command 'svn --version' failed. Please make sure a working copy of svn is installed on your system.">
+			<!-- error code from SVN? Most likely svn is not what we are looking on this system -->
+			<condition>
+				<isfailure code="${svn.exit.code}" />
+			</condition>
+		</fail>
+	</target>
+
+	<target name="publish" depends="ensure-svn-present,core-info,commit-current,update-current,clean,dist,commit-dist">
+	</target>
 </project>
diff --git a/validator/josm-validator.launch b/editgpx/josm-editgpx.launch
similarity index 97%
copy from validator/josm-validator.launch
copy to editgpx/josm-editgpx.launch
index fd6b2ff..068fa0c 100644
--- a/validator/josm-validator.launch
+++ b/editgpx/josm-editgpx.launch
@@ -8,5 +8,5 @@
 </listAttribute>
 <stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JDK 6"/>
 <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.openstreetmap.josm.gui.MainApplication"/>
-<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="validator"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="editgpx"/>
 </launchConfiguration>
diff --git a/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxLayer.java b/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxLayer.java
index de997af..4d4f56f 100644
--- a/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxLayer.java
+++ b/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxLayer.java
@@ -12,8 +12,13 @@ import java.awt.Point;
 import java.awt.Toolkit;
 import java.awt.event.ActionEvent;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 
 import javax.swing.AbstractAction;
 import javax.swing.Icon;
@@ -24,7 +29,7 @@ import javax.swing.JSeparator;
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.data.gpx.GpxData;
-import org.openstreetmap.josm.data.gpx.GpxTrack;
+import org.openstreetmap.josm.data.gpx.ImmutableGpxTrack;
 import org.openstreetmap.josm.data.gpx.WayPoint;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Node;
@@ -41,183 +46,195 @@ import org.openstreetmap.josm.tools.ImageProvider;
 
 public class EditGpxLayer extends Layer {
 
-    private static Icon icon = new ImageIcon(Toolkit.getDefaultToolkit().createImage(EditGpxPlugin.class.getResource("/images/editgpx_layer.png")));
-    private DataSet dataSet;
-    private GPXLayerImportAction layerImport;
-
-    public EditGpxLayer(String str, DataSet ds) {
-        super(str);
-        dataSet = ds;
-        layerImport = new GPXLayerImportAction(dataSet);
-    }
-
-    /**
-     * check if dataSet is empty
-     * if so show import dialog to user
-     */
-    public void initializeImport() {
-        try {
-            if(dataSet.getNodes().isEmpty() ) {
-                layerImport.activateImport();
-            }
-        } catch (Exception e) {
-            System.out.println(e.getMessage());
-            e.printStackTrace();
-        }
-    }
-
-    @Override
-    public Icon getIcon() {
-        return icon;
-    }
-
-    @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(layerImport),
-            new JMenuItem(new ConvertToGpxLayerAction()),
-            new JMenuItem(new ConvertToAnonTimeGpxLayerAction()),
-            new JSeparator(),
-            new JMenuItem(new LayerListPopup.InfoAction(this))};
-    }
-
-    @Override
-    public String getToolTipText() {
-        return tr("Layer for editing GPX tracks");
-    }
-
-    @Override
-    public boolean isMergable(Layer other) {
-        // TODO
-        return false;
-    }
-
-    @Override
-    public void mergeFrom(Layer from) {
-        // TODO
-    }
-
-    @Override
-    public void paint(Graphics2D g, MapView mv, Bounds bounds) {
-        g.setColor(Color.yellow);
-
-        //don't iterate through dataSet whiling making changes
-        synchronized(layerImport.importing) {
-            for(Node n: dataSet.getNodes()) {
-                if (!n.isDeleted()) {
-                    Point pnt = Main.map.mapView.getPoint(n.getEastNorth());
-                    g.drawOval(pnt.x - 2, pnt.y - 2, 4, 4);
-                }
-            }
-        }
-    }
-
-
-    public void reset(){
-        //TODO implement a reset
-    }
-
-
-    @Override
-    public void visitBoundingBox(BoundingXYVisitor v) {
-        // TODO Auto-generated method stub
-    }
-
-
-    /**
-     * convert a DataSet to GPX
-     *
-     * @param boolean anonTime If true set all time and date in GPX to 01/01/1970 00:00 ?
-     * @return GPXData
-     */
-    private GpxData toGpxData(boolean anonTime) {
-        GpxData gpxData = new GpxData();
-        HashSet<Node> doneNodes = new HashSet<Node>();
-        //add all ways
-        for (Way w : dataSet.getWays()) {
-            if (w.incomplete || w.isDeleted()) continue;
-            GpxTrack trk = new GpxTrack();
-            gpxData.tracks.add(trk);
-
-            if (w.get("name") != null)
-                trk.attr.put("name", w.get("name"));
-
-            ArrayList<WayPoint> trkseg = null;
-            for (Node n : w.getNodes()) {
-                if (n.incomplete || n.isDeleted()) {
-                    trkseg = null;
-                    continue;
-                }
-
-                Date tstamp = n.getTimestamp();
-
-                if (trkseg == null) {
-                    trkseg = new ArrayList<WayPoint>();
-                    trk.trackSegs.add(trkseg);
-                }
-                doneNodes.add(n);
-
-                WayPoint wpt = new WayPoint(n.getCoor());
-                if (anonTime) {
-                    wpt.attr.put("time", "1970-01-01T00:00:00Z");
-                } else {
-                    wpt.attr.put("time", DateUtils.fromDate(tstamp));
-                }
-                wpt.setTime();
-
-                trkseg.add(wpt);
-            }
-        }
-
-        // add nodes as waypoints
-        for (Node n : dataSet.getNodes()) {
-            if (n.incomplete || n.isDeleted() || doneNodes.contains(n)) continue;
-
-            Date tstamp = n.getTimestamp();
-
-            WayPoint wpt = new WayPoint(n.getCoor());
-            if (anonTime) {
-                wpt.attr.put("time", "1970-01-01T00:00:00Z");
-            } else {
-                wpt.attr.put("time", DateUtils.fromDate(tstamp));
-            }
-            wpt.setTime();
-
-            if (n.getKeys() != null && n.keySet().contains("name")) {
-                wpt.attr.put("name", n.get("name"));
-            }
-            gpxData.waypoints.add(wpt);
-        }
-        return gpxData;
-    }
-
-    //context item "Convert to GPX layer"
-    public class ConvertToGpxLayerAction extends AbstractAction {
-        public ConvertToGpxLayerAction() {
-            super(tr("Convert to GPX layer"), ImageProvider.get("converttogpx"));
-        }
-        public void actionPerformed(ActionEvent e) {
-            Main.main.addLayer(new GpxLayer(toGpxData(false), tr("Converted from: {0}", getName())));
-            Main.main.removeLayer(EditGpxLayer.this);
-        }
-    }
-
-    //context item "Convert to GPX layer with anonymised time"
-    public class ConvertToAnonTimeGpxLayerAction extends AbstractAction {
-        public ConvertToAnonTimeGpxLayerAction() {
-            super(tr("Convert to GPX layer with anonymised time"), ImageProvider.get("converttogpx"));
-        }
-        public void actionPerformed(ActionEvent e) {
-            Main.main.addLayer(new GpxLayer(toGpxData(true), tr("Converted from: {0}", getName())));
-            Main.main.removeLayer(EditGpxLayer.this);
-        }
-    }
+	private static Icon icon = new ImageIcon(Toolkit.getDefaultToolkit().createImage(EditGpxPlugin.class.getResource("/images/editgpx_layer.png")));
+	private DataSet dataSet;
+	private GPXLayerImportAction layerImport;
+
+	public EditGpxLayer(String str, DataSet ds) {
+		super(str);
+		dataSet = ds;
+		layerImport = new GPXLayerImportAction(dataSet);
+	}
+
+	/**
+	 * check if dataSet is empty
+	 * if so show import dialog to user
+	 */
+	public void initializeImport() {
+		try {
+			if(dataSet.getNodes().isEmpty() ) {
+				layerImport.activateImport();
+			}
+		} catch (Exception e) {
+			System.out.println(e.getMessage());
+			e.printStackTrace();
+		}
+	}
+
+	@Override
+	public Icon getIcon() {
+		return icon;
+	}
+
+	@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(layerImport),
+				new JMenuItem(new ConvertToGpxLayerAction()),
+				new JMenuItem(new ConvertToAnonTimeGpxLayerAction()),
+				new JSeparator(),
+				new JMenuItem(new LayerListPopup.InfoAction(this))};
+	}
+
+	@Override
+	public String getToolTipText() {
+		return tr("Layer for editing GPX tracks");
+	}
+
+	@Override
+	public boolean isMergable(Layer other) {
+		// TODO
+		return false;
+	}
+
+	@Override
+	public void mergeFrom(Layer from) {
+		// TODO
+	}
+
+	@Override
+	public void paint(Graphics2D g, MapView mv, Bounds bounds) {
+		g.setColor(Color.yellow);
+
+		//don't iterate through dataSet whiling making changes
+		synchronized(layerImport.importing) {
+			for(Node n: dataSet.getNodes()) {
+				if (!n.isDeleted()) {
+					Point pnt = Main.map.mapView.getPoint(n.getEastNorth());
+					g.drawOval(pnt.x - 2, pnt.y - 2, 4, 4);
+				}
+			}
+		}
+	}
+
+
+	public void reset(){
+		//TODO implement a reset
+	}
+
+
+	@Override
+	public void visitBoundingBox(BoundingXYVisitor v) {
+		// TODO Auto-generated method stub
+	}
+
+
+	/**
+	 * convert a DataSet to GPX
+	 *
+	 * @param boolean anonTime If true set all time and date in GPX to 01/01/1970 00:00 ?
+	 * @return GPXData
+	 */
+	private GpxData toGpxData(boolean anonTime) {
+		GpxData gpxData = new GpxData();
+		HashSet<Node> doneNodes = new HashSet<Node>();
+		//add all ways
+		for (Way w : dataSet.getWays()) {
+			if (w.isIncomplete() || w.isDeleted()) continue;
+			List<Collection<WayPoint>> segments = new ArrayList<Collection<WayPoint>>();
+
+			List<WayPoint> trkseg = null;
+			for (Node n : w.getNodes()) {
+				if (n.isIncomplete() || n.isDeleted()) {
+					trkseg = null;
+					continue;
+				}
+
+				Date tstamp = n.getTimestamp();
+
+				if (trkseg == null) {
+					trkseg = new ArrayList<WayPoint>();
+					segments.add(trkseg);
+				}
+				doneNodes.add(n);
+
+				WayPoint wpt = new WayPoint(n.getCoor());
+				if (anonTime) {
+					wpt.attr.put("time", "1970-01-01T00:00:00Z");
+				} else {
+					wpt.attr.put("time", DateUtils.fromDate(tstamp));
+				}
+				wpt.setTime();
+
+				trkseg.add(wpt);
+			}
+
+			// Do not create empty segments
+			for (Iterator<Collection<WayPoint>>  segIt = segments.iterator(); segIt.hasNext(); ) {
+				if (segIt.next().isEmpty()) {
+					segIt.remove();
+				}
+			}
+
+			Map<String, Object> trkAttributes = new HashMap<String, Object>();
+			if (w.get("name") != null) {
+				trkAttributes.put("name", w.get("name"));
+			}
+			if (!segments.isEmpty()) {
+				gpxData.tracks.add(new ImmutableGpxTrack(segments, trkAttributes));
+			}
+
+		}
+
+		// add nodes as waypoints
+		for (Node n : dataSet.getNodes()) {
+			if (n.isIncomplete() || n.isDeleted() || doneNodes.contains(n)) continue;
+
+			Date tstamp = n.getTimestamp();
+
+			WayPoint wpt = new WayPoint(n.getCoor());
+			if (anonTime) {
+				wpt.attr.put("time", "1970-01-01T00:00:00Z");
+			} else {
+				wpt.attr.put("time", DateUtils.fromDate(tstamp));
+			}
+			wpt.setTime();
+
+			if (n.getKeys() != null && n.keySet().contains("name")) {
+				wpt.attr.put("name", n.get("name"));
+			}
+			gpxData.waypoints.add(wpt);
+		}
+		return gpxData;
+	}
+
+	//context item "Convert to GPX layer"
+	public class ConvertToGpxLayerAction extends AbstractAction {
+		public ConvertToGpxLayerAction() {
+			super(tr("Convert to GPX layer"), ImageProvider.get("converttogpx"));
+		}
+		public void actionPerformed(ActionEvent e) {
+			Main.main.addLayer(new GpxLayer(toGpxData(false), tr("Converted from: {0}", getName())));
+			Main.main.removeLayer(EditGpxLayer.this);
+		}
+	}
+
+	//context item "Convert to GPX layer with anonymised time"
+	public class ConvertToAnonTimeGpxLayerAction extends AbstractAction {
+		public ConvertToAnonTimeGpxLayerAction() {
+			super(tr("Convert to GPX layer with anonymised time"), ImageProvider.get("converttogpx"));
+		}
+		public void actionPerformed(ActionEvent e) {
+			Main.main.addLayer(new GpxLayer(toGpxData(true), tr("Converted from: {0}", getName())));
+			Main.main.removeLayer(EditGpxLayer.this);
+		}
+	}
 }
diff --git a/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxMode.java b/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxMode.java
index d62935e..ae17cb9 100644
--- a/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxMode.java
+++ b/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxMode.java
@@ -8,6 +8,7 @@ import java.awt.Cursor;
 import java.awt.Graphics;
 import java.awt.Point;
 import java.awt.Rectangle;
+import java.awt.event.InputEvent;
 import java.awt.event.MouseEvent;
 
 import org.openstreetmap.josm.Main;
@@ -50,7 +51,7 @@ public class EditGpxMode extends MapMode {
 
 
     @Override public void mouseDragged(MouseEvent e) {
-        if ( (e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) ==  MouseEvent.BUTTON1_DOWN_MASK) {
+        if ( (e.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) ==  InputEvent.BUTTON1_DOWN_MASK) {
             //if button1 is hold, draw the rectangle.
             paintRect(pointPressed, e.getPoint());
         }
diff --git a/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxPlugin.java b/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxPlugin.java
index 400eb55..5345966 100644
--- a/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxPlugin.java
+++ b/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxPlugin.java
@@ -13,9 +13,11 @@ import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.gui.IconToggleButton;
 import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
 import org.openstreetmap.josm.gui.layer.Layer;
-import org.openstreetmap.josm.gui.layer.Layer.LayerChangeListener;
 import org.openstreetmap.josm.plugins.Plugin;
+import org.openstreetmap.josm.plugins.PluginInformation;
 
 import static org.openstreetmap.josm.tools.I18n.tr;
 
@@ -41,7 +43,8 @@ public class EditGpxPlugin extends Plugin {
     protected static DataSet dataSet;
     public static boolean active = false;
 
-    public EditGpxPlugin() {
+    public EditGpxPlugin(PluginInformation info) {
+    	super(info);
         dataSet = new DataSet();
         mode = new EditGpxMode(Main.map, "editgpx", tr("edit gpx tracks"), dataSet);
 
@@ -84,7 +87,7 @@ public class EditGpxPlugin extends Plugin {
         if(eGpxLayer == null) {
             eGpxLayer = new EditGpxLayer(tr("EditGpx"), dataSet);
             Main.main.addLayer(eGpxLayer);
-            Layer.listeners.add(new LayerChangeListener(){
+            MapView.addLayerChangeListener(new LayerChangeListener(){
 
                 public void activeLayerChange(final Layer oldLayer, final Layer newLayer) {
                     if(newLayer instanceof EditGpxLayer)
@@ -98,7 +101,7 @@ public class EditGpxPlugin extends Plugin {
                     if(oldLayer == eGpxLayer) {
                         eGpxLayer = null;
                         //dataSet = new DataSet();
-
+                        MapView.removeLayerChangeListener(this);
                     }
                 }
             });
diff --git a/editgpx/src/org/openstreetmap/josm/plugins/editgpx/GPXLayerImportAction.java b/editgpx/src/org/openstreetmap/josm/plugins/editgpx/GPXLayerImportAction.java
index be1d608..654ebda 100644
--- a/editgpx/src/org/openstreetmap/josm/plugins/editgpx/GPXLayerImportAction.java
+++ b/editgpx/src/org/openstreetmap/josm/plugins/editgpx/GPXLayerImportAction.java
@@ -25,6 +25,7 @@ import javax.swing.JOptionPane;
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.gpx.GpxTrack;
+import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
 import org.openstreetmap.josm.data.gpx.WayPoint;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Node;
@@ -111,9 +112,9 @@ class GPXLayerImportAction extends AbstractAction {
 
             synchronized(importing) {
                 for (GpxTrack trk : gpx.data.tracks) {
-                    for (Collection<WayPoint> segment : trk.trackSegs) {
+                    for (GpxTrackSegment segment : trk.getSegments()) {
                         Way w = new Way();
-                        for (WayPoint p : segment) {
+                        for (WayPoint p : segment.getWayPoints()) {
                             Node n = new Node(p.getCoor());
                             String timestr = p.getString("time");
                             if(timestr != null)
diff --git a/lakewalker/.classpath b/lakewalker/.classpath
index 227cb45..17b8e6a 100644
--- a/lakewalker/.classpath
+++ b/lakewalker/.classpath
@@ -1,7 +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>
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JDK 5"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/JOSM"/>
+	<classpathentry kind="output" path="build"/>
+</classpath>
diff --git a/lakewalker/.settings/org.eclipse.jdt.ui.prefs b/lakewalker/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..dd6f6e0
--- /dev/null
+++ b/lakewalker/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,54 @@
+#Sun Jan 24 21:18:20 CET 2010
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=false
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=true
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/lakewalker/build.xml b/lakewalker/build.xml
index e2662af..a17568e 100644
--- a/lakewalker/build.xml
+++ b/lakewalker/build.xml
@@ -1,56 +1,185 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+** This is the build file for the lakewalker plugin
+**
+** Maintaining versions
+** ====================
+** see README.template
+**
+** Usage
+** =====
+** To build it run
+**
+**    > ant  dist
+**
+** To install the generated plugin locally (in your default plugin directory) run
+**
+**    > ant  install
+**
+** To build against the core in ../../core, create a correct manifest and deploy to
+** SVN, 
+**    set the properties commit.message and plugin.main.version
+** and run
+**    > ant  publish
+**
+**
+-->
 <project name="lakewalker" 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="Brent Easton, Jason Reid"/>
-                <attribute name="Main-Class" value="org.openstreetmap.josm.plugins.lakewalker.LakewalkerApp"/>
-                <attribute name="Plugin-Class" value="org.openstreetmap.josm.plugins.lakewalker.LakewalkerPlugin" />
-                <attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
-                <attribute name="Plugin-Description" value="Helps vectorizing WMS images." />
-                <attribute name="Plugin-Mainversion" value="2012"/>
-                <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>
+
+	<property name="commit.message" value="Changed the constructor signature of the plugin main class" />
+	<property name="plugin.main.version" value="2830" />
+
+	<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="Brent Easton, Jason Reid"/>
+				<attribute name="Main-Class" value="org.openstreetmap.josm.plugins.lakewalker.LakewalkerApp"/>
+				<attribute name="Plugin-Class" value="org.openstreetmap.josm.plugins.lakewalker.LakewalkerPlugin" />
+				<attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
+				<attribute name="Plugin-Description" value="Helps vectorizing WMS images." />
+				<attribute name="Plugin-Mainversion" value="${plugin.main.version}"/>
+				<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>
+
+	<!--
+		 ************************** Publishing the plugin *********************************** 
+		-->
+	<!--
+		** extracts the JOSM release for the JOSM version in ../core and saves it in the 
+		** property ${coreversion.info.entry.revision}
+		**
+		-->
+	<target name="core-info">
+		<exec append="false" output="core.info.xml" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="info"/>
+			<arg value="--xml"/>
+			<arg value="../../core"/>
+		</exec>
+		<xmlproperty file="core.info.xml" prefix="coreversion" keepRoot="true" collapseAttributes="true"/>
+		<echo>Building against core revision ${coreversion.info.entry.revision}.</echo>
+		<echo>Plugin-Mainversion is set to ${plugin.main.version}.</echo>
+		<delete file="core.info.xml" />
+	</target>
+
+	<!--
+		** commits the source tree for this plugin
+		-->
+	<target name="commit-current">
+		<echo>Commiting the plugin source with message '${commit.message}' ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="commit"/>
+			<arg value="-m '${commit.message}'"/>
+			<arg value="."/>
+		</exec>
+	</target>
+
+	<!--
+		** updates (svn up) the source tree for this plugin
+		-->
+	<target name="update-current">
+		<echo>Updating plugin source ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="up"/>
+			<arg value="."/>
+		</exec>
+		<echo>Updating ${plugin.jar} ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="up"/>
+			<arg value="../dist/${plugin.jar}"/>
+		</exec>
+	</target>
+
+	<!--
+		** commits the plugin.jar 
+		-->
+	<target name="commit-dist">
+		<echo>
+	***** Properties of published ${plugin.jar} *****
+	Commit message    : '${commit.message}'					
+	Plugin-Mainversion: ${plugin.main.version}
+	JOSM build version: ${coreversion.info.entry.revision}
+	Plugin-Version    : ${version.entry.commit.revision}
+	***** / Properties of published ${plugin.jar} *****					
+						
+	Now commiting ${plugin.jar} ...
+	</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="-m '${commit.message}'"/>
+			<arg value="commit"/>
+			<arg value="${plugin.jar}"/>
+		</exec>
+	</target>
+
+	<!-- ** make sure svn is present as a command line tool ** -->
+	<target name="ensure-svn-present">
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false" failonerror="false" resultproperty="svn.exit.code">
+			<env key="LANG" value="C" />
+			<arg value="--version" />
+		</exec>
+		<fail message="Fatal: command 'svn --version' failed. Please make sure svn is installed on your system.">
+			<!-- return code not set at all? Most likely svn isn't installed -->
+			<condition>
+				<not>
+					<isset property="svn.exit.code" />
+				</not>
+			</condition>
+		</fail>
+		<fail message="Fatal: command 'svn --version' failed. Please make sure a working copy of svn is installed on your system.">
+			<!-- error code from SVN? Most likely svn is not what we are looking on this system -->
+			<condition>
+				<isfailure code="${svn.exit.code}" />
+			</condition>
+		</fail>
+	</target>
+
+	<target name="publish" depends="ensure-svn-present,core-info,commit-current,update-current,clean,dist,commit-dist">
+	</target>
 </project>
diff --git a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/BooleanConfigurer.java b/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/BooleanConfigurer.java
index 05d90b1..cdf5b28 100644
--- a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/BooleanConfigurer.java
+++ b/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/BooleanConfigurer.java
@@ -13,7 +13,7 @@
  * Library General Public License for more details.
  *
  * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, copies are available 
+ * License along with this library; if not, copies are available
  * at http://www.opensource.org.
  */
 package org.openstreetmap.josm.plugins.lakewalker;
@@ -22,65 +22,70 @@ package org.openstreetmap.josm.plugins.lakewalker;
  * Configurer for Boolean values
  */
 public class BooleanConfigurer extends Configurer {
-  private javax.swing.JCheckBox box;
+	private javax.swing.JCheckBox box;
 
-  public BooleanConfigurer() {
-    this(false);
-  }
-  
-  public BooleanConfigurer(boolean val) {
-    this(null, "", val);
-  }
-  
-  public BooleanConfigurer(String key, String name, Boolean val) {
-    super(key, name, val);
-  }
+	public BooleanConfigurer() {
+		this(false);
+	}
 
-  public BooleanConfigurer(String key, String name, boolean val) {
-    super(key, name, val ? Boolean.TRUE : Boolean.FALSE);
-  }
+	public BooleanConfigurer(boolean val) {
+		this(null, "", val);
+	}
 
-  public BooleanConfigurer(String key, String name) {
-    this(key, name, Boolean.FALSE);
-  }
+	public BooleanConfigurer(String key, String name, Boolean val) {
+		super(key, name, val);
+	}
 
-  public String getValueString() {
-    return booleanValue().toString();
-  }
+	public BooleanConfigurer(String key, String name, boolean val) {
+		super(key, name, val ? Boolean.TRUE : Boolean.FALSE);
+	}
 
-  public void setValue(Object o) {
-    super.setValue(o);
-    if (box != null
-      && !o.equals(new Boolean(box.isSelected()))) {
-      box.setSelected(booleanValue().booleanValue());
-    }
-  }
+	public BooleanConfigurer(String key, String name) {
+		this(key, name, Boolean.FALSE);
+	}
 
-  public void setValue(String s) {
-    setValue(Boolean.valueOf(s));
-  }
+	@Override
+	public String getValueString() {
+		return booleanValue().toString();
+	}
 
-  public void setName(String s) {
-    super.setName(s);
-    if (box != null) {
-      box.setText(s);
-    }
-  }
+	@Override
+	public void setValue(Object o) {
+		super.setValue(o);
+		if (box != null
+				&& !o.equals(box.isSelected())) {
+			box.setSelected(booleanValue().booleanValue());
+		}
+	}
 
-  public java.awt.Component getControls() {
-    if (box == null) {
-      box = new javax.swing.JCheckBox(getName());
-      box.setSelected(booleanValue().booleanValue());
-      box.addItemListener(new java.awt.event.ItemListener() {
-        public void itemStateChanged(java.awt.event.ItemEvent e) {
-          setValue(new Boolean(box.isSelected()));
-        }
-      });
-    }
-    return box;
-  }
+	@Override
+	public void setValue(String s) {
+		setValue(Boolean.valueOf(s));
+	}
 
-  public Boolean booleanValue() {
-    return (Boolean) value;
-  }
+	@Override
+	public void setName(String s) {
+		super.setName(s);
+		if (box != null) {
+			box.setText(s);
+		}
+	}
+
+	@Override
+	public java.awt.Component getControls() {
+		if (box == null) {
+			box = new javax.swing.JCheckBox(getName());
+			box.setSelected(booleanValue().booleanValue());
+			box.addItemListener(new java.awt.event.ItemListener() {
+				public void itemStateChanged(java.awt.event.ItemEvent e) {
+					setValue(box.isSelected());
+				}
+			});
+		}
+		return box;
+	}
+
+	public Boolean booleanValue() {
+		return (Boolean) value;
+	}
 }
diff --git a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/DoubleConfigurer.java b/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/DoubleConfigurer.java
index 4ced3f7..1fbbac7 100644
--- a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/DoubleConfigurer.java
+++ b/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/DoubleConfigurer.java
@@ -35,7 +35,8 @@ public class DoubleConfigurer extends StringConfigurer {
         super(key, name, val == null ? null : val.toString());
     }
 
-    public void setValue(String s) {
+    @Override
+	public void setValue(String s) {
         Double d = null;
         try {
             d = Double.valueOf(s);
@@ -47,14 +48,16 @@ public class DoubleConfigurer extends StringConfigurer {
             setValue(d);
     }
 
-    public void setValue(Object o) {
+    @Override
+	public void setValue(Object o) {
         if (!noUpdate && nameField != null && o != null) {
             nameField.setText(o.toString());
         }
         super.setValue(o);
     }
 
-    public String getValueString() {
+    @Override
+	public String getValueString() {
         if (value == null || value.equals("")) {
             return null;
         }
diff --git a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/IntConfigurer.java b/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/IntConfigurer.java
index 210b56b..ea87299 100644
--- a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/IntConfigurer.java
+++ b/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/IntConfigurer.java
@@ -22,52 +22,55 @@ package org.openstreetmap.josm.plugins.lakewalker;
  * A Configurer for Integer values
  */
 public class IntConfigurer extends StringConfigurer {
-  
-  public IntConfigurer() {
-    super();
-  }
-  
-  public IntConfigurer(String key, String name) {
-    this(key, name, new Integer(0));
-  }
 
-  public IntConfigurer(String key, String name, Integer val) {
-    super(key, name);
-    if (val != null) {
-      setValue(val);
-    }
-  }
+	public IntConfigurer() {
+		super();
+	}
 
-  public void setValue(String s) {
-    Integer i = null;
-    try {
-      i = Integer.valueOf(s);
-    }
-    catch (NumberFormatException e) {
-      i = null;
-    }
-    if (i != null) {
-      setValue(i);
-    }
-  }
-  
-  public int getIntValue(int defaultValue) {
-    if (getValue() instanceof Integer) {
-      return ((Integer)getValue()).intValue();
-    }
-    else {
-      return defaultValue;
-    }
-  }
+	public IntConfigurer(String key, String name) {
+		this(key, name, 0);
+	}
 
-  public void setValue(Object o) {
-    if (!noUpdate && nameField != null && o != null) {
-      nameField.setText(o.toString());
-    }
-    super.setValue(o);
-  }
+	public IntConfigurer(String key, String name, Integer val) {
+		super(key, name);
+		if (val != null) {
+			setValue(val);
+		}
+	}
 
-  public String getValueString() {
-    return value == null ? null : value.toString();
-  }
+	@Override
+	public void setValue(String s) {
+		Integer i = null;
+		try {
+			i = Integer.valueOf(s);
+		}
+		catch (NumberFormatException e) {
+			i = null;
+		}
+		if (i != null) {
+			setValue(i);
+		}
+	}
+
+	public int getIntValue(int defaultValue) {
+		if (getValue() instanceof Integer) {
+			return ((Integer)getValue()).intValue();
+		}
+		else {
+			return defaultValue;
+		}
+	}
+
+	@Override
+	public void setValue(Object o) {
+		if (!noUpdate && nameField != null && o != null) {
+			nameField.setText(o.toString());
+		}
+		super.setValue(o);
+	}
+
+	@Override
+	public String getValueString() {
+		return value == null ? null : value.toString();
+	}
 }
diff --git a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/Lakewalker.java b/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/Lakewalker.java
index 3903c23..756521b 100644
--- a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/Lakewalker.java
+++ b/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/Lakewalker.java
@@ -4,22 +4,15 @@ import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.io.File;
 import java.util.ArrayList;
-import java.util.Collection;
-import java.util.LinkedList;
+import java.util.List;
 
-import org.openstreetmap.josm.command.Command;
-import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 
 public class Lakewalker {
-    protected Collection<Command> commands = new LinkedList<Command>();
-    protected Collection<Way> ways = new ArrayList<Way>();
     protected boolean cancel;
 
-    private int waylen;
     private int maxnode;
     private int threshold;
-    private double epsilon;
     private int resolution;
     private int tilesize;
     private String startdir;
@@ -34,10 +27,8 @@ public class Lakewalker {
     double start_radius_small = 0.0002;
 
     public Lakewalker(int waylen, int maxnode, int threshold, double epsilon, int resolution, int tilesize, String startdir, String wmslayer, File workingdir){
-        this.waylen = waylen;
         this.maxnode = maxnode;
         this.threshold = threshold;
-        this.epsilon = epsilon;
         this.resolution = resolution;
         this.tilesize = tilesize;
         this.startdir = startdir;
@@ -382,8 +373,8 @@ public class Lakewalker {
             }
         }
 
-        ArrayList<double[]> seg_a = new ArrayList<double[]>();
-        ArrayList<double[]> seg_b = new ArrayList<double[]>();
+        List<double[]> seg_a;
+        List<double[]> seg_b;
 
         if(farthest_dist > epsilon){
             seg_a = douglasPeucker(sublist(nodes,0,farthest_node+1),epsilon, depth+1);
@@ -439,7 +430,7 @@ public class Lakewalker {
      *
      * @author Jason Reid
      */
-    private class LakewalkerBBox {
+    private static class LakewalkerBBox {
 
         private double top = 90;
         private double left = -180;
diff --git a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerAction.java b/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerAction.java
index 0524c97..d2eb2e9 100644
--- a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerAction.java
+++ b/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerAction.java
@@ -72,7 +72,7 @@ class LakewalkerAction extends JosmAction implements MouseListener {
     */
     private void cleanupCache() {
         final long maxCacheAge = System.currentTimeMillis()-Main.pref.getInteger(LakewalkerPreferences.PREF_MAXCACHEAGE, 100)*24*60*60*1000L;
-        final long maxCacheSize = Main.pref.getInteger(LakewalkerPreferences.PREF_MAXCACHESIZE, 300)*1024*1024;
+        final long maxCacheSize = Main.pref.getInteger(LakewalkerPreferences.PREF_MAXCACHESIZE, 300)*1024*1024L;
 
         for (String wmsFolder : LakewalkerPreferences.WMSLAYERS) {
             String wmsCacheDirName = Main.pref.getPreferencesDir()+"plugins/Lakewalker/"+wmsFolder;
@@ -176,7 +176,7 @@ class LakewalkerAction extends JosmAction implements MouseListener {
                 nodelist = lw.trace(pos.lat(),pos.lon(),topLeft.lon(),botRight.lon(),topLeft.lat(),botRight.lat(),
                         progressMonitor.createSubTaskMonitor(1, false));
             } catch(LakewalkerException e){
-                System.out.println(e.getError());
+                System.out.println(e.getMessage());
             }
 
             System.out.println(nodelist.size()+" nodes generated");
@@ -246,6 +246,7 @@ class LakewalkerAction extends JosmAction implements MouseListener {
                     commands.add(new AddCommand(n));
 
                 } catch (Exception ex) {
+                	ex.printStackTrace();
                 }
 
                 way.addNode(n);
diff --git a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerApp.java b/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerApp.java
index 11560c7..34062b7 100644
--- a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerApp.java
+++ b/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerApp.java
@@ -39,21 +39,20 @@ public class LakewalkerApp {
         Lakewalker lw = new Lakewalker(waylen,maxnode,threshold,dp,resolution,tilesize,startdir,wmslayer,working_dir);
         try {
             nodelist = lw.trace(lat,lon,leftlon,rightlon,toplat,botlat, NullProgressMonitor.INSTANCE);
-        } catch(LakewalkerException e){
-            System.out.println(e.getError());
-        }
-
-        System.out.println(nodelist.size()+" nodes generated");
 
-        nodelist = lw.vertexReduce(nodelist, dp);
+            System.out.println(nodelist.size()+" nodes generated");
 
-        System.out.println("After vertex reduction, "+nodelist.size()+" nodes remain.");
+            nodelist = lw.vertexReduce(nodelist, dp);
 
-        nodelist = lw.douglasPeucker(nodelist, dp, 0);
-
-        System.out.println("After dp approximation, "+nodelist.size()+" nodes remain.");
+            System.out.println("After vertex reduction, "+nodelist.size()+" nodes remain.");
 
+            nodelist = lw.douglasPeucker(nodelist, dp, 0);
+            System.out.println("After dp approximation, "+nodelist.size()+" nodes remain.");
 
+        } catch(LakewalkerException e){
+            System.out.println(e.getMessage());
+            e.printStackTrace();
+        }
 
     }
 }
diff --git a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerException.java b/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerException.java
index 48409a7..5c6789e 100644
--- a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerException.java
+++ b/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerException.java
@@ -3,19 +3,11 @@ package org.openstreetmap.josm.plugins.lakewalker;
 import static org.openstreetmap.josm.tools.I18n.tr;
 
 class LakewalkerException extends Exception {
-    String error;
-
     public LakewalkerException(){
-        super();
-        this.error = tr("An unknown error has occurred");
+    	super(tr("An unknown error has occurred"));
     }
 
     public LakewalkerException(String err){
-        super();
-        this.error = err;
-    }
-
-    public String getError(){
-      return this.error;
+        super(err);
     }
 }
diff --git a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerPlugin.java b/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerPlugin.java
index b4c8395..590f596 100644
--- a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerPlugin.java
+++ b/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerPlugin.java
@@ -6,6 +6,7 @@ import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.gui.MainMenu;
 import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
 import org.openstreetmap.josm.plugins.Plugin;
+import org.openstreetmap.josm.plugins.PluginInformation;
 
 /**
  * Interface to Darryl Shpak's Lakewalker python module
@@ -13,13 +14,15 @@ import org.openstreetmap.josm.plugins.Plugin;
  * @author Brent Easton
  */
 public class LakewalkerPlugin extends Plugin {
-  public LakewalkerPlugin() {
-    MainMenu.add(Main.main.menu.toolsMenu, new LakewalkerAction(tr("Lake Walker")));
-  }
+	public LakewalkerPlugin(PluginInformation info) {
+		super(info);
+		MainMenu.add(Main.main.menu.toolsMenu, new LakewalkerAction(tr("Lake Walker")));
+	}
 
-  public PreferenceSetting getPreferenceSetting()
-  {
-    return new LakewalkerPreferences();
-  }
+	@Override
+	public PreferenceSetting getPreferenceSetting()
+	{
+		return new LakewalkerPreferences();
+	}
 
 }
diff --git a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerPreferences.java b/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerPreferences.java
index a4f5f3d..344b3d5 100644
--- a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerPreferences.java
+++ b/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerPreferences.java
@@ -3,13 +3,15 @@ package org.openstreetmap.josm.plugins.lakewalker;
 import static org.openstreetmap.josm.tools.I18n.marktr;
 import static org.openstreetmap.josm.tools.I18n.tr;
 
+import java.awt.GridBagConstraints;
+
 import javax.swing.Box;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.gui.preferences.PreferenceDialog;
 import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
+import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.I18n;
 
@@ -65,15 +67,15 @@ public class LakewalkerPreferences implements PreferenceSetting {
     protected StringConfigurer sourceConfig = new StringConfigurer();
     protected JLabel sourceLabel = new JLabel(tr("Source text"));
 
-    public void addGui(PreferenceDialog gui) {
+    public void addGui(PreferenceTabbedPane gui) {
         maxSegsConfig.setToolTipText(tr("Maximum number of segments allowed in each generated way. Default 250."));
         maxNodesConfig.setToolTipText(tr("Maximum number of nodes to generate before bailing out (before simplifying lines). Default 50000."));
         thresholdConfig.setToolTipText(tr("Maximum gray value to accept as water (based on Landsat IR-1 data). Can be in the range 0-255. Default 90."));
         epsilonConfig.setToolTipText(tr("Accuracy of Douglas-Peucker line simplification, measured in degrees.<br>Lower values give more nodes, and more accurate lines. Default 0.0003."));
         landsatResConfig.setToolTipText(tr("Resolution of Landsat tiles, measured in pixels per degree. Default 4000."));
         landsatSizeConfig.setToolTipText(tr("Size of one landsat tile, measured in pixels. Default 2000."));
-        eastOffsetConfig.setToolTipText(tr("Offset all points in East direction (degrees). Default 0."));   
-        northOffsetConfig.setToolTipText(tr("Offset all points in North direction (degrees). Default 0."));   
+        eastOffsetConfig.setToolTipText(tr("Offset all points in East direction (degrees). Default 0."));
+        northOffsetConfig.setToolTipText(tr("Offset all points in North direction (degrees). Default 0."));
         startDirConfig.setToolTipText(tr("Direction to search for land. Default east."));
         lakeTypeConfig.setToolTipText(tr("Tag ways as water, coastline, land or nothing. Default is water."));
         wmsConfig.setToolTipText(tr("Which WMS layer to use for tracing against. Default is IR1."));
@@ -103,7 +105,7 @@ public class LakewalkerPreferences implements PreferenceSetting {
 
     public void buildPreferences(JPanel prefPanel) {
         GBC labelConstraints = GBC.std().insets(10,5,5,0);
-        GBC dataConstraints = GBC.eol().insets(0,5,0,0).fill(GBC.HORIZONTAL);
+        GBC dataConstraints = GBC.eol().insets(0,5,0,0).fill(GridBagConstraints.HORIZONTAL);
 
         prefPanel.add(maxSegsLabel, labelConstraints);
         prefPanel.add(maxSegsConfig.getControls(), dataConstraints);
@@ -116,13 +118,13 @@ public class LakewalkerPreferences implements PreferenceSetting {
         prefPanel.add(landsatResLabel, labelConstraints);
         prefPanel.add(landsatResConfig.getControls(), dataConstraints);
         prefPanel.add(landsatSizeLabel, labelConstraints);
-        prefPanel.add(landsatSizeConfig.getControls(), dataConstraints);    
+        prefPanel.add(landsatSizeConfig.getControls(), dataConstraints);
         prefPanel.add(eastOffsetLabel, labelConstraints);
         prefPanel.add(eastOffsetConfig.getControls(), dataConstraints);
         prefPanel.add(northOffsetLabel, labelConstraints);
         prefPanel.add(northOffsetConfig.getControls(), dataConstraints);
         prefPanel.add(startDirLabel, labelConstraints);
-        prefPanel.add(startDirConfig.getControls(), dataConstraints);    
+        prefPanel.add(startDirConfig.getControls(), dataConstraints);
         prefPanel.add(lakeTypeLabel, labelConstraints);
         prefPanel.add(lakeTypeConfig.getControls(), dataConstraints);
         prefPanel.add(wmsLabel, labelConstraints);
@@ -134,7 +136,7 @@ public class LakewalkerPreferences implements PreferenceSetting {
         prefPanel.add(sourceLabel, labelConstraints);
         prefPanel.add(sourceConfig.getControls(), dataConstraints);
 
-        prefPanel.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.VERTICAL));
+        prefPanel.add(Box.createVerticalGlue(), GBC.eol().fill(GridBagConstraints.VERTICAL));
     }
 
     /*
diff --git a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerReader.java b/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerReader.java
deleted file mode 100644
index 4add238..0000000
--- a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerReader.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/* LakewalkerReader.java
- *
- * Read and process data from a Lakwalker python module
- *
- */
-package org.openstreetmap.josm.plugins.lakewalker;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.io.BufferedReader;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.LinkedList;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.command.AddCommand;
-import org.openstreetmap.josm.command.Command;
-import org.openstreetmap.josm.command.SequenceCommand;
-import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.gui.progress.ProgressMonitor;
-
-public class LakewalkerReader {
-    protected Collection<Command> commands = new LinkedList<Command>();
-    protected Collection<Way> ways = new ArrayList<Way>();
-    protected boolean cancel;
-
-    /*
-    * Read the data
-    */
-    public void read(BufferedReader input, ProgressMonitor progressMonitor) {
-        /*
-        * Lakewalker will output data it stdout. Each line has a code in
-        * character 1 indicating the type of data on the line:
-        *
-        * m text - Status message l name [size] - Access landsat image name. size
-        * is returned if it needs to be downloaded. e text - Error message s nnn -
-        * Start node data stream, nnn seperate tracings to follow t nnn - Start
-        * tracing, nnn nodes to follow x [o] - End of Tracing. o indicates do not
-        * connect last node to first n lat lon [o] - Node. o indicates it is an
-        * open node (not connected to the previous node) z - End of data stream
-        */
-
-    	progressMonitor.beginTask(null);
-    	try {
-    		Way way = new Way();
-    		String line;
-    		progressMonitor.indeterminateSubTask(tr("Initializing"));
-    		double eastOffset = Main.pref.getDouble(LakewalkerPreferences.PREF_EAST_OFFSET, 0.0);
-    		double northOffset = Main.pref.getDouble(LakewalkerPreferences.PREF_NORTH_OFFSET, 0.0);
-    		char option = ' ';
-
-    		try {
-    			Node n = null;  // The current node being created
-    			Node tn = null; // The last node of the previous way
-    			Node fn = null; // Node to hold the first node in the trace
-
-    			while ((line = input.readLine()) != null) {
-    				if (cancel)
-    					return;
-    				System.out.println(line);
-    				option = line.charAt(0);
-    				switch (option) {
-    				case 'n':
-    					String[] tokens = line.split(" ");
-
-    					if(tn==null){
-    						try {
-    							LatLon ll = new LatLon(Double.parseDouble(tokens[1])+northOffset,
-    									Double.parseDouble(tokens[2])+eastOffset);
-    							n = new Node(ll);
-    							if(fn==null)
-    								fn = n;
-    							commands.add(new AddCommand(n));
-    						}
-    						catch (Exception ex) {}
-    					} else {
-    						// If there is a last node, and this node has the same coordinates
-    						// then we substitute for the previous node
-    						n = tn;
-    						tn = null;
-    					}
-    					way.addNode(n);
-    					break;
-    				case 's':
-    					progressMonitor.indeterminateSubTask(line.substring(2));
-    					break;
-    				case 'x':
-    					String waytype = Main.pref.get(LakewalkerPreferences.PREF_WAYTYPE, "water");
-
-    					if(!waytype.equals("none"))
-    						way.put("natural",waytype);
-    					way.put("source", Main.pref.get(LakewalkerPreferences.PREF_SOURCE, "Landsat"));
-    					commands.add(new AddCommand(way));
-    					break;
-    				case 't':
-    					way = new Way();
-    					tn = n;
-    					break;
-    				case 'e':
-    					cancel = true;
-    					break;
-    				}
-    			}
-    			input.close();
-
-    			// Add the start node to the end of the trace to form a closed shape
-    			way.addNode(fn);
-    		}
-    		catch (Exception ex) { }
-
-    		if (!commands.isEmpty()) {
-    			Main.main.undoRedo.add(new SequenceCommand(tr("Lakewalker trace"), commands));
-    			Main.main.getCurrentDataSet().setSelected(ways);
-    		}
-    	} finally {
-    		progressMonitor.finishTask();
-    	}
-    }
-
-    /*
-    * User has hit the cancel button
-    */
-    public void cancel() {
-        cancel = true;
-    }
-}
\ No newline at end of file
diff --git a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerWMS.java b/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerWMS.java
index 8871fff..60a5dd5 100644
--- a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerWMS.java
+++ b/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerWMS.java
@@ -12,7 +12,9 @@ import java.net.URL;
 import java.text.DecimalFormat;
 import java.text.NumberFormat;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Vector;
 
 import javax.imageio.ImageIO;
@@ -26,9 +28,9 @@ public class LakewalkerWMS {
     private int imagey;
 
     // Vector to cache images in memory
-    private Vector<BufferedImage> images = new Vector<BufferedImage>();
+    private List<BufferedImage> images = new Vector<BufferedImage>();
     // Hashmap to hold the mapping of cached images
-    private HashMap<String,Integer> imageindex = new HashMap<String,Integer>();
+    private Map<String,Integer> imageindex = new HashMap<String,Integer>();
 
     private int resolution;
     private int tilesize;
@@ -178,8 +180,8 @@ public class LakewalkerWMS {
         try {
             image = this.getTile(x,y, progressMonitor);
         } catch(LakewalkerException e){
-            System.out.println(e.getError());
-            throw new LakewalkerException(e.getMessage());
+            System.out.println(e.getMessage());
+            throw e;
         }
 
         int tx = floor(x,this.tilesize);
diff --git a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/StringConfigurer.java b/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/StringConfigurer.java
index 49e2bb6..c5526ad 100644
--- a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/StringConfigurer.java
+++ b/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/StringConfigurer.java
@@ -13,7 +13,7 @@
  * Library General Public License for more details.
  *
  * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, copies are available 
+ * License along with this library; if not, copies are available
  * at http://www.opensource.org.
  */
 package org.openstreetmap.josm.plugins.lakewalker;
@@ -33,7 +33,7 @@ public class StringConfigurer extends Configurer {
   public StringConfigurer() {
     this(null, "");
   }
-  
+
   public StringConfigurer(String key, String name) {
     this(key, name, "");
   }
@@ -42,11 +42,13 @@ public class StringConfigurer extends Configurer {
     super(key, name, val);
   }
 
-  public String getValueString() {
+  @Override
+public String getValueString() {
     return (String) value;
   }
 
-  public void setValue(String s) {
+  @Override
+public void setValue(String s) {
     if (!noUpdate && nameField != null) {
       nameField.setText(s);
     }
@@ -56,8 +58,9 @@ public class StringConfigurer extends Configurer {
   public void setToolTipText(String s) {
     nameField.setToolTipText(s);
   }
-  
-  public java.awt.Component getControls() {
+
+  @Override
+public java.awt.Component getControls() {
     if (p == null) {
       p = new JPanel();
       p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
@@ -68,7 +71,8 @@ public class StringConfigurer extends Configurer {
       nameField.setText(getValueString());
       p.add(nameField);
       nameField.addKeyListener(new java.awt.event.KeyAdapter() {
-        public void keyReleased(java.awt.event.KeyEvent evt) {
+        @Override
+		public void keyReleased(java.awt.event.KeyEvent evt) {
           noUpdate = true;
           setValue(nameField.getText());
           noUpdate = false;
diff --git a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/StringEnumConfigurer.java b/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/StringEnumConfigurer.java
index b19acba..7ea8deb 100644
--- a/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/StringEnumConfigurer.java
+++ b/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/StringEnumConfigurer.java
@@ -32,8 +32,8 @@ import java.awt.Component;
 import java.awt.Dimension;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+
 import javax.swing.Box;
-import javax.swing.DefaultComboBoxModel;
 import javax.swing.JComboBox;
 import javax.swing.JLabel;
 
@@ -62,7 +62,8 @@ public class StringEnumConfigurer extends Configurer {
     public void setToolTipText(String s) {
         tooltipText = s;
     }
-    public Component getControls() {
+    @Override
+	public Component getControls() {
         if (panel == null) {
             panel = Box.createHorizontalBox();
             panel.add(new JLabel(name));
@@ -81,15 +82,18 @@ public class StringEnumConfigurer extends Configurer {
         }
         return panel;
     }
-    public void setValue(Object o) {
+
+    @Override
+	public void setValue(Object o) {
         if(o == null)
-            o = new Integer(0);
+            o = 0;
         super.setValue(o);
         if(!noUpdate && box != null)
             box.setSelectedIndex((Integer)o);
     }
 
-    public void setValue(String s) {
+    @Override
+	public void setValue(String s) {
         Integer n = 0;
         for (int i = 0; i < transValues.length; ++i)
         {
@@ -101,7 +105,8 @@ public class StringEnumConfigurer extends Configurer {
         setValue(n);
     }
 
-    public String getValueString() {
+    @Override
+	public String getValueString() {
         return validValues[(Integer)value];
     }
 }
diff --git a/livegps/build.xml b/livegps/build.xml
index 3a36827..9f4e8ee 100644
--- a/livegps/build.xml
+++ b/livegps/build.xml
@@ -1,57 +1,188 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+** This is the build file for the livegps plugin
+**
+** Maintaining versions
+** ====================
+** see README.template
+**
+** Usage
+** =====
+** To build it run
+**
+**    > ant  dist
+**
+** To install the generated plugin locally (in your default plugin directory) run
+**
+**    > ant  install
+**
+** To build against the core in ../../core, create a correct manifest and deploy to
+** SVN, 
+**    set the properties commit.message and plugin.main.version
+** and run
+**    > ant  publish
+**
+**
+-->
 <project name="livegps" 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="livegps.LiveGpsPlugin"/>
-                <attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
-                <attribute name="Plugin-Description" value="Support live GPS input (moving dot) through a connection to gpsd server."/>
-                <attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/index.php/JOSM/Plugins/LiveGPS"/>
-                <attribute name="Plugin-Mainversion" value="2450"/>
-                <attribute name="Plugin-Stage" value="50"/>
-                <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>
+
+	<property name="commit.message" value="Changed the constructor signature of the plugin main class" />
+	<property name="plugin.main.version" value="2907" />
+	
+
+	<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="livegps.LiveGpsPlugin"/>
+				<attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
+				<attribute name="Plugin-Description" value="Support live GPS input (moving dot) through a connection to gpsd server."/>
+				<attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/index.php/JOSM/Plugins/LiveGPS"/>
+				<attribute name="Plugin-Mainversion" value="${plugin.main.version}"/>
+				<attribute name="Plugin-Stage" value="50"/>
+				<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>
+
+
+	<!--
+		 ************************** Publishing the plugin *********************************** 
+		-->
+	<!--
+		** extracts the JOSM release for the JOSM version in ../core and saves it in the 
+		** property ${coreversion.info.entry.revision}
+		**
+		-->
+	<target name="core-info">
+		<exec append="false" output="core.info.xml" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="info"/>
+			<arg value="--xml"/>
+			<arg value="../../core"/>
+		</exec>
+		<xmlproperty file="core.info.xml" prefix="coreversion" keepRoot="true" collapseAttributes="true"/>
+		<echo>Building against core revision ${coreversion.info.entry.revision}.</echo>
+		<echo>Plugin-Mainversion is set to ${plugin.main.version}.</echo>
+		<delete file="core.info.xml" />
+	</target>
+
+	<!--
+		** commits the source tree for this plugin
+		-->
+	<target name="commit-current">
+		<echo>Commiting the plugin source with message '${commit.message}' ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="commit"/>
+			<arg value="-m '${commit.message}'"/>
+			<arg value="."/>
+		</exec>
+	</target>
+
+	<!--
+		** updates (svn up) the source tree for this plugin
+		-->
+	<target name="update-current">
+		<echo>Updating plugin source ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="up"/>
+			<arg value="."/>
+		</exec>
+		<echo>Updating ${plugin.jar} ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="up"/>
+			<arg value="../dist/${plugin.jar}"/>
+		</exec>
+	</target>
+
+	<!--
+		** commits the plugin.jar 
+		-->
+	<target name="commit-dist">
+		<echo>
+	***** Properties of published ${plugin.jar} *****
+	Commit message    : '${commit.message}'					
+	Plugin-Mainversion: ${plugin.main.version}
+	JOSM build version: ${coreversion.info.entry.revision}
+	Plugin-Version    : ${version.entry.commit.revision}
+	***** / Properties of published ${plugin.jar} *****					
+						
+	Now commiting ${plugin.jar} ...
+	</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="-m '${commit.message}'"/>
+			<arg value="commit"/>
+			<arg value="${plugin.jar}"/>
+		</exec>
+	</target>
+
+	<!-- ** make sure svn is present as a command line tool ** -->
+	<target name="ensure-svn-present">
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false" failonerror="false" resultproperty="svn.exit.code">
+			<env key="LANG" value="C" />
+			<arg value="--version" />
+		</exec>
+		<fail message="Fatal: command 'svn --version' failed. Please make sure svn is installed on your system.">
+			<!-- return code not set at all? Most likely svn isn't installed -->
+			<condition>
+				<not>
+					<isset property="svn.exit.code" />
+				</not>
+			</condition>
+		</fail>
+		<fail message="Fatal: command 'svn --version' failed. Please make sure a working copy of svn is installed on your system.">
+			<!-- error code from SVN? Most likely svn is not what we are looking on this system -->
+			<condition>
+				<isfailure code="${svn.exit.code}" />
+			</condition>
+		</fail>
+	</target>
+
+	<target name="publish" depends="ensure-svn-present,core-info,commit-current,update-current,clean,dist,commit-dist">
+	</target>
 </project>
diff --git a/utilsplugin/josm-utilsplugin.launch b/livegps/josm-livegps.launch
similarity index 96%
rename from utilsplugin/josm-utilsplugin.launch
rename to livegps/josm-livegps.launch
index a51a882..d2780b6 100644
--- a/utilsplugin/josm-utilsplugin.launch
+++ b/livegps/josm-livegps.launch
@@ -8,5 +8,5 @@
 </listAttribute>
 <stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JDK 6"/>
 <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.openstreetmap.josm.gui.MainApplication"/>
-<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="JOSM-utilsplugin"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="livegps"/>
 </launchConfiguration>
diff --git a/livegps/src/livegps/AppendableGpxTrackSegment.java b/livegps/src/livegps/AppendableGpxTrackSegment.java
new file mode 100644
index 0000000..43e2137
--- /dev/null
+++ b/livegps/src/livegps/AppendableGpxTrackSegment.java
@@ -0,0 +1,57 @@
+package livegps;
+
+import java.util.Collection;
+
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
+import org.openstreetmap.josm.data.gpx.WayPoint;
+import org.openstreetmap.josm.tools.CopyList;
+
+/**
+ * Thread safe implementation of GpxTrackSegement
+ *
+ */
+public class AppendableGpxTrackSegment implements GpxTrackSegment {
+
+	private WayPoint[] wayPoints = new WayPoint[16];
+	private int size;
+	private Bounds bounds;
+	private double length;
+
+	public Bounds getBounds() {
+		return bounds;
+	}
+
+	public Collection<WayPoint> getWayPoints() {
+		return new CopyList<WayPoint>(wayPoints, size);
+	}
+
+	public void addWaypoint(WayPoint p) {
+		if (wayPoints.length == size) {
+			WayPoint[] newWaypoints = new WayPoint[wayPoints.length * 2];
+			System.arraycopy(wayPoints, 0, newWaypoints, 0, wayPoints.length);
+			wayPoints = newWaypoints;
+		}
+
+		if (size > 0) {
+			Double distance = wayPoints[size - 1].getCoor().greatCircleDistance(p.getCoor());
+			if (!distance.isNaN() && !distance.isInfinite()) {
+				length += distance;
+			}
+		}
+
+		if (bounds == null) {
+			bounds = new Bounds(p.getCoor());
+		} else {
+			bounds.extend(p.getCoor());
+		}
+
+		wayPoints[size] = p;
+		size++;
+	}
+
+	public double length() {
+		return length;
+	}
+
+}
diff --git a/livegps/src/livegps/ILiveGpsSuppressor.java b/livegps/src/livegps/ILiveGpsSuppressor.java
new file mode 100644
index 0000000..50ef2c2
--- /dev/null
+++ b/livegps/src/livegps/ILiveGpsSuppressor.java
@@ -0,0 +1,20 @@
+package livegps;
+
+/**
+ * Interface for class LiveGpsSuppressor, only has a query if currently an update is allowed.
+ * 
+ * @author casualwalker 
+ *
+ */
+public interface ILiveGpsSuppressor {
+
+	/**
+	 * Query, if an update is currently allowed.
+	 * When it is allowed, it will disable the allowUpdate flag as a side effect.
+	 * (this means, one thread got to issue an update event)
+	 *
+	 * @return true, if an update is currently allowed; false, if the update shall be suppressed.
+	 */
+	boolean isAllowUpdate();
+
+}
diff --git a/livegps/src/livegps/LiveGpsAcquirer.java b/livegps/src/livegps/LiveGpsAcquirer.java
index 9d33d4d..0fac800 100644
--- a/livegps/src/livegps/LiveGpsAcquirer.java
+++ b/livegps/src/livegps/LiveGpsAcquirer.java
@@ -1,226 +1,269 @@
 package livegps;
 
 import static org.openstreetmap.josm.tools.I18n.tr;
+
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
 import java.io.BufferedReader;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.net.InetAddress;
 import java.net.Socket;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Properties;
 
-import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.coor.LatLon;
 
 public class LiveGpsAcquirer implements Runnable {
-    Socket gpsdSocket;
-    BufferedReader gpsdReader;
-    boolean connected = false;
-    String gpsdHost = Main.pref.get("livegps.gpsd.host","localhost");
-    int gpsdPort = Main.pref.getInteger("livegps.gpsd.port", 2947);
-    boolean shutdownFlag = false;
-    private List<PropertyChangeListener> propertyChangeListener = new ArrayList<PropertyChangeListener>();
-    private PropertyChangeEvent lastStatusEvent;
-    private PropertyChangeEvent lastDataEvent;
-
-    /**
-     * Adds a property change listener to the acquirer.
-     * @param listener the new listener
-     */
-    public void addPropertyChangeListener(PropertyChangeListener listener) {
-        if(!propertyChangeListener.contains(listener)) {
-            propertyChangeListener.add(listener);
-        }
-    }
-
-    /**
-     * Remove a property change listener from the acquirer.
-     * @param listener the new listener
-     */
-    public void removePropertyChangeListener(PropertyChangeListener listener) {
-        if(propertyChangeListener.contains(listener)) {
-            propertyChangeListener.remove(listener);
-        }
-    }
-
-    /**
-     * Fire a gps status change event. Fires events with key "gpsstatus" and a {@link LiveGpsStatus}
-     * object as value.
-     * @param status the status.
-     * @param statusMessage the status message.
-     */
-    public void fireGpsStatusChangeEvent(LiveGpsStatus.GpsStatus status, String statusMessage) {
-        PropertyChangeEvent event = new PropertyChangeEvent(this, "gpsstatus", null, new LiveGpsStatus(status, statusMessage));
-        if(!event.equals(lastStatusEvent)) {
-            firePropertyChangeEvent(event);
-            lastStatusEvent = event;
-        }
-    }
-
-    /**
-     * Fire a gps data change event to all listeners. Fires events with key "gpsdata" and a
-     * {@link LiveGpsData} object as values.
-     * @param oldData the old gps data.
-     * @param newData the new gps data.
-     */
-    public void fireGpsDataChangeEvent(LiveGpsData oldData, LiveGpsData newData) {
-        PropertyChangeEvent event = new PropertyChangeEvent(this, "gpsdata", oldData, newData);
-        if(!event.equals(lastDataEvent)) {
-            firePropertyChangeEvent(event);
-            lastDataEvent = event;
-        }
-    }
-
-    /**
-     * Fires the given event to all listeners.
-     * @param event the event to fire.
-     */
-    protected void firePropertyChangeEvent(PropertyChangeEvent event) {
-        for (PropertyChangeListener listener : propertyChangeListener) {
-            listener.propertyChange(event);
-        }
-    }
-
-    public void run() {
-        LiveGpsData oldGpsData = null;
-        LiveGpsData gpsData = null;
-        shutdownFlag = false;
-        while(!shutdownFlag) {
-            double lat = 0;
-            double lon = 0;
-            float speed = 0;
-            float course = 0;
-            boolean haveFix = false;
-
-            try
-            {
-                if (!connected)
-                {
-                    System.out.println("LiveGps tries to connect to gpsd");
-                    fireGpsStatusChangeEvent(LiveGpsStatus.GpsStatus.CONNECTING, tr("Connecting"));
-                    InetAddress[] addrs = InetAddress.getAllByName(gpsdHost);
-                    for (int i=0; i < addrs.length && gpsdSocket == null; i++) {
-                        try {
-                            gpsdSocket = new Socket(addrs[i], gpsdPort);
-                            break;
-                        } catch (Exception e) {
-                            System.out.println("LiveGps: Could not open connection to gpsd: " + e);
-                            gpsdSocket = null;
-                        }
-                    }
-
-                    if (gpsdSocket != null)
-                    {
-                        gpsdReader = new BufferedReader(new InputStreamReader(gpsdSocket.getInputStream()));
-                        gpsdSocket.getOutputStream().write(new byte[] { 'w', 13, 10 });
-                        fireGpsStatusChangeEvent(LiveGpsStatus.GpsStatus.CONNECTING, tr("Connecting"));
-                        connected = true;
-                    System.out.println("LiveGps: Connected to gpsd");
-                    }
-                }
-
-
-                if(connected) {
-                    // <FIXXME date="23.06.2007" author="cdaller">
-                    // TODO this read is blocking if gps is connected but has no fix, so gpsd does not send positions
-                    String line = gpsdReader.readLine();
-                    // </FIXXME>
-                    if (line == null) break;
-                    String words[] = line.split(",");
-
-                    if ((words.length == 0) || (!words[0].equals("GPSD"))) {
-                        // unexpected response.
-                        continue;
-                    }
-
-                    for (int i = 1; i < words.length; i++) {
-
-                        if ((words[i].length() < 2) || (words[i].charAt(1) != '=')) {
-                            // unexpected response.
-                            continue;
-                        }
-
-                        char what = words[i].charAt(0);
-                        String value = words[i].substring(2);
-                        oldGpsData = gpsData;
-                        gpsData = new LiveGpsData();
-                        switch(what) {
-                        case 'O':
-                            // full report, tab delimited.
-                            String[] status = value.split("\\s+");
-                            if (status.length >= 5) {
-                                lat = Double.parseDouble(status[3]);
-                                lon = Double.parseDouble(status[4]);
-                                try {
-                                    speed = Float.parseFloat(status[9]);
-                                    course = Float.parseFloat(status[8]);
-                                    //view.setSpeed(speed);
-                                    //view.setCourse(course);
-                                } catch (NumberFormatException nex) {}
-                                haveFix = true;
-                            }
-                            break;
-                        case 'P':
-                            // position report, tab delimited.
-                            String[] pos = value.split("\\s+");
-                            if (pos.length >= 2) {
-                                lat = Double.parseDouble(pos[0]);
-                                lon = Double.parseDouble(pos[1]);
-                                speed = Float.NaN;
-                                course = Float.NaN;
-                                haveFix = true;
-                            }
-                        default:
-                            // not interested
-                        }
-                        fireGpsStatusChangeEvent(LiveGpsStatus.GpsStatus.CONNECTED, tr("Connected"));
-                        gpsData.setFix(haveFix);
-                        if (haveFix) {
-                            //view.setCurrentPosition(lat, lon);
-                            gpsData.setLatLon(new LatLon(lat, lon));
-                            gpsData.setSpeed(speed);
-                            gpsData.setCourse(course);
-                            fireGpsDataChangeEvent(oldGpsData, gpsData);
-                        }
-                    }
-                } else {
-                    // not connected:
-                    fireGpsStatusChangeEvent(LiveGpsStatus.GpsStatus.DISCONNECTED, tr("Not connected"));
-                    try { Thread.sleep(1000); } catch (InterruptedException ignore) {};
-                }
-            } catch(IOException iox) {
-                connected = false;
-                if(gpsData != null) {
-                    gpsData.setFix(false);
-                    fireGpsDataChangeEvent(oldGpsData, gpsData);
-                }
-                fireGpsStatusChangeEvent(LiveGpsStatus.GpsStatus.CONNECTION_FAILED, tr("Connection Failed"));
-                try { Thread.sleep(1000); } catch (InterruptedException ignore) {};
-                // send warning to layer
-
-            }
-        }
-
-        fireGpsStatusChangeEvent(LiveGpsStatus.GpsStatus.DISCONNECTED, tr("Not connected"));
-        if (gpsdSocket != null) {
-            try {
-              gpsdSocket.close();
-              gpsdSocket = null;
-                  System.out.println("LiveGps: Disconnected from gpsd");
-            }
-            catch (Exception e) {
-              System.out.println("LiveGps: Unable to close socket; reconnection may not be possible");
-            }
-        }
-    }
-
-    public void shutdown()
-    {
-        shutdownFlag = true;
-    }
+	Socket gpsdSocket;
+	BufferedReader gpsdReader;
+	boolean connected = false;
+	String gpsdHost;
+	int gpsdPort;
+	boolean shutdownFlag = false;
+	private final List<PropertyChangeListener> propertyChangeListener = new ArrayList<PropertyChangeListener>();
+	private PropertyChangeEvent lastStatusEvent;
+	private PropertyChangeEvent lastDataEvent;
+
+	/**
+	 * Constructor, initializes the configurable settings. 
+	 */
+	public LiveGpsAcquirer() {
+		super();
+
+		gpsdHost = Main.pref.get("livegps.gpsd.host", "localhost");
+		gpsdPort = Main.pref.getInteger("livegps.gpsd.port", 2947);
+		// put the settings back in to the preferences, makes keys appear.
+		Main.pref.put("livegps.gpsd.host", gpsdHost);
+		Main.pref.putInteger("livegps.gpsd.port", gpsdPort);
+	}
+
+	/**
+	 * Adds a property change listener to the acquirer.
+	 * @param listener the new listener
+	 */
+	public void addPropertyChangeListener(PropertyChangeListener listener) {
+		if (!propertyChangeListener.contains(listener)) {
+			propertyChangeListener.add(listener);
+		}
+	}
+
+	/**
+	 * Remove a property change listener from the acquirer.
+	 * @param listener the new listener
+	 */
+	public void removePropertyChangeListener(PropertyChangeListener listener) {
+		if (propertyChangeListener.contains(listener)) {
+			propertyChangeListener.remove(listener);
+		}
+	}
+
+	/**
+	 * Fire a gps status change event. Fires events with key "gpsstatus" and a {@link LiveGpsStatus}
+	 * object as value.
+	 * The status event may be sent any time.
+	 * @param status the status.
+	 * @param statusMessage the status message.
+	 */
+	public void fireGpsStatusChangeEvent(LiveGpsStatus.GpsStatus status,
+			String statusMessage) {
+		PropertyChangeEvent event = new PropertyChangeEvent(this, "gpsstatus",
+				null, new LiveGpsStatus(status, statusMessage));
+
+		if (!event.equals(lastStatusEvent)) {
+			firePropertyChangeEvent(event);
+			lastStatusEvent = event;
+		}
+	}
+
+	/**
+	 * Fire a gps data change event to all listeners. Fires events with key "gpsdata" and a
+	 * {@link LiveGpsData} object as values.
+	 * This event is only sent, when the suppressor permits it. This
+	 * event will cause the UI to re-draw itself, which has some performance penalty,
+	 * @param oldData the old gps data.
+	 * @param newData the new gps data.
+	 */
+	public void fireGpsDataChangeEvent(LiveGpsData oldData, LiveGpsData newData) {
+		PropertyChangeEvent event = new PropertyChangeEvent(this, "gpsdata",
+				oldData, newData);
+
+		if (!event.equals(lastDataEvent)) {
+			firePropertyChangeEvent(event);
+			lastDataEvent = event;
+		}
+	}
+
+	/**
+	 * Fires the given event to all listeners.
+	 * @param event the event to fire.
+	 */
+	protected void firePropertyChangeEvent(PropertyChangeEvent event) {
+		for (PropertyChangeListener listener : propertyChangeListener) {
+			listener.propertyChange(event);
+		}
+	}
+
+	public void run() {
+		LiveGpsData oldGpsData = null;
+		LiveGpsData gpsData = null;
+
+		shutdownFlag = false;
+		while (!shutdownFlag) {
+			double lat = 0;
+			double lon = 0;
+			float speed = 0;
+			float course = 0;
+			boolean haveFix = false;
+
+			try {
+				if (!connected) {
+					System.out.println("LiveGps tries to connect to gpsd");
+					fireGpsStatusChangeEvent(
+							LiveGpsStatus.GpsStatus.CONNECTING,
+							tr("Connecting"));
+					InetAddress[] addrs = InetAddress.getAllByName(gpsdHost);
+					for (int i = 0; i < addrs.length && gpsdSocket == null; i++) {
+						try {
+							gpsdSocket = new Socket(addrs[i], gpsdPort);
+							break;
+						} catch (Exception e) {
+							System.out
+									.println("LiveGps: Could not open connection to gpsd: "
+											+ e);
+							gpsdSocket = null;
+						}
+					}
+
+					if (gpsdSocket != null) {
+						gpsdReader = new BufferedReader(new InputStreamReader(
+								gpsdSocket.getInputStream()));
+						gpsdSocket.getOutputStream().write(
+								new byte[] { 'w', 13, 10 });
+						fireGpsStatusChangeEvent(
+								LiveGpsStatus.GpsStatus.CONNECTING,
+								tr("Connecting"));
+						connected = true;
+						System.out.println("LiveGps: Connected to gpsd");
+					}
+				}
+
+				if (connected) {
+					// <FIXXME date="23.06.2007" author="cdaller">
+					// TODO this read is blocking if gps is connected but has no
+					// fix, so gpsd does not send positions
+					String line = gpsdReader.readLine();
+					// </FIXXME>
+					if (line == null)
+						break;
+					String words[] = line.split(",");
+
+					if ((words.length == 0) || (!words[0].equals("GPSD"))) {
+						// unexpected response.
+						continue;
+					}
+
+					for (int i = 1; i < words.length; i++) {
+
+						if ((words[i].length() < 2)
+								|| (words[i].charAt(1) != '=')) {
+							// unexpected response.
+							continue;
+						}
+
+						char what = words[i].charAt(0);
+						String value = words[i].substring(2);
+						oldGpsData = gpsData;
+						gpsData = new LiveGpsData();
+						switch (what) {
+						case 'O':
+							// full report, tab delimited.
+							String[] status = value.split("\\s+");
+							if (status.length >= 5) {
+								lat = Double.parseDouble(status[3]);
+								lon = Double.parseDouble(status[4]);
+								try {
+									speed = Float.parseFloat(status[9]);
+									course = Float.parseFloat(status[8]);
+									// view.setSpeed(speed);
+									// view.setCourse(course);
+								} catch (NumberFormatException nex) {
+								}
+								haveFix = true;
+							}
+							break;
+						case 'P':
+							// position report, tab delimited.
+							String[] pos = value.split("\\s+");
+							if (pos.length >= 2) {
+								lat = Double.parseDouble(pos[0]);
+								lon = Double.parseDouble(pos[1]);
+								speed = Float.NaN;
+								course = Float.NaN;
+								haveFix = true;
+							}
+						default:
+							// not interested
+						}
+						fireGpsStatusChangeEvent(
+								LiveGpsStatus.GpsStatus.CONNECTED,
+								tr("Connected"));
+						gpsData.setFix(haveFix);
+						if (haveFix) {
+							// view.setCurrentPosition(lat, lon);
+							gpsData.setLatLon(new LatLon(lat, lon));
+							gpsData.setSpeed(speed);
+							gpsData.setCourse(course);
+							fireGpsDataChangeEvent(oldGpsData, gpsData);
+						}
+					}
+				} else {
+					// not connected:
+					fireGpsStatusChangeEvent(
+							LiveGpsStatus.GpsStatus.DISCONNECTED,
+							tr("Not connected"));
+					try {
+						Thread.sleep(1000);
+					} catch (InterruptedException ignore) {
+					}
+					;
+				}
+			} catch (IOException iox) {
+				connected = false;
+				if (gpsData != null) {
+					gpsData.setFix(false);
+					fireGpsDataChangeEvent(oldGpsData, gpsData);
+				}
+				fireGpsStatusChangeEvent(
+						LiveGpsStatus.GpsStatus.CONNECTION_FAILED,
+						tr("Connection Failed"));
+				try {
+					Thread.sleep(1000);
+				} catch (InterruptedException ignore) {
+				}
+				;
+				// send warning to layer
+
+			}
+		}
+
+		fireGpsStatusChangeEvent(LiveGpsStatus.GpsStatus.DISCONNECTED,
+				tr("Not connected"));
+		if (gpsdSocket != null) {
+			try {
+				gpsdSocket.close();
+				gpsdSocket = null;
+				System.out.println("LiveGps: Disconnected from gpsd");
+			} catch (Exception e) {
+				System.out
+						.println("LiveGps: Unable to close socket; reconnection may not be possible");
+			}
+		}
+	}
+
+	public void shutdown() {
+		shutdownFlag = true;
+	}
+
 }
diff --git a/livegps/src/livegps/LiveGpsData.java b/livegps/src/livegps/LiveGpsData.java
index c547713..56df8f6 100644
--- a/livegps/src/livegps/LiveGpsData.java
+++ b/livegps/src/livegps/LiveGpsData.java
@@ -8,7 +8,6 @@ import static org.openstreetmap.josm.tools.I18n.tr;
 import java.awt.Point;
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.Way;
 
diff --git a/livegps/src/livegps/LiveGpsLayer.java b/livegps/src/livegps/LiveGpsLayer.java
index 3d46b89..c358481 100644
--- a/livegps/src/livegps/LiveGpsLayer.java
+++ b/livegps/src/livegps/LiveGpsLayer.java
@@ -8,9 +8,9 @@ import java.awt.Point;
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
 import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.Bounds;
@@ -22,136 +22,163 @@ import org.openstreetmap.josm.gui.MapView;
 import org.openstreetmap.josm.gui.layer.GpxLayer;
 
 public class LiveGpsLayer extends GpxLayer implements PropertyChangeListener {
-    public static final String LAYER_NAME = tr("LiveGPS layer");
-    public static final String KEY_LIVEGPS_COLOR ="color.livegps.position";
-    LatLon lastPos;
-    WayPoint lastPoint;
-    GpxTrack trackBeingWritten;
-    Collection<WayPoint> trackSegment;
-    float speed;
-    float course;
-    String status;
-    //JLabel lbl;
-    boolean autocenter;
-    private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
-
-    public LiveGpsLayer(GpxData data)
-    {
-        super (data, LAYER_NAME);
-        trackBeingWritten = new GpxTrack();
-        trackBeingWritten.attr.put("desc", "josm live gps");
-        trackSegment = new ArrayList<WayPoint>();
-        trackBeingWritten.trackSegs.add(trackSegment);
-        data.tracks.add(trackBeingWritten);
-    }
-
-    void setCurrentPosition(double lat, double lon)
-    {
-        //System.out.println("adding pos " + lat + "," + lon);
-        LatLon thisPos = new LatLon(lat, lon);
-        if ((lastPos != null) && (thisPos.equalsEpsilon(lastPos))) {
-            // no change in position
-            // maybe show a "paused" cursor or some such
-            return;
-        }
-
-        lastPos = thisPos;
-        lastPoint = new WayPoint(thisPos);
-        lastPoint.attr.put("time", dateFormat.format(new Date()));
-        // synchronize when adding data, as otherwise the autosave action
-        // needs concurrent access and this results in an exception!
-        synchronized (LiveGpsLock.class) {
-            trackSegment.add(lastPoint);
-        }
-        if (autocenter) {
-            center();
-        }
-
-        //Main.map.repaint();
-    }
-
-    public void center()
-    {
-        if (lastPoint != null)
-            Main.map.mapView.zoomTo(lastPoint.getCoor());
-    }
-
-//  void setStatus(String status)
-//  {
-//      this.status = status;
-//      Main.map.repaint();
-//        System.out.println("LiveGps status: " + status);
-//  }
-
-    void setSpeed(float metresPerSecond)
-    {
-        speed = metresPerSecond;
-        //Main.map.repaint();
-    }
-
-    void setCourse(float degrees)
-    {
-        course = degrees;
-        //Main.map.repaint();
-    }
-
-    public void setAutoCenter(boolean ac)
-    {
-        autocenter = ac;
-    }
-
-    @Override public void paint(Graphics2D g, MapView mv, Bounds bounds)
-    {
-        //System.out.println("in paint");
-        synchronized (LiveGpsLock.class) {
-            //System.out.println("in synced paint");
-            super.paint(g, mv, bounds);
-//          int statusHeight = 50;
-//          Rectangle mvs = mv.getBounds();
-//          mvs.y = mvs.y + mvs.height - statusHeight;
-//          mvs.height = statusHeight;
-//          g.setColor(new Color(1.0f, 1.0f, 1.0f, 0.8f));
-//          g.fillRect(mvs.x, mvs.y, mvs.width, mvs.height);
-
-            if (lastPoint != null)
-            {
-                Point screen = mv.getPoint(lastPoint.getCoor());
-                g.setColor(Main.pref.getColor(KEY_LIVEGPS_COLOR, Color.RED));
-                g.drawOval(screen.x-10, screen.y-10,20,20);
-                g.drawOval(screen.x-9, screen.y-9,18,18);
-            }
-
-//          lbl.setText("gpsd: "+status+" Speed: " + speed + " Course: "+course);
-//          lbl.setBounds(0, 0, mvs.width-10, mvs.height-10);
-//          Graphics sub = g.create(mvs.x+5, mvs.y+5, mvs.width-10, mvs.height-10);
-//          lbl.paint(sub);
-
-//          if(status != null) {
-//          g.setColor(Color.WHITE);
-//          g.drawString("gpsd: " + status, 5, mv.getBounds().height - 15); // lower left corner
-//          }
-        }
-    }
-
-    /* (non-Javadoc)
-     * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
-     */
-    public void propertyChange(PropertyChangeEvent evt) {
-        if(!isVisible()) {
-            return;
-        }
-        if("gpsdata".equals(evt.getPropertyName())) {
-            LiveGpsData data = (LiveGpsData) evt.getNewValue();
-            if(data.isFix()) {
-                setCurrentPosition(data.getLatitude(), data.getLongitude());
-                if(!Float.isNaN(data.getSpeed())) {
-                    setSpeed(data.getSpeed());
-                }
-                if(!Float.isNaN(data.getCourse())) {
-                    setCourse(data.getCourse());
-                }
-                Main.map.repaint();
-            }
-        }
-    }
+	public static final String LAYER_NAME = tr("LiveGPS layer");
+	public static final String KEY_LIVEGPS_COLOR = "color.livegps.position";
+	LatLon lastPos;
+	WayPoint lastPoint;
+	private final AppendableGpxTrackSegment trackSegment;
+	float speed;
+	float course;
+	String status;
+	// JLabel lbl;
+	boolean autocenter;
+	private SimpleDateFormat dateFormat = new SimpleDateFormat(
+	"yyyy-MM-dd'T'HH:mm:ss.SSS");
+
+	/**
+	 * The suppressor is queried, if the GUI shall be re-drawn.
+	 */
+	private ILiveGpsSuppressor suppressor;
+
+	public LiveGpsLayer(GpxData data) {
+		super(data, LAYER_NAME);
+		trackSegment = new AppendableGpxTrackSegment();
+
+		Map<String, Object> attr = new HashMap<String, Object>();
+		attr.put("desc", "josm live gps");
+
+		GpxTrack trackBeingWritten = new SingleSegmentGpxTrack(trackSegment, attr);
+		data.tracks.add(trackBeingWritten);
+	}
+
+	void setCurrentPosition(double lat, double lon) {
+		// System.out.println("adding pos " + lat + "," + lon);
+		LatLon thisPos = new LatLon(lat, lon);
+		if ((lastPos != null) && (thisPos.equalsEpsilon(lastPos))) {
+			// no change in position
+			// maybe show a "paused" cursor or some such
+			return;
+		}
+
+		lastPos = thisPos;
+		lastPoint = new WayPoint(thisPos);
+		lastPoint.attr.put("time", dateFormat.format(new Date()));
+		trackSegment.addWaypoint(lastPoint);
+		if (autocenter && allowRedraw()) {
+			center();
+		}
+
+		// Main.map.repaint();
+	}
+
+	public void center() {
+		if (lastPoint != null)
+			Main.map.mapView.zoomTo(lastPoint.getCoor());
+	}
+
+	// void setStatus(String status)
+	// {
+	// this.status = status;
+	// Main.map.repaint();
+	// System.out.println("LiveGps status: " + status);
+	// }
+
+	void setSpeed(float metresPerSecond) {
+		speed = metresPerSecond;
+		// Main.map.repaint();
+	}
+
+	void setCourse(float degrees) {
+		course = degrees;
+		// Main.map.repaint();
+	}
+
+	public void setAutoCenter(boolean ac) {
+		autocenter = ac;
+	}
+
+	@Override
+	public void paint(Graphics2D g, MapView mv, Bounds bounds) {
+		// System.out.println("in paint");
+		// System.out.println("in synced paint");
+		super.paint(g, mv, bounds);
+		// int statusHeight = 50;
+		// Rectangle mvs = mv.getBounds();
+		// mvs.y = mvs.y + mvs.height - statusHeight;
+		// mvs.height = statusHeight;
+		// g.setColor(new Color(1.0f, 1.0f, 1.0f, 0.8f));
+		// g.fillRect(mvs.x, mvs.y, mvs.width, mvs.height);
+
+		if (lastPoint != null) {
+			Point screen = mv.getPoint(lastPoint.getCoor());
+			g.setColor(Main.pref.getColor(KEY_LIVEGPS_COLOR, Color.RED));
+			g.drawOval(screen.x - 10, screen.y - 10, 20, 20);
+			g.drawOval(screen.x - 9, screen.y - 9, 18, 18);
+		}
+
+		// lbl.setText("gpsd: "+status+" Speed: " + speed +
+		// " Course: "+course);
+		// lbl.setBounds(0, 0, mvs.width-10, mvs.height-10);
+		// Graphics sub = g.create(mvs.x+5, mvs.y+5, mvs.width-10,
+		// mvs.height-10);
+		// lbl.paint(sub);
+
+		// if(status != null) {
+		// g.setColor(Color.WHITE);
+		// g.drawString("gpsd: " + status, 5, mv.getBounds().height - 15);
+		// // lower left corner
+		// }
+	}
+
+	/* (non-Javadoc)
+	 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
+	 */
+	public void propertyChange(PropertyChangeEvent evt) {
+		if (!isVisible()) {
+			return;
+		}
+		if ("gpsdata".equals(evt.getPropertyName())) {
+			LiveGpsData data = (LiveGpsData) evt.getNewValue();
+			if (data.isFix()) {
+				setCurrentPosition(data.getLatitude(), data.getLongitude());
+				if (!Float.isNaN(data.getSpeed())) {
+					setSpeed(data.getSpeed());
+				}
+				if (!Float.isNaN(data.getCourse())) {
+					setCourse(data.getCourse());
+				}
+				if (!autocenter && allowRedraw()) {
+					Main.map.repaint();
+				}
+			}
+		}
+	}
+
+	/**
+	 * @param suppressor the suppressor to set
+	 */
+	public void setSuppressor(ILiveGpsSuppressor suppressor) {
+		this.suppressor = suppressor;
+	}
+
+	/**
+	 * @return the suppressor
+	 */
+	public ILiveGpsSuppressor getSuppressor() {
+		return suppressor;
+	}
+
+	/**
+	 * Check, if a redraw is currently allowed.
+	 *
+	 * @return true, if a redraw is permitted, false, if a re-draw
+	 * should be suppressed.
+	 */
+	private boolean allowRedraw() {
+		if (this.suppressor != null) {
+			return this.suppressor.isAllowUpdate();
+		} else {
+			return true;
+		}
+	}
 }
diff --git a/livegps/src/livegps/LiveGpsLock.java b/livegps/src/livegps/LiveGpsLock.java
deleted file mode 100644
index 948674e..0000000
--- a/livegps/src/livegps/LiveGpsLock.java
+++ /dev/null
@@ -1,16 +0,0 @@
-/**
- *
- */
-package livegps;
-
-/**
- * This class is only used to prevent concurrent object modification. So all classes that
- * read or write live gps data must synchronize to this class. Especially the save action
- * takes quite long, so concurrency problems occur.
- *
- * @author cdaller
- *
- */
-public class LiveGpsLock {
-
-}
diff --git a/livegps/src/livegps/LiveGpsPlugin.java b/livegps/src/livegps/LiveGpsPlugin.java
index bad5b19..c946328 100644
--- a/livegps/src/livegps/LiveGpsPlugin.java
+++ b/livegps/src/livegps/LiveGpsPlugin.java
@@ -19,204 +19,248 @@ import org.openstreetmap.josm.actions.JosmAction;
 import org.openstreetmap.josm.data.gpx.GpxData;
 import org.openstreetmap.josm.gui.MainMenu;
 import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
 import org.openstreetmap.josm.gui.layer.Layer;
-import org.openstreetmap.josm.gui.layer.Layer.LayerChangeListener;
 import org.openstreetmap.josm.plugins.Plugin;
+import org.openstreetmap.josm.plugins.PluginInformation;
 import org.openstreetmap.josm.tools.Shortcut;
 
-public class LiveGpsPlugin extends Plugin implements LayerChangeListener
-{
-    private LiveGpsAcquirer acquirer = null;
-    private Thread acquirerThread = null;
-    private JMenu lgpsmenu;
-    private JCheckBoxMenuItem lgpscapture;
-    private JMenuItem lgpscenter;
-    private JCheckBoxMenuItem lgpsautocenter;
-    private LiveGpsDialog lgpsdialog;
-    List<PropertyChangeListener>listenerQueue;
-
-    private GpxData data = new GpxData();
-    private LiveGpsLayer lgpslayer = null;
-
-    public class CaptureAction extends JosmAction {
-        public CaptureAction() {
-            super(tr("Capture GPS Track"), "capturemenu", tr("Connect to gpsd server and show current position in LiveGPS layer."),
-                Shortcut.registerShortcut("menu:livegps:capture", tr("Menu: {0}", tr("Capture GPS Track")),
-                KeyEvent.VK_R, Shortcut.GROUP_MENU), true);
-        }
-
-        public void actionPerformed(ActionEvent e) {
-            enableTracking(lgpscapture.isSelected());
-        }
-    }
-
-    public class CenterAction extends JosmAction {
-        public CenterAction() {
-            super(tr("Center Once"), "centermenu", tr("Center the LiveGPS layer to current position."),
-            Shortcut.registerShortcut("edit:centergps", tr("Edit: {0}", tr("Center Once")),
-            KeyEvent.VK_HOME, Shortcut.GROUP_EDIT), true);
-        }
-
-        public void actionPerformed(ActionEvent e) {
-            if(lgpslayer != null) {
-                lgpslayer.center();
-            }
-        }
-    }
-
-    public class AutoCenterAction extends JosmAction {
-        public AutoCenterAction() {
-            super(tr("Auto-Center"), "autocentermenu", tr("Continuously center the LiveGPS layer to current position."),
-            Shortcut.registerShortcut("menu:livegps:autocenter", tr("Menu: {0}", tr("Capture GPS Track")),
-            KeyEvent.VK_HOME, Shortcut.GROUP_MENU), true);
-        }
-
-        public void actionPerformed(ActionEvent e) {
-            if(lgpslayer != null) {
-                setAutoCenter(lgpsautocenter.isSelected());
-            }
-        }
-    }
-
-    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
-    }
-
-    public void layerAdded(Layer newLayer) {
-    }
-
-    public void layerRemoved(Layer oldLayer) {
-        if(oldLayer == lgpslayer)
-        {
-            enableTracking(false);
-            lgpscapture.setSelected(false);
-            removePropertyChangeListener(lgpslayer);
-            Layer.listeners.remove(this);
-            lgpslayer = null;
-        }
-    }
-
-    public LiveGpsPlugin()
-    {
-        MainMenu menu = Main.main.menu;
-        lgpsmenu = menu.addMenu(marktr("LiveGPS"), KeyEvent.VK_G, menu.defaultMenuPos, ht("/Plugin/LiveGPS"));
-
-        JosmAction captureAction = new CaptureAction();
-        lgpscapture = new JCheckBoxMenuItem(captureAction);
-        lgpsmenu.add(lgpscapture);
-        lgpscapture.setAccelerator(captureAction.getShortcut().getKeyStroke());
-
-        JosmAction centerAction = new CenterAction();
-        JMenuItem centerMenu = new JMenuItem(centerAction);
-        lgpsmenu.add(centerMenu);
-        centerMenu.setAccelerator(centerAction.getShortcut().getKeyStroke());
-
-        JosmAction autoCenterAction = new AutoCenterAction();
-        lgpsautocenter = new JCheckBoxMenuItem(autoCenterAction);
-        lgpsmenu.add(lgpsautocenter);
-        lgpsautocenter.setAccelerator(autoCenterAction.getShortcut().getKeyStroke());
-    }
-
-    /**
-     * Set to <code>true</code> if the current position should always be in the center of the map.
-     * @param autoCenter if <code>true</code> the map is always centered.
-     */
-    public void setAutoCenter(boolean autoCenter) {
-        lgpsautocenter.setSelected(autoCenter); // just in case this method was not called from the menu
-        if(lgpslayer != null) {
-            lgpslayer.setAutoCenter(autoCenter);
-            if (autoCenter) lgpslayer.center();
-        }
-    }
-
-    /**
-     * Returns <code>true</code> if autocenter is selected.
-     * @return <code>true</code> if autocenter is selected.
-     */
-    public boolean isAutoCenter() {
-        return lgpsautocenter.isSelected();
-    }
-
-    /**
-     * Enable or disable gps tracking
-     * @param enable if <code>true</code> tracking is started.
-     */
-    public void enableTracking(boolean enable) {
-        if ((acquirer != null) && (!enable))
-        {
-            acquirer.shutdown();
-            acquirerThread = null;
-        }
-        else if(enable)
-        {
-            if (acquirer == null) {
-                acquirer = new LiveGpsAcquirer();
-                if (lgpslayer == null) {
-                    lgpslayer = new LiveGpsLayer(data);
-                    Main.main.addLayer(lgpslayer);
-                    Layer.listeners.add(this);
-                    lgpslayer.setAutoCenter(isAutoCenter());
-                }
-                // connect layer with acquirer:
-                addPropertyChangeListener(lgpslayer);
-                // add all listeners that were added before the acquirer existed:
-                if(listenerQueue != null) {
-                    for(PropertyChangeListener listener : listenerQueue) {
-                        addPropertyChangeListener(listener);
-                    }
-                    listenerQueue.clear();
-                }
-            }
-            if(acquirerThread == null) {
-                acquirerThread = new Thread(acquirer);
-                acquirerThread.start();
-            }
-        }
-    }
-
-
-    /**
-     * Add a listener for gps events.
-     * @param listener the listener.
-     */
-    public void addPropertyChangeListener(PropertyChangeListener listener) {
-        if(acquirer != null) {
-            acquirer.addPropertyChangeListener(listener);
-        } else {
-            if(listenerQueue == null) {
-                listenerQueue = new ArrayList<PropertyChangeListener>();
-            }
-            listenerQueue.add(listener);
-        }
-    }
-
-    /**
-     * Remove a listener for gps events.
-     * @param listener the listener.
-     */
-    public void removePropertyChangeListener(PropertyChangeListener listener) {
-        if(acquirer != null)
-            acquirer.removePropertyChangeListener(listener);
-        else if(listenerQueue != null && listenerQueue.contains(listener))
-            listenerQueue.remove(listener);
-    }
-
-    /* (non-Javadoc)
-     * @see org.openstreetmap.josm.plugins.Plugin#mapFrameInitialized(org.openstreetmap.josm.gui.MapFrame, org.openstreetmap.josm.gui.MapFrame)
-     */
-    @Override
-    public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
-        if(newFrame != null) {
-            // add dialog
-            newFrame.addToggleDialog(lgpsdialog = new LiveGpsDialog(newFrame));
-            // connect listeners with acquirer:
-            addPropertyChangeListener(lgpsdialog);
-        }
-    }
-
-    /**
-     * @return the lgpsmenu
-     */
-    public JMenu getLgpsMenu() {
-        return this.lgpsmenu;
-    }
+public class LiveGpsPlugin extends Plugin implements LayerChangeListener {
+	private LiveGpsAcquirer acquirer = null;
+	private Thread acquirerThread = null;
+	private JMenu lgpsmenu;
+	private JCheckBoxMenuItem lgpscapture;
+	private JMenuItem lgpscenter;
+	private JCheckBoxMenuItem lgpsautocenter;
+	private LiveGpsDialog lgpsdialog;
+	List<PropertyChangeListener> listenerQueue;
+
+	private GpxData data = new GpxData();
+	private LiveGpsLayer lgpslayer = null;
+
+	/**
+	 * The LiveGpsSuppressor is queried, if an event shall be suppressed.
+	 */
+	private LiveGpsSuppressor suppressor;
+
+	/**
+	 * separate thread, where the LiveGpsSuppressor executes.
+	 */
+	private Thread suppressorThread;
+
+	public class CaptureAction extends JosmAction {
+		public CaptureAction() {
+			super(
+					tr("Capture GPS Track"),
+					"capturemenu",
+					tr("Connect to gpsd server and show current position in LiveGPS layer."),
+					Shortcut.registerShortcut("menu:livegps:capture", tr(
+							"Menu: {0}", tr("Capture GPS Track")),
+							KeyEvent.VK_R, Shortcut.GROUP_MENU), true);
+		}
+
+		public void actionPerformed(ActionEvent e) {
+			enableTracking(lgpscapture.isSelected());
+		}
+	}
+
+	public class CenterAction extends JosmAction {
+		public CenterAction() {
+			super(tr("Center Once"), "centermenu",
+					tr("Center the LiveGPS layer to current position."),
+					Shortcut.registerShortcut("edit:centergps", tr("Edit: {0}",
+							tr("Center Once")), KeyEvent.VK_HOME,
+							Shortcut.GROUP_EDIT), true);
+		}
+
+		public void actionPerformed(ActionEvent e) {
+			if (lgpslayer != null) {
+				lgpslayer.center();
+			}
+		}
+	}
+
+	public class AutoCenterAction extends JosmAction {
+		public AutoCenterAction() {
+			super(
+					tr("Auto-Center"),
+					"autocentermenu",
+					tr("Continuously center the LiveGPS layer to current position."),
+					Shortcut.registerShortcut("menu:livegps:autocenter", tr(
+							"Menu: {0}", tr("Capture GPS Track")),
+							KeyEvent.VK_HOME, Shortcut.GROUP_MENU), true);
+		}
+
+		public void actionPerformed(ActionEvent e) {
+			if (lgpslayer != null) {
+				setAutoCenter(lgpsautocenter.isSelected());
+			}
+		}
+	}
+
+	public void activeLayerChange(Layer oldLayer, Layer newLayer) {
+	}
+
+	public void layerAdded(Layer newLayer) {
+	}
+
+	public void layerRemoved(Layer oldLayer) {
+		if (oldLayer == lgpslayer) {
+			enableTracking(false);
+			lgpscapture.setSelected(false);
+			removePropertyChangeListener(lgpslayer);
+			MapView.removeLayerChangeListener(this);
+			lgpslayer = null;
+		}
+	}
+
+	public LiveGpsPlugin(PluginInformation info) {
+		super(info);
+		MainMenu menu = Main.main.menu;
+		lgpsmenu = menu.addMenu(marktr("LiveGPS"), KeyEvent.VK_G,
+				menu.defaultMenuPos, ht("/Plugin/LiveGPS"));
+
+		JosmAction captureAction = new CaptureAction();
+		lgpscapture = new JCheckBoxMenuItem(captureAction);
+		lgpsmenu.add(lgpscapture);
+		lgpscapture.setAccelerator(captureAction.getShortcut().getKeyStroke());
+
+		JosmAction centerAction = new CenterAction();
+		JMenuItem centerMenu = new JMenuItem(centerAction);
+		lgpsmenu.add(centerMenu);
+		centerMenu.setAccelerator(centerAction.getShortcut().getKeyStroke());
+
+		JosmAction autoCenterAction = new AutoCenterAction();
+		lgpsautocenter = new JCheckBoxMenuItem(autoCenterAction);
+		lgpsmenu.add(lgpsautocenter);
+		lgpsautocenter.setAccelerator(autoCenterAction.getShortcut()
+				.getKeyStroke());
+	}
+
+	/**
+	 * Set to <code>true</code> if the current position should always be in the center of the map.
+	 * @param autoCenter if <code>true</code> the map is always centered.
+	 */
+	public void setAutoCenter(boolean autoCenter) {
+		lgpsautocenter.setSelected(autoCenter); // just in case this method was
+		// not called from the menu
+		if (lgpslayer != null) {
+			lgpslayer.setAutoCenter(autoCenter);
+			if (autoCenter)
+				lgpslayer.center();
+		}
+	}
+
+	/**
+	 * Returns <code>true</code> if autocenter is selected.
+	 * @return <code>true</code> if autocenter is selected.
+	 */
+	public boolean isAutoCenter() {
+		return lgpsautocenter.isSelected();
+	}
+
+	/**
+	 * Enable or disable gps tracking
+	 * @param enable if <code>true</code> tracking is started.
+	 */
+	public void enableTracking(boolean enable) {
+		if ((acquirer != null) && (!enable)) {
+			acquirer.shutdown();
+			acquirerThread = null;
+
+			// also stop the suppressor
+			if (suppressor != null) {
+				suppressor.shutdown();
+				suppressorThread = null;
+				if (lgpslayer != null) {
+					lgpslayer.setSuppressor(null);
+				}
+			}
+		} else if (enable) {
+			// also start the suppressor
+			if (suppressor == null) {
+				suppressor = new LiveGpsSuppressor();
+			}
+			if (suppressorThread == null) {
+				suppressorThread = new Thread(suppressor);
+				suppressorThread.start();
+			}
+
+			if (acquirer == null) {
+				acquirer = new LiveGpsAcquirer();
+				if (lgpslayer == null) {
+					lgpslayer = new LiveGpsLayer(data);
+					Main.main.addLayer(lgpslayer);
+					MapView.addLayerChangeListener(this);
+					lgpslayer.setAutoCenter(isAutoCenter());
+				}
+				// connect layer with acquirer:
+				addPropertyChangeListener(lgpslayer);
+
+				// connect layer with suppressor:
+				lgpslayer.setSuppressor(suppressor);
+				// add all listeners that were added before the acquirer
+				// existed:
+				if (listenerQueue != null) {
+					for (PropertyChangeListener listener : listenerQueue) {
+						addPropertyChangeListener(listener);
+					}
+					listenerQueue.clear();
+				}
+			}
+			if (acquirerThread == null) {
+				acquirerThread = new Thread(acquirer);
+				acquirerThread.start();
+			}
+
+		}
+	}
+
+	/**
+	 * Add a listener for gps events.
+	 * @param listener the listener.
+	 */
+	public void addPropertyChangeListener(PropertyChangeListener listener) {
+		if (acquirer != null) {
+			acquirer.addPropertyChangeListener(listener);
+		} else {
+			if (listenerQueue == null) {
+				listenerQueue = new ArrayList<PropertyChangeListener>();
+			}
+			listenerQueue.add(listener);
+		}
+	}
+
+	/**
+	 * Remove a listener for gps events.
+	 * @param listener the listener.
+	 */
+	public void removePropertyChangeListener(PropertyChangeListener listener) {
+		if (acquirer != null)
+			acquirer.removePropertyChangeListener(listener);
+		else if (listenerQueue != null && listenerQueue.contains(listener))
+			listenerQueue.remove(listener);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.Plugin#mapFrameInitialized(org.openstreetmap.josm.gui.MapFrame, org.openstreetmap.josm.gui.MapFrame)
+	 */
+	@Override
+	public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
+		if (newFrame != null) {
+			// add dialog
+			newFrame.addToggleDialog(lgpsdialog = new LiveGpsDialog(newFrame));
+			// connect listeners with acquirer:
+			addPropertyChangeListener(lgpsdialog);
+		}
+	}
+
+	/**
+	 * @return the lgpsmenu
+	 */
+	public JMenu getLgpsMenu() {
+		return this.lgpsmenu;
+	}
+
 }
diff --git a/livegps/src/livegps/LiveGpsSuppressor.java b/livegps/src/livegps/LiveGpsSuppressor.java
new file mode 100644
index 0000000..1f48cfb
--- /dev/null
+++ b/livegps/src/livegps/LiveGpsSuppressor.java
@@ -0,0 +1,136 @@
+package livegps;
+
+import org.openstreetmap.josm.Main;
+
+/**
+ * The LiveGpsSuppressor permits update events only once within a given timespan.
+ * This is useful, when too frequent updates consume large parts of the CPU resources (esp.
+ * on low-end devices, such as netbooks).
+ *
+ * Its own thread wakes up after the sleepTime and enables the allowUpdate flag.
+ * When another thread (the LiveGpsAcquirere) "asks for permission",
+ * the first call is permitted, but it also disables the updates for the following calls,
+ * until the sleepTime has elapsed.
+ *
+ * @author casualwalker
+ *
+ */
+public class LiveGpsSuppressor implements Runnable, ILiveGpsSuppressor {
+
+	/**
+	 * Default sleep time is 5 seconds.
+	 */
+	private static final int DEFAULT_SLEEP_TIME = 5;
+
+	/**
+	 * The currently used sleepTime.
+	 */
+	private int sleepTime = DEFAULT_SLEEP_TIME;
+
+	/**
+	 * The flag allowUpdate is enabled once during the sleepTime.
+	 */
+	private boolean allowUpdate = false;
+
+	/**
+	 * Controls if this thread is still in used.
+	 */
+	private boolean shutdownFlag = false;
+
+	/**
+	 * Run thread enables the allowUpdate flag once during its cycle.
+	 * @see java.lang.Runnable#run()
+	 */
+	public void run() {
+		initSleepTime();
+
+		shutdownFlag = false;
+		// stop the thread, when explicitely shut down or when disabled by
+		// config setting
+		while (!shutdownFlag && isEnabled()) {
+			setAllowUpdate(true);
+
+			try {
+				Thread.sleep(getSleepTime());
+			} catch (InterruptedException e) {
+				// TODO I never knew, how to handle this??? Probably just carry
+				// on
+			}
+		}
+
+	}
+
+	/**
+	 * Retrieve the sleepTime from the configuration.
+	 * If no such configuration key exists, it will be initialized here.
+	 */
+	private void initSleepTime() {
+		// fetch it from the user setting, or use the default value.
+		int sleepSeconds = 0;
+		sleepSeconds = Main.pref.getInteger("livegps.refreshinterval",
+				DEFAULT_SLEEP_TIME);
+		// creates the setting, if none present.
+		Main.pref.putInteger("livegps.refreshinterval", sleepSeconds);
+
+		// convert seconds into milliseconds internally.
+		this.sleepTime = sleepSeconds * 1000;
+	}
+
+	/**
+	 * Set the allowUpdate flag. May only privately accessible!
+	 * @param allowUpdate the allowUpdate to set
+	 */
+	private synchronized void setAllowUpdate(boolean allowUpdate) {
+		this.allowUpdate = allowUpdate;
+	}
+
+	/**
+	 * Query, if an update is currently allowed.
+	 * When it is allowed, it will disable the allowUpdate flag as a side effect.
+	 * (this means, one thread got to issue an update event)
+	 *
+	 * @return true, if an update is currently allowed; false, if the update shall be suppressed.
+	 * @see livegps.ILiveGpsSuppressor#isAllowUpdate()
+	 */
+	public synchronized boolean isAllowUpdate() {
+
+		// if disabled, always permit a re-draw.
+		if (!isEnabled()) {
+			return true;
+		} else {
+
+			if (allowUpdate) {
+				allowUpdate = false;
+				return true;
+			} else {
+				return false;
+			}
+		}
+	}
+
+	/**
+	 * A value below 1 disables this feature.
+	 * This ensures that a small value does not run this thread
+	 * in a tight loop.
+	 * 
+	 * @return true, if suppressing is enabled
+	 */
+	private boolean isEnabled() {
+		return this.sleepTime > 0;
+	}
+
+	/**
+	 * Shut this thread down.
+	 */
+	public void shutdown() {
+		shutdownFlag = true;
+	}
+
+	/**
+	 * @return the defaultSleepTime
+	 */
+	private int getSleepTime() {
+		return this.sleepTime;
+	}
+
+}
diff --git a/livegps/src/livegps/SingleSegmentGpxTrack.java b/livegps/src/livegps/SingleSegmentGpxTrack.java
new file mode 100644
index 0000000..3cded20
--- /dev/null
+++ b/livegps/src/livegps/SingleSegmentGpxTrack.java
@@ -0,0 +1,38 @@
+package livegps;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.gpx.GpxTrack;
+import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
+
+public class SingleSegmentGpxTrack implements GpxTrack {
+
+	private final Map<String, Object> attributes;
+	private final GpxTrackSegment trackSegment;
+
+	public SingleSegmentGpxTrack(GpxTrackSegment trackSegment, Map<String, Object> attributes) {
+		this.attributes = Collections.unmodifiableMap(attributes);
+		this.trackSegment = trackSegment;
+	}
+
+
+	public Map<String, Object> getAttributes() {
+		return attributes;
+	}
+
+	public Bounds getBounds() {
+		return trackSegment.getBounds();
+	}
+
+	public Collection<GpxTrackSegment> getSegments() {
+		return Collections.singleton(trackSegment);
+	}
+
+	public double length() {
+		return trackSegment.length();
+	}
+
+}
diff --git a/measurement/build.xml b/measurement/build.xml
index 527d1ec..fe755dc 100644
--- a/measurement/build.xml
+++ b/measurement/build.xml
@@ -1,55 +1,185 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+** This is the build file for the measurement plugin
+**
+** Maintaining versions
+** ====================
+** see README.template
+**
+** Usage
+** =====
+** To build it run
+**
+**    > ant  dist
+**
+** To install the generated plugin locally (in your default plugin directory) run
+**
+**    > ant  install
+**
+** To build against the core in ../../core, create a correct manifest and deploy to
+** SVN, 
+**    set the properties commit.message and plugin.main.version
+** and run
+**    > ant  publish
+**
+**
+-->
 <project name="measurement" 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="Raphael Mack, Reza Mohammadi"/>
-                <attribute name="Plugin-Class" value="org.openstreetmap.josm.plugins.measurement.MeasurementPlugin"/>
-                <attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
-                <attribute name="Plugin-Description" value="Provide a measurement dialog and a layer to measure length and angle of segments, area surrounded by a (simple) closed way and create measurement paths (which also can be imported from a gps layer)."/>
-                <attribute name="Plugin-Mainversion" value="2450"/>
-                <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>
+
+	<property name="commit.message" value="Changed the constructor signature of the plugin main class" />
+	<property name="plugin.main.version" value="2907" />
+
+
+	<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="Raphael Mack, Reza Mohammadi"/>
+				<attribute name="Plugin-Class" value="org.openstreetmap.josm.plugins.measurement.MeasurementPlugin"/>
+				<attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
+				<attribute name="Plugin-Description" value="Provide a measurement dialog and a layer to measure length and angle of segments, area surrounded by a (simple) closed way and create measurement paths (which also can be imported from a gps layer)."/>
+				<attribute name="Plugin-Mainversion" value="${plugin.main.version}"/>
+				<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>
+
+	<!--
+		 ************************** Publishing the plugin *********************************** 
+		-->
+	<!--
+		** extracts the JOSM release for the JOSM version in ../core and saves it in the 
+		** property ${coreversion.info.entry.revision}
+		**
+		-->
+	<target name="core-info">
+		<exec append="false" output="core.info.xml" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="info"/>
+			<arg value="--xml"/>
+			<arg value="../../core"/>
+		</exec>
+		<xmlproperty file="core.info.xml" prefix="coreversion" keepRoot="true" collapseAttributes="true"/>
+		<echo>Building against core revision ${coreversion.info.entry.revision}.</echo>
+		<echo>Plugin-Mainversion is set to ${plugin.main.version}.</echo>
+		<delete file="core.info.xml" />
+	</target>
+
+	<!--
+		** commits the source tree for this plugin
+		-->
+	<target name="commit-current">
+		<echo>Commiting the plugin source with message '${commit.message}' ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="commit"/>
+			<arg value="-m '${commit.message}'"/>
+			<arg value="."/>
+		</exec>
+	</target>
+
+	<!--
+		** updates (svn up) the source tree for this plugin
+		-->
+	<target name="update-current">
+		<echo>Updating plugin source ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="up"/>
+			<arg value="."/>
+		</exec>
+		<echo>Updating ${plugin.jar} ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="up"/>
+			<arg value="../dist/${plugin.jar}"/>
+		</exec>
+	</target>
+
+	<!--
+		** commits the plugin.jar 
+		-->
+	<target name="commit-dist">
+		<echo>
+	***** Properties of published ${plugin.jar} *****
+	Commit message    : '${commit.message}'					
+	Plugin-Mainversion: ${plugin.main.version}
+	JOSM build version: ${coreversion.info.entry.revision}
+	Plugin-Version    : ${version.entry.commit.revision}
+	***** / Properties of published ${plugin.jar} *****					
+						
+	Now commiting ${plugin.jar} ...
+	</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="-m '${commit.message}'"/>
+			<arg value="commit"/>
+			<arg value="${plugin.jar}"/>
+		</exec>
+	</target>
+
+	<!-- ** make sure svn is present as a command line tool ** -->
+	<target name="ensure-svn-present">
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false" failonerror="false" resultproperty="svn.exit.code">
+			<env key="LANG" value="C" />
+			<arg value="--version" />
+		</exec>
+		<fail message="Fatal: command 'svn --version' failed. Please make sure svn is installed on your system.">
+			<!-- return code not set at all? Most likely svn isn't installed -->
+			<condition>
+				<not>
+					<isset property="svn.exit.code" />
+				</not>
+			</condition>
+		</fail>
+		<fail message="Fatal: command 'svn --version' failed. Please make sure a working copy of svn is installed on your system.">
+			<!-- error code from SVN? Most likely svn is not what we are looking on this system -->
+			<condition>
+				<isfailure code="${svn.exit.code}" />
+			</condition>
+		</fail>
+	</target>
+
+	<target name="publish" depends="ensure-svn-present,core-info,commit-current,update-current,clean,dist,commit-dist">
+	</target>
 </project>
diff --git a/measurement/src/org/openstreetmap/josm/plugins/measurement/MeasurementDialog.java b/measurement/src/org/openstreetmap/josm/plugins/measurement/MeasurementDialog.java
index 1669f3a..3bb7a1a 100644
--- a/measurement/src/org/openstreetmap/josm/plugins/measurement/MeasurementDialog.java
+++ b/measurement/src/org/openstreetmap/josm/plugins/measurement/MeasurementDialog.java
@@ -113,7 +113,7 @@ public class MeasurementDialog extends ToggleDialog implements ActionListener
                                 Node lastNode = null;
                 for(OsmPrimitive p:arg0){
                                     // ignore incomplete nodes
-                                    if(p instanceof Node && !((Node)p).incomplete){
+                                    if(p instanceof Node && !((Node)p).isIncomplete()){
                                         Node n =(Node)p;
                                         if(lastNode == null){
                                             lastNode = n;
diff --git a/measurement/src/org/openstreetmap/josm/plugins/measurement/MeasurementLayer.java b/measurement/src/org/openstreetmap/josm/plugins/measurement/MeasurementLayer.java
index 75602fd..a34fd33 100644
--- a/measurement/src/org/openstreetmap/josm/plugins/measurement/MeasurementLayer.java
+++ b/measurement/src/org/openstreetmap/josm/plugins/measurement/MeasurementLayer.java
@@ -31,6 +31,7 @@ import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.gpx.GpxTrack;
+import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
 import org.openstreetmap.josm.data.gpx.WayPoint;
 import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
 import org.openstreetmap.josm.gui.MapView;
@@ -315,8 +316,8 @@ public class MeasurementLayer extends Layer {
                 }
 
                 for (GpxTrack trk : gpx.data.tracks) {
-                    for (Collection<WayPoint> trkseg : trk.trackSegs) {
-                        for(WayPoint p: trkseg){
+                    for (GpxTrackSegment trkseg : trk.getSegments()) {
+                        for(WayPoint p: trkseg.getWayPoints()){
                             points.add(p);
                         }
                     }
diff --git a/measurement/src/org/openstreetmap/josm/plugins/measurement/MeasurementPlugin.java b/measurement/src/org/openstreetmap/josm/plugins/measurement/MeasurementPlugin.java
index 85220c3..527db86 100644
--- a/measurement/src/org/openstreetmap/josm/plugins/measurement/MeasurementPlugin.java
+++ b/measurement/src/org/openstreetmap/josm/plugins/measurement/MeasurementPlugin.java
@@ -5,9 +5,11 @@ import static org.openstreetmap.josm.tools.I18n.tr;
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.gui.IconToggleButton;
 import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
 import org.openstreetmap.josm.gui.layer.Layer;
-import org.openstreetmap.josm.gui.layer.Layer.LayerChangeListener;
 import org.openstreetmap.josm.plugins.Plugin;
+import org.openstreetmap.josm.plugins.PluginInformation;
 
 public class MeasurementPlugin extends Plugin {
 
@@ -16,7 +18,8 @@ public class MeasurementPlugin extends Plugin {
     protected static MeasurementDialog measurementDialog;
     protected static MeasurementLayer currentLayer;
 
-    public MeasurementPlugin() {
+    public MeasurementPlugin(PluginInformation info) {
+    	super(info);
         mode = new MeasurementMode(Main.map, "measurement", tr("measurement mode"));
         btn = new IconToggleButton(mode);
         btn.setVisible(true);
@@ -35,7 +38,7 @@ public class MeasurementPlugin extends Plugin {
         if(currentLayer == null){
             currentLayer = new MeasurementLayer(tr("Measurements"));
             Main.main.addLayer(currentLayer);
-            Layer.listeners.add(new LayerChangeListener(){
+            MapView.addLayerChangeListener(new LayerChangeListener(){
                 public void activeLayerChange(final Layer oldLayer, final Layer newLayer) {
                     if(newLayer instanceof MeasurementLayer)
                         MeasurementPlugin.currentLayer = (MeasurementLayer)newLayer;
@@ -43,6 +46,8 @@ public class MeasurementPlugin extends Plugin {
                 public void layerAdded(final Layer newLayer) {
                 }
                 public void layerRemoved(final Layer oldLayer) {
+                	if (oldLayer != null && oldLayer == currentLayer)
+                		MapView.removeLayerChangeListener(this);
                 }
             });
         }
diff --git a/openvisible/build.xml b/openvisible/build.xml
index 2cd93bd..9bcb609 100644
--- a/openvisible/build.xml
+++ b/openvisible/build.xml
@@ -1,57 +1,191 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+** This is the build file for the openvisible plugin.
+**
+** Maintaining versions
+** ====================
+** see README.template
+**
+** Usage
+** =====
+** To build it run
+**
+**    > ant  dist
+**
+** To install the generated plugin locally (in you default plugin directory) run
+**
+**    > ant  install
+**
+** The generated plugin jar is not automatically available in JOSMs plugin configuration
+** dialog. You have to check it in first.
+**
+** Use the ant target 'publish' to check in the plugin and make it available to other
+** JOSM users:
+**    set the properties commit.message and plugin.main.version
+** and run
+**    > ant  publish
+**
+**
+-->
 <project name="openvisible" 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="Christof Dallermassl"/>
-                <attribute name="Plugin-Class" value="at.dallermassl.josm.plugin.openvisible.OpenVisiblePlugin"/>
-                <attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
-                <attribute name="Plugin-Dependencies" value="jgrapht-jdk1.5"/>
-                <attribute name="Plugin-Description" value="Allows opening gpx/osm files that intersect the currently visible screen area"/>
-                <attribute name="Plugin-Mainversion" value="2082"/>
-                <attribute name="Plugin-Stage" value="50"/>
-                <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>
+
+	<!-- enter the SVN commit message -->
+	<property name="commit.message" value="Changed the constructor signature of the plugin main class; updated build.xml" />
+	<!-- enter the *lowest* JOSM version this plugin is currently compatible with -->
+	<property name="plugin.main.version" value="2830" />
+
+	<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="Christof Dallermassl"/>
+				<attribute name="Plugin-Class" value="at.dallermassl.josm.plugin.openvisible.OpenVisiblePlugin"/>
+				<attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
+				<attribute name="Plugin-Dependencies" value="jgrapht-jdk1.5"/>
+				<attribute name="Plugin-Description" value="Allows opening gpx/osm files that intersect the currently visible screen area"/>
+				<attribute name="Plugin-Mainversion" value="${plugin.main.version}"/>
+				<attribute name="Plugin-Stage" value="50"/>
+				<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>
+
+	<!--
+	************************** Publishing the plugin *********************************** 
+	-->
+	<!--
+		** extracts the JOSM release for the JOSM version in ../core and saves it in the 
+		** property ${coreversion.info.entry.revision}
+		**
+		-->
+	<target name="core-info">
+		<exec append="false" output="core.info.xml" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="info"/>
+			<arg value="--xml"/>
+			<arg value="../../core"/>
+		</exec>
+		<xmlproperty file="core.info.xml" prefix="coreversion" keepRoot="true" collapseAttributes="true"/>
+		<echo>Building against core revision ${coreversion.info.entry.revision}.</echo>
+		<echo>Plugin-Mainversion is set to ${plugin.main.version}.</echo>
+		<delete file="core.info.xml" />
+	</target>
+
+	<!--
+		** commits the source tree for this plugin
+		-->
+	<target name="commit-current">
+		<echo>Commiting the plugin source with message '${commit.message}' ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="commit"/>
+			<arg value="-m '${commit.message}'"/>
+			<arg value="."/>
+		</exec>
+	</target>
+
+	<!--
+		** updates (svn up) the source tree for this plugin
+		-->
+	<target name="update-current">
+		<echo>Updating plugin source ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="up"/>
+			<arg value="."/>
+		</exec>
+		<echo>Updating ${plugin.jar} ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="up"/>
+			<arg value="../dist/${plugin.jar}"/>
+		</exec>
+	</target>
+
+	<!--
+		** commits the plugin.jar 
+		-->
+	<target name="commit-dist">
+		<echo>
+	***** Properties of published ${plugin.jar} *****
+	Commit message    : '${commit.message}'					
+	Plugin-Mainversion: ${plugin.main.version}
+	JOSM build version: ${coreversion.info.entry.revision}
+	Plugin-Version    : ${version.entry.commit.revision}
+	***** / Properties of published ${plugin.jar} *****					
+						
+	Now commiting ${plugin.jar} ...
+	</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="-m '${commit.message}'"/>
+			<arg value="commit"/>
+			<arg value="${plugin.jar}"/>
+		</exec>
+	</target>
+
+	<!-- ** make sure svn is present as a command line tool ** -->
+	<target name="ensure-svn-present">
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false" failonerror="false" resultproperty="svn.exit.code">
+			<env key="LANG" value="C" />
+			<arg value="--version" />
+		</exec>
+		<fail message="Fatal: command 'svn --version' failed. Please make sure svn is installed on your system.">
+			<!-- return code not set at all? Most likely svn isn't installed -->
+			<condition>
+				<not>
+					<isset property="svn.exit.code" />
+				</not>
+			</condition>
+		</fail>
+		<fail message="Fatal: command 'svn --version' failed. Please make sure a working copy of svn is installed on your system.">
+			<!-- error code from SVN? Most likely svn is not what we are looking on this system -->
+			<condition>
+				<isfailure code="${svn.exit.code}" />
+			</condition>
+		</fail>
+	</target>
+
+	<target name="publish" depends="ensure-svn-present,core-info,commit-current,update-current,clean,dist,commit-dist">
+	</target>
 </project>
diff --git a/openvisible/copyright.txt b/openvisible/copyright.txt
index 1bd98c0..8508b74 100644
--- a/openvisible/copyright.txt
+++ b/openvisible/copyright.txt
@@ -1,6 +1,7 @@
-Plugin openvisible
+Plugin openvisibl 
 
 This plugin is copyrighted 2008-2009 
 by Christof Dallermassl <christof at dallermassl.at>.
 
-It is distributed under GPL-v2 license (see file  LICENSE in this directory).
+It is distributed under GPL-v3 or later license 
+(see file gpl-3.0.txt in this directory).
diff --git a/surveyor/LICENSE b/openvisible/gpl-2.0.txt
similarity index 98%
rename from surveyor/LICENSE
rename to openvisible/gpl-2.0.txt
index 37b7a4d..d511905 100644
--- a/surveyor/LICENSE
+++ b/openvisible/gpl-2.0.txt
@@ -1,12 +1,12 @@
-      GNU GENERAL PUBLIC LICENSE
-           Version 2, June 1991
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
 
  Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
-          Preamble
+			    Preamble
 
   The licenses for most software are designed to take away your
 freedom to share and change it.  By contrast, the GNU General Public
@@ -56,7 +56,7 @@ patent must be licensed for everyone's free use or not licensed at all.
   The precise terms and conditions for copying, distribution and
 modification follow.
 
-        GNU GENERAL PUBLIC LICENSE
+		    GNU GENERAL PUBLIC LICENSE
    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 
   0. This License applies to any program or other work which contains
@@ -255,7 +255,7 @@ make exceptions for this.  Our decision will be guided by the two goals
 of preserving the free status of all derivatives of our free software and
 of promoting the sharing and reuse of software generally.
 
-          NO WARRANTY
+			    NO WARRANTY
 
   11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
 FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
@@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
 PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGES.
 
-         END OF TERMS AND CONDITIONS
+		     END OF TERMS AND CONDITIONS
 
-      How to Apply These Terms to Your New Programs
+	    How to Apply These Terms to Your New Programs
 
   If you develop a new program, and you want it to be of the greatest
 possible use to the public, the best way to achieve this is to make it
diff --git a/openvisible/gpl-3.0.txt b/openvisible/gpl-3.0.txt
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/openvisible/gpl-3.0.txt
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/openvisible/src/at/dallermassl/josm/plugin/openvisible/OpenVisibleAction.java b/openvisible/src/at/dallermassl/josm/plugin/openvisible/OpenVisibleAction.java
index e7a6a1e..4f13c00 100644
--- a/openvisible/src/at/dallermassl/josm/plugin/openvisible/OpenVisibleAction.java
+++ b/openvisible/src/at/dallermassl/josm/plugin/openvisible/OpenVisibleAction.java
@@ -119,10 +119,15 @@ public class OpenVisibleAction extends JosmAction {
         if (new GpxImporter().acceptFile(file)) {
             GpxReader r = null;
             if (file.getName().endsWith(".gpx.gz")) {
-                r = new GpxReader(new GZIPInputStream(new FileInputStream(file)), file.getAbsoluteFile().getParentFile());
+                r = new GpxReader(new GZIPInputStream(new FileInputStream(file)));
             } else{
-                r = new GpxReader(new FileInputStream(file), file.getAbsoluteFile().getParentFile());
+                r = new GpxReader(new FileInputStream(file));
             }
+            if (!r.parse(true)) {
+                // input was not properly parsed, abort
+                JOptionPane.showMessageDialog(Main.parent, tr("Parsing file \"{0}\" failed", file));
+                throw new IllegalStateException();
+            }				
             r.data.storageFile = file;
             GpxLayer gpxLayer = new GpxLayer(r.data, fn);
             Main.main.addLayer(gpxLayer);
diff --git a/openvisible/src/at/dallermassl/josm/plugin/openvisible/OpenVisiblePlugin.java b/openvisible/src/at/dallermassl/josm/plugin/openvisible/OpenVisiblePlugin.java
index 91276f2..bb4f759 100644
--- a/openvisible/src/at/dallermassl/josm/plugin/openvisible/OpenVisiblePlugin.java
+++ b/openvisible/src/at/dallermassl/josm/plugin/openvisible/OpenVisiblePlugin.java
@@ -6,6 +6,7 @@ package at.dallermassl.josm.plugin.openvisible;
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.gui.MainMenu;
 import org.openstreetmap.josm.plugins.Plugin;
+import org.openstreetmap.josm.plugins.PluginInformation;
 
 /**
  * @author cdaller
@@ -13,8 +14,8 @@ import org.openstreetmap.josm.plugins.Plugin;
  */
 public class OpenVisiblePlugin extends Plugin {
 
-    public OpenVisiblePlugin() {
-        super();
+    public OpenVisiblePlugin(PluginInformation info) {
+        super(info);
         MainMenu.add(Main.main.menu.fileMenu, new OpenVisibleAction());
     }
 
diff --git a/routing/build.xml b/routing/build.xml
index 28e873a..46eb30d 100644
--- a/routing/build.xml
+++ b/routing/build.xml
@@ -1,75 +1,204 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+** This is the build file for the routing plugin
+**
+** Maintaining versions
+** ====================
+** see README.template
+**
+** Usage
+** =====
+** To build it run
+**
+**    > ant  dist
+**
+** To install the generated plugin locally (in your default plugin directory) run
+**
+**    > ant  install
+**
+** To build against the core in ../../core, create a correct manifest and deploy to
+** SVN, 
+**    set the properties commit.message and plugin.main.version
+** and run
+**    > ant  publish
+**
+**
+-->
 <project name="routing" default="dist" basedir=".">
+
+	<property name="commit.message" value="Changed the constructor signature of the plugin main class" />
+	<property name="plugin.main.version" value="2830" />
+
 	<!-- Define some properties -->
-    <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="jgrapht"                value="lib/jgrapht-jdk1.5.jar"/>
-    <property name="log4j"                  value="lib/log4j-1.2.15.jar"/>
-    <property name="ant.build.javac.target" value="1.5"/>
+	<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="jgrapht"                value="lib/jgrapht-jdk1.5.jar"/>
+	<property name="log4j"                  value="lib/log4j-1.2.15.jar"/>
+	<property name="ant.build.javac.target" value="1.5"/>
 	<!-- Some initializations for several other targets -->
-    <target name="init">
-        <mkdir dir="${plugin.build.dir}"/>
-    </target>
+	<target name="init">
+		<mkdir dir="${plugin.build.dir}"/>
+	</target>
 	<!-- Compile sources -->
-    <target name="compile" depends="init" description="Compile sources">
-        <echo message="creating ${plugin.jar}"/>
-        <javac srcdir="src" debug="true" destdir="${plugin.build.dir}">
-            <compilerarg value="-Xlint:deprecation"/>
-            <compilerarg value="-Xlint:unchecked"/>
-            <classpath>
-                <pathelement location="${josm}"/>
-                <pathelement location="${jgrapht}"/>
-                <pathelement location="${log4j}"/>
-            </classpath>
-        </javac>
-    </target>
+	<target name="compile" depends="init" description="Compile sources">
+		<echo message="creating ${plugin.jar}"/>
+		<javac srcdir="src" debug="true" destdir="${plugin.build.dir}">
+			<compilerarg value="-Xlint:deprecation"/>
+			<compilerarg value="-Xlint:unchecked"/>
+			<classpath>
+				<pathelement location="${josm}"/>
+				<pathelement location="${jgrapht}"/>
+				<pathelement location="${log4j}"/>
+			</classpath>
+		</javac>
+	</target>
 	<!-- Generate distribution -->
-    <target name="dist" depends="compile,revision" description="Generate distribution">
-        <unjar dest="${plugin.build.dir}" src="${jgrapht}"/>
-        <unjar dest="${plugin.build.dir}" src="${log4j}"/>
-        <copy todir="${plugin.build.dir}/">
-            <fileset dir="resources">
-                <include name="*.xml"/>
-            </fileset>
-        </copy>
-        <copy todir="${plugin.build.dir}/images">
-            <fileset dir="images"/>
-        </copy>
-        <jar destfile="${plugin.jar}" basedir="${plugin.build.dir}">
-            <manifest>
-                <attribute name="Author" value="Jose Vidal <vidalfree at gmail.com>, Juangui Jordán <juangui at gmail.com>"/>
-                <attribute name="Plugin-Class" value="com.innovant.josm.plugin.routing.RoutingPlugin"/>
-                <attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
-                <attribute name="Plugin-Description" value="Provides routing capabilities."/>
-                <attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/index.php/JOSM/Plugins/Routing"/>
-                <attribute name="Plugin-Mainversion" value="2450"/>
-                <attribute name="Plugin-Stage" value="50"/>
-                <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>
+	<target name="dist" depends="compile,revision" description="Generate distribution">
+		<unjar dest="${plugin.build.dir}" src="${jgrapht}"/>
+		<unjar dest="${plugin.build.dir}" src="${log4j}"/>
+		<copy todir="${plugin.build.dir}/">
+			<fileset dir="resources">
+				<include name="*.xml"/>
+			</fileset>
+		</copy>
+		<copy todir="${plugin.build.dir}/images">
+			<fileset dir="images"/>
+		</copy>
+		<jar destfile="${plugin.jar}" basedir="${plugin.build.dir}">
+			<manifest>
+				<attribute name="Author" value="Jose Vidal <vidalfree at gmail.com>, Juangui Jordán <juangui at gmail.com>"/>
+				<attribute name="Plugin-Class" value="com.innovant.josm.plugin.routing.RoutingPlugin"/>
+				<attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
+				<attribute name="Plugin-Description" value="Provides routing capabilities."/>
+				<attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/index.php/JOSM/Plugins/Routing"/>
+				<attribute name="Plugin-Mainversion" value="${plugin.main.version}"/>
+				<attribute name="Plugin-Stage" value="50"/>
+				<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>
+
+	<!--
+		 ************************** Publishing the plugin *********************************** 
+		-->
+	<!--
+		** extracts the JOSM release for the JOSM version in ../core and saves it in the 
+		** property ${coreversion.info.entry.revision}
+		**
+		-->
+	<target name="core-info">
+		<exec append="false" output="core.info.xml" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="info"/>
+			<arg value="--xml"/>
+			<arg value="../../core"/>
+		</exec>
+		<xmlproperty file="core.info.xml" prefix="coreversion" keepRoot="true" collapseAttributes="true"/>
+		<echo>Building against core revision ${coreversion.info.entry.revision}.</echo>
+		<echo>Plugin-Mainversion is set to ${plugin.main.version}.</echo>
+		<delete file="core.info.xml" />
+	</target>
+
+	<!--
+		** commits the source tree for this plugin
+		-->
+	<target name="commit-current">
+		<echo>Commiting the plugin source with message '${commit.message}' ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="commit"/>
+			<arg value="-m '${commit.message}'"/>
+			<arg value="."/>
+		</exec>
+	</target>
+
+	<!--
+		** updates (svn up) the source tree for this plugin
+		-->
+	<target name="update-current">
+		<echo>Updating plugin source ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="up"/>
+			<arg value="."/>
+		</exec>
+		<echo>Updating ${plugin.jar} ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="up"/>
+			<arg value="../dist/${plugin.jar}"/>
+		</exec>
+	</target>
+
+	<!--
+		** commits the plugin.jar 
+		-->
+	<target name="commit-dist">
+		<echo>
+	***** Properties of published ${plugin.jar} *****
+	Commit message    : '${commit.message}'					
+	Plugin-Mainversion: ${plugin.main.version}
+	JOSM build version: ${coreversion.info.entry.revision}
+	Plugin-Version    : ${version.entry.commit.revision}
+	***** / Properties of published ${plugin.jar} *****					
+						
+	Now commiting ${plugin.jar} ...
+	</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="-m '${commit.message}'"/>
+			<arg value="commit"/>
+			<arg value="${plugin.jar}"/>
+		</exec>
+	</target>
+
+	<!-- ** make sure svn is present as a command line tool ** -->
+	<target name="ensure-svn-present">
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false" failonerror="false" resultproperty="svn.exit.code">
+			<env key="LANG" value="C" />
+			<arg value="--version" />
+		</exec>
+		<fail message="Fatal: command 'svn --version' failed. Please make sure svn is installed on your system.">
+			<!-- return code not set at all? Most likely svn isn't installed -->
+			<condition>
+				<not>
+					<isset property="svn.exit.code" />
+				</not>
+			</condition>
+		</fail>
+		<fail message="Fatal: command 'svn --version' failed. Please make sure a working copy of svn is installed on your system.">
+			<!-- error code from SVN? Most likely svn is not what we are looking on this system -->
+			<condition>
+				<isfailure code="${svn.exit.code}" />
+			</condition>
+		</fail>
+	</target>
+
+	<target name="publish" depends="ensure-svn-present,core-info,commit-current,update-current,clean,dist,commit-dist">
+	</target>
 </project>
diff --git a/routing/src/com/innovant/josm/plugin/routing/RoutingLayer.java b/routing/src/com/innovant/josm/plugin/routing/RoutingLayer.java
index a53c3d7..7f42c37 100644
--- a/routing/src/com/innovant/josm/plugin/routing/RoutingLayer.java
+++ b/routing/src/com/innovant/josm/plugin/routing/RoutingLayer.java
@@ -134,9 +134,9 @@ public class RoutingLayer extends Layer {
         Node nearest = null;
         double minDist = 0;
         for (Way w : dataLayer.data.getWays()) {
-            if (w.isDeleted() || w.incomplete || w.get("highway")==null) continue;
+            if (w.isDeleted() || w.isIncomplete() || w.get("highway")==null) continue;
             for (Node n : w.getNodes()) {
-                if (n.isDeleted() || n.incomplete) continue;
+                if (n.isDeleted() || n.isIncomplete()) continue;
 
                 Point P = Main.map.mapView.getPoint(n);
                 double dist = p.distanceSq(P);
diff --git a/routing/src/com/innovant/josm/plugin/routing/RoutingPlugin.java b/routing/src/com/innovant/josm/plugin/routing/RoutingPlugin.java
index d91443b..0187792 100644
--- a/routing/src/com/innovant/josm/plugin/routing/RoutingPlugin.java
+++ b/routing/src/com/innovant/josm/plugin/routing/RoutingPlugin.java
@@ -27,7 +27,6 @@
 
 package com.innovant.josm.plugin.routing;
 
-import static org.openstreetmap.josm.tools.I18n.marktr;
 import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.util.ArrayList;
@@ -37,11 +36,13 @@ import org.apache.log4j.xml.DOMConfigurator;
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.gui.IconToggleButton;
 import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.gui.layer.Layer.LayerChangeListener;
 import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
 import org.openstreetmap.josm.plugins.Plugin;
+import org.openstreetmap.josm.plugins.PluginInformation;
 
 import com.innovant.josm.plugin.routing.actions.AddRouteNodeAction;
 import com.innovant.josm.plugin.routing.actions.MoveRouteNodeAction;
@@ -125,8 +126,8 @@ public class RoutingPlugin extends Plugin implements LayerChangeListener {
     /**
      * Default Constructor
      */
-    public RoutingPlugin() {
-        super();
+    public RoutingPlugin(PluginInformation info) {
+        super(info);
         plugin = this; // Assign reference to the plugin class
         DOMConfigurator.configure("log4j.xml");
         logger.debug("Loading routing plugin...");
@@ -138,7 +139,7 @@ public class RoutingPlugin extends Plugin implements LayerChangeListener {
         // Add menu
         menu = new RoutingMenu();
         // Register this class as LayerChangeListener
-        Layer.listeners.add(this);
+        MapView.addLayerChangeListener(this);
         logger.debug("Finished loading plugin");
     }
 
diff --git a/routing/src/com/innovant/josm/plugin/routing/gui/RoutingPreferenceDialog.java b/routing/src/com/innovant/josm/plugin/routing/gui/RoutingPreferenceDialog.java
index 488f700..61b7f94 100644
--- a/routing/src/com/innovant/josm/plugin/routing/gui/RoutingPreferenceDialog.java
+++ b/routing/src/com/innovant/josm/plugin/routing/gui/RoutingPreferenceDialog.java
@@ -56,6 +56,7 @@ import org.apache.log4j.Logger;
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.gui.preferences.PreferenceDialog;
 import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
+import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
 import org.openstreetmap.josm.tools.GBC;
 
 import com.innovant.josm.jrt.osm.OsmWayTypes;
@@ -79,7 +80,7 @@ public class RoutingPreferenceDialog implements PreferenceSetting {
         readPreferences();
     }
 
-    public void addGui(final PreferenceDialog gui) {
+    public void addGui(final PreferenceTabbedPane gui) {
 
         JPanel principal = gui.createPreferenceTab("routing",
                 tr("Routing Plugin Preferences"), tr("Configure routing preferences."));
@@ -186,7 +187,7 @@ public class RoutingPreferenceDialog implements PreferenceSetting {
         return false;
     }
 
-    private void edit(final PreferenceDialog gui, final JTable list) {
+    private void edit(final PreferenceTabbedPane gui, final JTable list) {
         if (list.getSelectedRowCount() != 1) {
             JOptionPane.showMessageDialog(gui,
                     tr("Please select the row to edit."));
diff --git a/slippymap/build.xml b/slippymap/build.xml
index b387b4e..6727f85 100644
--- a/slippymap/build.xml
+++ b/slippymap/build.xml
@@ -1,56 +1,189 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+** This is the build file for the slippymap plugin
+**
+** Maintaining versions
+** ====================
+** see README.template
+**
+** Usage
+** =====
+** To build it run
+**
+**    > ant  dist
+**
+** To install the generated plugin locally (in your default plugin directory) run
+**
+**    > ant  install
+**
+** To build against the core in ../../core, create a correct manifest and deploy to
+** SVN, 
+**    set the properties commit.message and plugin.main.version
+** and run
+**    > ant  publish
+**
+**
+-->
 <project name="slippymap" 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.slippymap.SlippyMapPlugin"/>
-                <attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
-                <attribute name="Plugin-Description" value="Displays a slippy map grid in JOSM. Can load tiles from slippy map as background and request updates."/>
-                <attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/index.php/JOSM/Plugins/SlippyMap"/>
-                <attribute name="Plugin-Mainversion" value="2450"/>
-                <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>
+
+	<property name="commit.message" value="Added haiti imagery tile source" />
+	<property name="plugin.main.version" value="2830" />
+
+	<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.slippymap.SlippyMapPlugin"/>
+				<attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
+				<attribute name="Plugin-Description" value="Displays a slippy map grid in JOSM. Can load tiles from slippy map as background and request updates."/>
+				<attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/index.php/JOSM/Plugins/SlippyMap"/>
+				<attribute name="Plugin-Mainversion" value="${plugin.main.version}"/>
+				<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>
+
+	<!--
+			 ************************** Publishing the plugin *********************************** 
+			-->
+	<!--
+			** extracts the JOSM release for the JOSM version in ../core and saves it in the 
+			** property ${coreversion.info.entry.revision}
+			**
+			-->
+	<target name="core-info">
+		<exec append="false" output="core.info.xml" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="info"/>
+			<arg value="--xml"/>
+			<arg value="../../core"/>
+		</exec>
+		<xmlproperty file="core.info.xml" prefix="coreversion" keepRoot="true" collapseAttributes="true"/>
+		<echo>Building against core revision ${coreversion.info.entry.revision}.</echo>
+		<echo>Plugin-Mainversion is set to ${plugin.main.version}.</echo>
+		<delete file="core.info.xml" />
+	</target>
+
+	<!--
+			** commits the source tree for this plugin
+			-->
+	<target name="commit-current">
+		<echo>Commiting the plugin source with message '${commit.message}' ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="commit"/>
+			<arg value="-m '${commit.message}'"/>
+			<arg value="."/>
+		</exec>
+	</target>
+
+	<!--
+			** updates (svn up) the source tree for this plugin
+			-->
+	<target name="update-current">
+		<echo>Updating plugin source ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="up"/>
+			<arg value="."/>
+		</exec>
+		<echo>Updating ${plugin.jar} ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="up"/>
+			<arg value="../dist/${plugin.jar}"/>
+		</exec>
+	</target>
+
+	<!--
+			** commits the plugin.jar 
+			-->
+	<target name="commit-dist">
+		<echo>
+		***** Properties of published ${plugin.jar} *****
+		Commit message    : '${commit.message}'					
+		Plugin-Mainversion: ${plugin.main.version}
+		JOSM build version: ${coreversion.info.entry.revision}
+		Plugin-Version    : ${version.entry.commit.revision}
+		***** / Properties of published ${plugin.jar} *****					
+							
+		Now commiting ${plugin.jar} ...
+		</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="-m '${commit.message}'"/>
+			<arg value="commit"/>
+			<arg value="${plugin.jar}"/>
+		</exec>
+	</target>
+
+	<!-- ** make sure svn is present as a command line tool ** -->
+	<target name="ensure-svn-present">
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false" failonerror="false" resultproperty="svn.exit.code">
+			<env key="LANG" value="C" />
+			<arg value="--version" />
+		</exec>
+		<fail message="Fatal: command 'svn --version' failed. Please make sure svn is installed on your system.">
+			<!-- return code not set at all? Most likely svn isn't installed -->
+			<condition>
+				<not>
+					<isset property="svn.exit.code" />
+				</not>
+			</condition>
+		</fail>
+		<fail message="Fatal: command 'svn --version' failed. Please make sure a working copy of svn is installed on your system.">
+			<!-- error code from SVN? Most likely svn is not what we are looking on this system -->
+			<condition>
+				<isfailure code="${svn.exit.code}" />
+			</condition>
+		</fail>
+	</target>
+
+	<target name="publish" depends="ensure-svn-present,core-info,commit-current,update-current,clean,dist,commit-dist">
+	</target>
+	
+	<target name="dev-install">
+		<copy file="${plugin.jar}" todir="c:/data/projekte/osm/josm-dev/plugins" />
+	</target>
 </project>
diff --git a/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapLayer.java b/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapLayer.java
index 663a982..bbd0fd6 100644
--- a/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapLayer.java
+++ b/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapLayer.java
@@ -38,6 +38,7 @@ import org.openstreetmap.gui.jmapviewer.interfaces.TileSource;
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.RenameLayerAction;
 import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
 import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
@@ -46,6 +47,7 @@ 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;
+import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
 
 /**
  * Class that displays a slippy map layer.
@@ -211,7 +213,7 @@ public class SlippyMapLayer extends Layer implements PreferenceChangedListener,
                 }));
 
         // FIXME: currently ran in errors
-		
+
 		tileOptionMenu.add(new JMenuItem(
                 new AbstractAction(tr("Snap to tile size")) {
                     public void actionPerformed(ActionEvent ae) {
@@ -250,21 +252,24 @@ public class SlippyMapLayer extends Layer implements PreferenceChangedListener,
                     }
                 });
 
-                listeners.add(new LayerChangeListener() {
+                MapView.addLayerChangeListener(new LayerChangeListener() {
                     public void activeLayerChange(Layer oldLayer, Layer newLayer) {
+                    	//
                     }
 
                     public void layerAdded(Layer newLayer) {
+                    	//
                     }
 
                     public void layerRemoved(Layer oldLayer) {
-                        Main.pref.listener.remove(SlippyMapLayer.this);
+                    	MapView.removeLayerChangeListener(this);
+                        Main.pref.removePreferenceChangeListener(SlippyMapLayer.this);
                     }
                 });
             }
         });
 
-        Main.pref.listener.add(this);
+        Main.pref.addPreferenceChangeListener(this);
     }
 
     void zoomChanged()
@@ -794,17 +799,6 @@ public class SlippyMapLayer extends Layer implements PreferenceChangedListener,
                 if (nr_queued > 0)
                     out("queued to load: " + nr_queued + "/" + tiles.size() + " tiles at zoom: " + zoom);
         }
-        boolean topTile(Tile t) {
-            if (t.getYtile() == z12y0 )
-                return true;
-            return false;
-        }
-
-        boolean leftTile(Tile t) {
-            if (t.getXtile() == z12x0 )
-                return true;
-            return false;
-        }
     }
 
     boolean autoZoomEnabled()
@@ -1031,25 +1025,22 @@ public class SlippyMapLayer extends Layer implements PreferenceChangedListener,
         return x * 45.0 / Math.pow(2.0, zoom - 3) - 180.0;
     }
 
-    private static int nr_loaded = 0;
-    private static int at_zoom = -1;
-
     /*
      * (non-Javadoc)
      *
      * @seeorg.openstreetmap.josm.data.Preferences.PreferenceChangedListener#
      * preferenceChanged(java.lang.String, java.lang.String)
      */
-    public void preferenceChanged(String key, String newValue) {
-        if (key.startsWith(SlippyMapPreferences.PREFERENCE_PREFIX)) {
+    public void preferenceChanged(PreferenceChangeEvent event) {
+        if (event.getKey().startsWith(SlippyMapPreferences.PREFERENCE_PREFIX)) {
             // System.err.println(this + ".preferenceChanged('" + key + "', '"
             // + newValue + "') called");
             // when fade background changed, no need to clear tile storage
             // TODO move this code to SlippyMapPreferences class.
-            if (!key.equals(SlippyMapPreferences.PREFERENCE_FADE_BACKGROUND)) {
+            if (!event.getKey().equals(SlippyMapPreferences.PREFERENCE_FADE_BACKGROUND)) {
                 autoZoomPopup.setSelected(SlippyMapPreferences.getAutozoom());
             }
-            if (key.equals(SlippyMapPreferences.PREFERENCE_TILE_SOURCE)) {
+            if (event.getKey().equals(SlippyMapPreferences.PREFERENCE_TILE_SOURCE)) {
                 newTileStorage();
             }
             redraw();
@@ -1058,6 +1049,6 @@ public class SlippyMapLayer extends Layer implements PreferenceChangedListener,
 
     @Override
     public void destroy() {
-        Main.pref.listener.remove(SlippyMapLayer.this);
+        Main.pref.removePreferenceChangeListener(SlippyMapLayer.this);
     }
 }
diff --git a/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapPlugin.java b/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapPlugin.java
index ffe6718..3b84be4 100644
--- a/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapPlugin.java
+++ b/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapPlugin.java
@@ -4,6 +4,7 @@ import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.gui.MapFrame;
 import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
 import org.openstreetmap.josm.plugins.Plugin;
+import org.openstreetmap.josm.plugins.PluginInformation;
 
 /**
  * Main class for the slippy map plugin.
@@ -13,8 +14,9 @@ import org.openstreetmap.josm.plugins.Plugin;
  */
 public class SlippyMapPlugin extends Plugin
 {
-    public SlippyMapPlugin()
+    public SlippyMapPlugin(PluginInformation info)
     {
+    	super(info);
     }
 
     public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame)
diff --git a/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapPreferenceSetting.java b/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapPreferenceSetting.java
index 13b956e..3b13dd4 100644
--- a/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapPreferenceSetting.java
+++ b/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapPreferenceSetting.java
@@ -19,6 +19,7 @@ import org.openstreetmap.gui.jmapviewer.interfaces.*;
 
 import org.openstreetmap.josm.gui.preferences.PreferenceDialog;
 import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
+import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
 import org.openstreetmap.josm.tools.GBC;
 
 /**
@@ -39,7 +40,7 @@ public class SlippyMapPreferenceSetting implements PreferenceSetting {
     private JSpinner minZoomLvl = new JSpinner();
     private JSlider fadeBackground = new JSlider(0, 100);
     
-    public void addGui(PreferenceDialog gui)
+    public void addGui(PreferenceTabbedPane gui)
     {
         minZoomLvl = new JSpinner(new SpinnerNumberModel(SlippyMapPreferences.DEFAULT_MIN_ZOOM, SlippyMapPreferences.MIN_ZOOM, SlippyMapPreferences.MAX_ZOOM, 1));
         maxZoomLvl = new JSpinner(new SpinnerNumberModel(SlippyMapPreferences.DEFAULT_MAX_ZOOM, SlippyMapPreferences.MIN_ZOOM, SlippyMapPreferences.MAX_ZOOM, 1));
diff --git a/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapPreferences.java b/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapPreferences.java
index 814a0ef..90aad6a 100644
--- a/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapPreferences.java
+++ b/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapPreferences.java
@@ -277,8 +277,31 @@ public class SlippyMapPreferences
             return TileUpdate.IfNoneMatch;
         }
     }
+    
+
+    public static class HaitiImagery extends OsmTileSource.AbstractOsmTileSource {
+        public HaitiImagery() {
+            super("HaitiImagery", "http://gravitystorm.dev.openstreetmap.org/imagery/haiti");
+        }
+
+        public int getMaxZoom() {
+            return 21;
+        }
+
+        public String getTilePath(int zoom, int tilex, int tiley) {
+        	return "/" + zoom + "/" + tilex + "/" + tiley + ".png";
+        }
+
+        public TileUpdate getTileUpdate() {
+            return TileUpdate.IfNoneMatch;
+        }
+    }
 
     public static class Custom extends OsmTileSource.AbstractOsmTileSource {
+
+        String extension;
+        String path;
+
         public Custom(String name, String url) {
             super(name, url);
         }
@@ -286,13 +309,35 @@ public class SlippyMapPreferences
             super(name, url);
             this.extension = extension;
         }
-        String extension;
+        public Custom(String name, String url, String extension, String path) {
+            super(name, url);
+            this.extension = extension;
+            this.path = path;
+        }
+
         @Override
         public String getExtension() {
             if (extension == null)
                 return super.getExtension();
             return extension;
         }
+
+        @Override
+        public int getMaxZoom() {
+            return 21;
+        }
+
+        @Override
+        public String getTilePath(int zoom, int tilex, int tiley) {
+            if (path == null)
+                return super.getTilePath(zoom,tilex,tiley);
+            String tilepath = path;
+            tilepath=tilepath.replaceAll("%z",String.valueOf(zoom));
+            tilepath=tilepath.replaceAll("%x",String.valueOf(tilex));
+            tilepath=tilepath.replaceAll("%y",String.valueOf(tiley));
+            return tilepath;
+        }
+
         public TileUpdate getTileUpdate() {
             return TileUpdate.IfNoneMatch;
         }
@@ -307,17 +352,20 @@ public class SlippyMapPreferences
             // slippymap.custom_tile_source_1.name=OOC layer
             // slippymap.custom_tile_source_1.url=http://a.ooc.openstreetmap.org/npe
             // slippymap.custom_tile_source_1.ext=png
+            // slippymap.custom_tile_source_1.path=/%z/%x/%y
 
             if (!(short_key.endsWith("name")))
                 continue;
             String url_key = short_key.replaceFirst("name","url");
             String ext_key = short_key.replaceFirst("name","ext");
+            String path_key = short_key.replaceFirst("name","path");
             String name = customSources.get(key);
             String url = customSources.get(PREFERENCE_TILE_CUSTOM_SOURCE + url_key);
             String ext = customSources.get(PREFERENCE_TILE_CUSTOM_SOURCE + ext_key);
-            // ext may be null, but that's OK
-            System.out.println("found new tile source: '" +name+"' url:'"+url+"'"+"' ext:'"+ext+"'");
-            ret.add(new Custom(name, url, ext));
+            String path = customSources.get(PREFERENCE_TILE_CUSTOM_SOURCE + path_key);
+            // ext and path may be null, but that's OK
+            System.out.println("found new tile source: '" +name+"' url:'"+url+"'"+"' ext:'"+ext+"' path:'"+path+"'");
+            ret.add(new Custom(name, url, ext, path));
         }
         return ret;
     }
@@ -336,6 +384,7 @@ public class SlippyMapPreferences
         sources.add(new FreeMapySkPokus());
         sources.add(new FreeMapySk());
         sources.add(new NearMap());
+        sources.add(new HaitiImagery());
         sources.addAll(getCustomSources());
         // Probably need to either add these or let users add them somehow
         //      "http://hypercube.telascience.org/tiles/1.0.0/coastline", // coastline
diff --git a/surveyor/build.xml b/surveyor/build.xml
index a435964..f91afb4 100644
--- a/surveyor/build.xml
+++ b/surveyor/build.xml
@@ -1,69 +1,204 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+** This is the build file for the surveyor plugin.
+**
+** Maintaining versions
+** ====================
+** see README.template
+**
+** Usage
+** =====
+** To build it run
+**
+**    > ant  dist
+**
+** To install the generated plugin locally (in you default plugin directory) run
+**
+**    > ant  install
+**
+** The generated plugin jar is not automatically available in JOSMs plugin configuration
+** dialog. You have to check it in first.
+**
+** Use the ant target 'publish' to check in the plugin and make it available to other
+** JOSM users:
+**    set the properties commit.message and plugin.main.version
+** and run
+**    > ant  publish
+**
+**
+-->
 <project name="surveyor" 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="livegpsplugin.jar"      value="${plugin.dist.dir}/livegps.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" debug="true" destdir="${plugin.build.dir}">
-            <compilerarg value="-Xlint:deprecation"/>
-            <compilerarg value="-Xlint:unchecked"/>
-            <classpath>
-                <pathelement location="${josm}"/>
-                <pathelement location="${livegpsplugin.jar}"/>
-            </classpath>
-        </javac>
-    </target>
-    <target name="dist" depends="compile,revision">
-        <copy todir="${plugin.build.dir}/">
-            <fileset dir="resources">
-                <include name="*.xml"/>
-                <include name="audio/*"/>
-            </fileset>
-        </copy>
-        <copy todir="${plugin.build.dir}/images">
-            <fileset dir="images"/>
-        </copy>
-        <jar destfile="${plugin.jar}" basedir="${plugin.build.dir}">
-            <manifest>
-                <attribute name="Author" value="Christof Dallermassl"/>
-                <attribute name="Plugin-Class" value="at.dallermassl.josm.plugin.surveyor.SurveyorPlugin"/>
-                <attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
-                <attribute name="Plugin-Description" value="Allow adding markers/nodes on current gps positions."/>
-                <attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/index.php/JOSM/Plugins/Surveyor"/>
-                <attribute name="Plugin-Mainversion" value="2401"/>
-                <attribute name="Plugin-Requires" value="livegps"/>
-                <attribute name="Plugin-Stage" value="60"/>
-                <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>
+
+	<!-- enter the SVN commit message -->
+	<property name="commit.message" value="Changed the constructor signature of the plugin main class" />
+	<!-- enter the *lowest* JOSM version this plugin is currently compatible with -->
+	<property name="plugin.main.version" value="2907" />
+
+
+	<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="livegpsplugin.jar"      value="${plugin.dist.dir}/livegps.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" debug="true" destdir="${plugin.build.dir}">
+			<compilerarg value="-Xlint:deprecation"/>
+			<compilerarg value="-Xlint:unchecked"/>
+			<classpath>
+				<pathelement location="${josm}"/>
+				<pathelement location="${livegpsplugin.jar}"/>
+			</classpath>
+		</javac>
+	</target>
+	<target name="dist" depends="compile,revision">
+		<copy todir="${plugin.build.dir}/">
+			<fileset dir="resources">
+				<include name="*.xml"/>
+				<include name="audio/*"/>
+			</fileset>
+		</copy>
+		<copy todir="${plugin.build.dir}/images">
+			<fileset dir="images"/>
+		</copy>
+		<jar destfile="${plugin.jar}" basedir="${plugin.build.dir}">
+			<manifest>
+				<attribute name="Author" value="Christof Dallermassl"/>
+				<attribute name="Plugin-Class" value="at.dallermassl.josm.plugin.surveyor.SurveyorPlugin"/>
+				<attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
+				<attribute name="Plugin-Description" value="Allow adding markers/nodes on current gps positions."/>
+				<attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/index.php/JOSM/Plugins/Surveyor"/>
+				<attribute name="Plugin-Mainversion" value="${plugin.main.version}"/>
+				<attribute name="Plugin-Requires" value="livegps"/>
+				<attribute name="Plugin-Stage" value="60"/>
+				<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>
+
+	<!--
+		************************** Publishing the plugin *********************************** 
+		-->
+	<!--
+			** extracts the JOSM release for the JOSM version in ../core and saves it in the 
+			** property ${coreversion.info.entry.revision}
+			**
+			-->
+	<target name="core-info">
+		<exec append="false" output="core.info.xml" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="info"/>
+			<arg value="--xml"/>
+			<arg value="../../core"/>
+		</exec>
+		<xmlproperty file="core.info.xml" prefix="coreversion" keepRoot="true" collapseAttributes="true"/>
+		<echo>Building against core revision ${coreversion.info.entry.revision}.</echo>
+		<echo>Plugin-Mainversion is set to ${plugin.main.version}.</echo>
+		<delete file="core.info.xml" />
+	</target>
+
+	<!--
+			** commits the source tree for this plugin
+			-->
+	<target name="commit-current">
+		<echo>Commiting the plugin source with message '${commit.message}' ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="commit"/>
+			<arg value="-m '${commit.message}'"/>
+			<arg value="."/>
+		</exec>
+	</target>
+
+	<!--
+			** updates (svn up) the source tree for this plugin
+			-->
+	<target name="update-current">
+		<echo>Updating plugin source ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="up"/>
+			<arg value="."/>
+		</exec>
+		<echo>Updating ${plugin.jar} ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="up"/>
+			<arg value="../dist/${plugin.jar}"/>
+		</exec>
+	</target>
+
+	<!--
+			** commits the plugin.jar 
+			-->
+	<target name="commit-dist">
+		<echo>
+		***** Properties of published ${plugin.jar} *****
+		Commit message    : '${commit.message}'					
+		Plugin-Mainversion: ${plugin.main.version}
+		JOSM build version: ${coreversion.info.entry.revision}
+		Plugin-Version    : ${version.entry.commit.revision}
+		***** / Properties of published ${plugin.jar} *****					
+							
+		Now commiting ${plugin.jar} ...
+		</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C"/>
+			<arg value="-m '${commit.message}'"/>
+			<arg value="commit"/>
+			<arg value="${plugin.jar}"/>
+		</exec>
+	</target>
+
+	<!-- ** make sure svn is present as a command line tool ** -->
+	<target name="ensure-svn-present">
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false" failonerror="false" resultproperty="svn.exit.code">
+			<env key="LANG" value="C" />
+			<arg value="--version" />
+		</exec>
+		<fail message="Fatal: command 'svn --version' failed. Please make sure svn is installed on your system.">
+			<!-- return code not set at all? Most likely svn isn't installed -->
+			<condition>
+				<not>
+					<isset property="svn.exit.code" />
+				</not>
+			</condition>
+		</fail>
+		<fail message="Fatal: command 'svn --version' failed. Please make sure a working copy of svn is installed on your system.">
+			<!-- error code from SVN? Most likely svn is not what we are looking on this system -->
+			<condition>
+				<isfailure code="${svn.exit.code}" />
+			</condition>
+		</fail>
+	</target>
+
+	<target name="publish" depends="ensure-svn-present,core-info,commit-current,update-current,clean,dist,commit-dist">
+	</target>
 </project>
diff --git a/surveyor/copyright.txt b/surveyor/copyright.txt
index 4965647..2c1a43f 100644
--- a/surveyor/copyright.txt
+++ b/surveyor/copyright.txt
@@ -1,6 +1,7 @@
-Plugin surveyor
+Plugin surveyo 
 
 This plugin is copyrighted 2008-2009 
 by Christof Dallermassl <christof at dallermassl.at>.
 
-It is distributed under GPL-v2 license (see file  LICENSE in this directory).
+It is distributed under GPL-v3 or later license 
+(see file gpl-3.0.txt in this directory).
diff --git a/openvisible/LICENSE b/surveyor/gpl-2.0.txt
similarity index 98%
rename from openvisible/LICENSE
rename to surveyor/gpl-2.0.txt
index 37b7a4d..d511905 100644
--- a/openvisible/LICENSE
+++ b/surveyor/gpl-2.0.txt
@@ -1,12 +1,12 @@
-      GNU GENERAL PUBLIC LICENSE
-           Version 2, June 1991
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
 
  Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
-          Preamble
+			    Preamble
 
   The licenses for most software are designed to take away your
 freedom to share and change it.  By contrast, the GNU General Public
@@ -56,7 +56,7 @@ patent must be licensed for everyone's free use or not licensed at all.
   The precise terms and conditions for copying, distribution and
 modification follow.
 
-        GNU GENERAL PUBLIC LICENSE
+		    GNU GENERAL PUBLIC LICENSE
    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 
   0. This License applies to any program or other work which contains
@@ -255,7 +255,7 @@ make exceptions for this.  Our decision will be guided by the two goals
 of preserving the free status of all derivatives of our free software and
 of promoting the sharing and reuse of software generally.
 
-          NO WARRANTY
+			    NO WARRANTY
 
   11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
 FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
@@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
 PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGES.
 
-         END OF TERMS AND CONDITIONS
+		     END OF TERMS AND CONDITIONS
 
-      How to Apply These Terms to Your New Programs
+	    How to Apply These Terms to Your New Programs
 
   If you develop a new program, and you want it to be of the greatest
 possible use to the public, the best way to achieve this is to make it
diff --git a/surveyor/gpl-3.0.txt b/surveyor/gpl-3.0.txt
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/surveyor/gpl-3.0.txt
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/surveyor/src/at/dallermassl/josm/plugin/surveyor/AutoSaveEditLayerTimerTask.java b/surveyor/src/at/dallermassl/josm/plugin/surveyor/AutoSaveEditLayerTimerTask.java
index 5b772cf..575e084 100644
--- a/surveyor/src/at/dallermassl/josm/plugin/surveyor/AutoSaveEditLayerTimerTask.java
+++ b/surveyor/src/at/dallermassl/josm/plugin/surveyor/AutoSaveEditLayerTimerTask.java
@@ -14,8 +14,6 @@ import java.util.TimerTask;
 
 import javax.swing.JOptionPane;
 
-import livegps.LiveGpsLock;
-
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
@@ -52,7 +50,7 @@ public class AutoSaveEditLayerTimerTask extends TimerTask {
             // write to temporary file, on success, rename tmp file to target file:
             File tmpFile = new File(file.getAbsoluteFile()+".tmp");
             System.out.println("AutoSaving osm data to file " + file.getAbsolutePath());
-            synchronized(LiveGpsLock.class) {
+            synchronized(SurveyorLock.class) {
                 OsmWriter w = new OsmWriter(new PrintWriter(new FileOutputStream(tmpFile)), false, dataset.getVersion());
                 w.header();
                 w.writeDataSources(dataset);
diff --git a/surveyor/src/at/dallermassl/josm/plugin/surveyor/AutoSaveGpsLayerTimerTask.java b/surveyor/src/at/dallermassl/josm/plugin/surveyor/AutoSaveGpsLayerTimerTask.java
index b83c7b7..33e2ad3 100644
--- a/surveyor/src/at/dallermassl/josm/plugin/surveyor/AutoSaveGpsLayerTimerTask.java
+++ b/surveyor/src/at/dallermassl/josm/plugin/surveyor/AutoSaveGpsLayerTimerTask.java
@@ -15,8 +15,6 @@ import java.util.TimerTask;
 
 import javax.swing.JOptionPane;
 
-import livegps.LiveGpsLock;
-
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.gui.layer.GpxLayer;
 import org.openstreetmap.josm.io.GpxWriter;
@@ -75,9 +73,7 @@ public class AutoSaveGpsLayerTimerTask extends TimerTask {
             // @see LiveGpsLayer
             PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(tmpFile)));
             GpxWriter gpxWriter = new GpxWriter(out);
-            synchronized(LiveGpsLock.class) {
-                gpxWriter.write(gpsLayer.data);
-            }
+            gpxWriter.write(gpsLayer.data);
             tmpFile.renameTo(file);
         } catch (IOException ioExc) {
             ioExc.printStackTrace();
diff --git a/surveyor/src/at/dallermassl/josm/plugin/surveyor/SurveyorLock.java b/surveyor/src/at/dallermassl/josm/plugin/surveyor/SurveyorLock.java
new file mode 100644
index 0000000..5b80980
--- /dev/null
+++ b/surveyor/src/at/dallermassl/josm/plugin/surveyor/SurveyorLock.java
@@ -0,0 +1,5 @@
+package at.dallermassl.josm.plugin.surveyor;
+
+public class SurveyorLock {
+
+}
diff --git a/surveyor/src/at/dallermassl/josm/plugin/surveyor/SurveyorPlugin.java b/surveyor/src/at/dallermassl/josm/plugin/surveyor/SurveyorPlugin.java
index e30e295..bdb6065 100644
--- a/surveyor/src/at/dallermassl/josm/plugin/surveyor/SurveyorPlugin.java
+++ b/surveyor/src/at/dallermassl/josm/plugin/surveyor/SurveyorPlugin.java
@@ -6,21 +6,15 @@ package at.dallermassl.josm.plugin.surveyor;
 
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import java.util.Iterator;
-
-import javax.swing.AbstractAction;
 import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JFrame;
 import javax.swing.JMenu;
-import javax.swing.JOptionPane;
-import javax.swing.KeyStroke;
-import java.awt.event.KeyEvent;
 
 import livegps.LiveGpsPlugin;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.gui.MainMenu;
 import org.openstreetmap.josm.plugins.PluginHandler;
+import org.openstreetmap.josm.plugins.PluginInformation;
 
 /**
  * Plugin that uses live gps data and a button panel to add nodes/waypoints etc at the current
@@ -39,8 +33,7 @@ public class SurveyorPlugin {
     /**
      *
      */
-    public SurveyorPlugin() {
-        super();
+    public SurveyorPlugin(PluginInformation info) {
 
         LiveGpsPlugin gpsPlugin = (LiveGpsPlugin) PluginHandler.getPlugin("livegps");
         if(gpsPlugin == null)
diff --git a/surveyor/src/at/dallermassl/josm/plugin/surveyor/action/PlayAudioAction.java b/surveyor/src/at/dallermassl/josm/plugin/surveyor/action/PlayAudioAction.java
index 0a74464..a4bc62c 100644
--- a/surveyor/src/at/dallermassl/josm/plugin/surveyor/action/PlayAudioAction.java
+++ b/surveyor/src/at/dallermassl/josm/plugin/surveyor/action/PlayAudioAction.java
@@ -42,7 +42,7 @@ public class PlayAudioAction extends AbstractSurveyorAction {
                 try {
                     if(audioSource == null) {
                         audioSource = getParameters().get(0);
-                        System.out.println("reading audio from " + audioSource);
+                        //System.out.println("reading audio from " + audioSource);
                     }
                     InputStream in = new BufferedInputStream(ResourceLoader.getInputStream(audioSource));
                     AudioInputStream stream = AudioSystem.getAudioInputStream(in);
@@ -85,8 +85,6 @@ public class PlayAudioAction extends AbstractSurveyorAction {
                     e.printStackTrace();
                 }
             }
-
         });
-
     }
 }
diff --git a/surveyor/src/at/dallermassl/josm/plugin/surveyor/action/SetNodeAction.java b/surveyor/src/at/dallermassl/josm/plugin/surveyor/action/SetNodeAction.java
index 6629050..b0da086 100644
--- a/surveyor/src/at/dallermassl/josm/plugin/surveyor/action/SetNodeAction.java
+++ b/surveyor/src/at/dallermassl/josm/plugin/surveyor/action/SetNodeAction.java
@@ -9,15 +9,15 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Map.Entry;
 
-import livegps.LiveGpsLock;
-
 import org.dinopolis.util.collection.Tuple;
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Node;
 
 import at.dallermassl.josm.plugin.surveyor.GpsActionEvent;
 import at.dallermassl.josm.plugin.surveyor.SurveyorAction;
+import at.dallermassl.josm.plugin.surveyor.SurveyorLock;
 
 /**
  * Action that sets a node into the data layer. The first parameter is used as a property key
@@ -62,15 +62,18 @@ public class SetNodeAction implements SurveyorAction {
      */
     public void actionPerformed(GpsActionEvent event) {
         LatLon coordinates = event.getCoordinates();
-        System.out.println(getClass().getSimpleName() + " KOORD: " + coordinates.lat() + ", " + coordinates.lon() + " params: " + keyValues);
+        //System.out.println(getClass().getSimpleName() + " KOORD: " + coordinates.lat() + ", " + coordinates.lon() + " params: " + keyValues);
         Node node = new Node(coordinates);
         for(Entry<String, String> entry : keyValues) {
             node.put(entry.getKey(), entry.getValue());
         }
-        node.put("created_by", "JOSM-surveyor-plugin");
-        synchronized(LiveGpsLock.class) {
-            Main.map.mapView.getEditLayer().data.addPrimitive(node);
-            Main.main.getCurrentDataSet().setSelected(node);
+        synchronized(SurveyorLock.class) {
+            DataSet ds = Main.main.getCurrentDataSet();
+            if(ds != null)
+            {
+                ds.addPrimitive(node);
+                ds.setSelected(node);
+            }
         }
         Main.map.repaint();
     }
diff --git a/surveyor/src/at/dallermassl/josm/plugin/surveyor/action/SetWaypointAction.java b/surveyor/src/at/dallermassl/josm/plugin/surveyor/action/SetWaypointAction.java
index dc727a6..f75c377 100644
--- a/surveyor/src/at/dallermassl/josm/plugin/surveyor/action/SetWaypointAction.java
+++ b/surveyor/src/at/dallermassl/josm/plugin/surveyor/action/SetWaypointAction.java
@@ -11,7 +11,6 @@ import java.util.Collection;
 import javax.swing.JToggleButton;
 
 import livegps.LiveGpsLayer;
-import livegps.LiveGpsLock;
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.coor.LatLon;
@@ -23,6 +22,7 @@ import org.openstreetmap.josm.gui.layer.markerlayer.Marker;
 import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
 
 import at.dallermassl.josm.plugin.surveyor.GpsActionEvent;
+import at.dallermassl.josm.plugin.surveyor.SurveyorLock;
 import at.dallermassl.josm.plugin.surveyor.SurveyorPlugin;
 import at.dallermassl.josm.plugin.surveyor.action.gui.WaypointDialog;
 import at.dallermassl.josm.plugin.surveyor.util.LayerUtil;
@@ -37,7 +37,7 @@ import at.dallermassl.josm.plugin.surveyor.util.LayerUtil;
 public class SetWaypointAction extends AbstractSurveyorAction {
     private LiveGpsLayer liveGpsLayer;
     private MarkerLayer markerLayer;
-    public static final String MARKER_LAYER_NAME = "surveyorwaypointlayer";
+    public static final String MARKER_LAYER_NAME = tr("Surveyor waypoint layer");
     private WaypointDialog dialog;
 
     /**
@@ -53,7 +53,7 @@ public class SetWaypointAction extends AbstractSurveyorAction {
      */
     public void actionPerformed(GpsActionEvent event) {
         LatLon coordinates = event.getCoordinates();
-        System.out.println(getClass().getSimpleName() + " KOORD: " + coordinates.lat() + ", " + coordinates.lon());
+        //System.out.println(getClass().getSimpleName() + " KOORD: " + coordinates.lat() + ", " + coordinates.lon());
         String markerTitle = getParameters().get(0);
         Object source = event.getSource();
         if(source instanceof JToggleButton) {
@@ -69,7 +69,7 @@ public class SetWaypointAction extends AbstractSurveyorAction {
         }
 
         String markerText = markerTitle;
-        String inputText = dialog.openDialog(SurveyorPlugin.getSurveyorFrame(), "Waypoint Description");
+        String inputText = dialog.openDialog(SurveyorPlugin.getSurveyorFrame(), tr("Waypoint Description"));
         if(inputText != null && inputText.length() > 0) {
             inputText = inputText.replaceAll("<", "_"); // otherwise the gpx file is ruined
             markerText = markerText + " " + inputText;
@@ -85,7 +85,7 @@ public class SetWaypointAction extends AbstractSurveyorAction {
         waypoint.attr.put("name", markerText);
         if(iconName != null)
             waypoint.attr.put("sym", iconName);
-        synchronized(LiveGpsLock.class) {
+        synchronized(SurveyorLock.class) {
             //layer.data.add(new Marker(event.getCoordinates(), markerText, iconName));
             layer.data.add(new Marker(event.getCoordinates(), markerText, iconName, null, -1.0, 0.0));
             if(gpsLayer != null) {
diff --git a/surveyor/src/at/dallermassl/josm/plugin/surveyor/action/gui/WaypointDialog.java b/surveyor/src/at/dallermassl/josm/plugin/surveyor/action/gui/WaypointDialog.java
index eba62bb..7522abc 100644
--- a/surveyor/src/at/dallermassl/josm/plugin/surveyor/action/gui/WaypointDialog.java
+++ b/surveyor/src/at/dallermassl/josm/plugin/surveyor/action/gui/WaypointDialog.java
@@ -67,7 +67,7 @@ public class WaypointDialog {
         dialog.setVisible(true);
 
 
-        System.out.println("value: " + optionPane.getValue());
+        //System.out.println("value: " + optionPane.getValue());
         return textField.getText();
 
 //        int value = ((Integer) optionPane.getValue()).intValue();
diff --git a/svn-info.xml b/svn-info.xml
index 3d703d4..ffc5a4c 100644
--- a/svn-info.xml
+++ b/svn-info.xml
@@ -3,16 +3,16 @@
 <entry
    kind="dir"
    path="plugins"
-   revision="18946">
+   revision="20740">
 <url>http://svn.openstreetmap.org/applications/editors/josm/plugins</url>
 <repository>
 <root>http://svn.openstreetmap.org</root>
 <uuid>b9d5c4c9-76e1-0310-9c85-f3177eceb1e4</uuid>
 </repository>
 <commit
-   revision="18946">
-<author>stoecker</author>
-<date>2009-12-04T21:55:59.367019Z</date>
+   revision="20736">
+<author>guggis</author>
+<date>2010-03-29T17:15:59.216604Z</date>
 </commit>
 </entry>
 </info>
diff --git a/utilsplugin/.classpath b/utilsplugin/.classpath
deleted file mode 100644
index 17b8e6a..0000000
--- a/utilsplugin/.classpath
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JDK 5"/>
-	<classpathentry combineaccessrules="false" kind="src" path="/JOSM"/>
-	<classpathentry kind="output" path="build"/>
-</classpath>
diff --git a/utilsplugin/.project b/utilsplugin/.project
deleted file mode 100644
index 2e7e4d2..0000000
--- a/utilsplugin/.project
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>JOSM-utilsplugin</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>
diff --git a/utilsplugin/README b/utilsplugin/README
deleted file mode 100644
index ccabb5c..0000000
--- a/utilsplugin/README
+++ /dev/null
@@ -1,14 +0,0 @@
-The utils plugin has been created by Martijn van Oosterhout <kleptog at svana.org>
-and has been mostly merged into josm.
-
-Some of the remaining parts are written by
-Frederik Ramm <frederik at remote.org>.
-
-The "simplify way" action has been rewritten by
-Gabriel Ebner <ge at gabrielebner.at>.
-
-License: GPL v2 or later.
-
-The complete text of the GNU General Public License can be found
-in the LICENSE file in the OSM subversion root directory.
-
diff --git a/utilsplugin/build.xml b/utilsplugin/build.xml
deleted file mode 100644
index f2664d2..0000000
--- a/utilsplugin/build.xml
+++ /dev/null
@@ -1,55 +0,0 @@
-<project name="utilsplugin" 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="Martijn van Oosterhout"/>
-                <attribute name="Plugin-Class" value="UtilsPlugin.UtilsPlugin"/>
-                <attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
-                <attribute name="Plugin-Description" value="Several utilities that make your life easier: e.g. simplify way, join areas, jump to position."/>
-                <attribute name="Plugin-Mainversion" value="2402"/>
-                <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>
diff --git a/utilsplugin/data/Join Areas Tests.osm b/utilsplugin/data/Join Areas Tests.osm
deleted file mode 100644
index b99a326..0000000
--- a/utilsplugin/data/Join Areas Tests.osm	
+++ /dev/null
@@ -1,767 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<osm version='0.5' generator='JOSM'>
-  <bounds minlat='49.6358455937926' minlon='8.97891998291015' maxlat='49.6659612524238' maxlon='9.01926040649414' origin='JOSM' />
-  <bounds minlat='51.0727784461145' minlon='13.7410855293274' maxlat='51.07443677101' maxlon='13.743531703949' origin='OpenStreetMap server' />
-  <node id='-1' visible='true' lat='49.665557350679464' lon='8.980018030697323'>
-    <tag k='name' v='Multipolygon' />
-  </node>
-  <node id='-2' visible='true' lat='49.66293444373006' lon='8.979904268383734' />
-  <node id='-3' visible='true' lat='49.66309431357888' lon='8.98771163350794' />
-  <node id='-4' visible='true' lat='49.66550322539429' lon='8.987481709734286' />
-  <node id='-5' visible='true' lat='49.661140812390876' lon='8.980754551545285' />
-  <node id='-6' visible='true' lat='49.66414787714609' lon='8.98167662069808' />
-  <node id='-7' visible='true' lat='49.66193599760082' lon='8.983668051096597' />
-  <node id='-8' visible='true' lat='49.66423062929877' lon='8.985896954118042' />
-  <node id='-9' visible='true' lat='49.66122094281029' lon='8.987593944961972' />
-  <node id='-10' visible='true' lat='49.665246272951265' lon='8.996673744036638'>
-    <tag k='name' v='No Additional Inner Nodes' />
-  </node>
-  <node id='-11' visible='true' lat='49.66260897027721' lon='8.996995205661822' />
-  <node id='-12' visible='true' lat='49.66247822670222' lon='9.006405902938653' />
-  <node id='-13' visible='true' lat='49.66509579743186' lon='9.006492938770437' />
-  <node id='-14' visible='true' lat='49.663673852556485' lon='9.001872836660935' />
-  <node id='-15' visible='true' lat='49.66356462957665' lon='9.003786018319271' />
-  <node id='-16' visible='true' lat='49.659381328509475' lon='9.002998050852923' />
-  <node id='-17' visible='true' lat='49.658143795735675' lon='9.001321365825214' />
-  <node id='-18' visible='true' lat='49.66102960777179' lon='9.004102187558955' />
-  <node id='-19' visible='true' lat='49.65966007592634' lon='8.995756927212474'>
-    <tag k='name' v='With Inner Nodes, resolve tag conflicts beforehand' />
-  </node>
-  <node id='-20' visible='true' lat='49.65470614469758' lon='9.000967096568774' />
-  <node id='-21' visible='true' lat='49.658215448844345' lon='8.998101909487305' />
-  <node id='-22' visible='true' lat='49.65482452933729' lon='8.99800181533644' />
-  <node id='-23' visible='true' lat='49.65622420968986' lon='8.999630518959972' />
-  <node id='-24' visible='true' lat='49.656334599426415' lon='8.99596685442522' />
-  <node id='-25' visible='true' lat='49.664767306664714' lon='9.00358600531296' />
-  <node id='-26' visible='true' lat='49.65595437351232' lon='9.002670090930014' />
-  <node id='-27' visible='true' lat='49.66298227683501' lon='9.007574342263663' />
-  <node id='-28' visible='true' lat='49.652897713964435' lon='8.995398194580462'>
-    <tag k='name' v='Overlapping Itself' />
-  </node>
-  <node id='-29' visible='true' lat='49.64759565941927' lon='8.995601060044594' />
-  <node id='-30' visible='true' lat='49.657294551336726' lon='9.005523880219158' />
-  <node id='-31' visible='true' lat='49.65131105391522' lon='9.00298658642922' />
-  <node id='-32' visible='true' lat='49.659323888301465' lon='9.00052935158495' />
-  <node id='-33' visible='true' lat='49.65151745640557' lon='8.997992057795011' />
-  <node id='-34' visible='true' lat='49.648042897844014' lon='9.003942985529385' />
-  <node id='-35' visible='true' lat='49.64965980248303' lon='9.003039719712563' />
-  <node id='-36' visible='true' lat='49.647526853143034' lon='8.99921412331189' />
-  <node id='-37' visible='true' lat='49.64862774189198' lon='8.99756699152827' />
-  <node id='-38' visible='true' lat='49.650123242376026' lon='8.984223634986959' />
-  <node id='-39' visible='true' lat='49.6534782364111' lon='9.003730452396017' />
-  <node id='-40' visible='true' lat='49.64965980248303' lon='8.997301325111557' />
-  <node id='-41' visible='true' lat='49.648702988205066' lon='8.99108732452821' />
-  <node id='-42' visible='true' lat='49.6498411096278' lon='8.989584718400737' />
-  <node id='-43' visible='true' lat='49.64837612802103' lon='8.982669694368326' />
-  <node id='-44' visible='true' lat='49.65267519581664' lon='8.982531354736969'>
-    <tag k='name' v='Joining an two areas with self-overlap' />
-  </node>
-  <node id='-45' visible='true' lat='49.64821655131596' lon='8.986618619738293' />
-  <node id='-46' visible='true' lat='49.65263419499493' lon='8.992015874465995' />
-  <node id='-47' visible='true' lat='49.65180728142213' lon='8.98635078159476' />
-  <node id='-48' visible='true' lat='49.65154365880048' lon='8.989894759403137' />
-  <node id='-49' visible='true' lat='49.664258008517386' lon='8.994834196254615' />
-  <node id='-50' visible='true' lat='49.66111564855195' lon='8.994837077867599' />
-  <node id='-51' visible='true' lat='49.661575265881794' lon='9.002417415068946' />
-  <node id='-52' visible='true' lat='49.64910487989931' lon='8.98434746261959' />
-  <node id='-53' visible='true' lat='49.66439890567706' lon='9.000253362850133' />
-  <node id='-54' visible='true' lat='49.66336086872286' lon='9.000172520579218' />
-  <node id='-55' visible='true' lat='49.66163205844883' lon='8.996182583343169' />
-  <node id='-56' visible='true' lat='49.66327697326473' lon='8.996037451903568' />
-  <node id='-57' visible='true' lat='49.65366266054767' lon='8.983765181752341' />
-  <node id='-58' visible='true' lat='49.65093842995153' lon='8.98362536207706' />
-  <node id='-59' visible='true' lat='49.65083240952062' lon='8.981009751040055' />
-  <node id='-60' visible='true' lat='49.653656418352305' lon='8.980925219001294' />
-  <node id='-61' visible='true' lat='49.65918199608578' lon='8.97945358407826'>
-    <tag k='name' v='Intersection already have nodes added' />
-  </node>
-  <node id='-62' visible='true' lat='49.65687579780412' lon='8.979558364399258' />
-  <node id='-63' visible='true' lat='49.65684188230803' lon='8.984902160770126' />
-  <node id='-64' visible='true' lat='49.65918199608578' lon='8.984744990288629' />
-  <node id='-65' visible='true' lat='49.65687579780412' lon='8.980815728251226' />
-  <node id='-66' visible='true' lat='49.65809673992071' lon='8.980815728251226' />
-  <node id='-67' visible='true' lat='49.65792716645855' lon='8.983382846115664' />
-  <node id='-68' visible='true' lat='49.65701145955204' lon='8.98306850515267' />
-  <node id='-69' visible='true' lat='49.65545132661812' lon='8.981025288893223' />
-  <node id='-70' visible='true' lat='49.65558501959522' lon='8.988437026602341' />
-  <node id='-71' visible='true' lat='49.65931567881406' lon='8.986865321787379'>
-    <tag k='name' v='SOME Intersection already have nodes added' />
-  </node>
-  <node id='-72' visible='true' lat='49.65700948686801' lon='8.986970102108378' />
-  <node id='-73' visible='true' lat='49.65823042563044' lon='8.988227465960346' />
-  <node id='-74' visible='true' lat='49.65931567881406' lon='8.992156727997747' />
-  <node id='-75' visible='true' lat='49.65697557146509' lon='8.992313898479246' />
-  <node id='-76' visible='true' lat='49.65806085263415' lon='8.990794583824783' />
-  <node id='-77' visible='true' lat='49.65700948686801' lon='8.988227465960346' />
-  <node id='-78' visible='true' lat='49.660221488976575' lon='8.977137289660517' />
-  <node id='-79' visible='true' lat='49.66019710027813' lon='9.021519330497165' />
-  <node id='-80' visible='true' lat='49.66824309940781' lon='8.99379608098765' />
-  <node id='-81' visible='true' lat='49.665325869211465' lon='9.010629016616129'>
-    <tag k='name' v='Member of some (i.e. not multigon) relation' />
-  </node>
-  <node id='-82' visible='true' lat='49.65418064466472' lon='9.02166564057246' />
-  <node id='-83' visible='true' lat='49.66084008723247' lon='9.01744447037755' />
-  <node id='-84' visible='true' lat='49.66089950426598' lon='9.010651964271892' />
-  <node id='-85' visible='true' lat='49.66770174614116' lon='9.008788568211484' />
-  <node id='-86' action='modify' visible='true' lat='49.6353930124394' lon='8.99395938766279' />
-  <node id='-87' visible='true' lat='49.654142227092336' lon='8.97793106762297' />
-  <node id='-88' action='modify' visible='true' lat='49.63560427014124' lon='9.009633761966247' />
-  <node id='-89' visible='true' lat='49.66149367061061' lon='9.016824883671967' />
-  <node id='-90' visible='true' lat='49.66156794089354' lon='9.014644856374543' />
-  <node id='-91' visible='true' lat='49.6657566013461' lon='9.017559208656362' />
-  <node id='-92' visible='true' lat='49.665266457583265' lon='9.016733093048918' />
-  <node id='-93' visible='true' lat='49.662236368338334' lon='9.011707556436962' />
-  <node id='-94' visible='true' lat='49.66210268358402' lon='9.017513313344837' />
-  <node id='-95' visible='true' lat='49.663929676767346' lon='9.01471369934183' />
-  <node id='-96' visible='true' lat='49.663989090028004' lon='9.01179934706001' />
-  <node id='-97' visible='true' lat='49.656561909834345' lon='9.011712617586559' />
-  <node id='-98' visible='true' lat='49.65825541574074' lon='9.014718760491427' />
-  <node id='-99' visible='true' lat='49.65507724377221' lon='9.016274166792183' />
-  <node id='-100' visible='true' lat='49.65831483593041' lon='9.011804408209608' />
-  <node id='-101' visible='true' lat='49.65954150350348' lon='9.010225255249217'>
-    <tag k='name' v='One Area already part of multipolygon (as outer)' />
-  </node>
-  <node id='-102' visible='true' lat='49.65948208481168' lon='9.016329331682007' />
-  <node id='-103' visible='true' lat='49.66572689580407' lon='9.018683643788718' />
-  <node id='-104' visible='true' lat='49.66467233731082' lon='9.018729539100242' />
-  <node id='-105' visible='true' lat='49.650467504431084' lon='9.01556653387284' />
-  <node id='-106' visible='true' lat='49.650467504431084' lon='9.012653673442712' />
-  <node id='-107' visible='true' lat='49.6577783879124' lon='9.01859068072843' />
-  <node id='-108' visible='true' lat='49.659950690584154' lon='9.018522543642344' />
-  <node id='-109' visible='true' lat='49.659983770585875' lon='9.015660786026782' />
-  <node id='-110' visible='true' lat='49.65777838791238' lon='9.0156778202983' />
-  <node id='-111' visible='true' lat='49.655114612313845' lon='9.01024820290498' />
-  <node id='-112' visible='true' lat='49.65649630973553' lon='9.01456121513066' />
-  <node id='-113' visible='true' lat='49.649790825127035' lon='9.010994229724082' />
-  <node id='-114' visible='true' lat='49.64907390166997' lon='9.010241166221228' />
-  <node id='-115' visible='true' lat='49.64972521590133' lon='9.013842827268181' />
-  <node id='-116' visible='true' lat='49.652640133446276' lon='9.015498396786755' />
-  <node id='-117' visible='true' lat='49.65267321841768' lon='9.012636639171191' />
-  <node id='-118' visible='true' lat='49.653441916259965' lon='9.016322294998254' />
-  <node id='-119' visible='true' lat='49.651484566652904' lon='9.01400037262895' />
-  <node id='-120' visible='true' lat='49.649036528490285' lon='9.01626713010843' />
-  <node id='-121' visible='true' lat='49.64474487637503' lon='9.013313148784425' />
-  <node id='-122' visible='true' lat='49.64329477394559' lon='9.00982115694612' />
-  <node id='-123' visible='true' lat='49.64633804682556' lon='9.016044421132413' />
-  <node id='-124' visible='true' lat='49.6440995060445' lon='9.015089670434026' />
-  <node id='-125' visible='true' lat='49.64698953060391' lon='8.97763933322747' />
-  <node id='-126' visible='true' lat='49.64702795382207' lon='9.021373906176958' />
-  <node id='-127' visible='true' lat='49.651543995109876' lon='9.011086020347133' />
-  <node id='-128' visible='true' lat='49.65350134232707' lon='9.010218218565463'>
-    <tag k='name' v='One Area already part of multipolygon (as inner)' />
-  </node>
-  <node id='-129' visible='true' lat='49.64442618533402' lon='9.018507236795525' />
-  <node id='-130' visible='true' lat='49.64634787643868' lon='9.01859251804108' />
-  <node id='-131' visible='true' lat='49.646377327053195' lon='9.017591884759854' />
-  <node id='-132' visible='true' lat='49.64446300005248' lon='9.017591884759854' />
-  <node id='-133' action='modify' visible='true' lat='49.644279396738646' lon='8.99701844322583' />
-  <node id='-134' action='modify' visible='true' lat='49.645108516691536' lon='9.00501200093294' />
-  <node id='-135' action='modify' visible='true' lat='49.64579713321828' lon='9.001725329495672' />
-  <node id='-136' action='modify' visible='true' lat='49.643570600890634' lon='9.005424239693767' />
-  <node id='-137' visible='true' lat='49.645694403782294' lon='9.012131348650524' />
-  <node id='-138' visible='true' lat='49.646452701397266' lon='9.00974135512665'>
-    <tag k='name' v='Both part of other relations' />
-  </node>
-  <node id='-139' visible='true' lat='49.64566131406722' lon='9.01503858959705' />
-  <node id='-140' visible='true' lat='49.64477854294109' lon='9.010865000644996' />
-  <node id='-141' visible='true' lat='49.6436516438452' lon='9.013337536747516' />
-  <node id='-142' visible='true' lat='49.64333102750582' lon='9.015932402078883' />
-  <node id='-143' visible='true' lat='49.64364363066422' lon='9.010830064185653' />
-  <node id='-144' visible='true' lat='49.6440995060445' lon='9.012176810003897' />
-  <node id='-145' action='modify' visible='true' lat='49.644215448513066' lon='8.987601210318644' />
-  <node id='-146' action='modify' visible='true' lat='49.64509437228782' lon='8.985632145182455' />
-  <node id='-147' action='modify' visible='true' lat='49.64512070290696' lon='8.990191229749867' />
-  <node id='-148' action='modify' visible='true' lat='49.64400653203681' lon='8.985527741087623' />
-  <node id='-149' action='modify' visible='true' lat='49.64362715512701' lon='8.983795590458412' />
-  <node id='-150' action='modify' visible='true' lat='49.6438359138228' lon='8.988873075900425' />
-  <node id='-151' action='modify' visible='true' lat='49.64624752120218' lon='8.990209078516749' />
-  <node id='-152' action='modify' visible='true' lat='49.64561767902291' lon='8.987111582364214' />
-  <node id='-153' action='modify' visible='true' lat='49.645870282835396' lon='9.000573288940334' />
-  <node id='-154' action='modify' visible='true' lat='49.644533441390884' lon='9.001738472218983' />
-  <node id='-155' action='modify' visible='true' lat='49.64620102922634' lon='8.995285052653605' />
-  <node id='-156' action='modify' visible='true' lat='49.645549394972946' lon='8.997512960693886' />
-  <node id='-157' action='modify' visible='true' lat='49.64390917555046' lon='9.00236900726505' />
-  <node id='-158' action='modify' visible='true' lat='49.643583272941804' lon='8.996426078862356' />
-  <node id='-159' action='modify' visible='true' lat='49.645064815871' lon='8.999528632035787' />
-  <node id='-160' action='modify' visible='true' lat='49.64660348405886' lon='9.007804150387257' />
-  <node id='-161' visible='true' lat='49.67180165588925' lon='9.019276197911166'>
-    <tag k='name' v='out of bounds' />
-  </node>
-  <node id='-162' visible='true' lat='49.66726589111355' lon='9.018808975183893' />
-  <node id='-163' action='modify' visible='true' lat='49.64294039575888' lon='8.98264180269116' />
-  <node id='-164' action='modify' visible='true' lat='49.64654691824636' lon='8.982418392157395' />
-  <node id='-165' action='modify' visible='true' lat='49.6465677851024' lon='8.992596999330347' />
-  <node id='-166' action='modify' visible='true' lat='49.64305580574678' lon='8.992869020494213' />
-  <node id='-167' visible='true' lat='49.66722269132057' lon='9.026351284924155' />
-  <node id='-168' visible='true' lat='49.671931242953896' lon='9.026017554404675' />
-  <node id='-169' visible='true' lat='49.66903704959538' lon='9.022880487521558' />
-  <node id='-170' visible='true' lat='49.664846643627826' lon='9.02334771024883' />
-  <node id='-171' action='modify' visible='true' lat='49.64619224514668' lon='8.984061673983168' />
-  <node id='-172' action='modify' visible='true' lat='49.64560080131112' lon='8.988407502515859' />
-  <node id='-173' visible='true' lat='49.66476023970688' lon='9.029688590118962' />
-  <node id='-174' visible='true' lat='49.6687778596993' lon='9.028553906352727' />
-  <node id='-175' action='modify' visible='true' lat='49.64226790264086' lon='9.020479682913138' />
-  <node id='-176' action='modify' visible='true' lat='49.64222947566583' lon='8.976745109963648' />
-  <node id='-177' visible='true' lat='49.63766059241029' lon='8.985426371428245' />
-  <node id='-178' action='modify' visible='true' lat='49.64113713627012' lon='8.99764014460778' />
-  <node id='-179' visible='true' lat='49.63620969614912' lon='8.984267584902272' />
-  <node id='-180' visible='true' lat='49.63831098015055' lon='8.986005764691233' />
-  <node id='-181' action='modify' visible='true' lat='49.63833608786159' lon='9.001965476258553' />
-  <node id='-182' action='modify' visible='true' lat='49.63866179944343' lon='9.001060174285136' />
-  <node id='-183' action='modify' visible='true' lat='49.636707497273726' lon='8.996902491147958' />
-  <node id='-184' action='modify' visible='true' lat='49.63672921217317' lon='9.001496060420484' />
-  <node id='-185' visible='true' lat='49.64166284075567' lon='8.990370527272402' />
-  <node id='-186' visible='true' lat='49.64038715981111' lon='8.984846978165258' />
-  <node id='-187' visible='true' lat='49.63635979087037' lon='8.9920314546263' />
-  <node id='-188' visible='true' lat='49.63665997892509' lon='8.979825569886037' />
-  <node id='-189' visible='true' lat='49.64158780162527' lon='8.984460715989934' />
-  <node id='-190' visible='true' lat='49.63671001008765' lon='8.985696754950974' />
-  <node id='-191' visible='true' lat='49.639336573937996' lon='8.985619502515908' />
-  <node id='-192' visible='true' lat='49.64153777547409' lon='8.98052084180162' />
-  <node id='-193' action='modify' visible='true' lat='49.63919649619353' lon='9.000021094269913' />
-  <node id='-194' visible='true' lat='49.63655427055324' lon='9.003685105162774' />
-  <node id='-195' visible='true' lat='49.638889008438305' lon='9.003170088929009' />
-  <node id='-196' visible='true' lat='49.63766439678692' lon='9.008322826347838' />
-  <node id='-197' visible='true' lat='49.636803870494575' lon='9.005634441607576' />
-  <node id='-198' visible='true' lat='49.64135304304343' lon='9.008042625328157' />
-  <node id='-199' action='modify' visible='true' lat='49.641397690721426' lon='9.002032535663991' />
-  <node id='-200' visible='true' lat='49.639702839791006' lon='9.002946110514843' />
-  <node id='-201' visible='true' lat='49.641505032635514' lon='9.005561427326938' />
-  <node id='-202' action='modify' visible='true' lat='49.640355464550595' lon='9.000557228744347' />
-  <node id='-203' action='modify' visible='true' lat='49.63983876223289' lon='8.999763400318008' />
-  <node id='-204' action='modify' visible='true' lat='49.640963432528' lon='9.002300773285747' />
-  <node id='-205' action='modify' visible='true' lat='49.640355464550595' lon='9.00163017923136' />
-  <node id='-206' action='modify' visible='true' lat='49.641650361020126' lon='9.011375542032631' />
-  <node id='-207' action='modify' visible='true' lat='49.63994510769946' lon='9.011537754906723' />
-  <node id='-208' action='modify' visible='true' lat='49.63989778320692' lon='9.01301762121565' />
-  <node id='-209' action='modify' timestamp='2008-03-17T23:16:02Z' visible='true' lat='49.63851559945754' lon='9.011923928883068'>
-    <tag k='created_by' v='Merkaartor 0.10' />
-  </node>
-  <node id='-210' action='modify' timestamp='2008-03-17T23:16:00Z' visible='true' lat='49.63931004998166' lon='9.014994879645652'>
-    <tag k='created_by' v='Merkaartor 0.10' />
-  </node>
-  <node id='-211' action='modify' timestamp='2008-03-17T23:16:02Z' visible='true' lat='49.63656290879177' lon='9.01184224653937'>
-    <tag k='created_by' v='Merkaartor 0.10' />
-  </node>
-  <node id='-212' action='modify' timestamp='2008-03-19T00:23:09Z' visible='true' lat='49.638495992538296' lon='9.013041516659012'>
-    <tag k='created_by' v='Merkaartor 0.10' />
-  </node>
-  <node id='-213' action='modify' timestamp='2008-03-17T23:16:00Z' visible='true' lat='49.639297465489946' lon='9.013075043737933'>
-    <tag k='created_by' v='Merkaartor 0.10' />
-  </node>
-  <node id='-214' action='modify' timestamp='2008-03-17T23:16:01Z' visible='true' lat='49.63932787364639' lon='9.011341760369241'>
-    <tag k='created_by' v='Merkaartor 0.10' />
-  </node>
-  <node id='-215' action='modify' timestamp='2008-03-17T23:16:00Z' visible='true' lat='49.6362341674196' lon='9.011212347946481' />
-  <node id='-216' action='modify' timestamp='2008-06-18T15:47:24Z' visible='true' lat='49.63846974351432' lon='9.014959728094702' />
-  <node id='-217' action='modify' timestamp='2008-03-17T23:16:01Z' visible='true' lat='49.639285639926086' lon='9.016386267202325'>
-    <tag k='created_by' v='Merkaartor 0.10' />
-  </node>
-  <node id='-218' action='modify' timestamp='2008-03-17T23:16:01Z' visible='true' lat='49.63614569649766' lon='9.016254920813461'>
-    <tag k='created_by' v='Merkaartor 0.10' />
-  </node>
-  <node id='-219' action='modify' timestamp='2008-03-17T23:16:02Z' visible='true' lat='49.636497278618506' lon='9.01558299248487' />
-  <node id='-220' action='modify' visible='true' lat='49.64173715249402' lon='9.01288893804428' />
-  <node id='-221' action='modify' visible='true' lat='49.63997057825359' lon='9.017121223877993' />
-  <node id='-222' action='modify' visible='true' lat='49.6418769973781' lon='9.016690773382148' />
-  <node id='-223' action='modify' timestamp='2008-03-17T23:16:02Z' visible='true' lat='49.638457370514' lon='9.015664984322639'>
-    <tag k='created_by' v='Merkaartor 0.10' />
-  </node>
-  <way id='-224' visible='true'>
-    <nd ref='-171' />
-    <nd ref='-151' />
-    <nd ref='-147' />
-    <nd ref='-146' />
-    <nd ref='-148' />
-    <nd ref='-145' />
-    <nd ref='-152' />
-    <nd ref='-172' />
-    <nd ref='-150' />
-    <nd ref='-149' />
-    <nd ref='-171' />
-    <tag k='name' v='Thing in the Middle' />
-  </way>
-  <way id='-225' visible='true'>
-    <nd ref='-164' />
-    <nd ref='-163' />
-    <nd ref='-166' />
-    <nd ref='-165' />
-    <nd ref='-164' />
-    <tag k='parking' v='surface' />
-    <tag k='name' v='Outer blob' />
-    <tag k='amenity' v='parking' />
-  </way>
-  <way id='-226' visible='true'>
-    <nd ref='-117' />
-    <nd ref='-106' />
-    <nd ref='-105' />
-    <nd ref='-116' />
-    <nd ref='-117' />
-  </way>
-  <way id='-227' visible='true'>
-    <nd ref='-28' />
-    <nd ref='-39' />
-    <nd ref='-34' />
-    <nd ref='-37' />
-    <nd ref='-40' />
-    <nd ref='-35' />
-    <nd ref='-31' />
-    <nd ref='-33' />
-    <nd ref='-36' />
-    <nd ref='-29' />
-    <nd ref='-28' />
-    <tag k='parking' v='surface' />
-    <tag k='amenity' v='parking' />
-  </way>
-  <way id='-228' visible='true'>
-    <nd ref='-158' />
-    <nd ref='-155' />
-    <nd ref='-160' />
-    <nd ref='-136' />
-    <nd ref='-158' />
-    <tag k='parking' v='surface' />
-    <tag k='amenity' v='parking' />
-  </way>
-  <way id='-229' visible='true'>
-    <nd ref='-109' />
-    <nd ref='-110' />
-    <nd ref='-107' />
-    <nd ref='-108' />
-    <nd ref='-109' />
-  </way>
-  <way id='-230' visible='true'>
-    <nd ref='-70' />
-    <nd ref='-77' />
-    <nd ref='-73' />
-    <nd ref='-76' />
-    <nd ref='-70' />
-    <tag k='parking' v='surface' />
-    <tag k='amenity' v='parking' />
-  </way>
-  <way id='-231' visible='true'>
-    <nd ref='-10' />
-    <nd ref='-11' />
-    <nd ref='-12' />
-    <nd ref='-13' />
-    <nd ref='-10' />
-    <tag k='parking' v='surface' />
-    <tag k='amenity' v='parking' />
-  </way>
-  <way id='-232' visible='true'>
-    <nd ref='-99' />
-    <nd ref='-102' />
-    <nd ref='-101' />
-    <nd ref='-111' />
-    <nd ref='-99' />
-    <tag k='parking' v='surface' />
-    <tag k='amenity' v='parking' />
-  </way>
-  <way id='-233' action='modify' visible='true'>
-    <nd ref='-198' />
-    <nd ref='-201' />
-    <nd ref='-199' />
-    <nd ref='-204' />
-    <nd ref='-205' />
-    <nd ref='-200' />
-    <nd ref='-195' />
-    <nd ref='-181' />
-    <nd ref='-184' />
-    <nd ref='-194' />
-    <nd ref='-197' />
-    <nd ref='-196' />
-    <nd ref='-198' />
-    <tag k='parking' v='surface' />
-    <tag k='amenity' v='parking' />
-  </way>
-  <way id='-234' visible='true'>
-    <nd ref='-61' />
-    <nd ref='-62' />
-    <nd ref='-65' />
-    <nd ref='-68' />
-    <nd ref='-63' />
-    <nd ref='-64' />
-    <nd ref='-61' />
-    <tag k='parking' v='surface' />
-    <tag k='amenity' v='parking' />
-  </way>
-  <way id='-235' visible='true'>
-    <nd ref='-81' />
-    <nd ref='-84' />
-    <nd ref='-83' />
-    <nd ref='-94' />
-    <nd ref='-93' />
-    <nd ref='-96' />
-    <nd ref='-95' />
-    <nd ref='-90' />
-    <nd ref='-89' />
-    <nd ref='-92' />
-    <nd ref='-81' />
-    <tag k='parking' v='surface' />
-    <tag k='amenity' v='parking' />
-  </way>
-  <way id='-236' visible='true'>
-    <nd ref='-44' />
-    <nd ref='-46' />
-    <nd ref='-41' />
-    <nd ref='-52' />
-    <nd ref='-38' />
-    <nd ref='-42' />
-    <nd ref='-48' />
-    <nd ref='-47' />
-    <nd ref='-45' />
-    <nd ref='-43' />
-    <nd ref='-44' />
-    <tag k='parking' v='surface' />
-    <tag k='amenity' v='parking' />
-  </way>
-  <way id='-237' visible='true'>
-    <nd ref='-112' />
-    <nd ref='-97' />
-    <nd ref='-100' />
-    <nd ref='-98' />
-    <nd ref='-112' />
-  </way>
-  <way id='-238' visible='true'>
-    <nd ref='-120' />
-    <nd ref='-118' />
-    <nd ref='-128' />
-    <nd ref='-114' />
-    <nd ref='-120' />
-    <tag k='parking' v='surface' />
-    <tag k='amenity' v='parking' />
-  </way>
-  <way id='-239' visible='true'>
-    <nd ref='-78' />
-    <nd ref='-79' />
-    <tag k='highway' v='motorway' />
-    <tag k='lanes' v='5' />
-  </way>
-  <way id='-240' visible='true'>
-    <nd ref='-25' />
-    <nd ref='-15' />
-    <nd ref='-27' />
-    <tag k='highway' v='footway' />
-  </way>
-  <way id='-241' visible='true'>
-    <nd ref='-125' />
-    <nd ref='-126' />
-    <tag k='highway' v='motorway' />
-    <tag k='lanes' v='5' />
-  </way>
-  <way id='-242' action='modify' visible='true'>
-    <nd ref='-192' />
-    <nd ref='-189' />
-    <nd ref='-186' />
-    <nd ref='-191' />
-    <nd ref='-180' />
-    <nd ref='-177' />
-    <nd ref='-190' />
-    <nd ref='-179' />
-    <nd ref='-188' />
-    <nd ref='-192' />
-    <tag k='amenity' v='parking' />
-  </way>
-  <way id='-243' visible='true'>
-    <nd ref='-60' />
-    <nd ref='-59' />
-    <nd ref='-58' />
-    <nd ref='-57' />
-    <nd ref='-60' />
-    <tag k='parking' v='surface' />
-    <tag k='amenity' v='parking' />
-  </way>
-  <way id='-244' visible='true'>
-    <nd ref='-91' />
-    <nd ref='-103' />
-    <nd ref='-104' />
-  </way>
-  <way id='-245' action='modify' visible='true'>
-    <nd ref='-208' />
-    <nd ref='-221' />
-    <nd ref='-222' />
-    <nd ref='-220' />
-    <nd ref='-208' />
-    <tag k='parking' v='surface' />
-    <tag k='amenity' v='parking' />
-  </way>
-  <way id='-246' visible='true'>
-    <nd ref='-22' />
-    <nd ref='-21' />
-    <nd ref='-17' />
-    <nd ref='-20' />
-    <nd ref='-22' />
-    <tag k='landuse' v='basin' />
-  </way>
-  <way id='-247' action='modify' visible='true'>
-    <nd ref='-185' />
-    <nd ref='-189' />
-    <nd ref='-186' />
-    <nd ref='-191' />
-    <nd ref='-180' />
-    <nd ref='-177' />
-    <nd ref='-190' />
-    <nd ref='-179' />
-    <nd ref='-187' />
-    <nd ref='-185' />
-    <tag k='amenity' v='parking' />
-  </way>
-  <way id='-248' visible='true'>
-    <nd ref='-5' />
-    <nd ref='-6' />
-    <nd ref='-7' />
-    <nd ref='-8' />
-    <nd ref='-9' />
-    <nd ref='-5' />
-    <tag k='parking' v='surface' />
-    <tag k='amenity' v='parking' />
-  </way>
-  <way id='-249' timestamp='2008-06-18T15:47:24Z' visible='true'>
-    <nd ref='-216' />
-    <nd ref='-210' />
-    <nd ref='-213' />
-    <nd ref='-212' />
-    <nd ref='-216' />
-    <tag k='created_by' v='Potlatch 0.9c' />
-    <tag k='building' v='yes' />
-  </way>
-  <way id='-250' action='modify' visible='true'>
-    <nd ref='-178' />
-    <nd ref='-183' />
-    <nd ref='-184' />
-    <nd ref='-181' />
-    <nd ref='-182' />
-    <nd ref='-193' />
-    <nd ref='-203' />
-    <nd ref='-202' />
-    <nd ref='-205' />
-    <nd ref='-204' />
-    <nd ref='-199' />
-    <nd ref='-178' />
-    <tag k='parking' v='surface' />
-    <tag k='amenity' v='parking' />
-  </way>
-  <way id='-251' visible='true'>
-    <nd ref='-87' />
-    <nd ref='-82' />
-    <tag k='highway' v='motorway' />
-    <tag k='lanes' v='5' />
-  </way>
-  <way id='-252' visible='true'>
-    <nd ref='-153' />
-    <nd ref='-154' />
-    <nd ref='-133' />
-    <nd ref='-156' />
-    <nd ref='-153' />
-  </way>
-  <way id='-253' visible='true'>
-    <nd ref='-130' />
-    <nd ref='-129' />
-    <nd ref='-132' />
-    <nd ref='-131' />
-    <nd ref='-130' />
-  </way>
-  <way id='-254' visible='true'>
-    <nd ref='-115' />
-    <nd ref='-113' />
-    <nd ref='-127' />
-    <nd ref='-119' />
-    <nd ref='-115' />
-  </way>
-  <way id='-255' visible='true'>
-    <nd ref='-137' />
-    <nd ref='-144' />
-    <nd ref='-124' />
-    <nd ref='-139' />
-    <nd ref='-137' />
-  </way>
-  <way id='-256' visible='true'>
-    <nd ref='-32' />
-    <nd ref='-17' />
-    <nd ref='-30' />
-    <tag k='highway' v='footway' />
-  </way>
-  <way id='-257' timestamp='2008-06-17T03:52:47Z' visible='true'>
-    <nd ref='-210' />
-    <nd ref='-217' />
-    <nd ref='-218' />
-    <nd ref='-215' />
-    <nd ref='-214' />
-    <nd ref='-213' />
-    <nd ref='-212' />
-    <nd ref='-209' />
-    <nd ref='-211' />
-    <nd ref='-219' />
-    <nd ref='-223' />
-    <nd ref='-216' />
-    <nd ref='-210' />
-    <tag k='created_by' v='Merkaartor 0.10' />
-    <tag k='building' v='yes' />
-  </way>
-  <way id='-258' visible='true'>
-    <nd ref='-161' />
-    <nd ref='-162' />
-    <nd ref='-167' />
-    <nd ref='-168' />
-    <nd ref='-161' />
-    <tag k='parking' v='surface' />
-    <tag k='amenity' v='parking' />
-  </way>
-  <way id='-259' action='modify' visible='true'>
-    <nd ref='-206' />
-    <nd ref='-207' />
-    <nd ref='-208' />
-    <nd ref='-220' />
-    <nd ref='-206' />
-    <tag k='parking' v='surface' />
-    <tag k='amenity' v='parking' />
-  </way>
-  <way id='-260' visible='true'>
-    <nd ref='-169' />
-    <nd ref='-170' />
-    <nd ref='-173' />
-    <nd ref='-174' />
-    <nd ref='-169' />
-    <tag k='parking' v='surface' />
-    <tag k='amenity' v='parking' />
-  </way>
-  <way id='-261' visible='true'>
-    <nd ref='-159' />
-    <nd ref='-135' />
-    <nd ref='-134' />
-    <nd ref='-157' />
-    <nd ref='-159' />
-  </way>
-  <way id='-262' visible='true'>
-    <nd ref='-141' />
-    <nd ref='-143' />
-    <nd ref='-140' />
-    <nd ref='-121' />
-    <nd ref='-141' />
-  </way>
-  <way id='-263' visible='true'>
-    <nd ref='-18' />
-    <nd ref='-50' />
-    <nd ref='-49' />
-    <nd ref='-53' />
-    <nd ref='-54' />
-    <nd ref='-56' />
-    <nd ref='-55' />
-    <nd ref='-51' />
-    <nd ref='-14' />
-    <nd ref='-15' />
-    <nd ref='-18' />
-    <tag k='parking' v='surface' />
-    <tag k='amenity' v='parking' />
-  </way>
-  <way id='-264' visible='true'>
-    <nd ref='-176' />
-    <nd ref='-175' />
-    <tag k='highway' v='motorway' />
-    <tag k='lanes' v='5' />
-  </way>
-  <way id='-265' visible='true'>
-    <nd ref='-26' />
-    <nd ref='-16' />
-    <nd ref='-19' />
-    <nd ref='-24' />
-    <nd ref='-23' />
-    <nd ref='-26' />
-    <tag k='landuse' v='retail' />
-  </way>
-  <way id='-266' visible='true'>
-    <nd ref='-71' />
-    <nd ref='-72' />
-    <nd ref='-77' />
-    <nd ref='-75' />
-    <nd ref='-74' />
-    <nd ref='-71' />
-    <tag k='parking' v='surface' />
-    <tag k='amenity' v='parking' />
-  </way>
-  <way id='-267' visible='true'>
-    <nd ref='-85' />
-    <nd ref='-88' />
-    <tag k='highway' v='motorway' />
-    <tag k='lanes' v='5' />
-  </way>
-  <way id='-268' visible='true'>
-    <nd ref='-80' />
-    <nd ref='-86' />
-    <tag k='highway' v='motorway' />
-    <tag k='lanes' v='5' />
-  </way>
-  <way id='-269' visible='true'>
-    <nd ref='-142' />
-    <nd ref='-123' />
-    <nd ref='-138' />
-    <nd ref='-122' />
-    <nd ref='-142' />
-    <tag k='parking' v='surface' />
-    <tag k='amenity' v='parking' />
-  </way>
-  <way id='-270' visible='true'>
-    <nd ref='-69' />
-    <nd ref='-65' />
-    <nd ref='-66' />
-    <nd ref='-67' />
-    <nd ref='-68' />
-    <nd ref='-69' />
-    <tag k='parking' v='surface' />
-    <tag k='amenity' v='parking' />
-  </way>
-  <way id='-271' visible='true'>
-    <nd ref='-1' />
-    <nd ref='-2' />
-    <nd ref='-3' />
-    <nd ref='-4' />
-    <nd ref='-1' />
-    <tag k='parking' v='surface' />
-    <tag k='amenity' v='parking' />
-  </way>
-  <relation id='-272' visible='true'>
-    <member type='way' ref='-224' role='inner' />
-    <member type='way' ref='-225' role='outer' />
-    <tag k='name' v='6.' />
-    <tag k='type' v='multipolygon' />
-  </relation>
-  <relation id='-273' visible='true'>
-    <member type='way' ref='-252' role='inner' />
-    <member type='way' ref='-261' role='inner' />
-    <member type='way' ref='-228' role='outer' />
-    <tag k='name' v='5.' />
-    <tag k='type' v='multipolygon' />
-  </relation>
-  <relation id='-274' visible='true'>
-    <member type='way' ref='-262' role='inner' />
-    <member type='way' ref='-269' role='outer' />
-    <tag k='name' v='4. a' />
-    <tag k='type' v='multipolygon' />
-  </relation>
-  <relation id='-275' visible='true'>
-    <member type='way' ref='-237' role='inner' />
-    <member type='way' ref='-232' role='outer' />
-    <tag k='name' v='2.' />
-    <tag k='type' v='multipolygon' />
-  </relation>
-  <relation id='-276' visible='true'>
-  </relation>
-  <relation id='-277' visible='true'>
-    <member type='way' ref='-253' role='' />
-    <member type='way' ref='-255' role='' />
-    <tag k='name ' v='4. b' />
-  </relation>
-  <relation id='-278' visible='true'>
-    <member type='way' ref='-254' role='inner' />
-    <member type='way' ref='-238' role='outer' />
-    <tag k='name' v='3.' />
-    <tag k='type' v='multipolygon' />
-  </relation>
-  <relation id='-279' visible='true'>
-    <member type='way' ref='-235' role='area' />
-    <member type='node' ref='-93' role='node in area' />
-    <member type='node' ref='-95' role='node in area' />
-    <member type='way' ref='-244' role='some other way' />
-    <member type='node' ref='-90' role='to be deleted node in area' />
-    <tag k='name' v='1.' />
-  </relation>
-</osm>
diff --git a/utilsplugin/images/joinareas.png b/utilsplugin/images/joinareas.png
deleted file mode 100644
index 98267f8..0000000
Binary files a/utilsplugin/images/joinareas.png and /dev/null differ
diff --git a/utilsplugin/images/joinnodeway.png b/utilsplugin/images/joinnodeway.png
deleted file mode 100644
index ea176d9..0000000
Binary files a/utilsplugin/images/joinnodeway.png and /dev/null differ
diff --git a/utilsplugin/images/mergenodes.png b/utilsplugin/images/mergenodes.png
deleted file mode 100644
index fc41fb3..0000000
Binary files a/utilsplugin/images/mergenodes.png and /dev/null differ
diff --git a/utilsplugin/images/simplify.png b/utilsplugin/images/simplify.png
deleted file mode 100644
index 191ab68..0000000
Binary files a/utilsplugin/images/simplify.png and /dev/null differ
diff --git a/utilsplugin/src/UtilsPlugin/JoinAreasAction.java b/utilsplugin/src/UtilsPlugin/JoinAreasAction.java
deleted file mode 100644
index 397d74a..0000000
--- a/utilsplugin/src/UtilsPlugin/JoinAreasAction.java
+++ /dev/null
@@ -1,886 +0,0 @@
-package UtilsPlugin;
-
-import static org.openstreetmap.josm.tools.I18n.marktr;
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.GridBagLayout;
-import java.awt.Polygon;
-import java.awt.event.ActionEvent;
-import java.awt.event.KeyEvent;
-import java.awt.geom.Line2D;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
-import java.util.Map.Entry;
-
-import javax.swing.Box;
-import javax.swing.JComboBox;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.CombineWayAction;
-import org.openstreetmap.josm.actions.JosmAction;
-import org.openstreetmap.josm.actions.ReverseWayAction;
-import org.openstreetmap.josm.actions.SplitWayAction;
-import org.openstreetmap.josm.command.AddCommand;
-import org.openstreetmap.josm.command.ChangeCommand;
-import org.openstreetmap.josm.command.Command;
-import org.openstreetmap.josm.command.DeleteCommand;
-import org.openstreetmap.josm.command.SequenceCommand;
-import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.UndoRedoHandler;
-import org.openstreetmap.josm.data.coor.EastNorth;
-import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.osm.DataSet;
-import org.openstreetmap.josm.data.osm.DataSource;
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.Relation;
-import org.openstreetmap.josm.data.osm.RelationMember;
-import org.openstreetmap.josm.data.osm.TigerUtils;
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.gui.ExtendedDialog;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.tools.GBC;
-import org.openstreetmap.josm.tools.Shortcut;
-
-public class JoinAreasAction extends JosmAction {
-    // This will be used to commit commands and unite them into one large command sequence at the end
-    private LinkedList<Command> cmds = new LinkedList<Command>();
-    private int cmdsCount = 0;
-
-    // HelperClass
-    // Saves a node and two positions where to insert the node into the ways
-    private class NodeToSegs implements Comparable<NodeToSegs> {
-        public int pos;
-        public Node n;
-        public double dis;
-        public NodeToSegs(int pos, Node n, LatLon dis) {
-            this.pos = pos;
-            this.n = n;
-            this.dis = n.getCoor().greatCircleDistance(dis);
-        }
-
-        public int compareTo(NodeToSegs o) {
-            if(this.pos == o.pos)
-                return (this.dis - o.dis) > 0 ? 1 : -1;
-            return this.pos - o.pos;
-        }
-    };
-
-    // HelperClass
-    // Saves a relation and a role an OsmPrimitve was part of until it was stripped from all relations
-    private class RelationRole {
-        public Relation rel;
-        public String role;
-        public RelationRole(Relation rel, String role) {
-            this.rel = rel;
-            this.role = role;
-        }
-
-        @Override
-        public boolean equals(Object other) {
-            if (!(other instanceof RelationRole)) return false;
-            RelationRole otherMember = (RelationRole) other;
-            return otherMember.role.equals(role) && otherMember.rel.equals(rel);
-        }
-    }
-
-    // Adds the menu entry, Shortcuts, etc.
-    public JoinAreasAction() {
-        super(tr("Join overlapping Areas"), "joinareas", tr("Joins areas that overlap each other"), Shortcut.registerShortcut("tools:joinareas", tr("Tool: {0}", tr("Join overlapping Areas")),
-        KeyEvent.VK_J, Shortcut.GROUP_EDIT, Shortcut.SHIFT_DEFAULT), true);
-    }
-
-    /**
-     * Gets called whenever the shortcut is pressed or the menu entry is selected
-     * Checks whether the selected objects are suitable to join and joins them if so
-     */
-    public void actionPerformed(ActionEvent e) {
-        Collection<OsmPrimitive> selection = Main.main.getCurrentDataSet().getSelectedWays();
-
-        int ways = 0;
-        Way[] selWays = new Way[2];
-
-        LinkedList<Bounds> bounds = new LinkedList<Bounds>();
-        OsmDataLayer dataLayer = Main.map.mapView.getEditLayer();
-        for (DataSource ds : dataLayer.data.dataSources) {
-            if (ds.bounds != null)
-                bounds.add(ds.bounds);
-        }
-
-        boolean askedAlready = false;
-        for (OsmPrimitive prim : selection) {
-            Way way = (Way) prim;
-
-            // Too many ways
-            if(ways == 2) {
-                JOptionPane.showMessageDialog(Main.parent, tr("Only up to two areas can be joined at the moment."));
-                return;
-            }
-
-            if(!way.isClosed()) {
-                JOptionPane.showMessageDialog(Main.parent, tr("\"{0}\" is not closed and therefore can't be joined.", way.getName()));
-                return;
-            }
-
-            // This is copied from SimplifyAction and should be probably ported to tools
-            for (Node node : way.getNodes()) {
-                if(askedAlready) break;
-                boolean isInsideOneBoundingBox = false;
-                for (Bounds b : bounds) {
-                    if (b.contains(node.getCoor())) {
-                        isInsideOneBoundingBox = true;
-                        break;
-                    }
-                }
-
-                if (!isInsideOneBoundingBox) {
-                    int option = JOptionPane.showConfirmDialog(Main.parent,
-                            tr("The selected way(s) have nodes outside of the downloaded data region.\n"
-                                    + "This can lead to nodes being deleted accidentally.\n"
-                                    + "Are you really sure to continue?"),
-                            tr("Please abort if you are not sure"), JOptionPane.YES_NO_OPTION,
-                            JOptionPane.WARNING_MESSAGE);
-
-                    if (option != JOptionPane.YES_OPTION) return;
-                    askedAlready = true;
-                    break;
-                }
-            }
-
-            selWays[ways] = way;
-            ways++;
-        }
-
-        if (ways < 1) {
-            JOptionPane.showMessageDialog(Main.parent, tr("Please select at least one closed way the should be joined."));
-            return;
-        }
-
-        if(joinAreas(selWays[0], selWays[ways == 2 ? 1 : 0])) {
-            Main.map.mapView.repaint();
-            DataSet ds = Main.main.getCurrentDataSet();
-            ds.fireSelectionChanged();
-        } else
-            JOptionPane.showMessageDialog(Main.parent, tr("No intersection found. Nothing was changed."));
-    }
-
-
-    /**
-     * Will join two overlapping areas
-     * @param Way First way/area
-     * @param Way Second way/area
-     * @return boolean Whether to display the "no operation" message
-     */
-    private boolean joinAreas(Way a, Way b) {
-        // Fix self-overlapping first or other errors
-        boolean same = a.equals(b);
-        boolean hadChanges = false;
-        if(!same) {
-            if(checkForTagConflicts(a, b)) return true; // User aborted, so don't warn again
-            hadChanges = joinAreas(a, a);
-            hadChanges = joinAreas(b, b) || hadChanges;
-        }
-
-        ArrayList<OsmPrimitive> nodes = addIntersections(a, b);
-        if(nodes.size() == 0) return hadChanges;
-        commitCommands(marktr("Added node on all intersections"));
-
-        // Remove ways from all relations so ways can be combined/split quietly
-        ArrayList<RelationRole> relations = removeFromRelations(a);
-        if(!same) relations.addAll(removeFromRelations(b));
-
-        // Don't warn now, because it will really look corrupted
-        boolean warnAboutRelations = relations.size() > 0;
-
-        Collection<Way> allWays = splitWaysOnNodes(a, b, nodes);
-
-        // Find all nodes and inner ways save them to a list
-        Collection<Node> allNodes = getNodesFromWays(allWays);
-        Collection<Way> innerWays = findInnerWays(allWays, allNodes);
-
-        // Join outer ways
-        Way outerWay = joinOuterWays(allWays, innerWays);
-
-        // Fix Multipolygons if there are any
-        Collection<Way> newInnerWays = fixMultigons(innerWays, outerWay);
-
-        // Delete the remaining inner ways
-        if(innerWays != null && innerWays.size() > 0)
-            cmds.add(DeleteCommand.delete(Main.map.mapView.getEditLayer(), innerWays, true));
-        commitCommands(marktr("Delete Ways that are not part of an inner multipolygon"));
-
-        // We can attach our new multipolygon relation and pretend it has always been there
-        addOwnMultigonRelation(newInnerWays, outerWay, relations);
-        fixRelations(relations, outerWay);
-        commitCommands(marktr("Fix relations"));
-
-        stripTags(newInnerWays);
-        makeCommitsOneAction(
-            same
-                ? marktr("Joined self-overlapping area")
-                : marktr("Joined overlapping areas")
-        );
-
-        if(warnAboutRelations)
-            JOptionPane.showMessageDialog(Main.parent, tr("Some of the ways were part of relations that have been modified. Please verify no errors have been introduced."));
-
-        return true;
-    }
-
-    /**
-     * Checks if tags of two given ways differ, and presents the user a dialog to solve conflicts
-     * @param Way First way to check
-     * @param Way Second Way to check
-     * @return boolean True if not all conflicts could be resolved, False if everything's fine
-     */
-    private boolean checkForTagConflicts(Way a, Way b) {
-        ArrayList<Way> ways = new ArrayList<Way>();
-        ways.add(a);
-        ways.add(b);
-
-        // This is mostly copied and pasted from CombineWayAction.java and one day should be moved into tools
-        Map<String, Set<String>> props = new TreeMap<String, Set<String>>();
-        for (Way w : ways) {
-            for (Entry<String,String> e : w.entrySet()) {
-                if (!props.containsKey(e.getKey()))
-                    props.put(e.getKey(), new TreeSet<String>());
-                props.get(e.getKey()).add(e.getValue());
-            }
-        }
-
-        Way ax = new Way(a);
-        Way bx = new Way(b);
-
-        Map<String, JComboBox> components = new HashMap<String, JComboBox>();
-        JPanel p = new JPanel(new GridBagLayout());
-        for (Entry<String, Set<String>> e : props.entrySet()) {
-            if (TigerUtils.isTigerTag(e.getKey())) {
-                String combined = TigerUtils.combineTags(e.getKey(), e.getValue());
-                ax.put(e.getKey(), combined);
-                bx.put(e.getKey(), combined);
-            } else if (e.getValue().size() > 1) {
-                if("created_by".equals(e.getKey()))
-                {
-                    ax.put("created_by", "JOSM");
-                    bx.put("created_by", "JOSM");
-                } else {
-                    JComboBox c = new JComboBox(e.getValue().toArray());
-                    c.setEditable(true);
-                    p.add(new JLabel(e.getKey()), GBC.std());
-                    p.add(Box.createHorizontalStrut(10), GBC.std());
-                    p.add(c, GBC.eol());
-                    components.put(e.getKey(), c);
-                }
-            } else {
-                String val = e.getValue().iterator().next();
-                ax.put(e.getKey(), val);
-                bx.put(e.getKey(), val);
-            }
-        }
-
-        if (components.isEmpty())
-            return false; // No conflicts found
-
-        ExtendedDialog ed = new ExtendedDialog(Main.parent,
-        		tr("Enter values for all conflicts."),
-        		new String[] {tr("Solve Conflicts"), tr("Cancel")});
-        ed.setButtonIcons(new String[] {"dialogs/conflict.png", "cancel.png"});
-        ed.setContent(p);
-        ed.showDialog();
-
-        if (ed.getValue() != 1) return true; // user cancel, unresolvable conflicts
-
-        for (Entry<String, JComboBox> e : components.entrySet()) {
-            String val = e.getValue().getEditor().getItem().toString();
-            ax.put(e.getKey(), val);
-            bx.put(e.getKey(), val);
-        }
-
-        cmds.add(new ChangeCommand(a, ax));
-        cmds.add(new ChangeCommand(b, bx));
-        commitCommands(marktr("Fix tag conflicts"));
-        return false;
-    }
-
-    /**
-     * Will find all intersection and add nodes there for two given ways
-     * @param Way First way
-     * @param Way Second way
-     * @return ArrayList<OsmPrimitive> List of new nodes
-     */
-    private ArrayList<OsmPrimitive> addIntersections(Way a, Way b) {
-        boolean same = a.equals(b);
-        int nodesSizeA = a.getNodesCount();
-        int nodesSizeB = b.getNodesCount();
-
-        // We use OsmPrimitive here instead of Node because we later need to split a way at these nodes.
-        // With OsmPrimitve we can simply add the way and don't have to loop over the nodes
-        ArrayList<OsmPrimitive> nodes = new ArrayList<OsmPrimitive>();
-        ArrayList<NodeToSegs> nodesA = new ArrayList<NodeToSegs>();
-        ArrayList<NodeToSegs> nodesB = new ArrayList<NodeToSegs>();
-
-        for (int i = (same ? 1 : 0); i < nodesSizeA - 1; i++) {
-            for (int j = (same ? i + 2 : 0); j < nodesSizeB - 1; j++) {
-                // Avoid re-adding nodes that already exist on (some) intersections
-                if(a.getNode(i).equals(b.getNode(j)) || a.getNode(i+1).equals(b.getNode(j)))   {
-                    nodes.add(b.getNode(j));
-                    continue;
-                } else
-                if(a.getNode(i).equals(b.getNode(j+1)) || a.getNode(i+1).equals(b.getNode(j+1))) {
-                    nodes.add(b.getNode(j+1));
-                    continue;
-                }
-                LatLon intersection = getLineLineIntersection(
-                        a.getNode(i)  .getEastNorth().east(), a.getNode(i)  .getEastNorth().north(),
-                        a.getNode(i+1).getEastNorth().east(), a.getNode(i+1).getEastNorth().north(),
-                        b.getNode(j)  .getEastNorth().east(), b.getNode(j)  .getEastNorth().north(),
-                        b.getNode(j+1).getEastNorth().east(), b.getNode(j+1).getEastNorth().north());
-                if(intersection == null) continue;
-
-                // Create the node. Adding them to the ways must be delayed because we still loop over them
-                Node n = new Node(intersection);
-                cmds.add(new AddCommand(n));
-                nodes.add(n);
-                // The distance is needed to sort and add the nodes in direction of the way
-                nodesA.add(new NodeToSegs(i,  n, a.getNode(i).getCoor()));
-                if(same)
-                    nodesA.add(new NodeToSegs(j,  n, a.getNode(j).getCoor()));
-                else
-                    nodesB.add(new NodeToSegs(j,  n, b.getNode(j).getCoor()));
-            }
-        }
-
-        addNodesToWay(a, nodesA);
-        if(!same) addNodesToWay(b, nodesB);
-
-        return nodes;
-    }
-
-    /**
-     * Finds the intersection of two lines
-     * @return LatLon null if no intersection was found, the LatLon coordinates of the intersection otherwise
-     */
-    static private LatLon getLineLineIntersection(
-                double x1, double y1, double x2, double y2,
-                double x3, double y3, double x4, double y4) {
-
-        if (!Line2D.linesIntersect(x1, y1, x2, y2, x3, y3, x4, y4)) return null;
-
-        // Convert line from (point, point) form to ax+by=c
-        double a1 = y2 - y1;
-        double b1 = x1 - x2;
-        double c1 = x2*y1 - x1*y2;
-
-        double a2 = y4 - y3;
-        double b2 = x3 - x4;
-        double c2 = x4*y3 - x3*y4;
-
-        // Solve the equations
-        double det = a1*b2 - a2*b1;
-        if(det == 0) return null; // Lines are parallel
-
-        return Main.proj.eastNorth2latlon(new EastNorth(
-            (b1*c2 - b2*c1)/det,
-            (a2*c1 -a1*c2)/det
-        ));
-    }
-
-    /**
-     * Inserts given nodes with positions into the given ways
-     * @param Way The way to insert the nodes into
-     * @param Collection<NodeToSegs> The list of nodes with positions to insert
-     */
-    private void addNodesToWay(Way a, ArrayList<NodeToSegs> nodes) {
-        Way ax=new Way(a);
-        Collections.sort(nodes);
-
-        int numOfAdds = 1;
-        for(NodeToSegs n : nodes) {
-            ax.addNode(n.pos + numOfAdds, n.n);
-            numOfAdds++;
-        }
-
-        cmds.add(new ChangeCommand(a, ax));
-    }
-
-    /**
-     * Commits the command list with a description
-     * @param String The description of what the commands do
-     */
-    private void commitCommands(String description) {
-        switch(cmds.size()) {
-            case 0:
-                return;
-            case 1:
-                Main.main.undoRedo.add(cmds.getFirst());
-                break;
-            default:
-                Command c = new SequenceCommand(tr(description), cmds);
-                Main.main.undoRedo.add(c);
-                break;
-        }
-
-        cmds.clear();
-        cmdsCount++;
-    }
-
-    /**
-     * Removes a given OsmPrimitive from all relations
-     * @param OsmPrimitive Element to remove from all relations
-     * @return ArrayList<RelationRole> List of relations with roles the primitives was part of
-     */
-    private ArrayList<RelationRole> removeFromRelations(OsmPrimitive osm) {
-        ArrayList<RelationRole> result = new ArrayList<RelationRole>();
-        for (Relation r : Main.main.getCurrentDataSet().getRelations()) {
-            if (r.isDeleted() || r.incomplete) continue;
-            for (RelationMember rm : r.getMembers()) {
-                if (rm.getMember() != osm) continue;
-
-                Relation newRel = new Relation(r);
-                List<RelationMember> members = newRel.getMembers();
-                members.remove(rm);
-                newRel.setMembers(members);
-
-                cmds.add(new ChangeCommand(r, newRel));
-                RelationRole saverel =  new RelationRole(r, rm.getRole());
-                if(!result.contains(saverel)) result.add(saverel);
-                break;
-            }
-        }
-
-        commitCommands(marktr("Removed Element from Relations"));
-        return result;
-    }
-
-    /**
-     * This is a hacky implementation to make use of the splitWayAction code and
-     * should be improved. SplitWayAction needs to expose its splitWay function though.
-     */
-    private Collection<Way> splitWaysOnNodes(Way a, Way b, Collection<OsmPrimitive> nodes) {
-        ArrayList<Way> ways = new ArrayList<Way>();
-        ways.add(a);
-        if(!a.equals(b)) ways.add(b);
-
-        List<OsmPrimitive> affected = new ArrayList<OsmPrimitive>();
-        for (Way way : ways) {
-            nodes.add(way);
-            Main.main.getCurrentDataSet().setSelected(nodes);
-            nodes.remove(way);
-            new SplitWayAction().actionPerformed(null);
-            cmdsCount++;
-            affected.addAll(Main.main.getCurrentDataSet().getSelectedWays());
-        }
-        return osmprim2way(affected);
-    }
-
-    /**
-     * Converts a list of OsmPrimitives to a list of Ways
-     * @param Collection<OsmPrimitive> The OsmPrimitives list that's needed as a list of Ways
-     * @return Collection<Way> The list as list of Ways
-     */
-    static private Collection<Way> osmprim2way(Collection<OsmPrimitive> ways) {
-        Collection<Way> result = new ArrayList<Way>();
-        for(OsmPrimitive w: ways) {
-            if(w instanceof Way) result.add((Way) w);
-        }
-        return result;
-    }
-
-    /**
-     * Returns all nodes for given ways
-     * @param Collection<Way> The list of ways which nodes are to be returned
-     * @return Collection<Node> The list of nodes the ways contain
-     */
-    private Collection<Node> getNodesFromWays(Collection<Way> ways) {
-        Collection<Node> allNodes = new ArrayList<Node>();
-        for(Way w: ways) allNodes.addAll(w.getNodes());
-        return allNodes;
-    }
-
-    /**
-     * Finds all inner ways for a given list of Ways and Nodes from a multigon by constructing a polygon
-     * for each way, looking for inner nodes that are not part of this way. If a node is found, all ways
-     * containing this node are added to the list
-     * @param Collection<Way> A list of (splitted) ways that form a multigon
-     * @param Collection<Node> A list of nodes that belong to the multigon
-     * @return Collection<Way> A list of ways that are positioned inside the outer borders of the multigon
-     */
-    private Collection<Way> findInnerWays(Collection<Way> multigonWays, Collection<Node> multigonNodes) {
-        Collection<Way> innerWays = new ArrayList<Way>();
-        for(Way w: multigonWays) {
-            Polygon poly = new Polygon();
-            for(Node n: (w).getNodes()) poly.addPoint(latlonToXY(n.getCoor().lat()), latlonToXY(n.getCoor().lon()));
-
-            for(Node n: multigonNodes) {
-                if(!(w).containsNode(n) && poly.contains(latlonToXY(n.getCoor().lat()), latlonToXY(n.getCoor().lon()))) {
-                    getWaysByNode(innerWays, multigonWays, n);
-                }
-            }
-        }
-
-        return innerWays;
-    }
-
-    // Polygon only supports int coordinates, so convert them
-    private int latlonToXY(double val) {
-        return (int)Math.round(val*1000000);
-    }
-
-    /**
-     * Finds all ways that contain the given node.
-     * @param Collection<Way> A list to which matching ways will be added
-     * @param Collection<Way> A list of ways to check
-     * @param Node The node the ways should be checked against
-     */
-    private void getWaysByNode(Collection<Way> innerWays, Collection<Way> w, Node n) {
-        for(Way way : w) {
-            if(!(way).containsNode(n)) continue;
-            if(!innerWays.contains(way)) innerWays.add(way); // Will need this later for multigons
-        }
-    }
-
-    /**
-     * Joins the two outer ways and deletes all short ways that can't be part of a multipolygon anyway
-     * @param Collection<OsmPrimitive> The list of all ways that belong to that multigon
-     * @param Collection<Way> The list of inner ways that belong to that multigon
-     * @return Way The newly created outer way
-     */
-    private Way joinOuterWays(Collection<Way> multigonWays, Collection<Way> innerWays) {
-        ArrayList<Way> join = new ArrayList<Way>();
-        for(Way w: multigonWays) {
-            // Skip inner ways
-            if(innerWays.contains(w)) continue;
-
-            if(w.getNodesCount() <= 2)
-                cmds.add(new DeleteCommand(w));
-            else
-                join.add(w);
-        }
-
-        commitCommands(marktr("Join Areas: Remove Short Ways"));
-        return closeWay(joinWays(join));
-    }
-
-    /**
-     * Ensures a way is closed. If it isn't, last and first node are connected.
-     * @param Way the way to ensure it's closed
-     * @return Way The joined way.
-     */
-    private Way closeWay(Way w) {
-        if(w.isClosed())
-            return w;
-        Main.main.getCurrentDataSet().setSelected(w);
-        Way wnew = new Way(w);
-        wnew.addNode(wnew.firstNode());
-        cmds.add(new ChangeCommand(w, wnew));
-        commitCommands(marktr("Closed Way"));
-        return (Way)(Main.main.getCurrentDataSet().getSelectedWays().toArray())[0];
-    }
-
-    /**
-     * Joins a list of ways (using CombineWayAction and ReverseWayAction if necessary to quiet the former)
-     * @param ArrayList<Way> The list of ways to join
-     * @return Way The newly created way
-     */
-    private Way joinWays(ArrayList<Way> ways) {
-        if(ways.size() < 2) return ways.get(0);
-
-        // This will turn ways so all of them point in the same direction and CombineAction won't bug
-        // the user about this.
-        Way a = null;
-        for(Way b : ways) {
-            if(a == null) {
-                a = b;
-                continue;
-            }
-            if(a.getNode(0).equals(b.getNode(0)) ||
-               a.getNode(a.getNodesCount()-1).equals(b.getNode(b.getNodesCount()-1))) {
-                Main.main.getCurrentDataSet().setSelected(b);
-                new ReverseWayAction().actionPerformed(null);
-                cmdsCount++;
-            }
-            a = b;
-        }
-        Main.main.getCurrentDataSet().setSelected(ways);
-        // TODO: It might be possible that a confirmation dialog is presented even after reversing (for
-        // "strange" ways). If the user cancels this, makeCommitsOneAction will wrongly consume a previous
-        // action. Make CombineWayAction either silent or expose its combining capabilities.
-        new CombineWayAction().actionPerformed(null);
-        cmdsCount++;
-        return (Way)(Main.main.getCurrentDataSet().getSelectedWays().toArray())[0];
-    }
-
-    /**
-     * Finds all ways that may be part of a multipolygon relation and removes them from the given list.
-     * It will automatically combine "good" ways
-     * @param Collection<Way> The list of inner ways to check
-     * @param Way The newly created outer way
-     * @return ArrayList<Way> The List of newly created inner ways
-     */
-    private ArrayList<Way> fixMultigons(Collection<Way> uninterestingWays, Way outerWay) {
-        Collection<Node> innerNodes = getNodesFromWays(uninterestingWays);
-        Collection<Node> outerNodes = outerWay.getNodes();
-
-        // The newly created inner ways. uninterestingWays is passed by reference and therefore modified in-place
-        ArrayList<Way> newInnerWays = new ArrayList<Way>();
-
-        // Now we need to find all inner ways that contain a remaining node, but no outer nodes
-        // Remaining nodes are those that contain to more than one way. All nodes that belong to an
-        // inner multigon part will have at least two ways, so we can use this to find which ways do
-        // belong to the multigon.
-        ArrayList<Way> possibleWays = new ArrayList<Way>();
-        wayIterator: for(Way w : uninterestingWays) {
-            boolean hasInnerNodes = false;
-            for(Node n : w.getNodes()) {
-                if(outerNodes.contains(n)) continue wayIterator;
-                if(!hasInnerNodes && innerNodes.contains(n)) hasInnerNodes = true;
-            }
-            if(!hasInnerNodes || w.getNodesCount() < 2) continue;
-            possibleWays.add(w);
-        }
-
-        // This removes unnecessary ways that might have been added.
-        removeAlmostAlikeWays(possibleWays);
-        removePartlyUnconnectedWays(possibleWays);
-
-        // Join all ways that have one start/ending node in common
-        Way joined = null;
-        outerIterator: do {
-            joined = null;
-            for(Way w1 : possibleWays) {
-                if(w1.isClosed()) {
-                    if(!wayIsCollapsed(w1)) {
-                        uninterestingWays.remove(w1);
-                        newInnerWays.add(w1);
-                    }
-                    joined = w1;
-                    possibleWays.remove(w1);
-                    continue outerIterator;
-                }
-                for(Way w2 : possibleWays) {
-                    // w2 cannot be closed, otherwise it would have been removed above
-                    if(!waysCanBeCombined(w1, w2)) continue;
-
-                    ArrayList<Way> joinThem = new ArrayList<Way>();
-                    joinThem.add(w1);
-                    joinThem.add(w2);
-                    uninterestingWays.removeAll(joinThem);
-                    possibleWays.removeAll(joinThem);
-
-                    // Although we joined the ways, we cannot simply assume that they are closed
-                    joined = joinWays(joinThem);
-                    uninterestingWays.add(joined);
-                    possibleWays.add(joined);
-                    continue outerIterator;
-                }
-            }
-        } while(joined != null);
-        return newInnerWays;
-    }
-
-    /**
-     * Removes almost alike ways (= ways that are on top of each other for all nodes)
-     * @param ArrayList<Way> the ways to remove almost-duplicates from
-     */
-    private void removeAlmostAlikeWays(ArrayList<Way> ways) {
-        Collection<Way> removables = new ArrayList<Way>();
-        outer: for(int i=0; i < ways.size(); i++) {
-            Way a = ways.get(i);
-            for(int j=i+1; j < ways.size(); j++) {
-                Way b = ways.get(j);
-                List<Node> revNodes = new ArrayList<Node>(b.getNodes());
-                Collections.reverse(revNodes);
-                if(a.getNodes().equals(b.getNodes()) || a.getNodes().equals(revNodes)) {
-                    removables.add(a);
-                    continue outer;
-                }
-            }
-        }
-        ways.removeAll(removables);
-    }
-
-    /**
-     * Removes ways from the given list whose starting or ending node doesn't
-     * connect to other ways from the same list (it's like removing spikes).
-     * @param ArrayList<Way> The list of ways to remove "spikes" from
-     */
-    private void removePartlyUnconnectedWays(ArrayList<Way> ways) {
-        List<Way> removables = new ArrayList<Way>();
-        for(Way a : ways) {
-            if(a.isClosed()) continue;
-            boolean connectedStart = false;
-            boolean connectedEnd = false;
-            for(Way b : ways) {
-                if(a.equals(b))
-                    continue;
-                if(b.isFirstLastNode(a.firstNode()))
-                    connectedStart = true;
-                if(b.isFirstLastNode(a.lastNode()))
-                    connectedEnd = true;
-            }
-            if(!connectedStart || !connectedEnd)
-                removables.add(a);
-        }
-        ways.removeAll(removables);
-    }
-
-    /**
-     * Checks if a way is collapsed (i.e. looks like <---->)
-     * @param Way A *closed* way to check if it is collapsed
-     * @return boolean If the closed way is collapsed or not
-     */
-    private boolean wayIsCollapsed(Way w) {
-        if(w.getNodesCount() <= 3) return true;
-
-        // If a way contains more than one node twice, it must be collapsed (only start/end node may be the same)
-        Way x = new Way(w);
-        int count = 0;
-        for(Node n : w.getNodes()) {
-            x.removeNode(n);
-            if(x.containsNode(n)) count++;
-            if(count == 2) return true;
-        }
-        return false;
-    }
-
-    /**
-     * Checks if two ways share one starting/ending node
-     * @param Way first way
-     * @param Way second way
-     * @return boolean Wheter the ways share a starting/ending node or not
-     */
-    private boolean waysCanBeCombined(Way w1, Way w2) {
-        if(w1.equals(w2)) return false;
-
-        if(w1.getNode(0).equals(w2.getNode(0))) return true;
-        if(w1.getNode(0).equals(w2.getNode(w2.getNodesCount()-1))) return true;
-
-        if(w1.getNode(w1.getNodesCount()-1).equals(w2.getNode(0))) return true;
-        if(w1.getNode(w1.getNodesCount()-1).equals(w2.getNode(w2.getNodesCount()-1))) return true;
-
-        return false;
-    }
-
-    /**
-     * Will add own multipolygon relation to the "previously existing" relations. Fixup is done by fixRelations
-     * @param Collection<Way> List of already closed inner ways
-     * @param Way The outer way
-     * @param ArrayList<RelationRole> The list of relation with roles to add own relation to
-     */
-    private void addOwnMultigonRelation(Collection<Way> inner, Way outer, ArrayList<RelationRole> rels) {
-        if(inner.size() == 0) return;
-        // Create new multipolygon relation and add all inner ways to it
-        Relation newRel = new Relation();
-        newRel.put("type", "multipolygon");
-        for(Way w : inner)
-            newRel.addMember(new RelationMember("inner", w));
-        cmds.add(new AddCommand(newRel));
-
-        // We don't add outer to the relation because it will be handed to fixRelations()
-        // which will then do the remaining work. Collections are passed by reference, so no
-        // need to return it
-        rels.add(new RelationRole(newRel, "outer"));
-        //return rels;
-    }
-
-    /**
-     * Adds the previously removed relations again to the outer way. If there are multiple multipolygon
-     * relations where the joined areas were in "outer" role a new relation is created instead with all
-     * members of both. This function depends on multigon relations to be valid already, it won't fix them.
-     * @param ArrayList<RelationRole> List of relations with roles the (original) ways were part of
-     * @param Way The newly created outer area/way
-     */
-    private void fixRelations(ArrayList<RelationRole> rels, Way outer) {
-        ArrayList<RelationRole> multiouters = new ArrayList<RelationRole>();
-        for(RelationRole r : rels) {
-            if( r.rel.get("type") != null &&
-                r.rel.get("type").equalsIgnoreCase("multipolygon") &&
-                r.role.equalsIgnoreCase("outer")
-              ) {
-                multiouters.add(r);
-                continue;
-            }
-            // Add it back!
-            Relation newRel = new Relation(r.rel);
-            newRel.addMember(new RelationMember(r.role, outer));
-            cmds.add(new ChangeCommand(r.rel, newRel));
-        }
-
-        Relation newRel = null;
-        switch(multiouters.size()) {
-            case 0:
-                return;
-            case 1:
-                // Found only one to be part of a multipolygon relation, so just add it back as well
-                newRel = new Relation(multiouters.get(0).rel);
-                newRel.addMember(new RelationMember(multiouters.get(0).role, outer));
-                cmds.add(new ChangeCommand(multiouters.get(0).rel, newRel));
-                return;
-            default:
-                // Create a new relation with all previous members and (Way)outer as outer.
-                newRel = new Relation();
-                for(RelationRole r : multiouters) {
-                    // Add members
-                    for(RelationMember rm : r.rel.getMembers())
-                        if(!newRel.getMembers().contains(rm)) newRel.addMember(rm);
-                    // Add tags
-                    for (String key : r.rel.keySet()) {
-                        newRel.put(key, r.rel.get(key));
-                    }
-                    // Delete old relation
-                    cmds.add(new DeleteCommand(r.rel));
-                }
-                newRel.addMember(new RelationMember("outer", outer));
-                cmds.add(new AddCommand(newRel));
-        }
-    }
-
-    /**
-     * @param Collection<Way> The List of Ways to remove all tags from
-     */
-    private void stripTags(Collection<Way> ways) {
-        for(Way w: ways) stripTags(w);
-        commitCommands(marktr("Remove tags from inner ways"));
-    }
-
-    /**
-     * @param Way The Way to remove all tags from
-     */
-    private void stripTags(Way x) {
-        if(x.getKeys() == null) return;
-        Way y = new Way(x);
-        for (String key : x.keySet())
-            y.remove(key);
-        cmds.add(new ChangeCommand(x, y));
-    }
-
-    /**
-     * Takes the last cmdsCount actions back and combines them into a single action
-     * (for when the user wants to undo the join action)
-     * @param String The commit message to display
-     */
-    private void makeCommitsOneAction(String message) {
-        UndoRedoHandler ur = Main.main.undoRedo;
-        cmds.clear();
-        int i = Math.max(ur.commands.size() - cmdsCount, 0);
-        for(; i < ur.commands.size(); i++)
-            cmds.add(ur.commands.get(i));
-
-        for(i = 0; i < cmds.size(); i++)
-            ur.undo();
-
-        commitCommands(message == null ? marktr("Join Areas Function") : message);
-        cmdsCount = 0;
-    }
-}
diff --git a/utilsplugin/src/UtilsPlugin/JumpToAction.java b/utilsplugin/src/UtilsPlugin/JumpToAction.java
deleted file mode 100644
index b2dfb26..0000000
--- a/utilsplugin/src/UtilsPlugin/JumpToAction.java
+++ /dev/null
@@ -1,179 +0,0 @@
-package UtilsPlugin;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.BorderLayout;
-import java.awt.GridBagLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.KeyEvent;
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseListener;
-
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JTextField;
-import javax.swing.event.DocumentEvent;
-import javax.swing.event.DocumentListener;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.JosmAction;
-import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.gui.MapView;
-import org.openstreetmap.josm.tools.GBC;
-import org.openstreetmap.josm.tools.OsmUrlToBounds;
-import org.openstreetmap.josm.tools.Shortcut;
-
-public class JumpToAction extends JosmAction implements MouseListener {
-    public JumpToAction() {
-        super(tr("Jump To Position"), null, tr("Opens a dialog that allows to jump to a specific location"), Shortcut.registerShortcut("tools:jumpto", tr("Tool: {0}", tr("Jump To Position")),
-        KeyEvent.VK_G, Shortcut.GROUP_HOTKEY), true);
-    }
-
-    private JTextField url = new JTextField();
-    private JTextField lat = new JTextField();
-    private JTextField lon = new JTextField();
-    private JTextField zm = new JTextField();
-
-    private double zoomFactor = 0;
-    public void showJumpToDialog() {
-        MapView mv = Main.map.mapView;
-        LatLon curPos=mv.getProjection().eastNorth2latlon(mv.getCenter());
-        lat.setText(java.lang.Double.toString(curPos.lat()));
-        lon.setText(java.lang.Double.toString(curPos.lon()));
-
-        double dist = mv.getDist100Pixel();
-        zoomFactor = 1/dist;
-
-        zm.setText(java.lang.Long.toString(Math.round(dist*100)/100));
-        updateUrl(true);
-
-        JPanel panel = new JPanel(new BorderLayout());
-        panel.add(new JLabel("<html>"
-                              + tr("Enter Lat/Lon to jump to position.")
-                              + "<br>"
-                              + tr("You can also paste an URL from www.openstreetmap.org")
-                              + "<br>"
-                              + "</html>"),
-                  BorderLayout.NORTH);
-
-        class osmURLListener implements DocumentListener {
-            public void changedUpdate(DocumentEvent e) { parseURL(); }
-            public void insertUpdate(DocumentEvent e) { parseURL(); }
-            public void removeUpdate(DocumentEvent e) { parseURL(); }
-        }
-
-        class osmLonLatListener implements DocumentListener {
-            public void changedUpdate(DocumentEvent e) { updateUrl(false); }
-            public void insertUpdate(DocumentEvent e) { updateUrl(false); }
-            public void removeUpdate(DocumentEvent e) { updateUrl(false); }
-        }
-
-        osmLonLatListener x=new osmLonLatListener();
-        lat.getDocument().addDocumentListener(x);
-        lon.getDocument().addDocumentListener(x);
-        zm.getDocument().addDocumentListener(x);
-        url.getDocument().addDocumentListener(new osmURLListener());
-
-        JPanel p = new JPanel(new GridBagLayout());
-        panel.add(p, BorderLayout.NORTH);
-
-        p.add(new JLabel(tr("Latitude")), GBC.eol());
-        p.add(lat, GBC.eol().fill(GBC.HORIZONTAL));
-
-        p.add(new JLabel(tr("Longitude")), GBC.eol());
-        p.add(lon, GBC.eol().fill(GBC.HORIZONTAL));
-
-        p.add(new JLabel(tr("Zoom (in metres)")), GBC.eol());
-        p.add(zm, GBC.eol().fill(GBC.HORIZONTAL));
-
-        p.add(new JLabel(tr("URL")), GBC.eol());
-        p.add(url, GBC.eol().fill(GBC.HORIZONTAL));
-
-        Object[] buttons = { tr("Jump there"), tr("Cancel") };
-        LatLon ll = null;
-        double zoomLvl = 100;
-        while(ll == null) {
-            int option = JOptionPane.showOptionDialog(
-                            Main.parent,
-                            panel,
-                            tr("Jump to Position"),
-                            JOptionPane.OK_CANCEL_OPTION,
-                            JOptionPane.PLAIN_MESSAGE,
-                            null,
-                            buttons,
-                            buttons[0]);
-
-            if (option != JOptionPane.OK_OPTION) return;
-            try {
-                zoomLvl = Double.parseDouble(zm.getText());
-                ll = new LatLon(Double.parseDouble(lat.getText()), Double.parseDouble(lon.getText()));
-            } catch (Exception ex) {
-                JOptionPane.showMessageDialog(Main.parent, tr("Could not parse Latitude, Longitude or Zoom. Please check."), tr("Unable to parse Lon/Lat"), JOptionPane.ERROR_MESSAGE);
-            }
-        }
-
-        mv.zoomToFactor(mv.getProjection().latlon2eastNorth(ll), zoomFactor * zoomLvl);
-    }
-
-    private void parseURL() {
-        if(!url.hasFocus()) return;
-        Bounds b = OsmUrlToBounds.parse(url.getText());
-        if (b != null) {
-            lat.setText(Double.toString((b.getMin().lat() + b.getMax().lat())/2));
-            lon.setText(Double.toString((b.getMin().lon() + b.getMax().lon())/2));
-
-            int zoomLvl = 16;
-            String[] args = url.getText().substring(url.getText().indexOf('?')+1).split("&");
-            for (String arg : args) {
-                int eq = arg.indexOf('=');
-                if (eq == -1 || !arg.substring(0, eq).equalsIgnoreCase("zoom")) continue;
-
-                zoomLvl = Integer.parseInt(arg.substring(eq + 1));
-                break;
-            }
-
-            // 10 000 000 = 10 000 * 1000 = World * (km -> m)
-            zm.setText(Double.toString(Math.round(10000000 * Math.pow(2, (-1) * zoomLvl))));
-        }
-    }
-
-    private void updateUrl(boolean force) {
-        if(!lat.hasFocus() && !lon.hasFocus() && !zm.hasFocus() && !force) return;
-        try {
-            double dlat = Double.parseDouble(lat.getText());
-            double dlon = Double.parseDouble(lon.getText());
-            double m = Double.parseDouble(zm.getText());
-            // Inverse function to the one above. 18 is the current maximum zoom
-            // available on standard renderers, so choose this is in case m
-            // should be zero
-            int zoomLvl = 18;
-            if(m > 0)
-            	zoomLvl = (int)Math.round((-1) * Math.log(m/10000000)/Math.log(2));
-            
-            int decimals = (int) Math.pow(10, (zoomLvl / 3));
-            dlat = Math.round(dlat * decimals);
-            dlat /= decimals;
-            dlon = Math.round(dlon * decimals);
-            dlon /= decimals;
-            url.setText("http://www.openstreetmap.org/?lat="+dlat+"&lon="+dlon+"&zoom="+zoomLvl);
-        } catch (NumberFormatException x) {}
-    }
-
-    public void actionPerformed(ActionEvent e) {
-        showJumpToDialog();
-    }
-
-    public void mousePressed(MouseEvent e) {}
-
-    public void mouseReleased(MouseEvent e) {}
-
-    public void mouseEntered(MouseEvent e) {}
-
-    public void mouseExited(MouseEvent e) {}
-
-    public void mouseClicked(MouseEvent e) {
-        showJumpToDialog();
-    }
-}
diff --git a/utilsplugin/src/UtilsPlugin/SimplifyWayAction.java b/utilsplugin/src/UtilsPlugin/SimplifyWayAction.java
deleted file mode 100644
index d821577..0000000
--- a/utilsplugin/src/UtilsPlugin/SimplifyWayAction.java
+++ /dev/null
@@ -1,205 +0,0 @@
-package UtilsPlugin;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-import static org.openstreetmap.josm.tools.I18n.trn;
-
-import java.awt.event.ActionEvent;
-import java.awt.event.KeyEvent;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-
-import javax.swing.JOptionPane;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.JosmAction;
-import org.openstreetmap.josm.command.ChangeCommand;
-import org.openstreetmap.josm.command.Command;
-import org.openstreetmap.josm.command.DeleteCommand;
-import org.openstreetmap.josm.command.SequenceCommand;
-import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.osm.DataSource;
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.data.osm.visitor.CollectBackReferencesVisitor;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.tools.Shortcut;
-
-public class SimplifyWayAction extends JosmAction {
-    public SimplifyWayAction() {
-        super(tr("Simplify Way"), "simplify", tr("Delete unnecessary nodes from a way."), Shortcut.registerShortcut("tools:simplify", tr("Tool: {0}", tr("Simplify Way")),
-        KeyEvent.VK_Y, Shortcut.GROUP_EDIT, Shortcut.SHIFT_DEFAULT), true);
-    }
-
-    public void actionPerformed(ActionEvent e) {
-        Collection<OsmPrimitive> selection = Main.main.getCurrentDataSet().getSelected();
-
-        int ways = 0;
-        LinkedList<Bounds> bounds = new LinkedList<Bounds>();
-        OsmDataLayer dataLayer = Main.map.mapView.getEditLayer();
-        for (DataSource ds : dataLayer.data.dataSources) {
-            if (ds.bounds != null)
-                bounds.add(ds.bounds);
-        }
-        for (OsmPrimitive prim : selection) {
-            if (prim instanceof Way) {
-                if (bounds.size() > 0) {
-                    Way way = (Way) prim;
-                    // We check if each node of each way is at least in one download
-                    // bounding box. Otherwise nodes may get deleted that are necessary by
-                    // unloaded ways (see Ticket #1594)
-                    for (Node node : way.getNodes()) {
-                        boolean isInsideOneBoundingBox = false;
-                        for (Bounds b : bounds) {
-                            if (b.contains(node.getCoor())) {
-                                isInsideOneBoundingBox = true;
-                                break;
-                            }
-                        }
-                        if (!isInsideOneBoundingBox) {
-                            int option = JOptionPane.showConfirmDialog(Main.parent,
-                                    tr("The selected way(s) have nodes outside of the downloaded data region.\n"
-                                            + "This can lead to nodes being deleted accidentally.\n"
-                                            + "Are you really sure to continue?"),
-                                    tr("Please abort if you are not sure"), JOptionPane.YES_NO_CANCEL_OPTION,
-                                    JOptionPane.WARNING_MESSAGE);
-
-                            if (option != JOptionPane.YES_OPTION)
-                                return;
-                            break;
-                        }
-                    }
-                }
-
-                ways++;
-            }
-        }
-
-        if (ways == 0) {
-            JOptionPane.showMessageDialog(Main.parent, tr("Please select at least one way to simplify."));
-            return;
-        } else if (ways > 10) {
-            //TRANSLATION: Although for English the use of trn is needless it is important for other languages
-            int option = JOptionPane.showConfirmDialog(Main.parent, trn(
-                    "The selection contains {0} way. Are you sure you want to simplify it?",
-                    "The selection contains {0} ways. Are you sure you want to simplify them all?",
-                    ways,ways),
-                    tr("Are you sure?"), JOptionPane.YES_NO_OPTION);
-            if (option != JOptionPane.YES_OPTION)
-                return;
-        }
-
-        for (OsmPrimitive prim : selection) {
-            if (prim instanceof Way) {
-                simplifyWay((Way) prim);
-            }
-        }
-    }
-
-    public void simplifyWay(Way w) {
-        double threshold = Double.parseDouble(Main.pref.get("simplify-way.max-error", "3"));
-
-        Way wnew = new Way(w);
-
-        int toI = wnew.getNodesCount() - 1;
-        for (int i = wnew.getNodesCount() - 1; i >= 0; i--) {
-            CollectBackReferencesVisitor backRefsV = new CollectBackReferencesVisitor(Main.main.getCurrentDataSet(), false);
-            backRefsV.visit(wnew.getNode(i));
-            boolean used = false;
-            if (backRefsV.getData().size() == 1) {
-                used = Collections.frequency(w.getNodes(), wnew.getNode(i)) > 1;
-            } else {
-                backRefsV.getData().remove(w);
-                used = !backRefsV.getData().isEmpty();
-            }
-            if (!used)
-                used = wnew.getNode(i).isTagged();
-
-            if (used) {
-                simplifyWayRange(wnew, i, toI, threshold);
-                toI = i;
-            }
-        }
-        simplifyWayRange(wnew, 0, toI, threshold);
-
-        HashSet<Node> delNodes = new HashSet<Node>();
-        delNodes.addAll(w.getNodes());
-        delNodes.removeAll(wnew.getNodes());
-
-        if (wnew.getNodesCount() != w.getNodesCount()) {
-            Collection<Command> cmds = new LinkedList<Command>();
-            cmds.add(new ChangeCommand(w, wnew));
-            cmds.add(new DeleteCommand(delNodes));
-            Main.main.undoRedo.add(new SequenceCommand(trn("Simplify Way (remove {0} node)", "Simplify Way (remove {0} nodes)", delNodes.size(), delNodes.size()), cmds));
-            Main.map.repaint();
-        }
-    }
-
-    public void simplifyWayRange(Way wnew, int from, int to, double thr) {
-        if (to - from >= 2) {
-            ArrayList<Node> ns = new ArrayList<Node>();
-            simplifyWayRange(wnew, from, to, ns, thr);
-            List<Node> nodes = wnew.getNodes();
-            for (int j = to - 1; j > from; j--) {            	
-            	nodes.remove(j);            	
-            }            
-            nodes.addAll(from + 1, ns);
-            wnew.setNodes(nodes);
-        }
-    }
-
-    /*
-     * Takes an interval [from,to] and adds nodes from (from,to) to ns.
-     * (from and to are indices of wnew.nodes.)
-     */
-    public void simplifyWayRange(Way wnew, int from, int to, ArrayList<Node> ns, double thr) {
-        Node fromN = wnew.getNode(from), toN = wnew.getNode(to);
-
-        int imax = -1;
-        double xtemax = 0;
-        for (int i = from + 1; i < to; i++) {
-            Node n = wnew.getNode(i);
-            double xte = Math.abs(EARTH_RAD
-                    * xtd(fromN.getCoor().lat() * Math.PI / 180, fromN.getCoor().lon() * Math.PI / 180, toN.getCoor().lat() * Math.PI
-                            / 180, toN.getCoor().lon() * Math.PI / 180, n.getCoor().lat() * Math.PI / 180, n.getCoor().lon() * Math.PI
-                            / 180));
-            if (xte > xtemax) {
-                xtemax = xte;
-                imax = i;
-            }
-        }
-
-        if (imax != -1 && xtemax >= thr) {
-            simplifyWayRange(wnew, from, imax, ns, thr);
-            ns.add(wnew.getNode(imax));
-            simplifyWayRange(wnew, imax, to, ns, thr);
-        }
-    }
-
-    public static double EARTH_RAD = 6378137.0;
-
-    /* From Aviaton Formulary v1.3
-     * http://williams.best.vwh.net/avform.htm
-     */
-    public static double dist(double lat1, double lon1, double lat2, double lon2) {
-        return 2 * Math.asin(Math.sqrt(Math.pow(Math.sin((lat1 - lat2) / 2), 2) + Math.cos(lat1) * Math.cos(lat2)
-                * Math.pow(Math.sin((lon1 - lon2) / 2), 2)));
-    }
-
-    public static double course(double lat1, double lon1, double lat2, double lon2) {
-        return Math.atan2(Math.sin(lon1 - lon2) * Math.cos(lat2), Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1)
-                * Math.cos(lat2) * Math.cos(lon1 - lon2))
-                % (2 * Math.PI);
-    }
-
-    public static double xtd(double lat1, double lon1, double lat2, double lon2, double lat3, double lon3) {
-        double dist_AD = dist(lat1, lon1, lat3, lon3);
-        double crs_AD = course(lat1, lon1, lat3, lon3);
-        double crs_AB = course(lat1, lon1, lat2, lon2);
-        return Math.asin(Math.sin(dist_AD) * Math.sin(crs_AD - crs_AB));
-    }
-}
diff --git a/utilsplugin/src/UtilsPlugin/UtilsPlugin.java b/utilsplugin/src/UtilsPlugin/UtilsPlugin.java
deleted file mode 100644
index 2456ff6..0000000
--- a/utilsplugin/src/UtilsPlugin/UtilsPlugin.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package UtilsPlugin;
-
-import javax.swing.JMenuItem;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.gui.MainMenu;
-import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.plugins.Plugin;
-
-public class UtilsPlugin extends Plugin {
-    JMenuItem SimplifyWay;
-    JMenuItem JoinAreas;
-    JumpToAction JumpToAct = new JumpToAction();
-
-    public UtilsPlugin() {
-        SimplifyWay = MainMenu.add(Main.main.menu.toolsMenu, new SimplifyWayAction());
-        JoinAreas = MainMenu.add(Main.main.menu.toolsMenu, new JoinAreasAction());
-        SimplifyWay.setEnabled(false);
-    }
-
-    @Override
-    public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
-        if (oldFrame == null && newFrame != null) {
-            SimplifyWay.setEnabled(true);
-            JoinAreas.setEnabled(true);
-            newFrame.statusLine.addMouseListener(JumpToAct);
-        }
-    }
-}
diff --git a/validator/.classpath b/validator/.classpath
deleted file mode 100644
index 875df1c..0000000
--- a/validator/.classpath
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry kind="src" path="src"/>
-	<classpathentry including="images/" kind="src" path=""/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JDK 5"/>
-	<classpathentry combineaccessrules="false" kind="src" path="/JOSM"/>
-	<classpathentry kind="output" path="build"/>
-</classpath>
diff --git a/validator/.project b/validator/.project
deleted file mode 100644
index f56e39f..0000000
--- a/validator/.project
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>validator</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>
diff --git a/validator/.settings/org.eclipse.core.resources.prefs b/validator/.settings/org.eclipse.core.resources.prefs
deleted file mode 100644
index 2ffd7fc..0000000
--- a/validator/.settings/org.eclipse.core.resources.prefs
+++ /dev/null
@@ -1,3 +0,0 @@
-#Sun Sep 07 16:25:44 CEST 2008
-eclipse.preferences.version=1
-encoding/<project>=UTF-8
diff --git a/validator/.settings/org.eclipse.jdt.core.prefs b/validator/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index 19195a5..0000000
--- a/validator/.settings/org.eclipse.jdt.core.prefs
+++ /dev/null
@@ -1,258 +0,0 @@
-#Fri Jun 26 21:35:48 CEST 2009
-eclipse.preferences.version=1
-org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
-org.eclipse.jdt.core.formatter.alignment_for_assignment=0
-org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
-org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
-org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
-org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
-org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
-org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
-org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
-org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
-org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
-org.eclipse.jdt.core.formatter.blank_lines_after_package=1
-org.eclipse.jdt.core.formatter.blank_lines_before_field=0
-org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
-org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
-org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
-org.eclipse.jdt.core.formatter.blank_lines_before_method=1
-org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
-org.eclipse.jdt.core.formatter.blank_lines_before_package=0
-org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
-org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
-org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
-org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
-org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
-org.eclipse.jdt.core.formatter.comment.format_block_comments=false
-org.eclipse.jdt.core.formatter.comment.format_header=false
-org.eclipse.jdt.core.formatter.comment.format_html=false
-org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=false
-org.eclipse.jdt.core.formatter.comment.format_line_comments=false
-org.eclipse.jdt.core.formatter.comment.format_source_code=false
-org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
-org.eclipse.jdt.core.formatter.comment.indent_root_tags=false
-org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=do not insert
-org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
-org.eclipse.jdt.core.formatter.comment.line_length=100
-org.eclipse.jdt.core.formatter.compact_else_if=true
-org.eclipse.jdt.core.formatter.continuation_indentation=2
-org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
-org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
-org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
-org.eclipse.jdt.core.formatter.indent_empty_lines=false
-org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
-org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
-org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
-org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
-org.eclipse.jdt.core.formatter.indentation.size=4
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
-org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
-org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
-org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
-org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
-org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
-org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
-org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
-org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
-org.eclipse.jdt.core.formatter.lineSplit=120
-org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
-org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
-org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
-org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
-org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
-org.eclipse.jdt.core.formatter.tabulation.char=space
-org.eclipse.jdt.core.formatter.tabulation.size=4
-org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
-org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
diff --git a/validator/.settings/org.eclipse.jdt.ui.prefs b/validator/.settings/org.eclipse.jdt.ui.prefs
deleted file mode 100644
index dc5d284..0000000
--- a/validator/.settings/org.eclipse.jdt.ui.prefs
+++ /dev/null
@@ -1,4 +0,0 @@
-#Sun Sep 07 16:57:55 CEST 2008
-eclipse.preferences.version=1
-formatter_profile=_JOSM
-formatter_settings_version=11
diff --git a/validator/CONTRIBUTION b/validator/CONTRIBUTION
deleted file mode 100644
index 68a744b..0000000
--- a/validator/CONTRIBUTION
+++ /dev/null
@@ -1,5 +0,0 @@
-The validator plugin was originally designed and coded by Francisco R. Santos 
-<frsantos at gmail.com>, with many modifications by Gabriel Ebner 
-<ge at gabrielebner.at>, Joerg Ostertag <openstreetmap at ostertag.name> and others.
-Now it is maintained by the OpenStreetMap community.
-
diff --git a/validator/LICENSE b/validator/LICENSE
deleted file mode 100644
index fe31ef6..0000000
--- a/validator/LICENSE
+++ /dev/null
@@ -1,341 +0,0 @@
-
-		    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-	51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-

-		    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-

-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-

-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-

-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-			    NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-

-	    How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year  name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/validator/README b/validator/README
deleted file mode 100644
index a3dc612..0000000
--- a/validator/README
+++ /dev/null
@@ -1,2 +0,0 @@
-A OSM data validator that checks for common errors.
-
diff --git a/validator/build.xml b/validator/build.xml
deleted file mode 100644
index ed54538..0000000
--- a/validator/build.xml
+++ /dev/null
@@ -1,163 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-** This is the build.xml for the validator plugin
-**
-** Usage
-** =====
-** To build it run
-**
-**    > ant  dist
-**
-** To install the generated plugin locally (in your default plugin directory) run
-**
-**    > ant  install
-**
-** To build against the core in ../../core, create a correct manifest and deploy to
-** SVN, 
-**    set the properties commit.message and plugin.main.version
-** and run
-**    > ant  publish
-**
-**
--->
-<project name="validator" default="dist" basedir=".">
-	
-	<!-- 
-	  ** update before publishing 
-	-->
-	<property name="commit.message" value="Updated build.xml" />		
-	<property name="plugin.main.version" value="2452" />
-		
-		
-    <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="Francisco R. Santos"/>
-                <attribute name="Plugin-Class" value="org.openstreetmap.josm.plugins.validator.OSMValidatorPlugin"/>
-                <attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
-                <attribute name="Plugin-Description" value="An OSM data validator. It checks for problems in data, and provides fixes for the common ones. Spellcheck integrated for tag names."/>
-                <attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/index.php/JOSM/Plugins/Validator"/>
-                <attribute name="Plugin-Mainversion" value="${plugin.main.version}"/>
-                <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>
-	
-	<!--
-	 ************************** Publishing the plugin *********************************** 
-	-->
-		<!--
-		  ** extracts the JOSM release for the JOSM version in ../core and saves it in the 
-		  ** property ${coreversion.info.entry.revision}
-		  **
-		-->
-		<target name="core-info">
-	        <exec append="false" output="core.info.xml" executable="svn" failifexecutionfails="false">
-	                    <env key="LANG" value="C"/>
-	                    <arg value="info"/>
-	                    <arg value="--xml"/>
-	                    <arg value="../../core"/>
-	        </exec>
-	        <xmlproperty file="core.info.xml" prefix="coreversion" keepRoot="true" collapseAttributes="true"/>
-			<echo>Building against core revision ${coreversion.info.entry.revision}.</echo>			
-			<echo>Plugin-Mainversion is set to ${plugin.main.version}.</echo>
-			<delete file="core.info.xml" />
-		</target>
-
-		<!--
-		 ** commits the source tree for this plugin
-		-->
-		<target name="commit-current">
-			<echo>Commiting the plugin source with message '${commit.message}' ...</echo>
-		    <exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
-		                    <env key="LANG" value="C"/>
-			                <arg value="-m '${commit.message}'"/>
-		    				<arg value="commit"/>
-		                    <arg value="."/>
-		    </exec>	    
-		</target>
-
-		<!--
-		** updates (svn up) the source tree for this plugin
-		-->
-		<target name="update-current">
-			<echo>Updating plugin source ...</echo>
-		    <exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
-		                    <env key="LANG" value="C"/>
-		                    <arg value="up"/>
-		                    <arg value="."/>
-		    </exec>	    
-			<echo>Updating ${plugin.jar} ...</echo>
-		    <exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
-		                    <env key="LANG" value="C"/>
-		                    <arg value="up"/>
-		                    <arg value="../dist/${plugin.jar}"/>
-		    </exec>	    
-		</target>
-		
-		<!--
-		 ** commits the plugin.jar 
-		 -->
-		<target name="commit-dist">
-				<echo>
-***** Properties of published ${plugin.jar} *****
-Commit message    : '${commit.message}'					
-Plugin-Mainversion: ${plugin.main.version}
-JOSM build version: ${coreversion.info.entry.revision}
-Plugin-Version    : ${version.entry.commit.revision}
-***** / Properties of published ${plugin.jar} *****					
-					
-Now commiting ${plugin.jar} ...
-</echo>					
-			    <exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
-			                    <env key="LANG" value="C"/>
-				    			<arg value="-m '${commit.message}'"/>
-			    				<arg value="commit"/>	                			
-            			        <arg value="${plugin.jar}"/>
-			    </exec>	    
-	   	</target>
-				
-		<target name="publish" depends="core-info,commit-current,update-current,clean,dist,commit-dist">
-		</target>
-</project>
diff --git a/validator/ignoretags.cfg b/validator/ignoretags.cfg
deleted file mode 100644
index c28a228..0000000
--- a/validator/ignoretags.cfg
+++ /dev/null
@@ -1,362 +0,0 @@
-# JOSM IgnoreTags
-;
-; Ignore valid and semi-valid keys that start with...
-;
-S:opengeodb
-S:openGeoDB
-S:name:
-S:note:
-S:tiger:
-S:gnis:
-S:census:
-S:au.gov.abs:
-S:qroti:
-S:is_in
-S:wikipedia
-S:source_ref:
-;
-; Ignore valid and semi-valid keys that equal...
-;
-E:loc_name
-E:attribution
-E:admin_level
-E:old_name
-E:usage
-E:construction
-E:collection
-E:addr:state
-E:import_uuid
-E:image
-E:url
-E:website
-E:postal_code
-E:source:boundary
-E:hour_on
-E:hour_off
-E:tower:type
-E:rcn_ref
-E:place_name
-E:cycleway
-E:abutters
-E:survey_date
-E:right:state
-E:left:state
-;
-; Ignore valid and semi-valid keys that end with...
-;
-F::nswgnb
-F::forward
-F::backward
-F::left
-F::right
-;
-; Misc Tags
-;
-K:type=is_in
-K:bridge=viaduct
-K:bridge=aqueduct
-K:bridge=swing
-;
-; Highway Key/Value Pairs
-;
-K:highway=motorway_link
-K:highway=trunk_link
-K:highway=primary_link
-K:highway=secondary_link
-K:oneway=-1
-;
-; traffic_calming Tags
-;
-K:traffic_calming=yes
-K:traffic_calming=bump
-K:traffic_calming=chicane
-K:traffic_calming=cushion
-K:traffic_calming=hump
-K:traffic_calming=rumble_strip
-K:traffic_calming=table
-K:traffic_calming=choker
-;
-; Aeroway Key/Value Pairs
-;
-K:aeroway=apron
-K:aeroway=hanger
-K:aeroway=helipad
-K:aeroway=runway
-K:aeroway=taxiway
-K:aeroway=terminal
-T:aeroway=aerodrome|type=public
-;
-; Amenity Key/Value Pairs
-;
-K:amenity=arts_centre
-K:amenity=atm
-K:amenity=baby_hatch
-K:amenity=bank
-K:amenity=bbq
-K:amenity=bench
-K:amenity=biergarten
-K:amenity=bicycle_parking
-K:amenity=bicycle_rental
-K:amenity=bureau_de_change
-K:amenity=bus_station
-K:amenity=brothel
-K:amenity=cafe
-K:amenity=car_rental
-K:amenity=car_sharing
-K:amenity=cinema
-K:amenity=college
-K:amenity=courthouse
-K:amenity=crematorium
-K:amenity=dentist
-K:amenity=doctors
-K:amenity=drinking_water
-K:amenity=embassy
-K:amenity=emergency_phone
-K:amenity=fast_food
-K:amenity=ferry_terminal
-K:amenity=fire_station
-K:amenity=food_court
-K:amenity=fountain
-K:amenity=fuel
-K:amenity=gallery
-K:amenity=grave_yard
-K:amenity=grit_bin
-K:amenity=gym
-K:amenity=hospital
-K:amenity=hunting_stand
-K:amenity=kindergarten
-K:amenity=library
-K:amenity=marketplace
-K:amenity=nightclub
-K:amenity=parking
-K:amenity=pharmacy
-K:amenity=place_of_worship
-K:amenity=police
-K:amenity=post_box
-K:amenity=post_office
-K:amenity=prison
-K:amenity=pub
-K:amenity=public_building
-K:amenity=recycling
-K:amenity=restaurant
-K:amenity=school
-K:amenity=shelter
-K:amenity=signpost
-K:amenity=studio
-K:amenity=taxi
-K:amenity=telephone
-K:amenity=theatre
-K:amenity=toilets
-K:amenity=townhall
-K:amenity=university
-K:amenity=vending_machine
-K:amenity=veterinary
-K:amenity=waste_basket
-K:amenity=waste_disposal
-;
-; Cuisine Tags
-;
-K:cuisine=coffee_shop
-K:cuisine=fish_and_chips
-K:cuisine=pie
-;
-; Cycleway Tags
-;
-K:cycleway=lane
-K:cycleway=track
-K:cycleway=opposite_lane
-K:cycleway=opposite
-K:cycleway=opposite_track
-;
-; Historic Tags
-;
-K:historic=castle
-K:historic=monument
-K:historic=memorial
-K:historic=archaeological_site
-K:historic=ruins
-K:historic=battlefield
-K:historic=wreck
-K:historic=yes
-;
-; Man_made Tags
-;
-T:man_made=pipeline|type=water
-T:man_made=pipeline|type=oil
-T:man_made=pipeline|type=gas
-T:man_made=pipeline|type=sewage
-T:man_made=pipeline|location=underground
-T:man_made=pipeline|location=underwater
-T:man_made=pipeline|location=overground
-;
-; Military Tags
-;
-K:military=airfield
-K:military=bunker
-K:military=barracks
-K:military=danger_area
-K:military=range
-K:military=naval_base
-;
-; Natural Tags
-;
-K:natural=bay
-K:natural=beach
-K:natural=cave_entrance
-K:natural=cliff
-K:natural=fell
-K:natural=glacier
-K:natural=heath
-K:natural=marsh
-K:natural=mud
-K:natural=peak
-K:natural=scree
-K:natural=scrub
-K:natural=spring
-K:natural=tree
-K:natural=volcano
-K:natural=wetland
-;
-; Surface Key/Value Pairs
-;
-K:surface=dirt
-K:surface=wood
-;
-; Relation Tags
-;
-K:relation=to
-K:relation=from
-;
-; Religious Key/Value Pairs
-;
-T:religion=christian|denomination=anglican
-T:religion=muslim|denomination=alaouite
-T:religion=jewish|denomination=alternative
-T:religion=christian|denomination=apostolic
-T:religion=jewish|denomination=ashkenazi
-T:religion=christian|denomination=baptist
-T:religion=christian|denomination=catholic
-T:religion=christian|denomination=christian_community
-T:religion=christian|denomination=christian_scientist
-T:religion=jewish|denomination=conservative
-T:religion=christian|denomination=coptic_orthodox
-T:religion=christian|denomination=czechoslovak_hussite
-T:religion=muslim|denomination=druze
-T:religion=christian|denomination=dutch_reformed
-T:religion=christian|denomination=evangelical
-T:religion=pastafarian|denomination=EVKdFSMiD
-T:religion=christian|denomination=foursquare
-T:religion=christian|denomination=greek_orthodox
-T:religion=jewish|denomination=hasidic
-T:religion=jewish|denomination=humanistic
-T:religion=muslim|denomination=ibadi
-T:religion=muslim|denomination=ismaili
-T:religion=christian|denomination=jehovahs_witness
-T:religion=christian|denomination=kabbalah
-T:religion=christian|denomination=karaite
-T:religion=jewish|denomination=liberal
-T:religion=christian|denomination=living_waters_church
-T:religion=christian|denomination=lutheran
-T:religion=christian|denomination=maronite
-T:religion=other|denomination=masonic
-T:religion=christian|denomination=mennonite
-T:religion=christian|denomination=methodist
-T:religion=jewish|denomination=modern_orthodox
-T:religion=christian|denomination=mormon
-T:religion=jewish|denomination=neo_orthodox
-T:religion=christian|denomination=new_apostolic
-T:religion=christian|denomination=nondenominational
-T:religion=jewish|denomination=nondenominational
-T:religion=muslim|denomination=nondenominational
-T:religion=christian|denomination=old_catholic
-T:religion=christian|denomination=orthodox
-T:religion=jewish|denomination=orthodox
-T:religion=christian|denomination=pentecostal
-T:religion=christian|denomination=presbyterian
-T:religion=jewish|denomination=progressive
-T:religion=christian|denomination=protestant
-T:religion=christian|denomination=quaker
-T:religion=jewish|denomination=reconstructionist
-T:religion=jewish|denomination=reform
-T:religion=jewish|denomination=renewal
-T:religion=christian|denomination=roman_catholic
-T:religion=christian|denomination=russian_orthodox
-T:religion=christian|denomination=salvation_army
-T:religion=jewish|denomination=samaritan
-T:religion=christian|denomination=seventh_day_adventist
-T:religion=muslim|denomination=shia
-T:religion=muslim|denomination=sunni
-T:religion=jewish|denomination=ultra_orthodox
-T:religion=christian|denomination=united
-T:religion=christian|denomination=united_reformed
-T:religion=christian|denomination=uniting
-;
-; Shop Key/Value Pairs
-;
-K:shop=alcohol
-K:shop=bakery
-K:shop=beverages
-K:shop=bicycle
-K:shop=books
-K:shop=butcher
-K:shop=car
-K:shop=car_repair
-K:shop=chemist
-K:shop=clothes
-K:shop=computer
-K:shop=confectionery
-K:shop=convenience
-K:shop=department_store
-K:shop=dry_cleaning
-K:shop=doityourself
-K:shop=electronics
-K:shop=florist
-K:shop=furniture
-K:shop=garden_centre
-K:shop=greengrocer
-K:shop=hairdresser
-K:shop=hardware
-K:shop=hifi
-K:shop=kiosk
-K:shop=laundry
-K:shop=mall
-K:shop=motorcycle
-K:shop=optician
-K:shop=organic
-K:shop=outdoor
-K:shop=sports
-K:shop=stationery
-K:shop=supermarket
-K:shop=shoes
-K:shop=toys
-K:shop=travel_agency
-K:shop=video
-;
-; Sports Tags
-;
-K:sport=boxing
-K:sport=netball
-;
-; Tourism Tags
-;
-K:tourism=alpine_hut
-K:tourism=attraction
-K:tourism=artwork
-K:tourism=camp_site
-K:tourism=caravan_site
-K:tourism=chalet
-K:tourism=guest_house
-K:tourism=hostel
-K:tourism=hotel
-K:tourism=information
-K:tourism=motel
-K:tourism=museum
-K:tourism=picnic_site
-K:tourism=theme_park
-K:tourism=viewpoint
-K:tourism=zoo
-K:tourism=yes
-;
-; Type Key/Value Pairs
-;
-K:type=collection
diff --git a/validator/images/data/error.gif b/validator/images/data/error.gif
deleted file mode 100644
index 486faff..0000000
Binary files a/validator/images/data/error.gif and /dev/null differ
diff --git a/validator/images/data/other.gif b/validator/images/data/other.gif
deleted file mode 100644
index 2da001e..0000000
Binary files a/validator/images/data/other.gif and /dev/null differ
diff --git a/validator/images/data/warning.gif b/validator/images/data/warning.gif
deleted file mode 100644
index 2b2e50f..0000000
Binary files a/validator/images/data/warning.gif and /dev/null differ
diff --git a/validator/images/dialogs/fix.png b/validator/images/dialogs/fix.png
deleted file mode 100644
index 9af6a52..0000000
Binary files a/validator/images/dialogs/fix.png and /dev/null differ
diff --git a/validator/images/dialogs/validator.png b/validator/images/dialogs/validator.png
deleted file mode 100644
index 2a51812..0000000
Binary files a/validator/images/dialogs/validator.png and /dev/null differ
diff --git a/validator/images/layer/validator.png b/validator/images/layer/validator.png
deleted file mode 100644
index 517c4d1..0000000
Binary files a/validator/images/layer/validator.png and /dev/null differ
diff --git a/validator/images/preferences/validator.png b/validator/images/preferences/validator.png
deleted file mode 100644
index 7fcbc1d..0000000
Binary files a/validator/images/preferences/validator.png and /dev/null differ
diff --git a/validator/images/validator.png b/validator/images/validator.png
deleted file mode 100644
index 8f52cf6..0000000
Binary files a/validator/images/validator.png and /dev/null differ
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/ErrorLayer.java b/validator/src/org/openstreetmap/josm/plugins/validator/ErrorLayer.java
deleted file mode 100644
index 6de2c33..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/ErrorLayer.java
+++ /dev/null
@@ -1,143 +0,0 @@
-package org.openstreetmap.josm.plugins.validator;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.Component;
-import java.awt.Graphics2D;
-import java.util.Enumeration;
-import java.util.List;
-
-import javax.swing.Icon;
-import javax.swing.JMenuItem;
-import javax.swing.JSeparator;
-import javax.swing.tree.DefaultMutableTreeNode;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.RenameLayerAction;
-import org.openstreetmap.josm.data.Bounds;
-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.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.gui.layer.Layer.LayerChangeListener;
-import org.openstreetmap.josm.plugins.validator.util.Bag;
-import org.openstreetmap.josm.tools.ImageProvider;
-
-/**
- * A layer showing error messages.
- *
- * @author frsantos
- */
-public class ErrorLayer extends Layer implements LayerChangeListener {
-    private OSMValidatorPlugin plugin;
-
-    public ErrorLayer(OSMValidatorPlugin plugin) {
-        super(tr("Validation errors"));
-        this.plugin = plugin;
-        Layer.listeners.add(this);
-    }
-
-    /**
-     * Return a static icon.
-     */
-    @Override
-    public Icon getIcon() {
-        return ImageProvider.get("layer", "validator");
-    }
-
-    /**
-     * Draw all primitives in this layer but do not draw modified ones (they
-     * are drawn by the edit layer).
-     * Draw nodes last to overlap the ways they belong to.
-     */
-    @SuppressWarnings("unchecked")
-    @Override
-    public void paint(final Graphics2D g, final MapView mv, Bounds bounds) {
-        DefaultMutableTreeNode root = plugin.validationDialog.tree.getRoot();
-        if (root == null || root.getChildCount() == 0)
-            return;
-
-        DefaultMutableTreeNode severity = (DefaultMutableTreeNode) root.getLastChild();
-        while (severity != null) {
-            Enumeration<DefaultMutableTreeNode> errorMessages = severity.breadthFirstEnumeration();
-            while (errorMessages.hasMoreElements()) {
-                Object tn = errorMessages.nextElement().getUserObject();
-                if (tn instanceof TestError)
-                    ((TestError) tn).paint(g, mv);
-            }
-
-            // Severities in inverse order
-            severity = severity.getPreviousSibling();
-        }
-    }
-
-    @Override
-    public String getToolTipText() {
-        Bag<Severity, TestError> errorTree = new Bag<Severity, TestError>();
-        List<TestError> errors = plugin.validationDialog.tree.getErrors();
-        for (TestError e : errors) {
-            errorTree.add(e.getSeverity(), e);
-        }
-
-        StringBuilder b = new StringBuilder();
-        for (Severity s : Severity.values()) {
-            if (errorTree.containsKey(s))
-                b.append(tr(s.toString())).append(": ").append(errorTree.get(s).size()).append("<br>");
-        }
-
-        if (b.length() == 0)
-            return "<html>" + tr("No validation errors") + "</html>";
-        else
-            return "<html>" + tr("Validation errors") + ":<br>" + b + "</html>";
-    }
-
-    @Override
-    public void mergeFrom(Layer from) {
-    }
-
-    @Override
-    public boolean isMergable(Layer other) {
-        return false;
-    }
-
-    @Override
-    public void visitBoundingBox(BoundingXYVisitor v) {
-    }
-
-    @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 RenameLayerAction(null, this)), new JSeparator(),
-                new JMenuItem(new LayerListPopup.InfoAction(this)) };
-    }
-
-    @Override
-    public void destroy() {
-    }
-
-    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
-    }
-
-    public void layerAdded(Layer newLayer) {
-    }
-
-    /**
-     * If layer is the OSM Data layer, remove all errors
-     */
-    public void layerRemoved(Layer oldLayer) {
-        if (oldLayer instanceof OsmDataLayer &&  Main.map.mapView.getEditLayer() == null) {
-            Main.map.mapView.removeLayer(this);
-        } else if (oldLayer == this) {
-            OSMValidatorPlugin.errorLayer = null;
-        }
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/ErrorTreePanel.java b/validator/src/org/openstreetmap/josm/plugins/validator/ErrorTreePanel.java
deleted file mode 100644
index e079c6e..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/ErrorTreePanel.java
+++ /dev/null
@@ -1,327 +0,0 @@
-package org.openstreetmap.josm.plugins.validator;
-
-import java.awt.event.MouseEvent;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.Map.Entry;
-
-import javax.swing.JTree;
-import javax.swing.ToolTipManager;
-import javax.swing.tree.DefaultMutableTreeNode;
-import javax.swing.tree.DefaultTreeModel;
-import javax.swing.tree.TreePath;
-import javax.swing.tree.TreeSelectionModel;
-
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.plugins.validator.util.Bag;
-import org.openstreetmap.josm.plugins.validator.util.MultipleNameVisitor;
-
-/**
- * A panel that displays the error tree. The selection manager
- * respects clicks into the selection list. Ctrl-click will remove entries from
- * the list while single click will make the clicked entry the only selection.
- *
- * @author frsantos
- */
-
-public class ErrorTreePanel extends JTree {
-    /** Serializable ID */
-    private static final long serialVersionUID = 2952292777351992696L;
-
-    /**
-     * The validation data.
-     */
-    protected DefaultTreeModel treeModel = new DefaultTreeModel(new DefaultMutableTreeNode());
-
-    /** The list of errors shown in the tree */
-    private List<TestError> errors;
-
-    /**
-     * If {@link #filter} is not <code>null</code> only errors are displayed 
-     * that refer to one of the primitives in the filter.  
-     */
-    private Set<OsmPrimitive> filter = null;
-
-    /**
-     * Constructor
-     * @param errors The list of errors
-     */
-    public ErrorTreePanel(List<TestError> errors) {
-        ToolTipManager.sharedInstance().registerComponent(this);
-        this.setModel(treeModel);
-        this.setRootVisible(false);
-        this.setShowsRootHandles(true);
-        this.expandRow(0);
-        this.setVisibleRowCount(8);
-        this.setCellRenderer(new ErrorTreeRenderer());
-        this.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
-        setErrorList(errors);
-    }
-
-    public String getToolTipText(MouseEvent e) {
-        String res = null;
-        TreePath path = getPathForLocation(e.getX(), e.getY());
-        if (path != null) {
-            DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
-            Object nodeInfo = node.getUserObject();
-
-            if (nodeInfo instanceof TestError) {
-                TestError error = (TestError) nodeInfo;
-                MultipleNameVisitor v = new MultipleNameVisitor();
-                v.visit(error.getPrimitives());
-                res = "<html>" + v.getText() + "<br>" + error.getMessage();
-                String d = error.getDescription();
-                if (d != null)
-                    res += "<br>" + d;
-                res += "</html>";
-            } else
-                res = node.toString();
-        }
-        return res;
-    }
-
-    /** Constructor */
-    public ErrorTreePanel() {
-        this(null);
-    }
-
-    @Override
-    public void setVisible(boolean v) {
-        if (v)
-            buildTree();
-        else
-            treeModel.setRoot(new DefaultMutableTreeNode());
-        super.setVisible(v);
-    }
-
-    /**
-     * Builds the errors tree
-     */
-    public void buildTree() {
-        DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode();
-
-        if (errors == null || errors.isEmpty()) {
-            treeModel.setRoot(rootNode);
-            return;
-        }
-
-        // Remember the currently expanded rows
-        Set<Object> oldSelectedRows = new HashSet<Object>();
-        Enumeration<TreePath> expanded = getExpandedDescendants(new TreePath(getRoot()));
-        if (expanded != null) {
-            while (expanded.hasMoreElements()) {
-                TreePath path = expanded.nextElement();
-                DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
-                Object userObject = node.getUserObject();
-                if (userObject instanceof Severity)
-                    oldSelectedRows.add(userObject);
-                else if (userObject instanceof String) {
-                    String msg = (String) userObject;
-                    msg = msg.substring(0, msg.lastIndexOf(" ("));
-                    oldSelectedRows.add(msg);
-                }
-            }
-        }
-
-        Map<Severity, Bag<String, TestError>> errorTree = new HashMap<Severity, Bag<String, TestError>>();
-        Map<Severity, HashMap<String, Bag<String, TestError>>> errorTreeDeep = new HashMap<Severity, HashMap<String, Bag<String, TestError>>>();
-        for (Severity s : Severity.values()) {
-            errorTree.put(s, new Bag<String, TestError>(20));
-            errorTreeDeep.put(s, new HashMap<String, Bag<String, TestError>>());
-        }
-
-        for (TestError e : errors) {
-            if (e.getIgnored())
-                continue;
-            Severity s = e.getSeverity();
-            String d = e.getDescription();
-            String m = e.getMessage();
-            if (filter != null) {
-                boolean found = false;
-                for (OsmPrimitive p : e.getPrimitives()) {
-                    if (filter.contains(p)) {
-                        found = true;
-                        break;
-                    }
-                }
-                if (!found)
-                    continue;
-            }
-            if (d != null) {
-                Bag<String, TestError> b = errorTreeDeep.get(s).get(m);
-                if (b == null) {
-                    b = new Bag<String, TestError>(20);
-                    errorTreeDeep.get(s).put(m, b);
-                }
-                b.add(d, e);
-            } else
-                errorTree.get(s).add(m, e);
-        }
-
-        List<TreePath> expandedPaths = new ArrayList<TreePath>();
-        for (Severity s : Severity.values()) {
-            Bag<String, TestError> severityErrors = errorTree.get(s);
-            Map<String, Bag<String, TestError>> severityErrorsDeep = errorTreeDeep.get(s);
-            if (severityErrors.isEmpty() && severityErrorsDeep.isEmpty())
-                continue;
-
-            // Severity node
-            DefaultMutableTreeNode severityNode = new DefaultMutableTreeNode(s);
-            rootNode.add(severityNode);
-
-            if (oldSelectedRows.contains(s))
-                expandedPaths.add(new TreePath(new Object[] { rootNode, severityNode }));
-
-            for (Entry<String, List<TestError>> msgErrors : severityErrors.entrySet()) {
-                // Message node
-                List<TestError> errors = msgErrors.getValue();
-                String msg = msgErrors.getKey() + " (" + errors.size() + ")";
-                DefaultMutableTreeNode messageNode = new DefaultMutableTreeNode(msg);
-                severityNode.add(messageNode);
-
-                if (oldSelectedRows.contains(msgErrors.getKey())) {
-                    expandedPaths.add(new TreePath(new Object[] { rootNode, severityNode, messageNode }));
-                }
-
-                for (TestError error : errors) {
-                    // Error node
-                    DefaultMutableTreeNode errorNode = new DefaultMutableTreeNode(error);
-                    messageNode.add(errorNode);
-                }
-            }
-            for (Entry<String, Bag<String, TestError>> bag : severityErrorsDeep.entrySet()) {
-                // Group node
-                Bag<String, TestError> errorlist = bag.getValue();
-                DefaultMutableTreeNode groupNode = null;
-                if (errorlist.size() > 1) {
-                    String nmsg = bag.getKey() + " (" + errorlist.size() + ")";
-                    groupNode = new DefaultMutableTreeNode(nmsg);
-                    severityNode.add(groupNode);
-                    if (oldSelectedRows.contains(bag.getKey())) {
-                        expandedPaths.add(new TreePath(new Object[] { rootNode, severityNode, groupNode }));
-                    }
-                }
-
-                for (Entry<String, List<TestError>> msgErrors : errorlist.entrySet()) {
-                    // Message node
-                    List<TestError> errors = msgErrors.getValue();
-                    String msg;
-                    if (groupNode != null)
-                        msg = msgErrors.getKey() + " (" + errors.size() + ")";
-                    else
-                        msg = msgErrors.getKey() + " - " + bag.getKey() + " (" + errors.size() + ")";
-                    DefaultMutableTreeNode messageNode = new DefaultMutableTreeNode(msg);
-                    if (groupNode != null)
-                        groupNode.add(messageNode);
-                    else
-                        severityNode.add(messageNode);
-
-                    if (oldSelectedRows.contains(msgErrors.getKey())) {
-                        if (groupNode != null) {
-                            expandedPaths.add(new TreePath(new Object[] { rootNode, severityNode, groupNode,
-                                    messageNode }));
-                        } else {
-                            expandedPaths.add(new TreePath(new Object[] { rootNode, severityNode, messageNode }));
-                        }
-                    }
-
-                    for (TestError error : errors) {
-                        // Error node
-                        DefaultMutableTreeNode errorNode = new DefaultMutableTreeNode(error);
-                        messageNode.add(errorNode);
-                    }
-                }
-            }
-        }
-
-        treeModel.setRoot(rootNode);
-        for (TreePath path : expandedPaths) {
-            this.expandPath(path);
-        }
-    }
-
-    /**
-     * Sets the errors list used by a data layer
-     * @param errors The error list that is used by a data layer
-     */
-    public void setErrorList(List<TestError> errors) {
-        this.errors = errors;
-        if (isVisible())
-            buildTree();
-    }
-
-    /**
-     * Clears the current error list and adds these errors to it
-     * @param errors The validation errors
-     */
-    public void setErrors(List<TestError> newerrors) {
-        if (errors == null)
-            return;
-        errors.clear();
-        for (TestError error : newerrors) {
-            if (!error.getIgnored())
-                errors.add(error);
-        }
-        if (isVisible())
-            buildTree();
-    }
-
-    /**
-     * Returns the errors of the tree
-     * @return  the errors of the tree
-     */
-    public List<TestError> getErrors() {
-        return errors != null ? errors : Collections.<TestError> emptyList();
-    }
-
-    public Set<OsmPrimitive> getFilter() {
-        return filter;
-    }
-
-    public void setFilter(Set<OsmPrimitive> filter) {
-        if (filter != null && filter.size() == 0)
-            this.filter = null;
-        else
-            this.filter = filter;
-        if (isVisible())
-            buildTree();
-    }
-
-    /**
-     * Updates the current errors list
-     * @param errors The validation errors
-     */
-    public void resetErrors() {
-        List<TestError> e = new ArrayList<TestError>(errors);
-        setErrors(e);
-    }
-
-    /**
-     * Expands all tree
-     */
-    @SuppressWarnings("unchecked")
-    public void expandAll() {
-        DefaultMutableTreeNode root = getRoot();
-
-        int row = 0;
-        Enumeration<DefaultMutableTreeNode> children = root.breadthFirstEnumeration();
-        while (children.hasMoreElements()) {
-            children.nextElement();
-            expandRow(row++);
-        }
-    }
-
-    /**
-     * Returns the root node model.
-     * @return The root node model
-     */
-    public DefaultMutableTreeNode getRoot() {
-        return (DefaultMutableTreeNode) treeModel.getRoot();
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/ErrorTreeRenderer.java b/validator/src/org/openstreetmap/josm/plugins/validator/ErrorTreeRenderer.java
deleted file mode 100644
index 53f1de3..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/ErrorTreeRenderer.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.openstreetmap.josm.plugins.validator;
-
-import java.awt.Component;
-
-import javax.swing.JTree;
-import javax.swing.tree.DefaultMutableTreeNode;
-import javax.swing.tree.DefaultTreeCellRenderer;
-
-import org.openstreetmap.josm.plugins.validator.util.MultipleNameVisitor;
-import org.openstreetmap.josm.tools.ImageProvider;
-
-/**
- * Tree renderer for displaying errors
- * @author frsantos
- */
-public class ErrorTreeRenderer extends DefaultTreeCellRenderer
-{
-    /** Serializable ID */
-    private static final long serialVersionUID = 5567632718124640198L;
-
-    @Override
-    public Component getTreeCellRendererComponent(JTree tree, Object value,
-            boolean selected, boolean expanded, boolean leaf, int row,
-            boolean hasFocus)
-    {
-        super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
-
-        DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
-        Object nodeInfo = node.getUserObject();
-
-        if (nodeInfo instanceof Severity)
-        {
-            Severity s = (Severity)nodeInfo;
-            setIcon(ImageProvider.get("data", s.getIcon()));
-        }
-        else if (nodeInfo instanceof TestError)
-        {
-            TestError error = (TestError)nodeInfo;
-            MultipleNameVisitor v = new MultipleNameVisitor();
-            v.visit(error.getPrimitives());
-            setText(v.getText());
-            setIcon(v.getIcon());
-        }
-
-        return this;
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/GridLayer.java b/validator/src/org/openstreetmap/josm/plugins/validator/GridLayer.java
deleted file mode 100644
index dc1a730..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/GridLayer.java
+++ /dev/null
@@ -1,204 +0,0 @@
-package org.openstreetmap.josm.plugins.validator;
-
-import java.awt.Color;
-import java.awt.Component;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
-import java.awt.Point;
-import java.awt.geom.Point2D;
-
-import javax.swing.Icon;
-import javax.swing.JMenuItem;
-import javax.swing.JSeparator;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.RenameLayerAction;
-import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.coor.EastNorth;
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.Relation;
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.data.osm.visitor.AbstractVisitor;
-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.plugins.validator.util.Util;
-import org.openstreetmap.josm.tools.ImageProvider;
-
-/**
- * A debug layer for testing the grid cells a way crosses.
- *
- * @author frsantos
- */
-public class GridLayer extends Layer
-{
-    /**
-     * Constructor
-     * @param name
-     */
-    public GridLayer(String name)
-    {
-        super(name);
-    }
-
-    /**
-     * Return a static icon.
-     */
-    @Override public Icon getIcon() {
-        return ImageProvider.get("layer", "validator");
-    }
-
-    /**
-     * Draw the grid and highlight all cells acuppied by any selected primitive.
-     */
-    @Override
-    public void paint(final Graphics2D g, final MapView mv, Bounds bounds)
-    {
-        if( !Main.pref.hasKey(PreferenceEditor.PREF_DEBUG + ".grid") )
-            return;
-
-        int gridWidth = Integer.parseInt(Main.pref.get(PreferenceEditor.PREF_DEBUG + ".grid") );
-        int width = mv.getWidth();
-        int height = mv.getHeight();
-
-        EastNorth origin = mv.getEastNorth(0, 0);
-        EastNorth border = mv.getEastNorth(width, height);
-
-        if( border.east() * gridWidth > 50 )
-            return;
-
-        g.setColor(Color.RED.darker().darker());
-        HighlightCellVisitor visitor = new HighlightCellVisitor(g, mv, gridWidth);
-        for(OsmPrimitive p : Main.main.getCurrentDataSet().getSelected() )
-            p.visit(visitor);
-
-        long x0 = (long)Math.floor(origin.east()  * gridWidth);
-        long x1 = (long)Math.floor(border.east()  * gridWidth);
-        long y0 = (long)Math.floor(origin.north() * gridWidth) + 1;
-        long y1 = (long)Math.floor(border.north() * gridWidth) + 1;
-        long aux;
-        if( x0 > x1 ) { aux = x0; x0 = x1; x1 = aux; }
-        if( y0 > y1 ) { aux = y0; y0 = y1; y1 = aux; }
-
-        g.setColor(Color.RED.brighter().brighter());
-        for( double x = x0; x <= x1; x++)
-        {
-            Point point = mv.getPoint( new EastNorth(x/gridWidth, 0));
-            g.drawLine(point.x, 0, point.x, height);
-        }
-
-        for( double y = y0; y <= y1; y++)
-        {
-            Point point = mv.getPoint( new EastNorth(0, y/gridWidth));
-            g.drawLine(0, point.y, width, point.y);
-        }
-    }
-
-    @Override
-    public String getToolTipText()
-    {
-        return null;
-    }
-
-    @Override
-    public void mergeFrom(Layer from) {}
-
-    @Override
-    public boolean isMergable(Layer other) {
-        return false;
-    }
-
-    @Override
-    public void visitBoundingBox(BoundingXYVisitor v) {}
-
-    @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 RenameLayerAction(null, this)),
-                new JSeparator(),
-                new JMenuItem(new LayerListPopup.InfoAction(this))};
-    }
-
-    @Override public void destroy() { }
-
-    /**
-     * Visitor that highlights all cells the selected primitives go through
-     */
-    class HighlightCellVisitor extends AbstractVisitor
-    {
-        /** The MapView */
-        private final MapView mv;
-        /** The graphics */
-        private final Graphics g;
-        /** The grid width */
-        private final int gridDetail;
-        /** The width of a cell */
-        private int cellWidth;
-
-        /**
-         * Constructor
-         * @param g the graphics
-         * @param mv The MapView
-         * @param gridDetail The grid detail
-         */
-        public HighlightCellVisitor(final Graphics g, final MapView mv, int gridDetail)
-        {
-            this.g = g;
-            this.mv = mv;
-            this.gridDetail = gridDetail;
-
-            Point p = mv.getPoint( new EastNorth(0, 0) );
-            Point p2 = mv.getPoint( new EastNorth(1d/gridDetail, 1d/gridDetail) );
-            cellWidth = Math.abs(p2.x - p.x);
-        }
-
-        public void visit(Node n)
-        {
-            double x = n.getEastNorth().east() * gridDetail;
-            double y = n.getEastNorth().north()* gridDetail + 1;
-
-            drawCell( Math.floor(x), Math.floor(y) );
-        }
-
-        public void visit(Way w)
-        {
-            Node lastN = null;
-            for (Node n : w.getNodes()) {
-                if (lastN == null) {
-                    lastN = n;
-                    continue;
-                }
-                for (Point2D p : Util.getSegmentCells(lastN, n, gridDetail)) {
-                    drawCell( p.getX(), p.getY() );
-                }
-                lastN = n;
-            }
-        }
-
-        public void visit(Relation r) {}
-
-        /**
-         * Draws a solid cell at the (x,y) location
-         * @param x
-         * @param y
-         */
-        protected void drawCell(double x, double y)
-        {
-            Point p = mv.getPoint( new EastNorth(x/gridDetail, y/gridDetail) );
-            g.fillRect(p.x, p.y, cellWidth, cellWidth);
-        }
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/OSMValidatorPlugin.java b/validator/src/org/openstreetmap/josm/plugins/validator/OSMValidatorPlugin.java
deleted file mode 100644
index a916459..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/OSMValidatorPlugin.java
+++ /dev/null
@@ -1,310 +0,0 @@
-package org.openstreetmap.josm.plugins.validator;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeSet;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.swing.JOptionPane;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.UploadAction;
-import org.openstreetmap.josm.data.projection.Epsg4326;
-import org.openstreetmap.josm.data.projection.Lambert;
-import org.openstreetmap.josm.data.projection.Mercator;
-import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.gui.layer.Layer;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.gui.layer.Layer.LayerChangeListener;
-import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
-import org.openstreetmap.josm.plugins.Plugin;
-import org.openstreetmap.josm.plugins.validator.tests.Coastlines;
-import org.openstreetmap.josm.plugins.validator.tests.CrossingWays;
-import org.openstreetmap.josm.plugins.validator.tests.DuplicateNode;
-import org.openstreetmap.josm.plugins.validator.tests.DuplicateWay;
-import org.openstreetmap.josm.plugins.validator.tests.DuplicatedWayNodes;
-import org.openstreetmap.josm.plugins.validator.tests.NameMismatch;
-import org.openstreetmap.josm.plugins.validator.tests.NodesWithSameName;
-import org.openstreetmap.josm.plugins.validator.tests.OverlappingWays;
-import org.openstreetmap.josm.plugins.validator.tests.SelfIntersectingWay;
-import org.openstreetmap.josm.plugins.validator.tests.SimilarNamedWays;
-import org.openstreetmap.josm.plugins.validator.tests.TagChecker;
-import org.openstreetmap.josm.plugins.validator.tests.UnclosedWays;
-import org.openstreetmap.josm.plugins.validator.tests.UnconnectedWays;
-import org.openstreetmap.josm.plugins.validator.tests.UntaggedNode;
-import org.openstreetmap.josm.plugins.validator.tests.UntaggedWay;
-import org.openstreetmap.josm.plugins.validator.tests.WronglyOrderedWays;
-import org.openstreetmap.josm.plugins.validator.util.Util;
-
-/**
- *
- * A OSM data validator
- *
- * @author Francisco R. Santos <frsantos at gmail.com>
- */
-public class OSMValidatorPlugin extends Plugin implements LayerChangeListener {
-
-    protected static OSMValidatorPlugin plugin;
-
-    protected static ErrorLayer errorLayer = null;
-
-    /** The validate action */
-    ValidateAction validateAction = new ValidateAction(this);
-
-    /** The validation dialog */
-    ValidatorDialog validationDialog;
-
-    /** The list of errors per layer*/
-    Map<Layer, List<TestError>> layerErrors = new HashMap<Layer, List<TestError>>();
-
-    /** Grid detail, multiplier of east,north values for valuable cell sizing */
-    public static double griddetail;
-
-    public Collection<String> ignoredErrors = new TreeSet<String>();
-
-    /**
-     * All available tests
-     * TODO: is there any way to find out automagically all available tests?
-     */
-    @SuppressWarnings("unchecked")
-    public static Class<Test>[] allAvailableTests = new Class[] { DuplicateNode.class, // ID    1 ..   99
-            OverlappingWays.class, // ID  101 ..  199
-            UntaggedNode.class, // ID  201 ..  299
-            UntaggedWay.class, // ID  301 ..  399
-            SelfIntersectingWay.class, // ID  401 ..  499
-            DuplicatedWayNodes.class, // ID  501 ..  599
-            CrossingWays.class, // ID  601 ..  699
-            SimilarNamedWays.class, // ID  701 ..  799
-            NodesWithSameName.class, // ID  801 ..  899
-            Coastlines.class, // ID  901 ..  999
-            WronglyOrderedWays.class, // ID 1001 .. 1099
-            UnclosedWays.class, // ID 1101 .. 1199
-            TagChecker.class, // ID 1201 .. 1299
-            UnconnectedWays.class, // ID 1301 .. 1399
-            DuplicateWay.class, // ID 1401 .. 1499
-            NameMismatch.class, // ID  1501 ..  1599
-    };
-
-    /**
-     * Creates the plugin
-     */
-    public OSMValidatorPlugin() {
-        plugin = this;
-        checkPluginDir();
-        initializeGridDetail();
-        initializeTests(getTests());
-        loadIgnoredErrors();
-    }
-
-    /**
-     * Check if plugin directory exists (store ignored errors file)
-     */
-    private void checkPluginDir() {
-        try {
-        File pathDir = new File(Util.getPluginDir());
-        if (!pathDir.exists())
-            pathDir.mkdirs();
-        } catch (Exception e){
-            e.printStackTrace();
-        }
-    }
-
-    private void loadIgnoredErrors() {
-        ignoredErrors.clear();
-        if (Main.pref.getBoolean(PreferenceEditor.PREF_USE_IGNORE, true)) {
-            try {
-                final BufferedReader in = new BufferedReader(new FileReader(Util.getPluginDir() + "ignorederrors"));
-                for (String line = in.readLine(); line != null; line = in.readLine()) {
-                    ignoredErrors.add(line);
-                }
-            } catch (final FileNotFoundException e) {
-            } catch (final IOException e) {
-                e.printStackTrace();
-            }
-        }
-    }
-
-    public void saveIgnoredErrors() {
-        try {
-            final PrintWriter out = new PrintWriter(new FileWriter(Util.getPluginDir() + "ignorederrors"), false);
-            for (String e : ignoredErrors)
-                out.println(e);
-            out.close();
-        } catch (final IOException e) {
-            e.printStackTrace();
-        }
-    }
-
-    @Override
-    public PreferenceSetting getPreferenceSetting() {
-        return new PreferenceEditor(this);
-    }
-
-    private ValidateUploadHook uploadHook;
-    
-    @Override
-    public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
-        if (newFrame != null) {
-            validationDialog = new ValidatorDialog(this);
-            newFrame.addToggleDialog(validationDialog);
-            initializeErrorLayer();
-            if (Main.pref.hasKey(PreferenceEditor.PREF_DEBUG + ".grid"))
-                Main.main.addLayer(new GridLayer(tr("Grid")));
-            Layer.listeners.add(this);
-        } else
-            Layer.listeners.remove(this);
-
-        if (newFrame != null) {
-        	UploadAction.registerUploadHook(uploadHook = new ValidateUploadHook(this));
-        } else {
-        	UploadAction.unregisterUploadHook(uploadHook);
-        	uploadHook = null;
-        }
-    }
-
-    public void initializeErrorLayer() {
-        if (!Main.pref.getBoolean(PreferenceEditor.PREF_LAYER, true))
-            return;
-        if (errorLayer == null) {
-            errorLayer = new ErrorLayer(this);
-            Main.main.addLayer(errorLayer);
-        }
-    }
-
-    /** Gets a map from simple names to all tests. */
-    public static Map<String, Test> getAllTestsMap() {
-        Map<String, Test> tests = new HashMap<String, Test>();
-        for (Class<Test> testClass : getAllAvailableTests()) {
-            try {
-                Test test = testClass.newInstance();
-                tests.put(testClass.getSimpleName(), test);
-            } catch (Exception e) {
-                e.printStackTrace();
-                continue;
-            }
-        }
-        applyPrefs(tests, false);
-        applyPrefs(tests, true);
-        return tests;
-    }
-
-    private static void applyPrefs(Map<String, Test> tests, boolean beforeUpload) {
-        Pattern regexp = Pattern.compile("(\\w+)=(true|false),?");
-        Matcher m = regexp.matcher(Main.pref.get(beforeUpload ? PreferenceEditor.PREF_TESTS_BEFORE_UPLOAD
-                : PreferenceEditor.PREF_TESTS));
-        int pos = 0;
-        while (m.find(pos)) {
-            String testName = m.group(1);
-            Test test = tests.get(testName);
-            if (test != null) {
-                boolean enabled = Boolean.valueOf(m.group(2));
-                if (beforeUpload) {
-                    test.testBeforeUpload = enabled;
-                } else {
-                    test.enabled = enabled;
-                }
-            }
-            pos = m.end();
-        }
-    }
-
-    public static Collection<Test> getTests() {
-        return getAllTestsMap().values();
-    }
-
-    public static Collection<Test> getEnabledTests(boolean beforeUpload) {
-        Collection<Test> enabledTests = getTests();
-        for (Test t : new ArrayList<Test>(enabledTests)) {
-            if (beforeUpload ? t.testBeforeUpload : t.enabled)
-                continue;
-            enabledTests.remove(t);
-        }
-        return enabledTests;
-    }
-
-    /**
-     * Gets the list of all available test classes
-     *
-     * @return An array of the test classes
-     */
-    public static Class<Test>[] getAllAvailableTests() {
-        return allAvailableTests;
-    }
-
-    /**
-     * Initialize grid details based on current projection system. Values based on
-     * the original value fixed for EPSG:4326 (10000) using heuristics (that is, test&error
-     * until most bugs were discovered while keeping the processing time reasonable)
-     */
-    public void initializeGridDetail() {
-        if (Main.proj.toString().equals(new Epsg4326().toString()))
-            OSMValidatorPlugin.griddetail = 10000;
-        else if (Main.proj.toString().equals(new Mercator().toString()))
-            OSMValidatorPlugin.griddetail = 100000;
-        else if (Main.proj.toString().equals(new Lambert().toString()))
-            OSMValidatorPlugin.griddetail = 0.1;
-    }
-
-    /**
-     * Initializes all tests
-     * @param allTests The tests to initialize
-     */
-    public void initializeTests(Collection<Test> allTests) {
-        for (Test test : allTests) {
-            try {
-                if (test.enabled) {
-                    test.getClass().getMethod("initialize", new Class[] { OSMValidatorPlugin.class }).invoke(null,
-                            new Object[] { this });
-                }
-            } catch (InvocationTargetException ite) {
-                ite.getCause().printStackTrace();
-                JOptionPane.showMessageDialog(Main.parent, 
-                		tr("Error initializing test {0}:\n {1}", test.getClass()
-                        .getSimpleName(), ite.getCause().getMessage()),
-                        tr("Error"),
-                        JOptionPane.ERROR_MESSAGE);
-            } catch (Exception e) {
-                e.printStackTrace();
-                JOptionPane.showMessageDialog(Main.parent, 
-                		tr("Error initializing test {0}:\n {1}", test.getClass()
-                        .getSimpleName(), e),
-                        tr("Error"),
-                        JOptionPane.ERROR_MESSAGE);
-            }
-        }
-    }
-
-    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
-        if (newLayer instanceof OsmDataLayer) {
-            List<TestError> errors = layerErrors.get(newLayer);
-            validationDialog.tree.setErrorList(errors);
-            Main.map.repaint();
-        }
-    }
-
-    public void layerAdded(Layer newLayer) {
-        if (newLayer instanceof OsmDataLayer) {
-            layerErrors.put(newLayer, new ArrayList<TestError>());
-        }
-    }
-
-    public void layerRemoved(Layer oldLayer) {
-        layerErrors.remove(oldLayer);
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/PreferenceEditor.java b/validator/src/org/openstreetmap/josm/plugins/validator/PreferenceEditor.java
deleted file mode 100644
index 45fcf87..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/PreferenceEditor.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package org.openstreetmap.josm.plugins.validator;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.GridBagLayout;
-import java.util.Collection;
-
-import javax.swing.BorderFactory;
-import javax.swing.JCheckBox;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.gui.preferences.PreferenceDialog;
-import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
-import org.openstreetmap.josm.plugins.validator.util.Util;
-import org.openstreetmap.josm.tools.GBC;
-
-/**
- * Preference settings for the validator plugin
- * 
- * @author frsantos
- */
-public class PreferenceEditor implements PreferenceSetting
-{
-    private OSMValidatorPlugin plugin;
-
-    /** The preferences prefix */
-    public static final String PREFIX = "validator";
-
-    /** The preferences key for debug preferences */
-    public static final String PREF_DEBUG = PREFIX + ".debug";
-
-    /** The preferences key for debug preferences */
-    public static final String PREF_LAYER = PREFIX + ".layer";
-
-    /** The preferences key for enabled tests */
-    public static final String PREF_TESTS = PREFIX + ".tests";
-
-    /** The preferences key for enabled tests */
-    public static final String PREF_USE_IGNORE = PREFIX + ".ignore";
-
-    /** The preferences key for enabled tests before upload*/
-    public static final String PREF_TESTS_BEFORE_UPLOAD = PREFIX + ".testsBeforeUpload";
-
-    /** The preferences key for ignored severity other on upload */
-    public static final String PREF_OTHER_UPLOAD = PREFIX + ".otherUpload";
-
-    /**
-     * The preferences key for enabling the permanent filtering
-     * of the displayed errors in the tree regarding the current selection 
-     */
-    public static final String PREF_FILTER_BY_SELECTION = PREFIX + ".selectionFilter";
-
-    private JCheckBox prefUseIgnore;
-    private JCheckBox prefUseLayer;
-    private JCheckBox prefOtherUpload;
-
-    /** The list of all tests */
-    private Collection<Test> allTests;
-
-    public PreferenceEditor(OSMValidatorPlugin plugin) {
-        this.plugin = plugin;
-    }
-
-    public void addGui(PreferenceDialog gui)
-    {
-        JPanel testPanel = new JPanel(new GridBagLayout());
-        testPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
-
-        prefUseIgnore = new JCheckBox(tr("Use ignore list."), Main.pref.getBoolean(PREF_USE_IGNORE, true));
-        prefUseIgnore.setToolTipText(tr("Use the ignore list to suppress warnings."));
-        testPanel.add(prefUseIgnore, GBC.eol());
-
-        prefUseLayer = new JCheckBox(tr("Use error layer."), Main.pref.getBoolean(PREF_LAYER, true));
-        prefUseLayer.setToolTipText(tr("Use the error layer to display problematic elements."));
-        testPanel.add(prefUseLayer, GBC.eol());
-
-        prefOtherUpload = new JCheckBox(tr("Show informational level on upload."), Main.pref.getBoolean(PREF_OTHER_UPLOAD, false));
-        prefOtherUpload.setToolTipText(tr("Show the informational tests in the upload check windows."));
-        testPanel.add(prefOtherUpload, GBC.eol());
-
-        GBC a = GBC.eol().insets(-5,0,0,0);
-        a.anchor = GBC.EAST;
-        testPanel.add( new JLabel(tr("On demand")), GBC.std() );
-        testPanel.add( new JLabel(tr("On upload")), a );
-
-        allTests = OSMValidatorPlugin.getTests();
-        for(Test test: allTests)
-        {
-            test.addGui(testPanel);
-        }
-
-        JScrollPane testPane = new JScrollPane(testPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
-        testPane.setBorder(null);
-
-        String description = tr("An OSM data validator that checks for common errors made by users and editor programs.");
-        JPanel tab = gui.createPreferenceTab("validator", tr("Data validator"), description);
-        tab.add(testPane, GBC.eol().fill(GBC.BOTH));
-        tab.add(GBC.glue(0,10), a);
-    }
-
-    public boolean ok()
-    {
-        StringBuilder tests = new StringBuilder();
-        StringBuilder testsBeforeUpload = new StringBuilder();
-        Boolean res = false;
-
-        for (Test test : allTests)
-        {
-            if(test.ok())
-                res = false;
-            String name = test.getClass().getSimpleName();
-            tests.append( ',' ).append( name ).append( '=' ).append( test.enabled );
-            testsBeforeUpload.append( ',' ).append( name ).append( '=' ).append( test.testBeforeUpload );
-        }
-
-        if (tests.length() > 0 ) tests = tests.deleteCharAt(0);
-        if (testsBeforeUpload.length() > 0 ) testsBeforeUpload = testsBeforeUpload.deleteCharAt(0);
-
-        plugin.initializeTests( allTests );
-
-        Main.pref.put( PREF_TESTS, tests.toString());
-        Main.pref.put( PREF_TESTS_BEFORE_UPLOAD, testsBeforeUpload.toString());
-        Main.pref.put( PREF_USE_IGNORE, prefUseIgnore.isSelected());
-        Main.pref.put( PREF_OTHER_UPLOAD, prefOtherUpload.isSelected());
-        Main.pref.put( PREF_LAYER, prefUseLayer.isSelected());
-        return false;
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/Severity.java b/validator/src/org/openstreetmap/josm/plugins/validator/Severity.java
deleted file mode 100644
index 253b3c4..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/Severity.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package org.openstreetmap.josm.plugins.validator;
-
-import static org.openstreetmap.josm.tools.I18n.marktr;
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.Color;
-
-import org.openstreetmap.josm.Main;
-
-/** The error severity */
-public enum Severity {
-    /** Error messages */
-    ERROR(tr("Errors"), "error.gif",       Main.pref.getColor(marktr("validation error"), Color.RED)),
-    /** Warning messages */
-    WARNING(tr("Warnings"), "warning.gif", Main.pref.getColor(marktr("validation warning"), Color.YELLOW)),
-    /** Other messages */
-    OTHER(tr("Other"), "other.gif",        Main.pref.getColor(marktr("validation other"), Color.CYAN));
-
-    /** Description of the severity code */
-    private final String message;
-
-    /** Associated icon */
-    private final String icon;
-
-    /** Associated color */
-    private final Color color;
-
-    /**
-     * Constructor
-     *
-     * @param message Description
-     * @param icon Associated icon
-     * @param color The color of this severity
-     */
-    Severity(String message, String icon, Color color)
-    {
-        this.message = message;
-        this.icon = icon;
-        this.color = color;
-    }
-
-    @Override
-    public String toString()
-    {
-        return message;
-    }
-
-    /**
-     * Gets the associated icon
-     * @return the associated icon
-     */
-    public String getIcon()
-    {
-        return icon;
-    }
-
-    /**
-     * Gets the associated color
-     * @return The associated color
-     */
-    public Color getColor()
-    {
-        return color;
-    }
-
-
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/Test.java b/validator/src/org/openstreetmap/josm/plugins/validator/Test.java
deleted file mode 100644
index 26d738a..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/Test.java
+++ /dev/null
@@ -1,228 +0,0 @@
-package org.openstreetmap.josm.plugins.validator;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import javax.swing.JCheckBox;
-import javax.swing.JPanel;
-
-import org.openstreetmap.josm.command.Command;
-import org.openstreetmap.josm.data.osm.BackreferencedDataSet;
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.Relation;
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.data.osm.visitor.AbstractVisitor;
-import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
-import org.openstreetmap.josm.gui.progress.ProgressMonitor;
-import org.openstreetmap.josm.tools.GBC;
-
-/**
- * Parent class for all validation tests.
- * <p>
- * A test is a primitive visitor, so that it can access to all data to be
- * validated. These primitives are always visited in the same order: nodes
- * first, then ways.
- *
- * @author frsantos
- */
-public class Test extends AbstractVisitor
-{
-    /** Name of the test */
-    protected String name;
-
-    /** Description of the test */
-    protected String description;
-
-    /** Whether this test is enabled. Enabled by default */
-    protected boolean enabled = true;
-
-    /** The preferences check for validation */
-    protected JCheckBox checkEnabled;
-
-    /** The preferences check for validation on upload */
-    protected JCheckBox checkBeforeUpload;
-
-    /** Whether this test must check before upload. Enabled by default */
-    protected boolean testBeforeUpload = true;
-
-    /** Whether this test is performing just before an upload */
-    protected boolean isBeforeUpload;
-
-    /** The list of errors */
-    protected List<TestError> errors = new ArrayList<TestError>(30);
-
-    /** Whether the test is run on a partial selection data */
-    protected boolean partialSelection;
-
-    /** the progress monitor to use */
-    protected ProgressMonitor progressMonitor;
-
-    /**
-     * the data structure with child->parent references
-     */
-    protected BackreferencedDataSet backreferenceDataSet;
-
-    /**
-     * Constructor
-     * @param name Name of the test
-     * @param description Description of the test
-     */
-    public Test(String name, String description)
-    {
-        this.name = name;
-        this.description = description;
-    }
-
-    /**
-     * Constructor
-     * @param name Name of the test
-     */
-    public Test(String name)
-    {
-        this.name = name;
-    }
-
-    /**
-     * Initializes any global data used this tester.
-     * @param plugin The plugin
-     * @throws Exception When cannot initialize the test
-     */
-    public static void initialize(OSMValidatorPlugin plugin) throws Exception {}
-
-    /**
-     * Start the test using a given progress monitor
-     *
-     * @param progressMonitor  the progress monitor
-     */
-    public void startTest(ProgressMonitor progressMonitor) {
-        backreferenceDataSet = new BackreferencedDataSet();
-        if (progressMonitor == null) {
-                this.progressMonitor = NullProgressMonitor.INSTANCE;
-        } else {
-                this.progressMonitor = progressMonitor;
-        }
-        this.progressMonitor.beginTask(tr("Running test {0}", name));
-        errors = new ArrayList<TestError>(30);
-    }
-
-    /**
-     * Flag notifying that this test is run over a partial data selection
-     * @param partialSelection Whether the test is on a partial selection data
-     */
-    public void setPartialSelection(boolean partialSelection)
-    {
-        this.partialSelection = partialSelection;
-    }
-
-    /**
-     * Gets the validation errors accumulated until this moment.
-     * @return The list of errors
-     */
-    public List<TestError> getErrors()
-    {
-        return errors;
-    }
-
-    /**
-     * Notification of the end of the test. The tester may perform additional
-     * actions and destroy the used structures
-     */
-    public void endTest() {
-        progressMonitor.finishTask();
-        progressMonitor = null;
-        backreferenceDataSet = null;
-    }
-
-    /**
-     * Visits all primitives to be tested. These primitives are always visited
-     * in the same order: nodes first, then ways.
-     *
-     * @param selection The primitives to be tested
-     */
-    public void visit(Collection<OsmPrimitive> selection)
-    {
-        progressMonitor.setTicksCount(selection.size());
-        for (OsmPrimitive p : selection) {
-            if( p.isUsable() )
-                p.visit(this);
-            progressMonitor.worked(1);
-        }
-    }
-
-    public void visit(Node n) {}
-
-    public void visit(Way w) {}
-
-    public void visit(Relation r) {}
-
-    /**
-     * Allow the tester to manage its own preferences
-     * @param testPanel The panel to add any preferences component
-     */
-    public void addGui(JPanel testPanel)
-    {
-        checkEnabled = new JCheckBox(name, enabled);
-        checkEnabled.setToolTipText(description);
-        testPanel.add(checkEnabled, GBC.std());
-
-        GBC a = GBC.eol();
-        a.anchor = GBC.EAST;
-        checkBeforeUpload = new JCheckBox();
-        checkBeforeUpload.setSelected(testBeforeUpload);
-        testPanel.add(checkBeforeUpload, a);
-    }
-
-    /**
-     * Called when the used submits the preferences
-     */
-    public boolean ok()
-    {
-        enabled = checkEnabled.isSelected();
-        testBeforeUpload = checkBeforeUpload.isSelected();
-        return false;
-    }
-
-    /**
-     * Fixes the error with the appropiate command
-     *
-     * @param testError
-     * @return The command to fix the error
-     */
-    public Command fixError(TestError testError)
-    {
-        return null;
-    }
-
-    /**
-     * Returns true if the given error can be fixed automatically
-     *
-     * @param testError The error to check if can be fixed
-     * @return true if the error can be fixed
-     */
-    public boolean isFixable(TestError testError)
-    {
-        return false;
-    }
-
-    /**
-     * Returns true if this plugin must check the uploaded data before uploading
-     * @return true if this plugin must check the uploaded data before uploading
-     */
-    public boolean testBeforeUpload()
-    {
-        return testBeforeUpload;
-    }
-
-    /**
-     * Sets the flag that marks an upload check
-     * @param isUpload if true, the test is before upload
-     */
-    public void setBeforeUpload(boolean isUpload)
-    {
-        this.isBeforeUpload = isUpload;
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/TestError.java b/validator/src/org/openstreetmap/josm/plugins/validator/TestError.java
deleted file mode 100644
index 47aa3b6..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/TestError.java
+++ /dev/null
@@ -1,400 +0,0 @@
-package org.openstreetmap.josm.plugins.validator;
-
-import java.awt.Color;
-import java.awt.Graphics;
-import java.awt.Point;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.TreeSet;
-
-import org.openstreetmap.josm.command.Command;
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.Relation;
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.data.osm.WaySegment;
-import org.openstreetmap.josm.data.osm.visitor.AbstractVisitor;
-import org.openstreetmap.josm.gui.MapView;
-
-/**
- * Validation error
- * @author frsantos
- */
-public class TestError {
-    /** is this error on the ignore list */
-    private Boolean ignored = false;
-    /** Severity */
-    private Severity severity;
-    /** The error message */
-    private String message;
-    /** Deeper error description */
-    private String description;
-    private String description_en;
-    /** The affected primitives */
-    private List<? extends OsmPrimitive> primitives;
-    /** The primitives to be highlighted */
-    private List<?> highlighted;
-    /** The tester that raised this error */
-    private Test tester;
-    /** Internal code used by testers to classify errors */
-    private int code;
-    /** If this error is selected */
-    private boolean selected;
-
-    /**
-     * Constructors
-     * @param tester The tester
-     * @param severity The severity of this error
-     * @param message The error message
-     * @param primitive The affected primitive
-     * @param primitives The affected primitives
-     * @param code The test error reference code
-     */
-    public TestError(Test tester, Severity severity, String message, String description, String description_en,
-            int code, List<? extends OsmPrimitive> primitives, List<?> highlighted) {
-        this.tester = tester;
-        this.severity = severity;
-        this.message = message;
-        this.description = description;
-        this.description_en = description_en;
-        this.primitives = primitives;
-        this.highlighted = highlighted;
-        this.code = code;
-    }
-
-    public TestError(Test tester, Severity severity, String message, int code, List<? extends OsmPrimitive> primitives,
-            List<?> highlighted) {
-        this(tester, severity, message, null, null, code, primitives, highlighted);
-    }
-
-    public TestError(Test tester, Severity severity, String message, String description, String description_en,
-            int code, List<? extends OsmPrimitive> primitives) {
-        this(tester, severity, message, description, description_en, code, primitives, primitives);
-    }
-
-    public TestError(Test tester, Severity severity, String message, int code, List<? extends OsmPrimitive> primitives) {
-        this(tester, severity, message, null, null, code, primitives, primitives);
-    }
-
-    public TestError(Test tester, Severity severity, String message, int code, OsmPrimitive primitive) {
-        this(tester, severity, message, null, null, code, Collections.singletonList(primitive), Collections
-                .singletonList(primitive));
-    }
-
-    public TestError(Test tester, Severity severity, String message, String description, String description_en,
-            int code, OsmPrimitive primitive) {
-        this(tester, severity, message, description, description_en, code, Collections.singletonList(primitive));
-    }
-
-    /**
-     * Gets the error message
-     * @return the error message
-     */
-    public String getMessage() {
-        return message;
-    }
-
-    /**
-     * Gets the error message
-     * @return the error description
-     */
-    public String getDescription() {
-        return description;
-    }
-
-    /**
-     * Sets the error message
-     * @param message The error message
-     */
-    public void setMessage(String message) {
-        this.message = message;
-    }
-
-    /**
-     * Gets the list of primitives affected by this error
-     * @return the list of primitives affected by this error
-     */
-    public List<? extends OsmPrimitive> getPrimitives() {
-        return primitives;
-    }
-
-    /**
-     * Sets the list of primitives affected by this error
-     * @param primitives the list of primitives affected by this error
-     */
-
-    public void setPrimitives(List<OsmPrimitive> primitives) {
-        this.primitives = primitives;
-    }
-
-    /**
-     * Gets the severity of this error
-     * @return the severity of this error
-     */
-    public Severity getSeverity() {
-        return severity;
-    }
-
-    /**
-     * Sets the severity of this error
-     * @param severity the severity of this error
-     */
-    public void setSeverity(Severity severity) {
-        this.severity = severity;
-    }
-
-    /**
-     * Sets the ignore state for this error
-     */
-    public String getIgnoreState() {
-        Collection<String> strings = new TreeSet<String>();
-        String ignorestring = getIgnoreSubGroup();
-        for (OsmPrimitive o : primitives) {
-            // ignore data not yet uploaded
-            if (o.isNew())
-                return null;
-            String type = "u";
-            if (o instanceof Way)
-                type = "w";
-            else if (o instanceof Relation)
-                type = "r";
-            else if (o instanceof Node)
-                type = "n";
-            strings.add(type + "_" + o.getId());
-        }
-        for (String o : strings) {
-            ignorestring += ":" + o;
-        }
-        return ignorestring;
-    }
-
-    public String getIgnoreSubGroup() {
-        String ignorestring = getIgnoreGroup();
-        if (description_en != null)
-            ignorestring += "_" + description_en;
-        return ignorestring;
-    }
-
-    public String getIgnoreGroup() {
-        return Integer.toString(code);
-    }
-
-    public void setIgnored(boolean state) {
-        ignored = state;
-    }
-
-    public Boolean getIgnored() {
-        return ignored;
-    }
-
-    /**
-     * Gets the tester that raised this error
-     * @return the tester that raised this error
-     */
-    public Test getTester() {
-        return tester;
-    }
-
-    /**
-     * Gets the code
-     * @return the code
-     */
-    public int getCode() {
-        return code;
-    }
-
-    /**
-     * Returns true if the error can be fixed automatically
-     *
-     * @return true if the error can be fixed
-     */
-    public boolean isFixable() {
-        return tester != null && tester.isFixable(this);
-    }
-
-    /**
-     * Fixes the error with the appropiate command
-     *
-     * @return The command to fix the error
-     */
-    public Command getFix() {
-        if (tester == null)
-            return null;
-
-        return tester.fixError(this);
-    }
-
-    /**
-     * Paints the error on affected primitives
-     *
-     * @param g The graphics
-     * @param mv The MapView
-     */
-    public void paint(Graphics g, MapView mv) {
-        if (!ignored) {
-            PaintVisitor v = new PaintVisitor(g, mv);
-            visitHighlighted(v);
-        }
-    }
-
-    public void visitHighlighted(ValidatorVisitor v) {
-        for (Object o : highlighted) {
-            if (o instanceof OsmPrimitive)
-                v.visit((OsmPrimitive) o);
-            else if (o instanceof WaySegment)
-                v.visit((WaySegment) o);
-        }
-    }
-
-    /**
-     * Visitor that highlights the primitives affected by this error
-     * @author frsantos
-     */
-    class PaintVisitor extends AbstractVisitor implements ValidatorVisitor {
-        /** The graphics */
-        private final Graphics g;
-        /** The MapView */
-        private final MapView mv;
-
-        /**
-         * Constructor
-         * @param g The graphics
-         * @param mv The Mapview
-         */
-        public PaintVisitor(Graphics g, MapView mv) {
-            this.g = g;
-            this.mv = mv;
-        }
-
-        public void visit(OsmPrimitive p) {
-            if (p.isUsable()) {
-                p.visit(this);
-            }
-        }
-
-        /**
-         * Draws a circle around the node
-         * @param n The node
-         * @param color The circle color
-         */
-        public void drawNode(Node n, Color color) {
-            Point p = mv.getPoint(n);
-            g.setColor(color);
-            if (selected) {
-                g.fillOval(p.x - 5, p.y - 5, 10, 10);
-            } else
-                g.drawOval(p.x - 5, p.y - 5, 10, 10);
-        }
-
-        /**
-         * Draws a line around the segment
-         *
-         * @param s The segment
-         * @param color The color
-         */
-        public void drawSegment(Node n1, Node n2, Color color) {
-            Point p1 = mv.getPoint(n1);
-            Point p2 = mv.getPoint(n2);
-            g.setColor(color);
-
-            double t = Math.atan2(p2.x - p1.x, p2.y - p1.y);
-            double cosT = Math.cos(t);
-            double sinT = Math.sin(t);
-            int deg = (int) Math.toDegrees(t);
-            if (selected) {
-                int[] x = new int[] { (int) (p1.x + 5 * cosT), (int) (p2.x + 5 * cosT), (int) (p2.x - 5 * cosT),
-                        (int) (p1.x - 5 * cosT) };
-                int[] y = new int[] { (int) (p1.y - 5 * sinT), (int) (p2.y - 5 * sinT), (int) (p2.y + 5 * sinT),
-                        (int) (p1.y + 5 * sinT) };
-                g.fillPolygon(x, y, 4);
-                g.fillArc(p1.x - 5, p1.y - 5, 10, 10, deg, 180);
-                g.fillArc(p2.x - 5, p2.y - 5, 10, 10, deg, -180);
-            } else {
-                g.drawLine((int) (p1.x + 5 * cosT), (int) (p1.y - 5 * sinT), (int) (p2.x + 5 * cosT),
-                        (int) (p2.y - 5 * sinT));
-                g.drawLine((int) (p1.x - 5 * cosT), (int) (p1.y + 5 * sinT), (int) (p2.x - 5 * cosT),
-                        (int) (p2.y + 5 * sinT));
-                g.drawArc(p1.x - 5, p1.y - 5, 10, 10, deg, 180);
-                g.drawArc(p2.x - 5, p2.y - 5, 10, 10, deg, -180);
-            }
-        }
-
-        /**
-         * Draw a small rectangle.
-         * White if selected (as always) or red otherwise.
-         *
-         * @param n The node to draw.
-         */
-        public void visit(Node n) {
-            if (isNodeVisible(n))
-                drawNode(n, severity.getColor());
-        }
-
-        public void visit(Way w) {
-            Node lastN = null;
-            for (Node n : w.getNodes()) {
-                if (lastN == null) {
-                    lastN = n;
-                    continue;
-                }
-                if (isSegmentVisible(lastN, n)) {
-                    drawSegment(lastN, n, severity.getColor());
-                }
-                lastN = n;
-            }
-        }
-
-        public void visit(WaySegment ws) {
-            if (ws.lowerIndex < 0 || ws.lowerIndex + 1 >= ws.way.getNodesCount())
-                return;
-            Node a = ws.way.getNodes().get(ws.lowerIndex), b = ws.way.getNodes().get(ws.lowerIndex + 1);
-            if (isSegmentVisible(a, b)) {
-                drawSegment(a, b, severity.getColor());
-            }
-        }
-
-        public void visit(Relation r) {
-            /* No idea how to draw a relation. */
-        }
-
-        /**
-         * Checks if the given node is in the visible area.
-         * @param n The node to check for visibility
-         * @return true if the node is visible
-         */
-        protected boolean isNodeVisible(Node n) {
-            Point p = mv.getPoint(n);
-            return !((p.x < 0) || (p.y < 0) || (p.x > mv.getWidth()) || (p.y > mv.getHeight()));
-        }
-
-        /**
-         * Checks if the given segment is in the visible area.
-         * NOTE: This will return true for a small number of non-visible
-         *       segments.
-         * @param ls The segment to check
-         * @return true if the segment is visible
-         */
-        protected boolean isSegmentVisible(Node n1, Node n2) {
-            Point p1 = mv.getPoint(n1);
-            Point p2 = mv.getPoint(n2);
-            if ((p1.x < 0) && (p2.x < 0))
-                return false;
-            if ((p1.y < 0) && (p2.y < 0))
-                return false;
-            if ((p1.x > mv.getWidth()) && (p2.x > mv.getWidth()))
-                return false;
-            if ((p1.y > mv.getHeight()) && (p2.y > mv.getHeight()))
-                return false;
-            return true;
-        }
-    }
-
-    /**
-     * Sets the selection flag of this error
-     * @param selected if this error is selected
-     */
-    public void setSelected(boolean selected) {
-        this.selected = selected;
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/ValidateAction.java b/validator/src/org/openstreetmap/josm/plugins/validator/ValidateAction.java
deleted file mode 100644
index 547928f..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/ValidateAction.java
+++ /dev/null
@@ -1,187 +0,0 @@
-package org.openstreetmap.josm.plugins.validator;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.event.ActionEvent;
-import java.awt.event.KeyEvent;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import javax.swing.SwingUtilities;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.JosmAction;
-import org.openstreetmap.josm.data.osm.DataSet;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.gui.PleaseWaitRunnable;
-import org.openstreetmap.josm.io.OsmTransferException;
-import org.openstreetmap.josm.plugins.validator.util.AgregatePrimitivesVisitor;
-import org.openstreetmap.josm.tools.Shortcut;
-import org.xml.sax.SAXException;
-
-/**
- * The action that does the validate thing.
- * <p>
- * This action iterates through all active tests and give them the data, so that
- * each one can test it.
- *
- * @author frsantos
- */
-public class ValidateAction extends JosmAction {
-    private OSMValidatorPlugin plugin;
-
-    /** Serializable ID */
-    private static final long serialVersionUID = -2304521273582574603L;
-
-    /** Last selection used to validate */
-    private Collection<OsmPrimitive> lastSelection;
-
-    /**
-     * Constructor
-     */
-    public ValidateAction(OSMValidatorPlugin plugin) {
-        super(tr("Validation"), "validator", tr("Performs the data validation"),
-        Shortcut.registerShortcut("tools:validate", tr("Tool: {0}", tr("Validation")), KeyEvent.VK_V, Shortcut.GROUP_EDIT, Shortcut.SHIFT_DEFAULT), true);
-        this.plugin = plugin;
-    }
-
-    public void actionPerformed(ActionEvent ev) {
-        doValidate(ev, true);
-    }
-
-    /**
-     * Does the validation.
-     * <p>
-     * If getSelectedItems is true, the selected items (or all items, if no one
-     * is selected) are validated. If it is false, last selected items are
-     * revalidated
-     *
-     * @param ev The event
-     * @param getSelectedItems If selected or last selected items must be validated
-     */
-    public void doValidate(ActionEvent ev, boolean getSelectedItems) {
-        if (plugin.validateAction == null || Main.map == null || !Main.map.isVisible())
-            return;
-
-        OSMValidatorPlugin.plugin.initializeErrorLayer();
-
-        Collection<Test> tests = OSMValidatorPlugin.getEnabledTests(false);
-        if (tests.isEmpty())
-            return;
-
-        Collection<OsmPrimitive> selection;
-        if (getSelectedItems) {
-            selection = Main.main.getCurrentDataSet().getSelected();
-            if (selection.isEmpty()) {
-                selection = Main.main.getCurrentDataSet().allNonDeletedPrimitives();
-                lastSelection = null;
-            } else {
-                AgregatePrimitivesVisitor v = new AgregatePrimitivesVisitor();
-                selection = v.visit(selection);
-                lastSelection = selection;
-            }
-        } else {
-            if (lastSelection == null)
-                selection = Main.main.getCurrentDataSet().allNonDeletedPrimitives();
-            else
-                selection = lastSelection;
-        }
-
-        ValidationTask task = new ValidationTask(tests, selection, lastSelection);
-        Main.worker.submit(task);        
-    }
-
-    @Override
-    public void updateEnabledState() {
-        setEnabled(getEditLayer() != null);
-    }
-    
-    /**
-     * Asynchronous task for running a collection of tests against a collection
-     * of primitives 
-     *
-     */
-    
-    class ValidationTask extends PleaseWaitRunnable {
-    	private Collection<Test> tests;
-    	private Collection<OsmPrimitive> validatedPrimitmives;
-    	private Collection<OsmPrimitive> formerValidatedPrimitives;
-    	private boolean canceled;
-        private List<TestError> errors;
-        
-        /**
-         * 
-         * @param tests  the tests to run 
-         * @param validatedPrimitives the collection of primitives to validate. 
-         * @param formerValidatedPrimitives the last collection of primitives being validates. May be null.
-         */
-    	public ValidationTask(Collection<Test> tests, Collection<OsmPrimitive> validatedPrimitives, Collection<OsmPrimitive> formerValidatedPrimitives) {
-    		super(tr("Validating"), false /*don't ignore exceptions */);
-    		this.validatedPrimitmives  = validatedPrimitives;
-    		this.formerValidatedPrimitives = formerValidatedPrimitives;
-    		this.tests = tests;
-    	}
-    	
-		@Override
-		protected void cancel() {
-			this.canceled = true; 			
-		}
-
-		@Override
-		protected void finish() {
-			if (canceled) return;
-			
-			// update GUI on Swing EDT
-			//
-			Runnable r = new Runnable()  {
-				public void run() {
-			        plugin.validationDialog.tree.setErrors(errors);
-			        plugin.validationDialog.setVisible(true);
-			        Main.main.getCurrentDataSet().fireSelectionChanged();
-				}				
-			};
-			if (SwingUtilities.isEventDispatchThread()) {
-				r.run();				
-			} else {
-				SwingUtilities.invokeLater(r);
-			}
-		}
-
-		@Override
-		protected void realRun() throws SAXException, IOException,
-				OsmTransferException {
-			if (tests == null || tests.isEmpty()) return;		
-	        errors = new ArrayList<TestError>(200);
-	        getProgressMonitor().setTicksCount(tests.size() * validatedPrimitmives.size());
-	        int testCounter = 0;
-			for (Test test : tests) {				
-				if (canceled) return;
-				testCounter++;
-				getProgressMonitor().setCustomText(tr("Test {0}/{1}: Starting {2}", testCounter, tests.size(),test.name));
-	            test.setPartialSelection(formerValidatedPrimitives != null);
-	            test.startTest(getProgressMonitor().createSubTaskMonitor(validatedPrimitmives.size(), false));
-	            test.visit(validatedPrimitmives);
-	            test.endTest();
-	            errors.addAll(test.getErrors());
-	        }
-			tests = null;
-	        if (Main.pref.getBoolean(PreferenceEditor.PREF_USE_IGNORE, true)) {
-				getProgressMonitor().subTask(tr("Updating ignored errors ..."));
-	            for (TestError error : errors) {
-	            	if (canceled) return;
-	                List<String> s = new ArrayList<String>();
-	                s.add(error.getIgnoreState());
-	                s.add(error.getIgnoreGroup());
-	                s.add(error.getIgnoreSubGroup());
-	                for (String state : s) {
-	                    if (state != null && plugin.ignoredErrors.contains(state)) {
-	                        error.setIgnored(true);
-	                    }
-	                }
-	            }
-	        }
-		}
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/ValidateUploadHook.java b/validator/src/org/openstreetmap/josm/plugins/validator/ValidateUploadHook.java
deleted file mode 100644
index 6b24967..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/ValidateUploadHook.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package org.openstreetmap.josm.plugins.validator;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.GridBagLayout;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.upload.UploadHook;
-import org.openstreetmap.josm.data.APIDataSet;
-import org.openstreetmap.josm.data.osm.DataSet;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.plugins.validator.util.AgregatePrimitivesVisitor;
-import org.openstreetmap.josm.tools.GBC;
-
-/**
- * The action that does the validate thing.
- * <p>
- * This action iterates through all active tests and give them the data, so that
- * each one can test it.
- *
- * @author frsantos
- */
-public class ValidateUploadHook implements UploadHook
-{
-    /** Serializable ID */
-    private static final long serialVersionUID = -2304521273582574603L;
-
-    private OSMValidatorPlugin plugin;
-
-    public ValidateUploadHook(OSMValidatorPlugin plugin)
-    {
-        this.plugin = plugin;
-    }
-
-    /**
-     * Validate the modified data before uploading
-     */
-    public boolean checkUpload(APIDataSet apiDataSet)
-    {
-        Collection<Test> tests = OSMValidatorPlugin.getEnabledTests(true);
-        if( tests.isEmpty() )
-            return true;
-
-        AgregatePrimitivesVisitor v = new AgregatePrimitivesVisitor();
-        v.visit(apiDataSet.getPrimitivesToAdd());
-        Collection<OsmPrimitive> selection = v.visit(apiDataSet.getPrimitivesToUpdate());
-
-        List<TestError> errors = new ArrayList<TestError>(30);
-        for(Test test : tests)
-        {
-            test.setBeforeUpload(true);
-            test.setPartialSelection(true);
-            test.startTest(null);
-            test.visit(selection);
-            test.endTest();
-            if(Main.pref.getBoolean(PreferenceEditor.PREF_OTHER_UPLOAD, false))
-                errors.addAll( test.getErrors() );
-            else
-            {
-                for(TestError e : test.getErrors())
-                {
-                    if(e.getSeverity() != Severity.OTHER)
-                        errors.add(e);
-                }
-            }
-        }
-        tests = null;
-        if(errors == null || errors.isEmpty())
-            return true;
-
-        if(Main.pref.getBoolean(PreferenceEditor.PREF_USE_IGNORE, true))
-        {
-            int nume = 0;
-            for(TestError error : errors)
-            {
-                List<String> s = new ArrayList<String>();
-                s.add(error.getIgnoreState());
-                s.add(error.getIgnoreGroup());
-                s.add(error.getIgnoreSubGroup());
-                for(String state : s)
-                {
-                    if(state != null && plugin.ignoredErrors.contains(state))
-                    {
-                        error.setIgnored(true);
-                    }
-                }
-                if(!error.getIgnored())
-                    ++nume;
-            }
-            if(nume == 0)
-                return true;
-        }
-        return displayErrorScreen(errors);
-    }
-
-    /**
-     * Displays a screen where the actions that would be taken are displayed and
-     * give the user the possibility to cancel the upload.
-     * @param errors The errors displayed in the screen
-     * @return <code>true</code>, if the upload should continue. <code>false</code>
-     *          if the user requested cancel.
-     */
-    private boolean displayErrorScreen(List<TestError> errors)
-    {
-        JPanel p = new JPanel(new GridBagLayout());
-        ErrorTreePanel errorPanel = new ErrorTreePanel(errors);
-        errorPanel.expandAll();
-        p.add(new JScrollPane(errorPanel), GBC.eol());
-
-        int res  = JOptionPane.showConfirmDialog(Main.parent, p,
-        tr("Data with errors. Upload anyway?"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
-        if(res == JOptionPane.NO_OPTION)
-        {
-            plugin.validationDialog.tree.setErrors(errors);
-            plugin.validationDialog.setVisible(true);
-            Main.main.getCurrentDataSet().fireSelectionChanged();
-        }
-        return res == JOptionPane.YES_OPTION;
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/ValidatorDialog.java b/validator/src/org/openstreetmap/josm/plugins/validator/ValidatorDialog.java
deleted file mode 100644
index f7f2edf..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/ValidatorDialog.java
+++ /dev/null
@@ -1,521 +0,0 @@
-package org.openstreetmap.josm.plugins.validator;
-
-import static org.openstreetmap.josm.tools.I18n.marktr;
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.BorderLayout;
-import java.awt.GridLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.KeyEvent;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.Set;
-
-import javax.swing.JMenuItem;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JPopupMenu;
-import javax.swing.JScrollPane;
-import javax.swing.SwingUtilities;
-import javax.swing.event.TreeSelectionEvent;
-import javax.swing.event.TreeSelectionListener;
-import javax.swing.tree.DefaultMutableTreeNode;
-import javax.swing.tree.TreePath;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.command.Command;
-import org.openstreetmap.josm.data.SelectionChangedListener;
-import org.openstreetmap.josm.data.osm.DataSet;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.WaySegment;
-import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
-import org.openstreetmap.josm.gui.PleaseWaitRunnable;
-import org.openstreetmap.josm.gui.SideButton;
-import org.openstreetmap.josm.gui.dialogs.ToggleDialog;
-import org.openstreetmap.josm.gui.progress.ProgressMonitor;
-import org.openstreetmap.josm.io.OsmTransferException;
-import org.openstreetmap.josm.plugins.validator.tests.DuplicateNode;
-import org.openstreetmap.josm.tools.Shortcut;
-import org.xml.sax.SAXException;
-
-/**
- * A small tool dialog for displaying the current errors. The selection manager
- * respects clicks into the selection list. Ctrl-click will remove entries from
- * the list while single click will make the clicked entry the only selection.
- *
- * @author frsantos
- */
-public class ValidatorDialog extends ToggleDialog implements ActionListener, SelectionChangedListener {
-    private OSMValidatorPlugin plugin;
-
-    /** Serializable ID */
-    private static final long serialVersionUID = 2952292777351992696L;
-
-    /** The display tree */
-    protected ErrorTreePanel tree;
-
-    private SideButton fixButton;
-    /** The fix button */
-    private SideButton ignoreButton;
-    /** The ignore button */
-    private SideButton selectButton;
-    /** The select button */
-
-    private JPopupMenu popupMenu;
-    private TestError popupMenuError = null;
-
-    /** Last selected element */
-    private DefaultMutableTreeNode lastSelectedNode = null;
-
-    /**
-     * Constructor
-     */
-    public ValidatorDialog(OSMValidatorPlugin plugin) {
-        super(tr("Validation errors"), "validator", tr("Open the validation window."),
-        Shortcut.registerShortcut("subwindow:validator", tr("Toggle: {0}", tr("Validation errors")),
-        KeyEvent.VK_V, Shortcut.GROUP_LAYER, Shortcut.SHIFT_DEFAULT), 150);
-
-        this.plugin = plugin;
-        popupMenu = new JPopupMenu();
-
-        JMenuItem zoomTo = new JMenuItem(tr("Zoom to problem"));
-        zoomTo.addActionListener(new ActionListener() {
-            public void actionPerformed(ActionEvent e) {
-                zoomToProblem();
-            }
-        });
-        popupMenu.add(zoomTo);
-
-        tree = new ErrorTreePanel();
-        tree.addMouseListener(new ClickWatch());
-        tree.addTreeSelectionListener(new SelectionWatch());
-
-        add(new JScrollPane(tree), BorderLayout.CENTER);
-
-        JPanel buttonPanel = new JPanel(new GridLayout(1, 3));
-
-        selectButton = new SideButton(marktr("Select"), "select", "Validator",
-                tr("Set the selected elements on the map to the selected items in the list above."), this);
-        selectButton.setEnabled(false);
-        buttonPanel.add(selectButton);
-        buttonPanel.add(new SideButton(plugin.validateAction), "refresh");
-        fixButton = new SideButton(marktr("Fix"), "fix", "Validator", tr("Fix the selected errors."), this);
-        fixButton.setEnabled(false);
-        buttonPanel.add(fixButton);
-        if (Main.pref.getBoolean(PreferenceEditor.PREF_USE_IGNORE, true)) {
-            ignoreButton = new SideButton(marktr("Ignore"), "delete", "Validator",
-                    tr("Ignore the selected errors next time."), this);
-            ignoreButton.setEnabled(false);
-            buttonPanel.add(ignoreButton);
-        } else {
-            ignoreButton = null;
-        }
-        add(buttonPanel, BorderLayout.SOUTH);
-        DataSet.selListeners.add(this);
-    }
-
-    @Override
-    public void setVisible(boolean v) {
-        if (tree != null)
-            tree.setVisible(v);
-        super.setVisible(v);
-        Main.map.repaint();
-    }
-
-    /**
-     * Fix selected errors
-     *
-     * @param e
-     */
-    @SuppressWarnings("unchecked")
-    private void fixErrors(ActionEvent e) {
-        TreePath[] selectionPaths = tree.getSelectionPaths();
-        if (selectionPaths == null)
-            return;
-
-        Set<DefaultMutableTreeNode> processedNodes = new HashSet<DefaultMutableTreeNode>();
-
-        DuplicateNode.clearBackreferences();
-        LinkedList<TestError> errorsToFix = new LinkedList<TestError>();
-        for (TreePath path : selectionPaths) {
-            DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
-            if (node == null)
-                continue;
-
-            Enumeration<DefaultMutableTreeNode> children = node.breadthFirstEnumeration();
-            while (children.hasMoreElements()) {
-                DefaultMutableTreeNode childNode = children.nextElement();
-                if (processedNodes.contains(childNode))
-                    continue;
-
-                processedNodes.add(childNode);
-                Object nodeInfo = childNode.getUserObject();
-                if (nodeInfo instanceof TestError) {
-                    errorsToFix.add((TestError)nodeInfo);
-                }
-            }
-        }
-
-        // run fix task asynchronously
-        //
-        FixTask fixTask = new FixTask(errorsToFix);
-        Main.worker.submit(fixTask);
-    }
-
-    /**
-     * Set selected errors to ignore state
-     *
-     * @param e
-     */
-    @SuppressWarnings("unchecked")
-    private void ignoreErrors(ActionEvent e) {
-        int asked = JOptionPane.DEFAULT_OPTION;
-        boolean changed = false;
-        TreePath[] selectionPaths = tree.getSelectionPaths();
-        if (selectionPaths == null)
-            return;
-
-        Set<DefaultMutableTreeNode> processedNodes = new HashSet<DefaultMutableTreeNode>();
-        for (TreePath path : selectionPaths) {
-            DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
-            if (node == null)
-                continue;
-
-            Object mainNodeInfo = node.getUserObject();
-            if (!(mainNodeInfo instanceof TestError)) {
-                Set<String> state = new HashSet<String>();
-                // ask if the whole set should be ignored
-                if (asked == JOptionPane.DEFAULT_OPTION) {
-                    String[] a = new String[] { tr("Whole group"), tr("Single elements"), tr("Nothing") };
-                    asked = JOptionPane.showOptionDialog(Main.parent, tr("Ignore whole group or individual elements?"),
-                            tr("Ignoring elements"), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE, null,
-                            a, a[1]);
-                }
-                if (asked == JOptionPane.YES_NO_OPTION) {
-                    Enumeration<DefaultMutableTreeNode> children = node.breadthFirstEnumeration();
-                    while (children.hasMoreElements()) {
-                        DefaultMutableTreeNode childNode = children.nextElement();
-                        if (processedNodes.contains(childNode))
-                            continue;
-
-                        processedNodes.add(childNode);
-                        Object nodeInfo = childNode.getUserObject();
-                        if (nodeInfo instanceof TestError) {
-                            TestError err = (TestError) nodeInfo;
-                            err.setIgnored(true);
-                            changed = true;
-                            state.add(node.getDepth() == 1 ? err.getIgnoreSubGroup() : err.getIgnoreGroup());
-                        }
-                    }
-                    for (String s : state)
-                        plugin.ignoredErrors.add(s);
-                    continue;
-                } else if (asked == JOptionPane.CANCEL_OPTION)
-                    continue;
-            }
-
-            Enumeration<DefaultMutableTreeNode> children = node.breadthFirstEnumeration();
-            while (children.hasMoreElements()) {
-                DefaultMutableTreeNode childNode = children.nextElement();
-                if (processedNodes.contains(childNode))
-                    continue;
-
-                processedNodes.add(childNode);
-                Object nodeInfo = childNode.getUserObject();
-                if (nodeInfo instanceof TestError) {
-                    TestError error = (TestError) nodeInfo;
-                    String state = error.getIgnoreState();
-                    if (state != null)
-                        plugin.ignoredErrors.add(state);
-                    changed = true;
-                    error.setIgnored(true);
-                }
-            }
-        }
-        if (changed) {
-            tree.resetErrors();
-            plugin.saveIgnoredErrors();
-            Main.map.repaint();
-        }
-    }
-
-    private void showPopupMenu(MouseEvent e) {
-        if (!e.isPopupTrigger())
-            return;
-        popupMenuError = null;
-        TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
-        if (selPath == null)
-            return;
-        DefaultMutableTreeNode node = (DefaultMutableTreeNode) selPath.getPathComponent(selPath.getPathCount() - 1);
-        if (!(node.getUserObject() instanceof TestError))
-            return;
-        popupMenuError = (TestError) node.getUserObject();
-        popupMenu.show(e.getComponent(), e.getX(), e.getY());
-    }
-
-    private void zoomToProblem() {
-        if (popupMenuError == null)
-            return;
-        ValidatorBoundingXYVisitor bbox = new ValidatorBoundingXYVisitor();
-        popupMenuError.visitHighlighted(bbox);
-        if (bbox.getBounds() == null)
-            return;
-        bbox.enlargeBoundingBox();
-        Main.map.mapView.recalculateCenterScale(bbox);
-    }
-
-    /**
-     * Sets the selection of the map to the current selected items.
-     */
-    @SuppressWarnings("unchecked")
-    private void setSelectedItems() {
-        if (tree == null)
-            return;
-
-        Collection<OsmPrimitive> sel = new HashSet<OsmPrimitive>(40);
-
-        TreePath[] selectedPaths = tree.getSelectionPaths();
-        if (selectedPaths == null)
-            return;
-
-        for (TreePath path : selectedPaths) {
-            DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
-            Enumeration<DefaultMutableTreeNode> children = node.breadthFirstEnumeration();
-            while (children.hasMoreElements()) {
-                DefaultMutableTreeNode childNode = children.nextElement();
-                Object nodeInfo = childNode.getUserObject();
-                if (nodeInfo instanceof TestError) {
-                    TestError error = (TestError) nodeInfo;
-                    sel.addAll(error.getPrimitives());
-                }
-            }
-        }
-
-        Main.main.getCurrentDataSet().setSelected(sel);
-    }
-
-    public void actionPerformed(ActionEvent e) {
-        String actionCommand = e.getActionCommand();
-        if (actionCommand.equals("Select"))
-            setSelectedItems();
-        else if (actionCommand.equals("Fix"))
-            fixErrors(e);
-        else if (actionCommand.equals("Ignore"))
-            ignoreErrors(e);
-    }
-
-    /**
-     * Checks for fixes in selected element and, if needed, adds to the sel
-     * parameter all selected elements
-     *
-     * @param sel
-     *            The collection where to add all selected elements
-     * @param addSelected
-     *            if true, add all selected elements to collection
-     * @return whether the selected elements has any fix
-     */
-    @SuppressWarnings("unchecked")
-    private boolean setSelection(Collection<OsmPrimitive> sel, boolean addSelected) {
-        boolean hasFixes = false;
-
-        DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
-        if (lastSelectedNode != null && !lastSelectedNode.equals(node)) {
-            Enumeration<DefaultMutableTreeNode> children = lastSelectedNode.breadthFirstEnumeration();
-            while (children.hasMoreElements()) {
-                DefaultMutableTreeNode childNode = children.nextElement();
-                Object nodeInfo = childNode.getUserObject();
-                if (nodeInfo instanceof TestError) {
-                    TestError error = (TestError) nodeInfo;
-                    error.setSelected(false);
-                }
-            }
-        }
-
-        lastSelectedNode = node;
-        if (node == null)
-            return hasFixes;
-
-        Enumeration<DefaultMutableTreeNode> children = node.breadthFirstEnumeration();
-        while (children.hasMoreElements()) {
-            DefaultMutableTreeNode childNode = children.nextElement();
-            Object nodeInfo = childNode.getUserObject();
-            if (nodeInfo instanceof TestError) {
-                TestError error = (TestError) nodeInfo;
-                error.setSelected(true);
-
-                hasFixes = hasFixes || error.isFixable();
-                if (addSelected) {
-                    sel.addAll(error.getPrimitives());
-                }
-            }
-        }
-        selectButton.setEnabled(true);
-        if (ignoreButton != null)
-            ignoreButton.setEnabled(true);
-
-        return hasFixes;
-    }
-
-    /**
-     * Watches for clicks.
-     */
-    public class ClickWatch extends MouseAdapter {
-        @Override
-        public void mouseClicked(MouseEvent e) {
-            fixButton.setEnabled(false);
-            if (ignoreButton != null)
-                ignoreButton.setEnabled(false);
-            selectButton.setEnabled(false);
-
-            boolean isDblClick = e.getClickCount() > 1;
-
-            Collection<OsmPrimitive> sel = isDblClick ? new HashSet<OsmPrimitive>(40) : null;
-
-            boolean hasFixes = setSelection(sel, isDblClick);
-            fixButton.setEnabled(hasFixes);
-
-            if (isDblClick) {
-                Main.main.getCurrentDataSet().setSelected(sel);
-            }
-        }
-
-        @Override
-        public void mousePressed(MouseEvent e) {
-            showPopupMenu(e);
-        }
-
-        @Override
-        public void mouseReleased(MouseEvent e) {
-            showPopupMenu(e);
-        }
-
-    }
-
-    /**
-     * Watches for tree selection.
-     */
-    public class SelectionWatch implements TreeSelectionListener {
-        public void valueChanged(TreeSelectionEvent e) {
-            fixButton.setEnabled(false);
-            if (ignoreButton != null)
-                ignoreButton.setEnabled(false);
-            selectButton.setEnabled(false);
-
-            if (e.getSource() instanceof JScrollPane) {
-                System.out.println(e.getSource());
-                return;
-            }
-
-            boolean hasFixes = setSelection(null, false);
-            fixButton.setEnabled(hasFixes);
-            Main.map.repaint();
-        }
-    }
-
-    public static class ValidatorBoundingXYVisitor extends BoundingXYVisitor implements ValidatorVisitor {
-
-        public void visit(OsmPrimitive p) {
-            if (p.isUsable()) {
-                p.visit(this);
-            }
-        }
-
-        public void visit(WaySegment ws) {
-            if (ws.lowerIndex < 0 || ws.lowerIndex + 1 >= ws.way.getNodesCount())
-                return;
-            visit(ws.way.getNodes().get(ws.lowerIndex));
-            visit(ws.way.getNodes().get(ws.lowerIndex + 1));
-        }
-    }
-
-    public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
-        if (!Main.pref.getBoolean(PreferenceEditor.PREF_FILTER_BY_SELECTION, false))
-            return;
-        if (newSelection == null || newSelection.size() == 0)
-            tree.setFilter(null);
-        HashSet<OsmPrimitive> filter = new HashSet<OsmPrimitive>(newSelection);
-        tree.setFilter(filter);
-    }
-
-    /**
-     * Task for fixing a collection of {@see TestError}s. Can be run asynchronously.
-     *
-     *
-     */
-    class FixTask extends PleaseWaitRunnable {
-        private Collection<TestError> testErrors;
-        private boolean canceled;
-        private LinkedList<Command> fixCommands;
-
-
-        public FixTask(Collection<TestError> testErrors) {
-            super(tr("Fixing errors ..."), false /* don't ignore exceptions */);
-            this.testErrors = testErrors == null ? new ArrayList<TestError> (): testErrors;
-            fixCommands = new LinkedList<Command>();
-        }
-
-        @Override
-        protected void cancel() {
-            this.canceled = true;
-        }
-
-        @Override
-        protected void finish() {
-            // do nothing
-        }
-
-        @Override
-        protected void realRun() throws SAXException, IOException,
-                OsmTransferException {
-            ProgressMonitor monitor = getProgressMonitor();
-            try {
-                monitor.setTicksCount(testErrors.size());
-                int i=0;
-                for (TestError error: testErrors) {
-                    i++;
-                    monitor.subTask(tr("Fixing ({0}/{1}): ''{2}''", i, testErrors.size(),error.getMessage()));
-                    if (this.canceled)
-                        return;
-                    final Command fixCommand = error.getFix();
-                    if (fixCommand != null) {
-                        fixCommands.add(fixCommand);
-                        SwingUtilities.invokeAndWait(
-                                new Runnable() {
-                                    public void run() {
-                                        Main.main.undoRedo.addNoRedraw(fixCommand);
-                                    }
-                                }
-                        );
-                        error.setIgnored(true);
-                    }
-                    monitor.worked(1);
-                }
-                monitor.subTask(tr("Updating map ..."));
-                SwingUtilities.invokeAndWait(new Runnable() {
-                    public void run() {
-                        Main.main.undoRedo.afterAdd();
-                        Main.map.repaint();
-                        tree.resetErrors();
-                        Main.main.getCurrentDataSet().fireSelectionChanged();
-                    }
-                });
-            } catch(InterruptedException e) {
-                // FIXME: signature of realRun should have a generic checked exception we
-                // could throw here
-                throw new RuntimeException(e);
-            } catch(InvocationTargetException e) {
-                throw new RuntimeException(e);
-            } finally {
-                monitor.finishTask();
-            }
-        }
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/ValidatorVisitor.java b/validator/src/org/openstreetmap/josm/plugins/validator/ValidatorVisitor.java
deleted file mode 100644
index 4ca73fa..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/ValidatorVisitor.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.openstreetmap.josm.plugins.validator;
-
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.WaySegment;
-
-public interface ValidatorVisitor {
-    void visit(OsmPrimitive p);
-
-    void visit(WaySegment ws);
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/tests/ChangePropertyKeyCommand.java b/validator/src/org/openstreetmap/josm/plugins/validator/tests/ChangePropertyKeyCommand.java
deleted file mode 100644
index 4d5284f..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/tests/ChangePropertyKeyCommand.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.openstreetmap.josm.plugins.validator.tests;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-import static org.openstreetmap.josm.tools.I18n.trn;
-
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-
-import javax.swing.JLabel;
-import javax.swing.tree.DefaultMutableTreeNode;
-import javax.swing.tree.MutableTreeNode;
-
-import org.openstreetmap.josm.command.Command;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.plugins.validator.util.NameVisitor;
-import org.openstreetmap.josm.tools.ImageProvider;
-
-/**
- * Command that replaces the key of several objects
- *
- */
-public class ChangePropertyKeyCommand extends Command {
-    /**
-     * All primitives, that are affected with this command.
-     */
-    private final List<OsmPrimitive> objects;
-    /**
-     * The key that is subject to change.
-     */
-    private final String key;
-    /**
-     * The mew key.
-     */
-    private final String newKey;
-
-    /**
-     * Constructor
-     *
-     * @param objects all objects subject to change replacement
-     * @param key The key to replace
-     * @param newKey the new value of the key
-     */
-    public ChangePropertyKeyCommand(Collection<? extends OsmPrimitive> objects, String key, String newKey) {
-        this.objects = new LinkedList<OsmPrimitive>(objects);
-        this.key = key;
-        this.newKey = newKey;
-    }
-
-    @Override public boolean executeCommand() {
-        if (!super.executeCommand()) return false; // save old
-        for (OsmPrimitive osm : objects) {
-            if(osm.hasKeys())
-            {
-                osm.setModified(true);
-                String oldValue = osm.get(key);
-                osm.put(newKey, oldValue);
-                osm.remove(key);
-            }
-        }
-        return true;
-    }
-
-    @Override public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
-        modified.addAll(objects);
-    }
-
-    @Override public MutableTreeNode description() {
-        String text = tr( "Replace \"{0}\" by \"{1}\" for", key, newKey);
-        if (objects.size() == 1) {
-            NameVisitor v = new NameVisitor();
-            objects.iterator().next().visit(v);
-            text += " "+tr(v.className)+" "+v.name;
-        } else
-            text += " "+objects.size()+" "+trn("object","objects",objects.size());
-        DefaultMutableTreeNode root = new DefaultMutableTreeNode(new JLabel(text, ImageProvider.get("data", "key"), JLabel.HORIZONTAL));
-        if (objects.size() == 1)
-            return root;
-        NameVisitor v = new NameVisitor();
-        for (OsmPrimitive osm : objects) {
-            osm.visit(v);
-            root.add(new DefaultMutableTreeNode(v.toLabel()));
-        }
-        return root;
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/tests/Coastlines.java b/validator/src/org/openstreetmap/josm/plugins/validator/tests/Coastlines.java
deleted file mode 100644
index 0c808ad..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/tests/Coastlines.java
+++ /dev/null
@@ -1,202 +0,0 @@
-package org.openstreetmap.josm.plugins.validator.tests;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.geom.Area;
-import java.util.*;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.command.ChangeCommand;
-import org.openstreetmap.josm.command.Command;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.gui.progress.ProgressMonitor;
-import org.openstreetmap.josm.plugins.validator.Severity;
-import org.openstreetmap.josm.plugins.validator.Test;
-import org.openstreetmap.josm.plugins.validator.TestError;
-
-/**
- * Check coastlines for errors
- *
- * @author frsantos
- * @author Teemu Koskinen
- */
-public class Coastlines extends Test
-{
-    protected static int UNORDERED_COASTLINE = 901;
-    protected static int REVERSED_COASTLINE = 902;
-    protected static int UNCONNECTED_COASTLINE = 903;
-
-    private List<Way> coastlines;
-
-    private Area downloadedArea = null;
-
-    /**
-     * Constructor
-     */
-    public Coastlines()
-    {
-        super(tr("Coastlines."),
-              tr("This test checks that coastlines are correct."));
-    }
-
-    @Override
-    public void startTest(ProgressMonitor monitor)
-    {
-    	super.startTest(monitor);
-
-        OsmDataLayer layer = Main.map.mapView.getEditLayer();
-
-        if (layer != null)
-            downloadedArea = layer.data.getDataSourceArea();
-
-        coastlines = new LinkedList<Way>();
-    }
-
-    @Override
-    public void endTest()
-    {
-        for (Way c1 : coastlines) {
-            Node head = c1.firstNode();
-            Node tail = c1.lastNode();
-
-            if (head.equals(tail))
-                continue;
-
-            int headWays = 0;
-            int tailWays = 0;
-            boolean headReversed = false;
-            boolean tailReversed = false;
-            boolean headUnordered = false;
-            boolean tailUnordered = false;
-            Way next = null;
-            Way prev = null;
-
-            for (Way c2 : coastlines) {
-                if (c1 == c2)
-                    continue;
-
-                if (c2.containsNode(head)) {
-                    headWays++;
-                    next = c2;
-
-                    if (head.equals(c2.firstNode()))
-                        headReversed = true;
-                    else if (!head.equals(c2.lastNode()))
-                        headUnordered = true;
-                }
-
-                if (c2.containsNode(tail)) {
-                    tailWays++;
-                    prev = c2;
-
-                    if (tail.equals(c2.lastNode()))
-                        tailReversed = true;
-                    else if (!tail.equals(c2.firstNode()))
-                        tailUnordered = true;
-                }
-            }
-
-
-            List<OsmPrimitive> primitives = new ArrayList<OsmPrimitive>();
-            primitives.add(c1);
-
-            if (headWays == 0 || tailWays == 0) {
-                List<OsmPrimitive> highlight = new ArrayList<OsmPrimitive>();
-
-                System.out.println("Unconnected coastline: " + c1.getId());
-                if (headWays == 0 && (downloadedArea == null || downloadedArea.contains(head.getCoor()))) {
-                    System.out.println("headways: " +headWays+ " node: " + head.toString());
-                    highlight.add(head);
-                }
-                if (tailWays == 0 && (downloadedArea == null || downloadedArea.contains(tail.getCoor()))) {
-                    System.out.println("tailways: " +tailWays+ " tail: " + tail.toString());
-                    highlight.add(tail);
-                }
-
-                if (highlight.size() > 0)
-                    errors.add(new TestError(this, Severity.ERROR, tr("Unconnected coastline"),
-                                             UNCONNECTED_COASTLINE, primitives, highlight));
-            }
-
-            boolean unordered = false;
-            boolean reversed = false;
-
-            if (headWays == 1 && headReversed && tailWays == 1 && tailReversed)
-                reversed = true;
-
-            if (headWays > 1 || tailWays > 1)
-                unordered = true;
-            else if (headUnordered || tailUnordered)
-                unordered = true;
-            else if (reversed && next == prev)
-                unordered = true;
-
-            if (unordered) {
-                List<OsmPrimitive> highlight = new ArrayList<OsmPrimitive>();
-
-                System.out.println("Unordered coastline: " + c1.toString());
-                if (headWays > 1 || headUnordered || reversed) {
-                    System.out.println("head: " + head.toString());
-                    highlight.add(head);
-                }
-                if (tailWays > 1 || tailUnordered || reversed) {
-                    System.out.println("tail: " + tail.toString());
-                    highlight.add(tail);
-                }
-
-                errors.add(new TestError(this, Severity.ERROR, tr("Unordered coastline"),
-                                         UNORDERED_COASTLINE, primitives, highlight));
-            }
-            else if (reversed) {
-                errors.add(new TestError(this, Severity.ERROR, tr("Reversed coastline"),
-                                         REVERSED_COASTLINE, primitives));
-            }
-        }
-
-        coastlines = null;
-        downloadedArea = null;
-
-        super.endTest();
-    }
-
-    @Override
-    public void visit(Way way)
-    {
-        if (!way.isUsable())
-            return;
-
-        String natural = way.get("natural");
-        if (natural == null || !natural.equals("coastline"))
-            return;
-
-        coastlines.add(way);
-    }
-
-    @Override
-    public Command fixError(TestError testError) {
-        if (isFixable(testError)) {
-            Way way = (Way) testError.getPrimitives().iterator().next();
-            Way newWay = new Way(way);
-
-            List<Node> nodesCopy = newWay.getNodes();
-            Collections.reverse(nodesCopy);
-            newWay.setNodes(nodesCopy);
-
-            return new ChangeCommand(way, newWay);
-        }
-
-        return null;
-    }
-
-    @Override
-    public boolean isFixable(TestError testError) {
-        if (testError.getTester() instanceof Coastlines) {
-            return (testError.getCode() == REVERSED_COASTLINE);
-        }
-
-        return false;
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/tests/CrossingWays.java b/validator/src/org/openstreetmap/josm/plugins/validator/tests/CrossingWays.java
deleted file mode 100644
index 3c5d1d1..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/tests/CrossingWays.java
+++ /dev/null
@@ -1,220 +0,0 @@
-package org.openstreetmap.josm.plugins.validator.tests;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.geom.Line2D;
-import java.awt.geom.Point2D;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.data.osm.WaySegment;
-import org.openstreetmap.josm.gui.progress.ProgressMonitor;
-import org.openstreetmap.josm.plugins.validator.OSMValidatorPlugin;
-import org.openstreetmap.josm.plugins.validator.Severity;
-import org.openstreetmap.josm.plugins.validator.Test;
-import org.openstreetmap.josm.plugins.validator.TestError;
-import org.openstreetmap.josm.plugins.validator.util.Util;
-
-/**
- * Tests if there are segments that crosses in the same layer
- *
- * @author frsantos
- */
-public class CrossingWays extends Test
-{
-    protected static int CROSSING_WAYS = 601;
-
-    /** All way segments, grouped by cells */
-    Map<Point2D,List<ExtendedSegment>> cellSegments;
-    /** The already detected errors */
-    HashSet<WaySegment> errorSegments;
-    /** The already detected ways in error */
-    Map<List<Way>, List<WaySegment>> ways_seen;
-
-
-    /**
-     * Constructor
-     */
-    public CrossingWays()
-    {
-        super(tr("Crossing ways."),
-              tr("This test checks if two roads, railways, waterways or buildings crosses in the same layer, but are not connected by a node."));
-    }
-
-
-    @Override
-    public void startTest(ProgressMonitor monitor)
-    {
-    	super.startTest(monitor);
-        cellSegments = new HashMap<Point2D,List<ExtendedSegment>>(1000);
-        errorSegments = new HashSet<WaySegment>();
-        ways_seen = new HashMap<List<Way>, List<WaySegment>>(50);
-    }
-
-    @Override
-    public void endTest()
-    {
-    	super.endTest();
-        cellSegments = null;
-        errorSegments = null;
-        ways_seen = null;
-    }
-
-    @Override
-    public void visit(Way w)
-    {
-        if( !w.isUsable() )
-            return;
-
-        String coastline1 = w.get("natural");
-        boolean isCoastline1 = "water".equals(coastline1) || "coastline".equals(coastline1);
-        String railway1 = w.get("railway");
-        boolean isSubway1 = "subway".equals(railway1);
-        boolean isTram1 = "tram".equals(railway1);
-        boolean isBuilding = (w.get("building") != null);
-
-        if( w.get("highway") == null && w.get("waterway") == null && (railway1 == null || isSubway1 || isTram1)  && !isCoastline1 && !isBuilding)
-            return;
-
-        String layer1 = w.get("layer");
-
-        int nodesSize = w.getNodesCount();
-        for (int i = 0; i < nodesSize - 1; i++) {
-            WaySegment ws = new WaySegment(w, i);
-            ExtendedSegment es1 = new ExtendedSegment(ws, layer1, railway1, coastline1);
-            List<List<ExtendedSegment>> cellSegments = getSegments(es1.n1, es1.n2);
-            for( List<ExtendedSegment> segments : cellSegments)
-            {
-                for( ExtendedSegment es2 : segments)
-                {
-                    List<Way> prims;
-                    List<WaySegment> highlight;
-
-                    if (errorSegments.contains(ws) && errorSegments.contains(es2.ws))
-                        continue;
-
-                    String layer2 = es2.layer;
-                    String railway2 = es2.railway;
-                    String coastline2 = es2.coastline;
-                    if (layer1 == null ? layer2 != null : !layer1.equals(layer2))
-                        continue;
-
-                    if( !es1.intersects(es2) ) continue;
-                    if( isSubway1 && "subway".equals(railway2)) continue;
-                    if( isTram1 && "tram".equals(railway2)) continue;
-
-                    boolean isCoastline2 = coastline2 != null && (coastline2.equals("water") || coastline2.equals("coastline"));
-                    if( isCoastline1 != isCoastline2 ) continue;
-
-                    if((es1.railway != null && es1.railway.equals("abandoned")) || (railway2 != null && railway2.equals("abandoned"))) continue;
-
-                    prims = Arrays.asList(es1.ws.way, es2.ws.way);
-                    if ((highlight = ways_seen.get(prims)) == null)
-                    {
-                        highlight = new ArrayList<WaySegment>();
-                        highlight.add(es1.ws);
-                        highlight.add(es2.ws);
-
-                        errors.add(new TestError(this, Severity.WARNING,
-                        isBuilding ? tr("Crossing buildings") : tr("Crossing ways"), CROSSING_WAYS, prims, highlight));
-                        ways_seen.put(prims, highlight);
-                    }
-                    else
-                    {
-                        highlight.add(es1.ws);
-                        highlight.add(es2.ws);
-                    }
-                }
-                segments.add(es1);
-            }
-        }
-    }
-
-    /**
-    * Returns all the cells this segment crosses.  Each cell contains the list
-    * of segments already processed
-    *
-    * @param n1 The first node
-    * @param n2 The second node
-    * @return A list with all the cells the segment crosses
-    */
-    public List<List<ExtendedSegment>> getSegments(Node n1, Node n2)
-    {
-        List<List<ExtendedSegment>> cells = new ArrayList<List<ExtendedSegment>>();
-        for( Point2D cell : Util.getSegmentCells(n1, n2, OSMValidatorPlugin.griddetail) )
-        {
-            List<ExtendedSegment> segments = cellSegments.get( cell );
-            if( segments == null )
-            {
-                segments = new ArrayList<ExtendedSegment>();
-                cellSegments.put(cell, segments);
-            }
-            cells.add(segments);
-        }
-
-        return cells;
-    }
-
-    /**
-     * A way segment with some additional information
-     * @author frsantos
-     */
-    private class ExtendedSegment
-    {
-        public Node n1, n2;
-
-        public WaySegment ws;
-
-        /** The layer */
-        public String layer;
-
-        /** The railway type */
-        public String railway;
-
-        /** The coastline type */
-        public String coastline;
-
-        /**
-         * Constructor
-         * @param ws The way segment
-         * @param layer The layer of the way this segment is in
-         * @param railway The railway type of the way this segment is in
-         * @param coastline The coastlyne typo of the way the segment is in
-         */
-        public ExtendedSegment(WaySegment ws, String layer, String railway, String coastline)
-        {
-            this.ws = ws;
-            this.n1 = ws.way.getNodes().get(ws.lowerIndex);
-            this.n2 = ws.way.getNodes().get(ws.lowerIndex + 1);
-            this.layer = layer;
-            this.railway = railway;
-            this.coastline = coastline;
-        }
-
-        /**
-         * Checks whether this segment crosses other segment
-         * @param s2 The other segment
-         * @return true if both segements crosses
-         */
-        public boolean intersects(ExtendedSegment s2)
-        {
-            if( n1.equals(s2.n1) || n2.equals(s2.n2) ||
-                n1.equals(s2.n2)   || n2.equals(s2.n1) )
-            {
-                return false;
-            }
-
-            return Line2D.linesIntersect(
-                n1.getEastNorth().east(), n1.getEastNorth().north(),
-                n2.getEastNorth().east(), n2.getEastNorth().north(),
-                s2.n1.getEastNorth().east(), s2.n1.getEastNorth().north(),
-                s2.n2.getEastNorth().east(), s2.n2.getEastNorth().north());
-        }
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/tests/DuplicateNode.java b/validator/src/org/openstreetmap/josm/plugins/validator/tests/DuplicateNode.java
deleted file mode 100644
index 539468f..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/tests/DuplicateNode.java
+++ /dev/null
@@ -1,154 +0,0 @@
-package org.openstreetmap.josm.plugins.validator.tests;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.geom.Area;
-import java.util.Collection;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-import javax.swing.JOptionPane;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.MergeNodesAction;
-import org.openstreetmap.josm.command.Command;
-import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.osm.BackreferencedDataSet;
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil;
-import org.openstreetmap.josm.gui.progress.ProgressMonitor;
-import org.openstreetmap.josm.plugins.validator.Severity;
-import org.openstreetmap.josm.plugins.validator.Test;
-import org.openstreetmap.josm.plugins.validator.TestError;
-import org.openstreetmap.josm.plugins.validator.util.Bag;
-/**
- * Tests if there are duplicate nodes
- *
- * @author frsantos
- */
-public class DuplicateNode extends Test{
-
-	private static BackreferencedDataSet backreferences;
-
-	public static BackreferencedDataSet getBackreferenceDataSet() {
-		if (backreferences == null) {
-			backreferences = new BackreferencedDataSet();
-		}
-		return backreferences;
-	}
-
-	public static void clearBackreferences() {
-		backreferences = null;
-	}
-
-    protected static int DUPLICATE_NODE = 1;
-
-    /** Bag of all nodes */
-    Bag<LatLon, OsmPrimitive> nodes;
-
-    /**
-     * Constructor
-     */
-    public DuplicateNode()
-    {
-        super(tr("Duplicated nodes")+".",
-              tr("This test checks that there are no nodes at the very same location."));
-    }
-
-    @Override
-    public void startTest(ProgressMonitor monitor) {
-    	super.startTest(monitor);
-        nodes = new Bag<LatLon, OsmPrimitive>(1000);
-    }
-
-	@Override
-	public void endTest() {
-		for (List<OsmPrimitive> duplicated : nodes.values()) {
-			if (duplicated.size() > 1) {
-				boolean sameTags = true;
-				Map<String, String> keys0 = duplicated.get(0).getKeys();
-				keys0.remove("created_by");
-				for (int i = 0; i < duplicated.size(); i++) {
-					Map<String, String> keysI = duplicated.get(i).getKeys();
-					keysI.remove("created_by");
-					if (!keys0.equals(keysI))
-						sameTags = false;
-				}
-				if (!sameTags) {
-					TestError testError = new TestError(this, Severity.WARNING,
-							tr("Nodes at same position"), DUPLICATE_NODE,
-							duplicated);
-					errors.add(testError);
-				} else {
-					TestError testError = new TestError(this, Severity.ERROR,
-							tr("Duplicated nodes"), DUPLICATE_NODE, duplicated);
-					errors.add(testError);
-				}
-			}
-		}
-		super.endTest();
-		nodes = null;
-	}
-
-    @Override
-    public void visit(Node n)
-    {
-        if(n.isUsable())
-            nodes.add(n.getCoor(), n);
-    }
-
-    /**
-     * Merge the nodes into one.
-     * Copied from UtilsPlugin.MergePointsAction
-     */
-    @Override
-    public Command fixError(TestError testError)
-    {
-        Collection<OsmPrimitive> sel = new LinkedList<OsmPrimitive>(testError.getPrimitives());
-        LinkedHashSet<Node> nodes = new LinkedHashSet<Node>(OsmPrimitive.getFilteredList(sel, Node.class));
-        Node target = MergeNodesAction.selectTargetNode(nodes);
-        if(checkAndConfirmOutlyingDeletes(nodes))
-            return MergeNodesAction.mergeNodes(Main.main.getEditLayer(),getBackreferenceDataSet(), nodes, target);
-
-        return null;// undoRedo handling done in mergeNodes
-    }
-
-    @Override
-    public boolean isFixable(TestError testError)
-    {
-        return (testError.getTester() instanceof DuplicateNode);
-    }
-
-    /**
-     * Check whether user is about to delete data outside of the download area.
-     * Request confirmation if he is.
-     */
-    private static boolean checkAndConfirmOutlyingDeletes(LinkedHashSet<Node> del) {
-        Area a = Main.main.getCurrentDataSet().getDataSourceArea();
-        if (a != null) {
-            for (OsmPrimitive osm : del) {
-                if (osm instanceof Node && !osm.isNew()) {
-                    Node n = (Node) osm;
-                    if (!a.contains(n.getCoor())) {
-                        return ConditionalOptionPaneUtil.showConfirmationDialog(
-                            "delete_outside_nodes",
-                            Main.parent,
-                            tr("You are about to delete nodes outside of the area you have downloaded." +
-                                                "<br>" +
-                                                "This can cause problems because other objects (that you don't see) might use them." +
-                                                "<br>" +
-                                        "Do you really want to delete?") + "</html>",
-                            tr("Confirmation"),
-                            JOptionPane.YES_NO_OPTION,
-                            JOptionPane.QUESTION_MESSAGE,
-                            JOptionPane.YES_OPTION);
-                    }
-                }
-            }
-        }
-        return true;
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/tests/DuplicateWay.java b/validator/src/org/openstreetmap/josm/plugins/validator/tests/DuplicateWay.java
deleted file mode 100644
index 4711fa3..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/tests/DuplicateWay.java
+++ /dev/null
@@ -1,153 +0,0 @@
-package org.openstreetmap.josm.plugins.validator.tests;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Vector;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.command.Command;
-import org.openstreetmap.josm.command.DeleteCommand;
-import org.openstreetmap.josm.command.SequenceCommand;
-import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.gui.progress.ProgressMonitor;
-import org.openstreetmap.josm.plugins.validator.Severity;
-import org.openstreetmap.josm.plugins.validator.Test;
-import org.openstreetmap.josm.plugins.validator.TestError;
-import org.openstreetmap.josm.plugins.validator.util.Bag;
-/**
- * Tests if there are duplicate ways
- */
-public class DuplicateWay extends Test
-{
-
-    private class WayPair {
-        public List<LatLon> coor;
-        public Map<String, String> keys;
-        public WayPair(List<LatLon> _coor,Map<String, String> _keys) {
-            coor=_coor;
-            keys=_keys;
-        }
-        @Override
-        public int hashCode() {
-            return coor.hashCode()+keys.hashCode();
-        }
-        @Override
-        public boolean equals(Object obj) {
-            if (!(obj instanceof WayPair)) return false;
-            WayPair wp = (WayPair) obj;
-            return wp.coor.equals(coor) && wp.keys.equals(keys);
-        }
-    }
-
-    protected static int DUPLICATE_WAY = 1401;
-
-    /** Bag of all ways */
-    Bag<WayPair, OsmPrimitive> ways;
-
-    /**
-     * Constructor
-     */
-    public DuplicateWay()
-    {
-        super(tr("Duplicated ways")+".",
-              tr("This test checks that there are no ways with same tags and same node coordinates."));
-    }
-
-
-    @Override
-    public void startTest(ProgressMonitor monitor)
-    {
-    	super.startTest(monitor);
-        ways = new Bag<WayPair, OsmPrimitive>(1000);
-    }
-
-    @Override
-    public void endTest()
-    {
-    	super.endTest();
-        for(List<OsmPrimitive> duplicated : ways.values() )
-        {
-            if( duplicated.size() > 1)
-            {
-                TestError testError = new TestError(this, Severity.ERROR, tr("Duplicated ways"), DUPLICATE_WAY, duplicated);
-                errors.add( testError );
-            }
-        }
-        ways = null;
-    }
-
-    @Override
-    public void visit(Way w)
-    {
-        if( !w.isUsable() )
-            return;
-        List<Node> wNodes=w.getNodes();
-        Vector<LatLon> wLat=new Vector<LatLon>(wNodes.size());
-        for(int i=0;i<wNodes.size();i++) {
-                 wLat.add(wNodes.get(i).getCoor());
-        }
-        Map<String, String> wkeys=w.getKeys();
-        wkeys.remove("created_by");
-        WayPair wKey=new WayPair(wLat,wkeys);
-        ways.add(wKey, w);
-    }
-
-    /**
-     * Fix the error by removing all but one instance of duplicate ways
-     */
-    @Override
-    public Command fixError(TestError testError)
-    {
-        Collection<? extends OsmPrimitive> sel = testError.getPrimitives();
-        LinkedList<Way> ways = new LinkedList<Way>();
-
-        for (OsmPrimitive osm : sel)
-            if (osm instanceof Way)
-                ways.add((Way)osm);
-
-        if( ways.size() < 2 )
-            return null;
-
-        long idToKeep = 0;
-        // Only one way will be kept - the one with lowest positive ID, if such exist
-        // or one "at random" if no such exists. Rest of the ways will be deleted
-        for (Way w: ways) {
-            if (!w.isNew()) {
-                if (idToKeep == 0 || w.getId() < idToKeep) idToKeep = w.getId();
-            }
-        }
-
-        if (idToKeep > 0) {
-            //Remove chosen way from the list, rest of ways in the list will be deleted
-            for (Way w: ways) {
-                if (w.getId() == idToKeep) {
-                        ways.remove(w);
-                    break;
-                }
-            }
-        } else {
-            //Remove first way from the list, delete the rest
-            ways.remove(0);
-        }
-
-        //Delete all ways in the list
-        //Note: nodes are not deleted, these can be detected and deleted at next pass
-        Collection<Command> commands = new LinkedList<Command>();
-        commands.add(new DeleteCommand(ways));
-        Main.main.undoRedo.add(new SequenceCommand(tr("Delete duplicate ways"), commands));
-        return null;
-    }
-
-    @Override
-    public boolean isFixable(TestError testError)
-    {
-        return (testError.getTester() instanceof DuplicateWay);
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/tests/DuplicatedWayNodes.java b/validator/src/org/openstreetmap/josm/plugins/validator/tests/DuplicatedWayNodes.java
deleted file mode 100644
index b8578e1..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/tests/DuplicatedWayNodes.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package org.openstreetmap.josm.plugins.validator.tests;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.util.Arrays;
-import java.util.Collections;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.command.ChangeCommand;
-import org.openstreetmap.josm.command.Command;
-import org.openstreetmap.josm.command.DeleteCommand;
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.plugins.validator.Severity;
-import org.openstreetmap.josm.plugins.validator.Test;
-import org.openstreetmap.josm.plugins.validator.TestError;
-
-public class DuplicatedWayNodes extends Test {
-    protected static int DUPLICATE_WAY_NODE = 501;
-
-    public DuplicatedWayNodes() {
-        super(tr("Duplicated way nodes."),
-            tr("Checks for ways with identical consecutive nodes."));
-    }
-
-    @Override public void visit(Way w) {
-        if (!w.isUsable()) return;
-
-        Node lastN = null;
-        for (Node n : w.getNodes()) {
-            if (lastN == null) {
-                lastN = n;
-                continue;
-            }
-            if (lastN == n) {
-                errors.add(new TestError(this, Severity.ERROR, tr("Duplicated way nodes"), DUPLICATE_WAY_NODE,
-                    Arrays.asList(w), Arrays.asList(n)));
-                break;
-            }
-            lastN = n;
-        }
-    }
-
-    @Override public Command fixError(TestError testError) {
-        Way w = (Way) testError.getPrimitives().iterator().next();
-        Way wnew = new Way(w);
-        wnew.setNodes(null);
-        Node lastN = null;
-        for (Node n : w.getNodes()) {
-            if (lastN == null) {
-            	wnew.addNode(n);
-            } else if (n == lastN) {
-                // Skip this node
-            } else {
-            	wnew.addNode(n);
-            }
-            lastN = n;
-        }
-        if (wnew.getNodesCount() < 2) {
-            // Empty way, delete
-            return DeleteCommand.delete(Main.map.mapView.getEditLayer(), Collections.singleton(w));
-        } else {
-            return new ChangeCommand(w, wnew);
-        }
-    }
-
-    @Override public boolean isFixable(TestError testError) {
-        return testError.getTester() instanceof DuplicatedWayNodes;
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/tests/NameMismatch.java b/validator/src/org/openstreetmap/josm/plugins/validator/tests/NameMismatch.java
deleted file mode 100644
index 999db32..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/tests/NameMismatch.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package org.openstreetmap.josm.plugins.validator.tests;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Map.Entry;
-
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.plugins.validator.Severity;
-import org.openstreetmap.josm.plugins.validator.Test;
-import org.openstreetmap.josm.plugins.validator.TestError;
-
-/**
- * Check for missing name:* translations.
- * <p>
- * This test finds multilingual objects whose 'name' attribute is not
- * equal to any 'name:*' attribute and not a composition of some
- * 'name:*' attributes separated by ' - '.
- * <p>
- * For example, a node with name=Europe, name:de=Europa should have
- * name:en=Europe to avoid triggering this test.  An object with
- * name='Suomi - Finland' should have at least name:fi=Suomi and
- * name:sv=Finland to avoid a warning (name:et=Soome would not
- * matter).  Also, complain if an object has some name:* attribute but
- * no name.
- *
- * @author Skela
- */
-public class NameMismatch extends Test {
-    protected static final int NAME_MISSING = 1501;
-    protected static final int NAME_TRANSLATION_MISSING = 1502;
-
-    public NameMismatch() {
-        super(tr("Missing name:* translation."),
-            tr("This test finds multilingual objects whose 'name' attribute is not equal to some 'name:*' attribute and not a composition of 'name:*' attributes, e.g., Italia - Italien - Italy."));
-    }
-
-    /**
-     * Report a missing translation.
-     *
-     * @param p The primitive whose translation is missing
-     */
-    private void missingTranslation(OsmPrimitive p) {
-        errors.add(new TestError(this, Severity.OTHER,
-            tr("A name:* translation is missing."),
-            NAME_TRANSLATION_MISSING, p));
-    }
-
-    /**
-     * Check a primitive for a name mismatch.
-     *
-     * @param p The primitive to be tested
-     */
-    public void check(OsmPrimitive p) {
-        HashSet<String> names = new HashSet<String>();
-
-        for (Entry<String, String> entry : p.entrySet()) {
-            if (entry.getKey().startsWith("name:")) {
-                String name_s = entry.getValue();
-                if (name_s != null) {
-                    names.add(name_s);
-                }
-            }
-        }
-
-        if (names.isEmpty()) return;
-
-        String name = p.get("name");
-
-        if (name == null) {
-            errors.add(new TestError(this, Severity.OTHER,
-                tr("A name is missing, even though name:* exists."),
-                                     NAME_MISSING, p));
-	    return;
-	}
-
-        if (names.contains(name)) return;
-        /* If name is not equal to one of the name:*, it should be a
-        composition of some (not necessarily all) name:* labels.
-        Check if this is the case. */
-
-        String split_names[] = name.split(" - ");
-        if (split_names.length == 1) {
-            /* The name is not composed of multiple parts. Complain. */
-            missingTranslation(p);
-            return;
-        }
-
-        /* Check that each part corresponds to a translated name:*. */
-        for (String n : split_names) {
-            if (!names.contains(n)) {
-                missingTranslation(p);
-                return;
-            }
-        }
-    }
-
-    /**
-     * Checks a name mismatch in all primitives.
-     *
-     * @param selection The primitives to be tested
-     */
-    @Override public void visit(Collection<OsmPrimitive> selection) {
-        for (OsmPrimitive p : selection)
-            if (!p.isDeleted() && !p.incomplete)
-                check(p);
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/tests/NodesWithSameName.java b/validator/src/org/openstreetmap/josm/plugins/validator/tests/NodesWithSameName.java
deleted file mode 100644
index 831b4a0..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/tests/NodesWithSameName.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package org.openstreetmap.josm.plugins.validator.tests;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.util.Map;
-import java.util.List;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.ArrayList;
-
-
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.gui.progress.ProgressMonitor;
-import org.openstreetmap.josm.plugins.validator.Severity;
-import org.openstreetmap.josm.plugins.validator.Test;
-import org.openstreetmap.josm.plugins.validator.TestError;
-
-public class NodesWithSameName extends Test {
-    protected static int SAME_NAME = 801;
-
-    private Map<String, List<Node>> namesToNodes;
-
-    public NodesWithSameName() {
-        super(tr("Nodes with same name"),
-            tr("This test finds nodes that have the same name (might be duplicates)."));
-    }
-
-    @Override public void startTest(ProgressMonitor monitor) {
-        super.startTest(monitor);
-        namesToNodes = new HashMap<String, List<Node>>();
-    }
-
-    @Override public void visit(Node n) {
-        if (!n.isUsable()) return;
-
-        String name = n.get("name");
-        String sign = n.get("traffic_sign");
-        String highway = n.get("highway");
-        if (name == null
-            || (sign != null && sign.equals("city_limit"))
-            || (highway != null && highway.equals("bus_stop"))) {
-            return;
-        }
-
-        List<Node> nodes = namesToNodes.get(name);
-        if (nodes == null)
-            namesToNodes.put(name, nodes = new ArrayList<Node>());
-
-        nodes.add(n);
-    }
-
-    @Override public void endTest() {
-        for (List<Node> nodes : namesToNodes.values()) {
-            if (nodes.size() > 1) {
-                // Report the same-name nodes, unless each has a unique ref=*.
-                HashSet<String> refs = new HashSet<String>();
-
-                for (Node n : nodes) {
-                    String ref = n.get("ref");
-                    if (ref == null || !refs.add(ref)) {
-                        errors.add(new TestError(this, Severity.OTHER,
-                            tr("Nodes with same name"), SAME_NAME, nodes));
-                        break;
-                    }
-                }
-            }
-        }
-        super.endTest();
-        namesToNodes = null;
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/tests/OverlappingWays.java b/validator/src/org/openstreetmap/josm/plugins/validator/tests/OverlappingWays.java
deleted file mode 100644
index 1c3e21f..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/tests/OverlappingWays.java
+++ /dev/null
@@ -1,173 +0,0 @@
-package org.openstreetmap.josm.plugins.validator.tests;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.OsmUtils;
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.data.osm.WaySegment;
-import org.openstreetmap.josm.gui.progress.ProgressMonitor;
-import org.openstreetmap.josm.plugins.validator.Severity;
-import org.openstreetmap.josm.plugins.validator.Test;
-import org.openstreetmap.josm.plugins.validator.TestError;
-import org.openstreetmap.josm.plugins.validator.util.Bag;
-import org.openstreetmap.josm.tools.Pair;
-
-/**
- * Tests if there are overlapping ways
- *
- * @author frsantos
- */
-public class OverlappingWays extends Test
-{
-    /** Bag of all way segments */
-    Bag<Pair<Node,Node>, WaySegment> nodePairs;
-
-    protected static int OVERLAPPING_HIGHWAY = 101;
-    protected static int OVERLAPPING_RAILWAY = 102;
-    protected static int OVERLAPPING_WAY = 103;
-    protected static int OVERLAPPING_HIGHWAY_AREA = 111;
-    protected static int OVERLAPPING_RAILWAY_AREA = 112;
-    protected static int OVERLAPPING_WAY_AREA = 113;
-    protected static int OVERLAPPING_AREA = 120;
-
-    /** Constructor */
-    public OverlappingWays()
-    {
-        super(tr("Overlapping ways."),
-              tr("This test checks that a connection between two nodes "
-                + "is not used by more than one way."));
-
-    }
-
-
-    @Override
-    public void startTest(ProgressMonitor monitor)
-    {
-    	super.startTest(monitor);
-        nodePairs = new Bag<Pair<Node,Node>, WaySegment>(1000);
-    }
-
-    @Override
-    public void endTest()
-    {
-        Map<List<Way>, List<WaySegment>> ways_seen = new HashMap<List<Way>, List<WaySegment>>(500);
-
-        for (List<WaySegment> duplicated : nodePairs.values())
-        {
-            int ways = duplicated.size();
-
-            if (ways > 1)
-            {
-                List<OsmPrimitive> prims = new ArrayList<OsmPrimitive>();
-                List<Way> current_ways = new ArrayList<Way>();
-                List<WaySegment> highlight;
-                int highway = 0;
-                int railway = 0;
-                int area = 0;
-
-                for (WaySegment ws : duplicated)
-                {
-                    if (ws.way.get("highway") != null)
-                        highway++;
-                    else if (ws.way.get("railway") != null)
-                        railway++;
-                    Boolean ar = OsmUtils.getOsmBoolean(ws.way.get("area"));
-                    if (ar != null && ar)
-                        area++;
-                    if (ws.way.get("landuse") != null || ws.way.get("natural") != null
-                    || ws.way.get("amenity") != null || ws.way.get("leisure") != null
-                    || ws.way.get("building") != null)
-                    {
-                        area++; ways--;
-                    }
-
-                    prims.add(ws.way);
-                    current_ways.add(ws.way);
-                }
-                /* These ways not seen before
-                 * If two or more of the overlapping ways are
-                 * highways or railways mark a seperate error
-                 */
-                if ((highlight = ways_seen.get(current_ways)) == null)
-                {
-                    String errortype;
-                    int type;
-
-                    if(area > 0)
-                    {
-                        if (ways == 0 || duplicated.size() == area)
-                        {
-                            errortype = tr("Overlapping areas");
-                            type = OVERLAPPING_AREA;
-                        }
-                        else if (highway == ways)
-                        {
-                            errortype = tr("Overlapping highways (with area)");
-                            type = OVERLAPPING_HIGHWAY_AREA;
-                        }
-                        else if (railway == ways)
-                        {
-                            errortype = tr("Overlapping railways (with area)");
-                            type = OVERLAPPING_RAILWAY_AREA;
-                        }
-                        else
-                        {
-                            errortype = tr("Overlapping ways (with area)");
-                            type = OVERLAPPING_WAY_AREA;
-                        }
-                    }
-                    else if (highway == ways)
-                    {
-                        errortype = tr("Overlapping highways");
-                        type = OVERLAPPING_HIGHWAY;
-                    }
-                    else if (railway == ways)
-                    {
-                        errortype = tr("Overlapping railways");
-                        type = OVERLAPPING_RAILWAY;
-                    }
-                    else
-                    {
-                        errortype = tr("Overlapping ways");
-                        type = OVERLAPPING_WAY;
-                    }
-
-                    errors.add(new TestError(this, type < OVERLAPPING_HIGHWAY_AREA
-                    ? Severity.WARNING : Severity.OTHER, tr(errortype), type, prims, duplicated));
-                    ways_seen.put(current_ways, duplicated);
-                }
-                else    /* way seen, mark highlight layer only */
-                {
-                    for (WaySegment ws : duplicated)
-                        highlight.add(ws);
-                }
-            }
-        }
-        super.endTest();
-        nodePairs = null;
-    }
-
-    @Override
-    public void visit(Way w)
-    {
-        Node lastN = null;
-        int i = -2;
-        for (Node n : w.getNodes()) {
-            i++;
-            if (lastN == null) {
-                lastN = n;
-                continue;
-            }
-            nodePairs.add(Pair.sort(new Pair<Node,Node>(lastN, n)),
-                new WaySegment(w, i));
-            lastN = n;
-        }
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/tests/SelfIntersectingWay.java b/validator/src/org/openstreetmap/josm/plugins/validator/tests/SelfIntersectingWay.java
deleted file mode 100644
index 250add8..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/tests/SelfIntersectingWay.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.openstreetmap.josm.plugins.validator.tests;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.util.HashSet;
-import java.util.Arrays;
-
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.plugins.validator.Severity;
-import org.openstreetmap.josm.plugins.validator.Test;
-import org.openstreetmap.josm.plugins.validator.TestError;
-
-/**
- * Checks for self-intersecting ways.
- */
-public class SelfIntersectingWay extends Test {
-    protected static int SELF_INTERSECT = 401;
-
-    public SelfIntersectingWay() {
-        super(tr("Self-intersecting ways"),
-              tr("This test checks for ways " +
-                "that contain some of their nodes more than once."));
-    }
-
-    @Override public void visit(Way w) {
-        HashSet<Node> nodes = new HashSet<Node>();
-
-        for (int i = 1; i < w.getNodesCount() - 1; i++) {
-            Node n = w.getNode(i);
-            if (nodes.contains(n)) {
-                errors.add(new TestError(this,
-                    Severity.WARNING, tr("Self-intersecting ways"), SELF_INTERSECT,
-                    Arrays.asList(w), Arrays.asList(n)));
-                break;
-            } else {
-                nodes.add(n);
-            }
-        }
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/tests/SimilarNamedWays.java b/validator/src/org/openstreetmap/josm/plugins/validator/tests/SimilarNamedWays.java
deleted file mode 100644
index 7d7b3a8..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/tests/SimilarNamedWays.java
+++ /dev/null
@@ -1,173 +0,0 @@
-package org.openstreetmap.josm.plugins.validator.tests;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.geom.Point2D;
-import java.util.*;
-
-
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.gui.progress.ProgressMonitor;
-import org.openstreetmap.josm.plugins.validator.Severity;
-import org.openstreetmap.josm.plugins.validator.Test;
-import org.openstreetmap.josm.plugins.validator.TestError;
-import org.openstreetmap.josm.plugins.validator.util.Bag;
-import org.openstreetmap.josm.plugins.validator.util.Util;
-
-/**
- * Checks for similar named ways, symptom of a possible typo. It uses the
- * Levenshtein distance to check for similarity
- *
- * @author frsantos
- */
-public class SimilarNamedWays extends Test
-{
-    protected static int SIMILAR_NAMED = 701;
-
-    /** All ways, grouped by cells */
-    Map<Point2D,List<Way>> cellWays;
-    /** The already detected errors */
-    Bag<Way, Way> errorWays;
-
-    /**
-     * Constructor
-     */
-    public SimilarNamedWays()
-    {
-        super(tr("Similarly named ways")+".",
-              tr("This test checks for ways with similar names that may have been misspelled."));
-    }
-
-    @Override
-    public void startTest(ProgressMonitor monitor)
-    {
-    	super.startTest(monitor);
-        cellWays = new HashMap<Point2D,List<Way>>(1000);
-        errorWays = new Bag<Way, Way>();
-    }
-
-    @Override
-    public void endTest()
-    {
-        cellWays = null;
-        errorWays = null;
-        super.endTest();
-    }
-
-    @Override
-    public void visit(Way w)
-    {
-        if( !w.isUsable() )
-            return;
-
-        String name = w.get("name");
-        if( name == null || name.length() < 6 )
-            return;
-
-        List<List<Way>> theCellWays = Util.getWaysInCell(w, cellWays);
-        for( List<Way> ways : theCellWays)
-        {
-            for( Way w2 : ways)
-            {
-                if( errorWays.contains(w, w2) || errorWays.contains(w2, w) )
-                    continue;
-
-                String name2 = w2.get("name");
-                if( name2 == null || name2.length() < 6 )
-                    continue;
-
-                int levenshteinDistance = getLevenshteinDistance(name, name2);
-                if( 0 < levenshteinDistance && levenshteinDistance <= 2 )
-                {
-                    List<OsmPrimitive> primitives = new ArrayList<OsmPrimitive>();
-                    primitives.add(w);
-                    primitives.add(w2);
-                    errors.add( new TestError(this, Severity.WARNING, tr("Similarly named ways"), SIMILAR_NAMED, primitives) );
-                    errorWays.add(w, w2);
-                }
-            }
-            ways.add(w);
-        }
-    }
-
-    /**
-     * Compute Levenshtein distance
-     *
-     * @param s First word
-     * @param t Second word
-     * @return The distance between words
-     */
-    public int getLevenshteinDistance(String s, String t)
-    {
-        int d[][]; // matrix
-        int n; // length of s
-        int m; // length of t
-        int i; // iterates through s
-        int j; // iterates through t
-        char s_i; // ith character of s
-        char t_j; // jth character of t
-        int cost; // cost
-
-        // Step 1
-
-        n = s.length();
-        m = t.length();
-        if (n == 0) return m;
-        if (m == 0) return n;
-        d = new int[n + 1][m + 1];
-
-        // Step 2
-        for (i = 0; i <= n; i++) d[i][0] = i;
-        for (j = 0; j <= m; j++) d[0][j] = j;
-
-        // Step 3
-        for (i = 1; i <= n; i++)
-        {
-            s_i = s.charAt(i - 1);
-
-            // Step 4
-            for (j = 1; j <= m; j++)
-            {
-                t_j = t.charAt(j - 1);
-
-                // Step 5
-                if (s_i == t_j)
-                {
-                    cost = 0;
-                }
-                else
-                {
-                    cost = 1;
-                }
-
-                // Step 6
-                d[i][j] = Minimum(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost);
-            }
-        }
-
-        // Step 7
-        return d[n][m];
-    }
-
-    /**
-     * Get minimum of three values
-     * @param a First value
-     * @param b Second value
-     * @param c Third value
-     * @return The minimum of the tre values
-     */
-    private static int Minimum(int a, int b, int c)
-    {
-        int mi = a;
-        if (b < mi)
-        {
-            mi = b;
-        }
-        if (c < mi)
-        {
-            mi = c;
-        }
-        return mi;
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/tests/TagChecker.java b/validator/src/org/openstreetmap/josm/plugins/validator/tests/TagChecker.java
deleted file mode 100644
index dc8f206..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/tests/TagChecker.java
+++ /dev/null
@@ -1,1029 +0,0 @@
-package org.openstreetmap.josm.plugins.validator.tests;
-
-import static org.openstreetmap.josm.tools.I18n.marktr;
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.Dimension;
-import java.awt.GridBagLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.io.BufferedReader;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.UnsupportedEncodingException;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-
-import javax.swing.DefaultListModel;
-import javax.swing.JButton;
-import javax.swing.JCheckBox;
-import javax.swing.JLabel;
-import javax.swing.JList;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.command.ChangePropertyCommand;
-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.OsmUtils;
-import org.openstreetmap.josm.data.osm.Relation;
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.gui.preferences.TaggingPresetPreference;
-import org.openstreetmap.josm.gui.progress.ProgressMonitor;
-import org.openstreetmap.josm.gui.tagging.TaggingPreset;
-import org.openstreetmap.josm.io.MirroredInputStream;
-import org.openstreetmap.josm.plugins.validator.OSMValidatorPlugin;
-import org.openstreetmap.josm.plugins.validator.PreferenceEditor;
-import org.openstreetmap.josm.plugins.validator.Severity;
-import org.openstreetmap.josm.plugins.validator.Test;
-import org.openstreetmap.josm.plugins.validator.TestError;
-import org.openstreetmap.josm.plugins.validator.util.Bag;
-import org.openstreetmap.josm.plugins.validator.util.Entities;
-import org.openstreetmap.josm.plugins.validator.util.Util;
-import org.openstreetmap.josm.tools.GBC;
-
-/**
- * Check for mispelled or wrong properties
- *
- * @author frsantos
- */
-public class TagChecker extends Test
-{
-    /** The default data files */
-    public static final String DATA_FILE = "http://svn.openstreetmap.org/applications/editors/josm/plugins/validator/tagchecker.cfg";
-    public static final String IGNORE_FILE = "http://svn.openstreetmap.org/applications/editors/josm/plugins/validator/ignoretags.cfg";
-    public static final String SPELL_FILE = "http://svn.openstreetmap.org/applications/utils/planet.osm/java/speller/words.cfg";
-
-    /** The spell check key substitutions: the key should be substituted by the value */
-    protected static Map<String, String> spellCheckKeyData;
-    /** The spell check preset values */
-    protected static Bag<String, String> presetsValueData;
-    /** The TagChecker data */
-    protected static List<CheckerData> checkerData = new ArrayList<CheckerData>();
-    protected static ArrayList<String> ignoreDataStartsWith = new ArrayList<String>();
-    protected static ArrayList<String> ignoreDataEquals = new ArrayList<String>();
-    protected static ArrayList<String> ignoreDataEndsWith = new ArrayList<String>();
-    protected static ArrayList<IgnoreKeyPair> ignoreDataKeyPair = new ArrayList<IgnoreKeyPair>();
-    protected static ArrayList<IgnoreTwoKeyPair> ignoreDataTwoKeyPair = new ArrayList<IgnoreTwoKeyPair>();
-
-    /** The preferences prefix */
-    protected static final String PREFIX = PreferenceEditor.PREFIX + "." + TagChecker.class.getSimpleName();
-
-    public static final String PREF_CHECK_VALUES = PREFIX + ".checkValues";
-    public static final String PREF_CHECK_KEYS = PREFIX + ".checkKeys";
-    public static final String PREF_CHECK_COMPLEX = PREFIX + ".checkComplex";
-    public static final String PREF_CHECK_FIXMES = PREFIX + ".checkFixmes";
-    public static final String PREF_CHECK_PAINT = PREFIX + ".paint";
-
-    public static final String PREF_SOURCES = PREFIX + ".sources";
-    public static final String PREF_USE_DATA_FILE = PREFIX + ".usedatafile";
-    public static final String PREF_USE_IGNORE_FILE = PREFIX + ".useignorefile";
-    public static final String PREF_USE_SPELL_FILE = PREFIX + ".usespellfile";
-
-    public static final String PREF_CHECK_KEYS_BEFORE_UPLOAD = PREF_CHECK_KEYS + "BeforeUpload";
-    public static final String PREF_CHECK_VALUES_BEFORE_UPLOAD = PREF_CHECK_VALUES + "BeforeUpload";
-    public static final String PREF_CHECK_COMPLEX_BEFORE_UPLOAD = PREF_CHECK_COMPLEX + "BeforeUpload";
-    public static final String PREF_CHECK_FIXMES_BEFORE_UPLOAD = PREF_CHECK_FIXMES + "BeforeUpload";
-    public static final String PREF_CHECK_PAINT_BEFORE_UPLOAD = PREF_CHECK_PAINT + "BeforeUpload";
-
-    protected boolean checkKeys = false;
-    protected boolean checkValues = false;
-    protected boolean checkComplex = false;
-    protected boolean checkFixmes = false;
-    protected boolean checkPaint = false;
-
-    protected JCheckBox prefCheckKeys;
-    protected JCheckBox prefCheckValues;
-    protected JCheckBox prefCheckComplex;
-    protected JCheckBox prefCheckFixmes;
-    protected JCheckBox prefCheckPaint;
-
-    protected JCheckBox prefCheckKeysBeforeUpload;
-    protected JCheckBox prefCheckValuesBeforeUpload;
-    protected JCheckBox prefCheckComplexBeforeUpload;
-    protected JCheckBox prefCheckFixmesBeforeUpload;
-    protected JCheckBox prefCheckPaintBeforeUpload;
-
-    protected JCheckBox prefUseDataFile;
-    protected JCheckBox prefUseIgnoreFile;
-    protected JCheckBox prefUseSpellFile;
-
-    protected JButton addSrcButton;
-    protected JButton editSrcButton;
-    protected JButton deleteSrcButton;
-
-    protected static int EMPTY_VALUES      = 1200;
-    protected static int INVALID_KEY       = 1201;
-    protected static int INVALID_VALUE     = 1202;
-    protected static int FIXME             = 1203;
-    protected static int INVALID_SPACE     = 1204;
-    protected static int INVALID_KEY_SPACE = 1205;
-    protected static int INVALID_HTML      = 1206;
-    protected static int PAINT             = 1207;
-    /** 1250 and up is used by tagcheck */
-
-    /** List of sources for spellcheck data */
-    protected JList Sources;
-
-
-    protected static Entities entities = new Entities();
-    /**
-     * Constructor
-     */
-    public TagChecker()
-    {
-        super(tr("Properties checker :"),
-              tr("This plugin checks for errors in property keys and values."));
-    }
-
-    public static void initialize(OSMValidatorPlugin plugin) throws Exception
-    {
-        initializeData();
-        initializePresets();
-    }
-
-    /**
-     * Reads the spellcheck file into a HashMap.
-     * The data file is a list of words, beginning with +/-. If it starts with +,
-     * the word is valid, but if it starts with -, the word should be replaced
-     * by the nearest + word before this.
-     *
-     * @throws FileNotFoundException
-     * @throws IOException
-     */
-    private static void initializeData() throws IOException
-    {
-        spellCheckKeyData = new HashMap<String, String>();
-        String sources = Main.pref.get( PREF_SOURCES, "");
-        if(Main.pref.getBoolean(PREF_USE_DATA_FILE, true))
-        {
-            if( sources == null || sources.length() == 0)
-                sources = DATA_FILE;
-            else
-                sources = DATA_FILE + ";" + sources;
-        }
-        if(Main.pref.getBoolean(PREF_USE_IGNORE_FILE, true))
-        {
-            if( sources == null || sources.length() == 0)
-                sources = IGNORE_FILE;
-            else
-                sources = IGNORE_FILE + ";" + sources;
-        }
-        if(Main.pref.getBoolean(PREF_USE_SPELL_FILE, true))
-        {
-            if( sources == null || sources.length() == 0)
-                sources = SPELL_FILE;
-            else
-                sources = SPELL_FILE + ";" + sources;
-        }
-
-        String errorSources = "";
-        if(sources.length() == 0)
-            return;
-        for(String source: sources.split(";"))
-        {
-            try
-            {
-                MirroredInputStream s = new MirroredInputStream(source, Util.getPluginDir(), -1);
-                InputStreamReader r;
-                try
-                {
-                    r = new InputStreamReader(s, "UTF-8");
-                }
-                catch (UnsupportedEncodingException e)
-                {
-                    r = new InputStreamReader(s);
-                }
-                BufferedReader reader = new BufferedReader(r);
-
-                String okValue = null;
-                Boolean tagcheckerfile = false;
-                Boolean ignorefile = false;
-                String line;
-                while((line = reader.readLine()) != null && (tagcheckerfile || line.length() != 0))
-                {
-                    if(line.startsWith("#"))
-                    {
-                        if(line.startsWith("# JOSM TagChecker"))
-                            tagcheckerfile = true;
-                        if(line.startsWith("# JOSM IgnoreTags"))
-                            ignorefile = true;
-                        continue;
-                    }
-                    else if(ignorefile)
-                    {
-                        line = line.trim();
-                        if(line.length() < 4)
-                            continue;
-
-                        String key = line.substring(0, 2);
-                        line = line.substring(2);
-
-                        if(key.equals("S:"))
-                        {
-                            ignoreDataStartsWith.add(line);
-                        }
-                        else if(key.equals("E:"))
-                        {
-                            ignoreDataEquals.add(line);
-                        }
-                        else if(key.equals("F:"))
-                        {
-                            ignoreDataEndsWith.add(line);
-                        }
-                        else if(key.equals("K:"))
-                        {
-                            IgnoreKeyPair tmp = new IgnoreKeyPair();
-                            int mid = line.indexOf("=");
-                            tmp.key = line.substring(0, mid);
-                            tmp.value = line.substring(mid+1);
-                            ignoreDataKeyPair.add(tmp);
-                        }
-                        else if(key.equals("T:"))
-                        {
-                            IgnoreTwoKeyPair tmp = new IgnoreTwoKeyPair();
-                            int mid = line.indexOf("=");
-                            int split = line.indexOf("|");
-                            tmp.key1 = line.substring(0, mid);
-                            tmp.value1 = line.substring(mid+1, split);
-                            line = line.substring(split+1);
-                            mid = line.indexOf("=");
-                            tmp.key2 = line.substring(0, mid);
-                            tmp.value2 = line.substring(mid+1);
-                            ignoreDataTwoKeyPair.add(tmp);
-                        }
-                        continue;
-                    }
-                    else if(tagcheckerfile)
-                    {
-                        if(line.length() > 0)
-                        {
-                            CheckerData d = new CheckerData();
-                            String err = d.getData(line);
-
-                            if(err == null)
-                                checkerData.add(d);
-                            else
-                                System.err.println(tr("Invalid tagchecker line - {0}: {1}", err, line));
-                        }
-                    }
-                    else if(line.charAt(0) == '+')
-                    {
-                        okValue = line.substring(1);
-                    }
-                    else if(line.charAt(0) == '-' && okValue != null)
-                    {
-                        spellCheckKeyData.put(line.substring(1), okValue);
-                    }
-                    else
-                    {
-                        System.err.println(tr("Invalid spellcheck line: {0}", line));
-                    }
-                }
-            }
-            catch (IOException e)
-            {
-                errorSources += source + "\n";
-            }
-        }
-
-        if( errorSources.length() > 0 )
-            throw new IOException( tr("Could not access data file(s):\n{0}", errorSources) );
-    }
-
-    /**
-     * Reads the presets data.
-     *
-     * @throws Exception
-     */
-    public static void initializePresets() throws Exception
-    {
-        if( !Main.pref.getBoolean(PREF_CHECK_VALUES, true) )
-            return;
-
-        Collection<TaggingPreset> presets = TaggingPresetPreference.taggingPresets;
-        if(presets != null)
-        {
-            presetsValueData = new Bag<String, String>();
-            for(String a : OsmPrimitive.getUninterestingKeys())
-                presetsValueData.add(a);
-            for(String a : OsmPrimitive.getDirectionKeys())
-                presetsValueData.add(a);
-            for(String a : Main.pref.getCollection(PreferenceEditor.PREFIX + ".knownkeys",
-            Arrays.asList(new String[]{"is_in", "int_ref", "fixme", "population"})))
-                presetsValueData.add(a);
-            for(TaggingPreset p : presets)
-            {
-                for(TaggingPreset.Item i : p.data)
-                {
-                    if(i instanceof TaggingPreset.Combo)
-                    {
-                        TaggingPreset.Combo combo = (TaggingPreset.Combo) i;
-                        for(String value : combo.values.split(","))
-                            presetsValueData.add(combo.key, value);
-                    }
-                    else if(i instanceof TaggingPreset.Key)
-                    {
-                        TaggingPreset.Key k = (TaggingPreset.Key) i;
-                        presetsValueData.add(k.key, k.value);
-                    }
-                    else if(i instanceof TaggingPreset.Text)
-                    {
-                        TaggingPreset.Text k = (TaggingPreset.Text) i;
-                        presetsValueData.add(k.key);
-                    }
-                    else if(i instanceof TaggingPreset.Check)
-                    {
-                        TaggingPreset.Check k = (TaggingPreset.Check) i;
-                        presetsValueData.add(k.key, "yes");
-                        presetsValueData.add(k.key, "no");
-                    }
-                }
-            }
-        }
-    }
-
-    @Override
-    public void visit(Node n)
-    {
-        checkPrimitive(n);
-    }
-
-
-    @Override
-    public void visit(Relation n)
-    {
-        checkPrimitive(n);
-    }
-
-
-    @Override
-    public void visit(Way w)
-    {
-        checkPrimitive(w);
-    }
-
-    /**
-     * Checks the primitive properties
-     * @param p The primitive to check
-     */
-    private void checkPrimitive(OsmPrimitive p)
-    {
-        // Just a collection to know if a primitive has been already marked with error
-        Bag<OsmPrimitive, String> withErrors = new Bag<OsmPrimitive, String>();
-
-        if(checkComplex)
-        {
-            Map<String, String> props = (p.getKeys() == null) ? Collections.<String, String>emptyMap() : p.getKeys();
-            for(Entry<String, String> prop: props.entrySet() )
-            {
-                boolean ignore = true;
-                String key1 = prop.getKey();
-                String value1 = prop.getValue();
-
-                for(IgnoreTwoKeyPair a : ignoreDataTwoKeyPair)
-                {
-                    if(key1.equals(a.key1) && value1.equals(a.value1))
-                    {
-                        ignore = false;
-                        for(Entry<String, String> prop2: props.entrySet() )
-                        {
-                            String key2 = prop2.getKey();
-                            String value2 = prop2.getValue();
-                            for(IgnoreTwoKeyPair b : ignoreDataTwoKeyPair)
-                            {
-                                if(key2.equals(b.key2) && value2.equals(b.value2))
-                                {
-                                    ignore = true;
-                                    break;
-                                }
-                            }
-                            if(ignore)
-                                break;
-                        }
-                    }
-                    if(ignore)
-                        break;
-                }
-
-                if(!ignore)
-                {
-                    errors.add( new TestError(this, Severity.ERROR, tr("Illegal tag/value combinations"),
-                    tr("Illegal tag/value combinations"), tr("Illegal tag/value combinations"), 1272, p) );
-                    withErrors.add(p, "TC");
-                }
-            }
-
-            for(CheckerData d : checkerData)
-            {
-                if(d.match(p))
-                {
-                    errors.add( new TestError(this, d.getSeverity(), tr("Illegal tag/value combinations"),
-                    d.getDescription(), d.getDescriptionOrig(), d.getCode(), p) );
-                    withErrors.add(p, "TC");
-                }
-            }
-        }
-        if(checkPaint)
-        {
-            List<String> pe = p.getDataSet().getErrors(p);
-            if(pe != null)
-            {
-                for(String s: pe)
-                {
-                    /* passing translated text also to original string, as we already
-                    translated the stuff before. Makes the ignore file language dependend. */
-                    errors.add( new TestError(this, Severity.WARNING, tr("Painting problem"),
-                    s, s, PAINT, p) );
-                    withErrors.add(p, "P");
-                }
-            }
-        }
-
-        Map<String, String> props = (p.getKeys() == null) ? Collections.<String, String>emptyMap() : p.getKeys();
-        for(Entry<String, String> prop: props.entrySet() )
-        {
-            String s = marktr("Key ''{0}'' invalid.");
-            String key = prop.getKey();
-            String value = prop.getValue();
-            if( checkValues && (value==null || value.trim().length() == 0) && !withErrors.contains(p, "EV"))
-            {
-                errors.add( new TestError(this, Severity.WARNING, tr("Tags with empty values"),
-                tr(s, key), MessageFormat.format(s, key), EMPTY_VALUES, p) );
-                withErrors.add(p, "EV");
-            }
-            if( checkKeys && spellCheckKeyData.containsKey(key) && !withErrors.contains(p, "IPK"))
-            {
-                errors.add( new TestError(this, Severity.WARNING, tr("Invalid property key"),
-                tr(s, key), MessageFormat.format(s, key), INVALID_KEY, p) );
-                withErrors.add(p, "IPK");
-            }
-            if( checkKeys && key.indexOf(" ") >= 0 && !withErrors.contains(p, "IPK"))
-            {
-                errors.add( new TestError(this, Severity.WARNING, tr("Invalid white space in property key"),
-                tr(s, key), MessageFormat.format(s, key), INVALID_KEY_SPACE, p) );
-                withErrors.add(p, "IPK");
-            }
-            if( checkValues && value != null && (value.startsWith(" ") || value.endsWith(" ")) && !withErrors.contains(p, "SPACE"))
-            {
-                errors.add( new TestError(this, Severity.OTHER, tr("Property values start or end with white space"),
-                tr(s, key), MessageFormat.format(s, key), INVALID_SPACE, p) );
-                withErrors.add(p, "SPACE");
-            }
-            if( checkValues && value != null && !value.equals(entities.unescape(value)) && !withErrors.contains(p, "HTML"))
-            {
-                errors.add( new TestError(this, Severity.OTHER, tr("Property values contain HTML entity"),
-                tr(s, key), MessageFormat.format(s, key), INVALID_HTML, p) );
-                withErrors.add(p, "HTML");
-            }
-            if( checkValues && value != null && value.length() > 0 && presetsValueData != null)
-            {
-                List<String> values = presetsValueData.get(key);
-                if(values == null)
-                {
-                    Boolean ignore = false;
-                    for(String a : ignoreDataStartsWith)
-                    {
-                        if(key.startsWith(a))
-                            ignore = true;
-                    }
-                    for(String a : ignoreDataEquals)
-                    {
-                        if(key.equals(a))
-                            ignore = true;
-                    }
-                    for(String a : ignoreDataEndsWith)
-                    {
-                        if(key.endsWith(a))
-                            ignore = true;
-                    }
-                    if(!ignore)
-                    {
-                        String i = marktr("Key ''{0}'' not in presets.");
-                        errors.add( new TestError(this, Severity.OTHER, tr("Presets do not contain property key"),
-                        tr(i, key), MessageFormat.format(i, key), INVALID_VALUE, p) );
-                        withErrors.add(p, "UPK");
-                    }
-                }
-                else if(values.size() > 0 && !values.contains(prop.getValue()))
-                {
-                    boolean ignore = false;
-                    for(IgnoreKeyPair a : ignoreDataKeyPair)
-                    {
-                        if(key.equals(a.key) && value.equals(a.value))
-                            ignore = true;
-                    }
-
-                    for(IgnoreTwoKeyPair a : ignoreDataTwoKeyPair)
-                    {
-                        if(key.equals(a.key2) && value.equals(a.value2))
-                            ignore = true;
-                    }
-
-                    if(!ignore)
-                    {
-                        String i = marktr("Value ''{0}'' for key ''{1}'' not in presets.");
-                        errors.add( new TestError(this, Severity.OTHER, tr("Presets do not contain property value"),
-                        tr(i, prop.getValue(), key), MessageFormat.format(i, prop.getValue(), key), INVALID_VALUE, p) );
-                        withErrors.add(p, "UPV");
-                    }
-                }
-            }
-            if( checkFixmes && value != null && value.length() > 0 )
-            {
-                if( (value.contains("FIXME") || value.contains("check and delete") || key.contains("todo") || key.contains("fixme"))
-                && !withErrors.contains(p, "FIXME"))
-                {
-                    errors.add( new TestError(this, Severity.OTHER, tr("FIXMES"), FIXME, p) );
-                    withErrors.add(p, "FIXME");
-                }
-            }
-        }
-    }
-
-    @Override
-    public void startTest(ProgressMonitor monitor)
-    {
-        super.startTest(monitor);
-        checkKeys = Main.pref.getBoolean(PREF_CHECK_KEYS, true);
-        if( isBeforeUpload )
-            checkKeys = checkKeys && Main.pref.getBoolean(PREF_CHECK_KEYS_BEFORE_UPLOAD, true);
-
-        checkValues = Main.pref.getBoolean(PREF_CHECK_VALUES, true);
-        if( isBeforeUpload )
-            checkValues = checkValues && Main.pref.getBoolean(PREF_CHECK_VALUES_BEFORE_UPLOAD, true);
-
-        checkComplex = Main.pref.getBoolean(PREF_CHECK_COMPLEX, true);
-        if( isBeforeUpload )
-            checkComplex = checkValues && Main.pref.getBoolean(PREF_CHECK_COMPLEX_BEFORE_UPLOAD, true);
-
-        checkFixmes = Main.pref.getBoolean(PREF_CHECK_FIXMES, true);
-        if( isBeforeUpload )
-            checkFixmes = checkFixmes && Main.pref.getBoolean(PREF_CHECK_FIXMES_BEFORE_UPLOAD, true);
-
-        checkPaint = Main.pref.getBoolean(PREF_CHECK_PAINT, true);
-        if( isBeforeUpload )
-            checkPaint = checkPaint && Main.pref.getBoolean(PREF_CHECK_PAINT_BEFORE_UPLOAD, true);
-    }
-
-    @Override
-    public void visit(Collection<OsmPrimitive> selection)
-    {
-        if( checkKeys || checkValues || checkComplex || checkPaint || checkFixmes)
-            super.visit(selection);
-    }
-
-    @Override
-    public void addGui(JPanel testPanel)
-    {
-        GBC a = GBC.eol();
-        a.anchor = GBC.EAST;
-
-        testPanel.add( new JLabel(name), GBC.eol().insets(3,0,0,0) );
-
-        prefCheckKeys = new JCheckBox(tr("Check property keys."), Main.pref.getBoolean(PREF_CHECK_KEYS, true));
-        prefCheckKeys.setToolTipText(tr("Validate that property keys are valid checking against list of words."));
-        testPanel.add(prefCheckKeys, GBC.std().insets(20,0,0,0));
-
-        prefCheckKeysBeforeUpload = new JCheckBox();
-        prefCheckKeysBeforeUpload.setSelected(Main.pref.getBoolean(PREF_CHECK_KEYS_BEFORE_UPLOAD, true));
-        testPanel.add(prefCheckKeysBeforeUpload, a);
-
-        prefCheckComplex = new JCheckBox(tr("Use complex property checker."), Main.pref.getBoolean(PREF_CHECK_COMPLEX, true));
-        prefCheckComplex.setToolTipText(tr("Validate property values and tags using complex rules."));
-        testPanel.add(prefCheckComplex, GBC.std().insets(20,0,0,0));
-
-        prefCheckComplexBeforeUpload = new JCheckBox();
-        prefCheckComplexBeforeUpload.setSelected(Main.pref.getBoolean(PREF_CHECK_COMPLEX_BEFORE_UPLOAD, true));
-        testPanel.add(prefCheckComplexBeforeUpload, a);
-
-        Sources = new JList(new DefaultListModel());
-
-        String sources = Main.pref.get( PREF_SOURCES );
-        if(sources != null && sources.length() > 0)
-        {
-            for(String source : sources.split(";"))
-                ((DefaultListModel)Sources.getModel()).addElement(source);
-        }
-
-        addSrcButton = new JButton(tr("Add"));
-        addSrcButton.addActionListener(new ActionListener(){
-            public void actionPerformed(ActionEvent e) {
-                String source = JOptionPane.showInputDialog(
-                        Main.parent,
-                        tr("TagChecker source"),
-                        tr("TagChecker source"),
-                        JOptionPane.QUESTION_MESSAGE
-                        );
-                if (source != null)
-                    ((DefaultListModel)Sources.getModel()).addElement(source);
-                Sources.clearSelection();
-            }
-        });
-
-        editSrcButton = new JButton(tr("Edit"));
-        editSrcButton.addActionListener(new ActionListener(){
-            public void actionPerformed(ActionEvent e) {
-                int row = Sources.getSelectedIndex();
-                if(row == -1 && Sources.getModel().getSize() == 1)
-                {
-                    Sources.setSelectedIndex(0);
-                    row = 0;
-                }
-                if (row == -1)
-                {
-                    if(Sources.getModel().getSize() == 0)
-                    {
-                        String source = JOptionPane.showInputDialog(Main.parent, tr("TagChecker source"), tr("TagChecker source"), JOptionPane.QUESTION_MESSAGE);
-                        if (source != null)
-                            ((DefaultListModel)Sources.getModel()).addElement(source);
-                    }
-                    else
-                    {
-                        JOptionPane.showMessageDialog(
-                                Main.parent,
-                                tr("Please select the row to edit."),
-                                tr("Information"),
-                                JOptionPane.INFORMATION_MESSAGE
-                                );
-                    }
-                }
-                else {
-                    String source = (String)JOptionPane.showInputDialog(Main.parent,
-                            tr("TagChecker source"),
-                            tr("TagChecker source"),
-                            JOptionPane.QUESTION_MESSAGE, null, null,
-                            Sources.getSelectedValue());
-                    if (source != null)
-                        ((DefaultListModel)Sources.getModel()).setElementAt(source, row);
-                }
-                Sources.clearSelection();
-            }
-        });
-
-        deleteSrcButton = new JButton(tr("Delete"));
-        deleteSrcButton.addActionListener(new ActionListener(){
-            public void actionPerformed(ActionEvent e) {
-                if (Sources.getSelectedIndex() == -1)
-                    JOptionPane.showMessageDialog(Main.parent, tr("Please select the row to delete."), tr("Information"), JOptionPane.QUESTION_MESSAGE);
-                else {
-                    ((DefaultListModel)Sources.getModel()).remove(Sources.getSelectedIndex());
-                }
-            }
-        });
-        Sources.setMinimumSize(new Dimension(300,50));
-        Sources.setVisibleRowCount(3);
-
-        Sources.setToolTipText(tr("The sources (URL or filename) of spell check (see http://wiki.openstreetmap.org/index.php/User:JLS/speller) or tag checking data files."));
-        addSrcButton.setToolTipText(tr("Add a new source to the list."));
-        editSrcButton.setToolTipText(tr("Edit the selected source."));
-        deleteSrcButton.setToolTipText(tr("Delete the selected source from the list."));
-
-        testPanel.add(new JLabel(tr("Data sources")), GBC.eol().insets(23,0,0,0));
-        testPanel.add(new JScrollPane(Sources), GBC.eol().insets(23,0,0,0).fill(GBC.HORIZONTAL));
-        final JPanel buttonPanel = new JPanel(new GridBagLayout());
-        testPanel.add(buttonPanel, GBC.eol().fill(GBC.HORIZONTAL));
-        buttonPanel.add(addSrcButton, GBC.std().insets(0,5,0,0));
-        buttonPanel.add(editSrcButton, GBC.std().insets(5,5,5,0));
-        buttonPanel.add(deleteSrcButton, GBC.std().insets(0,5,0,0));
-
-        ActionListener disableCheckActionListener = new ActionListener(){
-            public void actionPerformed(ActionEvent e) {
-                handlePrefEnable();
-            }
-        };
-        prefCheckKeys.addActionListener(disableCheckActionListener);
-        prefCheckKeysBeforeUpload.addActionListener(disableCheckActionListener);
-        prefCheckComplex.addActionListener(disableCheckActionListener);
-        prefCheckComplexBeforeUpload.addActionListener(disableCheckActionListener);
-
-        handlePrefEnable();
-
-        prefCheckValues = new JCheckBox(tr("Check property values."), Main.pref.getBoolean(PREF_CHECK_VALUES, true));
-        prefCheckValues.setToolTipText(tr("Validate that property values are valid checking against presets."));
-        testPanel.add(prefCheckValues, GBC.std().insets(20,0,0,0));
-
-        prefCheckValuesBeforeUpload = new JCheckBox();
-        prefCheckValuesBeforeUpload.setSelected(Main.pref.getBoolean(PREF_CHECK_VALUES_BEFORE_UPLOAD, true));
-        testPanel.add(prefCheckValuesBeforeUpload, a);
-
-        prefCheckFixmes = new JCheckBox(tr("Check for FIXMES."), Main.pref.getBoolean(PREF_CHECK_FIXMES, true));
-        prefCheckFixmes.setToolTipText(tr("Looks for nodes or ways with FIXME in any property value."));
-        testPanel.add(prefCheckFixmes, GBC.std().insets(20,0,0,0));
-
-        prefCheckFixmesBeforeUpload = new JCheckBox();
-        prefCheckFixmesBeforeUpload.setSelected(Main.pref.getBoolean(PREF_CHECK_FIXMES_BEFORE_UPLOAD, true));
-        testPanel.add(prefCheckFixmesBeforeUpload, a);
-
-        prefCheckPaint = new JCheckBox(tr("Check for paint notes."), Main.pref.getBoolean(PREF_CHECK_PAINT, true));
-        prefCheckPaint.setToolTipText(tr("Check if map painting found data errors."));
-        testPanel.add(prefCheckPaint, GBC.std().insets(20,0,0,0));
-
-        prefCheckPaintBeforeUpload = new JCheckBox();
-        prefCheckPaintBeforeUpload.setSelected(Main.pref.getBoolean(PREF_CHECK_PAINT_BEFORE_UPLOAD, true));
-        testPanel.add(prefCheckPaintBeforeUpload, a);
-
-        prefUseDataFile = new JCheckBox(tr("Use default data file."), Main.pref.getBoolean(PREF_USE_DATA_FILE, true));
-        prefUseDataFile.setToolTipText(tr("Use the default data file (recommended)."));
-        testPanel.add(prefUseDataFile, GBC.eol().insets(20,0,0,0));
-
-        prefUseIgnoreFile = new JCheckBox(tr("Use default tag ignore file."), Main.pref.getBoolean(PREF_USE_IGNORE_FILE, true));
-        prefUseIgnoreFile.setToolTipText(tr("Use the default tag ignore file (recommended)."));
-        testPanel.add(prefUseIgnoreFile, GBC.eol().insets(20,0,0,0));
-
-        prefUseSpellFile = new JCheckBox(tr("Use default spellcheck file."), Main.pref.getBoolean(PREF_USE_SPELL_FILE, true));
-        prefUseSpellFile.setToolTipText(tr("Use the default spellcheck file (recommended)."));
-        testPanel.add(prefUseSpellFile, GBC.eol().insets(20,0,0,0));
-    }
-
-    public void handlePrefEnable()
-    {
-        boolean selected = prefCheckKeys.isSelected() || prefCheckKeysBeforeUpload.isSelected()
-        || prefCheckComplex.isSelected() || prefCheckComplexBeforeUpload.isSelected();
-        Sources.setEnabled( selected );
-        addSrcButton.setEnabled(selected);
-        editSrcButton.setEnabled(selected);
-        deleteSrcButton.setEnabled(selected);
-    }
-
-    @Override
-    public boolean ok()
-    {
-        enabled = prefCheckKeys.isSelected() || prefCheckValues.isSelected() || prefCheckComplex.isSelected() || prefCheckFixmes.isSelected();
-        testBeforeUpload = prefCheckKeysBeforeUpload.isSelected() || prefCheckValuesBeforeUpload.isSelected()
-        || prefCheckFixmesBeforeUpload.isSelected() || prefCheckComplexBeforeUpload.isSelected();
-
-        Main.pref.put(PREF_CHECK_VALUES, prefCheckValues.isSelected());
-        Main.pref.put(PREF_CHECK_COMPLEX, prefCheckComplex.isSelected());
-        Main.pref.put(PREF_CHECK_KEYS, prefCheckKeys.isSelected());
-        Main.pref.put(PREF_CHECK_FIXMES, prefCheckFixmes.isSelected());
-        Main.pref.put(PREF_CHECK_PAINT, prefCheckPaint.isSelected());
-        Main.pref.put(PREF_CHECK_VALUES_BEFORE_UPLOAD, prefCheckValuesBeforeUpload.isSelected());
-        Main.pref.put(PREF_CHECK_COMPLEX_BEFORE_UPLOAD, prefCheckComplexBeforeUpload.isSelected());
-        Main.pref.put(PREF_CHECK_KEYS_BEFORE_UPLOAD, prefCheckKeysBeforeUpload.isSelected());
-        Main.pref.put(PREF_CHECK_FIXMES_BEFORE_UPLOAD, prefCheckFixmesBeforeUpload.isSelected());
-        Main.pref.put(PREF_CHECK_PAINT_BEFORE_UPLOAD, prefCheckPaintBeforeUpload.isSelected());
-        Main.pref.put(PREF_USE_DATA_FILE, prefUseDataFile.isSelected());
-        Main.pref.put(PREF_USE_IGNORE_FILE, prefUseIgnoreFile.isSelected());
-        Main.pref.put(PREF_USE_SPELL_FILE, prefUseSpellFile.isSelected());
-        String sources = "";
-        if( Sources.getModel().getSize() > 0 )
-        {
-            String sb = "";
-            for (int i = 0; i < Sources.getModel().getSize(); ++i)
-                sb += ";"+Sources.getModel().getElementAt(i);
-            sources = sb.substring(1);
-        }
-        if(sources.length() == 0)
-            sources = null;
-        return Main.pref.put(PREF_SOURCES, sources);
-    }
-
-    @Override
-    public Command fixError(TestError testError)
-    {
-        List<Command> commands = new ArrayList<Command>(50);
-
-        int i = -1;
-        List<? extends OsmPrimitive> primitives = testError.getPrimitives();
-        for(OsmPrimitive p : primitives )
-        {
-            i++;
-            Map<String, String> tags = p.getKeys();
-            if( tags == null || tags.size() == 0 )
-                continue;
-
-            for(Entry<String, String> prop: tags.entrySet() )
-            {
-                String key = prop.getKey();
-                String value = prop.getValue();
-                if( value == null || value.trim().length() == 0 )
-                    commands.add( new ChangePropertyCommand(Collections.singleton(primitives.get(i)), key, null) );
-                else if(value.startsWith(" ") || value.endsWith(" "))
-                    commands.add( new ChangePropertyCommand(Collections.singleton(primitives.get(i)), key, value.trim()) );
-                else if(key.startsWith(" ") || key.endsWith(" "))
-                    commands.add( new ChangePropertyKeyCommand(Collections.singleton(primitives.get(i)), key, key.trim()) );
-                else
-                {
-                    String evalue = entities.unescape(value);
-                    if(!evalue.equals(value))
-                        commands.add( new ChangePropertyCommand(Collections.singleton(primitives.get(i)), key, evalue) );
-                    else
-                    {
-                        String replacementKey = spellCheckKeyData.get(key);
-                        if( replacementKey != null )
-                        {
-                            commands.add( new ChangePropertyKeyCommand(Collections.singleton(primitives.get(i)),
-                            key, replacementKey) );
-                        }
-                    }
-                }
-            }
-        }
-
-        if( commands.size() == 0 )
-            return null;
-        else if( commands.size() == 1 )
-            return commands.get(0);
-        else
-            return new SequenceCommand(tr("Fix properties"), commands);
-    }
-
-    @Override
-    public boolean isFixable(TestError testError)
-    {
-        if( testError.getTester() instanceof TagChecker)
-        {
-            int code = testError.getCode();
-            return code == INVALID_KEY || code == EMPTY_VALUES || code == INVALID_SPACE || code == INVALID_KEY_SPACE || code == INVALID_HTML;
-        }
-
-        return false;
-    }
-
-    private static class IgnoreTwoKeyPair {
-        public String key1;
-        public String value1;
-        public String key2;
-        public String value2;
-    }
-
-    private static class IgnoreKeyPair {
-        public String key;
-        public String value;
-    }
-
-    private static class CheckerData {
-        private String description;
-        private List<CheckerElement> data = new ArrayList<CheckerElement>();
-        private Integer type = 0;
-        private Integer code;
-        protected Severity severity;
-        protected static int NODE = 1;
-        protected static int WAY = 2;
-        protected static int RELATION = 3;
-        protected static int ALL = 4;
-        protected static int TAG_CHECK_ERROR  = 1250;
-        protected static int TAG_CHECK_WARN   = 1260;
-        protected static int TAG_CHECK_INFO   = 1270;
-
-        private class CheckerElement {
-            public Object tag;
-            public Object value;
-            public Boolean noMatch;
-            public Boolean tagAll = false;
-            public Boolean valueAll = false;
-            public Boolean valueBool = false;
-            private Pattern getPattern(String str) throws IllegalStateException, PatternSyntaxException
-            {
-                if(str.endsWith("/i"))
-                    return Pattern.compile(str.substring(1,str.length()-2), Pattern.CASE_INSENSITIVE);
-                else if(str.endsWith("/"))
-                    return Pattern.compile(str.substring(1,str.length()-1));
-                throw new IllegalStateException();
-            }
-            public CheckerElement(String exp) throws IllegalStateException, PatternSyntaxException
-            {
-                Matcher m = Pattern.compile("(.+)([!=]=)(.+)").matcher(exp);
-                m.matches();
-
-                String n = m.group(1).trim();
-                if(n.equals("*"))
-                    tagAll = true;
-                else
-                    tag = n.startsWith("/") ? getPattern(n) : n;
-                noMatch = m.group(2).equals("!=");
-                n = m.group(3).trim();
-                if(n.equals("*"))
-                    valueAll = true;
-                else if(n.equals("BOOLEAN_TRUE"))
-                {
-                    valueBool = true;
-                    value = OsmUtils.trueval;
-                }
-                else if(n.equals("BOOLEAN_FALSE"))
-                {
-                    valueBool = true;
-                    value = OsmUtils.falseval;
-                }
-                else
-                    value = n.startsWith("/") ? getPattern(n) : n;
-            }
-            public Boolean match(OsmPrimitive osm)
-            {
-                for(Entry<String, String> prop: osm.getKeys().entrySet())
-                {
-                    String key = prop.getKey();
-                    String val = valueBool ? OsmUtils.getNamedOsmBoolean(prop.getValue()) : prop.getValue();
-                    if((tagAll || (tag instanceof Pattern ? ((Pattern)tag).matcher(key).matches() : key.equals(tag)))
-                    && (valueAll || (value instanceof Pattern ? ((Pattern)value).matcher(val).matches() : val.equals(value))))
-                        return !noMatch;
-                }
-                return noMatch;
-            }
-        };
-
-        public String getData(String str)
-        {
-            Matcher m = Pattern.compile(" *# *([^#]+) *$").matcher(str);
-            str = m.replaceFirst("").trim();
-            try
-            {
-                description = m.group(1);
-                if(description != null && description.length() == 0)
-                    description = null;
-            }
-            catch (IllegalStateException e)
-            {
-                description = null;
-            }
-            String[] n = str.split(" *: *", 3);
-            if(n[0].equals("way"))
-                type = WAY;
-            else if(n[0].equals("node"))
-                type = NODE;
-            else if(n[0].equals("relation"))
-                type = RELATION;
-            else if(n[0].equals("*"))
-                type = ALL;
-            if(type == 0 || n.length != 3)
-                return tr("Could not find element type");
-            if(n[1].equals("W"))
-            {
-                severity = Severity.WARNING;
-                code = TAG_CHECK_WARN;
-            }
-            else if(n[1].equals("E"))
-            {
-                severity = Severity.ERROR;
-                code = TAG_CHECK_ERROR;
-            }
-            else if(n[1].equals("I"))
-            {
-                severity = Severity.OTHER;
-                code = TAG_CHECK_INFO;
-            }
-            else
-                return tr("Could not find warning level");
-            for(String exp: n[2].split(" *&& *"))
-            {
-                try
-                {
-                    data.add(new CheckerElement(exp));
-                }
-                catch(IllegalStateException e)
-                {
-                    return tr("Illegal expression ''{0}''", exp);
-                }
-                catch(PatternSyntaxException e)
-                {
-                    return tr("Illegal regular expression ''{0}''", exp);
-                }
-            }
-            return null;
-        }
-        public Boolean match(OsmPrimitive osm)
-        {
-            if(osm.getKeys() == null || (type == NODE && !(osm instanceof Node))
-            || (type == RELATION && !(osm instanceof Relation)) || (type == WAY && !(osm instanceof Way)))
-                return false;
-            for(CheckerElement ce : data)
-            {
-                if(!ce.match(osm))
-                    return false;
-            }
-            return true;
-        }
-        public String getDescription()
-        {
-            return tr(description);
-        }
-        public String getDescriptionOrig()
-        {
-            return description;
-        }
-        public Severity getSeverity()
-        {
-            return severity;
-        }
-        public int getCode()
-        {
-            return code + type;
-        }
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/tests/UnclosedWays.java b/validator/src/org/openstreetmap/josm/plugins/validator/tests/UnclosedWays.java
deleted file mode 100644
index 59d8739..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/tests/UnclosedWays.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package org.openstreetmap.josm.plugins.validator.tests;
-
-import static org.openstreetmap.josm.tools.I18n.marktr;
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.OsmUtils;
-import org.openstreetmap.josm.data.osm.Relation;
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.gui.progress.ProgressMonitor;
-import org.openstreetmap.josm.plugins.validator.Severity;
-import org.openstreetmap.josm.plugins.validator.Test;
-import org.openstreetmap.josm.plugins.validator.TestError;
-import org.openstreetmap.josm.plugins.validator.util.Bag;
-
-/**
- * Check area type ways for errors
- *
- * @author stoecker
- */
-public class UnclosedWays extends Test {
-    /** The already detected errors */
-    Bag<Way, Way> _errorWays;
-
-    /**
-     * Constructor
-     */
-    public UnclosedWays() {
-        super(tr("Unclosed Ways."), tr("This tests if ways which should be circular are closed."));
-    }
-
-    @Override
-    public void startTest(ProgressMonitor monitor) {
-        super.startTest(monitor);
-        _errorWays = new Bag<Way, Way>();
-    }
-
-    @Override
-    public void endTest() {
-        _errorWays = null;
-        super.endTest();
-    }
-
-    private String type;
-    private String etype;
-    private int mode;
-
-    public void set(int m, String text, String desc) {
-        etype = MessageFormat.format(text, desc);
-        type = tr(text, tr(desc));
-        mode = m;
-    }
-
-    public void set(int m, String text) {
-        etype = text;
-        type = tr(text);
-        mode = m;
-    }
-
-    @Override
-    public void visit(Way w) {
-        String test;
-        type = etype = null;
-        mode = 0;
-
-        if (!w.isUsable())
-            return;
-
-        test = w.get("natural");
-        if (test != null && !"coastline".equals(test) && !"cliff".equals(test))
-            set(1101, marktr("natural type {0}"), test);
-        test = w.get("landuse");
-        if (test != null)
-            set(1102, marktr("landuse type {0}"), test);
-        test = w.get("amenities");
-        if (test != null)
-            set(1103, marktr("amenities type {0}"), test);
-        test = w.get("sport");
-        if (test != null && !test.equals("water_slide"))
-            set(1104, marktr("sport type {0}"), test);
-        test = w.get("tourism");
-        if (test != null)
-            set(1105, marktr("tourism type {0}"), test);
-        test = w.get("shop");
-        if (test != null)
-            set(1106, marktr("shop type {0}"), test);
-        test = w.get("leisure");
-        if (test != null)
-            set(1107, marktr("leisure type {0}"), test);
-        test = w.get("waterway");
-        if (test != null && test.equals("riverbank"))
-            set(1108, marktr("waterway type {0}"), test);
-        Boolean btest = OsmUtils.getOsmBoolean(w.get("building"));
-        if (btest != null && btest)
-            set(1120, marktr("building"));
-        btest = OsmUtils.getOsmBoolean(w.get("area"));
-        if (btest != null && btest)
-            set(1130, marktr("area"));
-
-        if (type != null && !w.isClosed()) {
-            for (OsmPrimitive parent: this.backreferenceDataSet.getParents(w)) {
-                if (parent instanceof Relation && "multipolygon".equals(parent.get("type")))
-                    return;
-            }
-            Node f = w.firstNode();
-            Node l = w.lastNode();
-
-            List<OsmPrimitive> primitives = new ArrayList<OsmPrimitive>();
-            List<OsmPrimitive> highlight = new ArrayList<OsmPrimitive>();
-            primitives.add(w);
-
-            // The important parts of an unclosed way are the first and
-            // the last node which should be connected, therefore we highlight them
-            highlight.add(f);
-            highlight.add(l);
-
-            errors.add(new TestError(this, Severity.WARNING, tr("Unclosed way"),
-                            type, etype, mode, primitives, highlight));
-            _errorWays.add(w, w);
-        }
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/tests/UnconnectedWays.java b/validator/src/org/openstreetmap/josm/plugins/validator/tests/UnconnectedWays.java
deleted file mode 100644
index ce93a3d..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/tests/UnconnectedWays.java
+++ /dev/null
@@ -1,387 +0,0 @@
-package org.openstreetmap.josm.plugins.validator.tests;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.geom.Area;
-import java.awt.geom.Line2D;
-import java.awt.geom.Point2D;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.data.coor.EastNorth;
-import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.osm.BBox;
-import org.openstreetmap.josm.data.osm.DataSet;
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.OsmUtils;
-import org.openstreetmap.josm.data.osm.QuadBuckets;
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.gui.progress.ProgressMonitor;
-import org.openstreetmap.josm.plugins.validator.PreferenceEditor;
-import org.openstreetmap.josm.plugins.validator.Severity;
-import org.openstreetmap.josm.plugins.validator.Test;
-import org.openstreetmap.josm.plugins.validator.TestError;
-
-/**
- * Tests if there are segments that crosses in the same layer
- *
- * @author frsantos
- */
-public class UnconnectedWays extends Test
-{
-    protected static int UNCONNECTED_WAYS = 1301;
-    protected static final String PREFIX = PreferenceEditor.PREFIX + "." + UnconnectedWays.class.getSimpleName();
-
-    Set<MyWaySegment> ways;
-    Set<Node> endnodes; // nodes at end of way
-    Set<Node> endnodes_highway; // nodes at end of way
-    Set<Node> middlenodes; // nodes in middle of way
-    Set<Node> othernodes; // nodes appearing at least twice
-    //NodeSearchCache nodecache;
-    QuadBuckets<Node> nodecache;
-    Area ds_area;
-    DataSet ds;
-
-    double mindist;
-    double minmiddledist;
-    /**
-     * Constructor
-     */
-    public UnconnectedWays()
-    {
-        super(tr("Unconnected ways."),
-              tr("This test checks if a way has an endpoint very near to another way."));
-    }
-
-    @Override
-    public void startTest(ProgressMonitor monitor)
-    {
-        super.startTest(monitor);
-        ways = new HashSet<MyWaySegment>();
-        endnodes = new HashSet<Node>();
-        endnodes_highway = new HashSet<Node>();
-        middlenodes = new HashSet<Node>();
-        othernodes = new HashSet<Node>();
-        mindist = Main.pref.getDouble(PREFIX + ".node_way_distance", 10.0)/6378135.0;
-        minmiddledist = Main.pref.getDouble(PREFIX + ".way_way_distance", 0.0)/6378135.0;
-        this.ds = Main.main.getCurrentDataSet();
-        this.ds_area = ds.getDataSourceArea();
-    }
-
-    @Override
-    public void endTest()
-    {
-        //Area a = Main.ds.getDataSourceArea();
-        Map<Node, Way> map = new HashMap<Node, Way>();
-        long last = -1;
-        for (int iter = 0; iter < 1; iter++) {
-        last = System.currentTimeMillis();
-        long last_print = -1;
-        int nr = 0;
-        Collection<MyWaySegment> tmp_ways = ways;
-        for(MyWaySegment s : tmp_ways) {
-            nr++;
-            long now = System.currentTimeMillis();
-            if (now - last_print > 200) {
-                //System.err.println("processing segment nr: " + nr + " of " + ways.size());
-                last_print = now;
-            }
-            for(Node en : s.nearbyNodes(mindist)) {
-                if (en == null)
-                    continue;
-                //if("turning_circle".equals(en.get("highway")) ||
-                //        (isexit != null && isexit) || en.get("barrier") != null)
-                //    c4++;
-                if(!s.highway)
-                    continue;
-                if (!endnodes_highway.contains(en))
-                    continue;
-                Boolean isexit = OsmUtils.getOsmBoolean(en.get("noexit"));
-                if("turning_circle".equals(en.get("highway")) ||
-                   "bus_stop".equals(en.get("highway")) ||
-                  (isexit != null && isexit) || en.get("barrier") != null)
-                    continue;
-                // There's a small false-positive here.  Imagine an intersection
-                // like a 't'.  If the top part of the 't' is short enough, it
-                // will trigger the node at the very top of the 't' to be unconnected
-                // to the way that "crosses" the 't'.  We should probably check that
-                // the ways to which 'en' belongs are not connected to 's.w'.
-                map.put(en, s.w);
-            }
-        }
-        //System.out.println("p1 elapsed: " + (System.currentTimeMillis()-last));
-        last = System.currentTimeMillis();
-        }
-        for(Map.Entry<Node, Way> error : map.entrySet())
-        {
-            errors.add(new TestError(this, Severity.WARNING,
-            tr("Way end node near other highway"), UNCONNECTED_WAYS,
-            Arrays.asList(error.getKey(), error.getValue())));
-        }
-        map.clear();
-        for(MyWaySegment s : ways)
-        {
-            for(Node en : s.nearbyNodes(mindist))
-            {
-                if (endnodes_highway.contains(en) && !s.highway && !s.isArea()) {
-                    map.put(en, s.w);
-                } else if (endnodes.contains(en) && !s.isArea()) {
-                    map.put(en, s.w);
-                }
-            }
-        }
-        //System.out.println("p2 elapsed: " + (System.currentTimeMillis()-last));
-        last = System.currentTimeMillis();
-        for(Map.Entry<Node, Way> error : map.entrySet())
-        {
-            errors.add(new TestError(this, Severity.WARNING,
-            tr("Way end node near other way"), UNCONNECTED_WAYS,
-            Arrays.asList(error.getKey(), error.getValue())));
-        }
-        /* the following two use a shorter distance */
-        if(minmiddledist > 0.0)
-        {
-            map.clear();
-            for(MyWaySegment s : ways)
-            {
-                for(Node en : s.nearbyNodes(minmiddledist))
-                {
-                    if (!middlenodes.contains(en))
-                        continue;
-                    map.put(en, s.w);
-                }
-            }
-            //System.out.println("p3 elapsed: " + (System.currentTimeMillis()-last));
-            last = System.currentTimeMillis();
-            for(Map.Entry<Node, Way> error : map.entrySet())
-            {
-                errors.add(new TestError(this, Severity.OTHER,
-                tr("Way node near other way"), UNCONNECTED_WAYS,
-                Arrays.asList(error.getKey(), error.getValue())));
-            }
-            map.clear();
-            for(MyWaySegment s : ways)
-            {
-                for(Node en : s.nearbyNodes(minmiddledist))
-                {
-                    if (!othernodes.contains(en))
-                        continue;
-                    map.put(en, s.w);
-                }
-            }
-            //System.out.println("p4 elapsed: " + (System.currentTimeMillis()-last));
-            last = System.currentTimeMillis();
-            for(Map.Entry<Node, Way> error : map.entrySet())
-            {
-                errors.add(new TestError(this, Severity.OTHER,
-                tr("Connected way end node near other way"), UNCONNECTED_WAYS,
-                Arrays.asList(error.getKey(), error.getValue())));
-            }
-        }
-        ways = null;
-        endnodes = null;
-        super.endTest();
-        //System.out.println("p99 elapsed: " + (System.currentTimeMillis()-last));
-        last = System.currentTimeMillis();
-    }
-
-    private class MyWaySegment
-    {
-        private final Line2D line;
-        public final Way w;
-        public final boolean isAbandoned;
-        public final boolean isBoundary;
-        public final boolean highway;
-        private final double len;
-        private Set<Node> nearbyNodeCache;
-        double nearbyNodeCacheDist = -1.0;
-        final Node n1;
-        final Node n2;
-
-        public MyWaySegment(Way w, Node n1, Node n2)
-        {
-            this.w = w;
-            String railway = w.get("railway");
-            String highway = w.get("highway");
-            this.isAbandoned = "abandoned".equals(railway) || "yes".equals(w.get("disused"));
-            this.highway = (highway != null || railway != null) && !isAbandoned;
-            this.isBoundary = !this.highway && "administrative".equals(w.get("boundary"));
-            line = new Line2D.Double(n1.getEastNorth().east(), n1.getEastNorth().north(),
-                                     n2.getEastNorth().east(), n2.getEastNorth().north());
-            len = line.getP1().distance(line.getP2());
-            this.n1 = n1;
-            this.n2 = n2;
-        }
-
-        public boolean nearby(Node n, double dist)
-        {
-//            return !w.containsNode(n)
-//            && line.ptSegDist(n.getEastNorth().east(), n.getEastNorth().north()) < dist;
-            if (w == null)
-                Main.debug("way null");
-            if (w.containsNode(n))
-                return false;
-            EastNorth coord = n.getEastNorth();
-            if (coord == null)
-                return false;
-            Point2D p = new Point2D.Double(coord.east(), coord.north());
-            if (line.getP1().distance(p) > len+dist)
-                return false;
-            if (line.getP2().distance(p) > len+dist)
-                return false;
-            return line.ptSegDist(p) < dist;
-        }
-        public List<LatLon> getBounds(double fudge)
-        {
-            double x1 = n1.getCoor().lon();
-            double x2 = n2.getCoor().lon();
-            if (x1 > x2) {
-                double tmpx = x1;
-                x1 = x2;
-                x2 = tmpx;
-            }
-            double y1 = n1.getCoor().lat();
-            double y2 = n2.getCoor().lat();
-            if (y1 > y2) {
-                double tmpy = y1;
-                y1 = y2;
-                y2 = tmpy;
-            }
-            LatLon topLeft  = new LatLon(y2+fudge, x1-fudge);
-            LatLon botRight = new LatLon(y1-fudge, x2+fudge);
-            List<LatLon> ret = new ArrayList<LatLon>();
-            ret.add(topLeft);
-            ret.add(botRight);
-            return ret;
-        }
-
-        public Collection<Node> nearbyNodes(double dist)
-        {
-            // If you're looking for nodes that are farther
-            // away that we looked for last time, the cached
-            // result is no good
-            if (dist > nearbyNodeCacheDist) {
-                //if (nearbyNodeCacheDist != -1)
-                //    System.out.println("destroyed MyWaySegment nearby node cache:" + dist + " > " +  nearbyNodeCacheDist);
-                nearbyNodeCache = null;
-            }
-            if (nearbyNodeCache != null) {
-                // If we've cached an aread greater than the
-                // one now being asked for...
-                if (nearbyNodeCacheDist > dist) {
-                    //System.out.println("had to trim MyWaySegment nearby node cache.");
-                    // Used the cached result and trim out
-                    // the nodes that are not in the smaller
-                    // area, but keep the old larger cache.
-                    Set<Node> trimmed = new HashSet<Node>(nearbyNodeCache);
-                    for (Node n : new HashSet<Node>(nearbyNodeCache)) {
-                        if (!nearby(n, dist))
-                            trimmed.remove(n);
-                    }
-                    return trimmed;
-                }
-                return nearbyNodeCache;
-            }
-            /*
-             * We know that any point near the line must be at
-             * least as close as the other end of the line, plus
-             * a little fudge for the distance away ('dist').
-             */
-
-            // This needs to be a hash set because the searches
-            // overlap a bit and can return duplicate nodes.
-            nearbyNodeCache = null;
-            List<LatLon> bounds = this.getBounds(dist);
-            List<Node> found_nodes = ds.searchNodes(new BBox(bounds.get(0), bounds.get(1)));
-            if (found_nodes == null)
-                return Collections.emptySet();
-
-            for (Node n : found_nodes) {
-                if (!nearby(n, dist) ||
-                     (ds_area != null && !ds_area.contains(n.getCoor())))
-                    continue;
-                // It is actually very rare for us to find a node
-                // so defer as much of the work as possible, like
-                // allocating the hash set
-                if (nearbyNodeCache == null)
-                    nearbyNodeCache = new HashSet<Node>();
-                nearbyNodeCache.add(n);
-            }
-            nearbyNodeCacheDist = dist;
-            if (nearbyNodeCache == null)
-                nearbyNodeCache = Collections.emptySet();
-            return nearbyNodeCache;
-        }
-
-        public boolean isArea() {
-            return w.get("landuse") != null
-                || w.get("leisure") != null
-                || w.get("building") != null;
-        }
-    }
-
-    List<MyWaySegment> getWaySegments(Way w)
-    {
-        List<MyWaySegment> ret = new ArrayList<MyWaySegment>();
-        if (!w.isUsable()
-            || w.get("barrier") != null
-            || "cliff".equals(w.get("natural")))
-            return ret;
-
-        int size = w.getNodesCount();
-        if(size < 2)
-            return ret;
-        for(int i = 1; i < size; ++i)
-        {
-            if(i < size-1)
-                addNode(w.getNode(i), middlenodes);
-            MyWaySegment ws = new MyWaySegment(w, w.getNode(i-1), w.getNode(i));
-            if (ws.isBoundary || ws.isAbandoned)
-                continue;
-            ret.add(ws);
-        }
-        return ret;
-    }
-
-    @Override
-    public void visit(Way w)
-    {
-        ways.addAll(getWaySegments(w));
-        Set<Node> set = endnodes;
-        if(w.get("highway") != null || w.get("railway") != null)
-            set = endnodes_highway;
-        addNode(w.firstNode(), set);
-        addNode(w.lastNode(), set);
-    }
-    @Override
-    public void visit(Node n)
-    {
-    }
-    private void addNode(Node n, Set<Node> s)
-    {
-        boolean m = middlenodes.contains(n);
-        boolean e = endnodes.contains(n);
-        boolean eh = endnodes_highway.contains(n);
-        boolean o = othernodes.contains(n);
-        if(!m && !e && !o && !eh)
-            s.add(n);
-        else if(!o)
-        {
-            othernodes.add(n);
-            if(e)
-                endnodes.remove(n);
-            else if(eh)
-                endnodes_highway.remove(n);
-            else
-                middlenodes.remove(n);
-        }
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/tests/UntaggedNode.java b/validator/src/org/openstreetmap/josm/plugins/validator/tests/UntaggedNode.java
deleted file mode 100644
index 6c6e09e..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/tests/UntaggedNode.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package org.openstreetmap.josm.plugins.validator.tests;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.command.Command;
-import org.openstreetmap.josm.command.DeleteCommand;
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.gui.progress.ProgressMonitor;
-import org.openstreetmap.josm.plugins.validator.Severity;
-import org.openstreetmap.josm.plugins.validator.Test;
-import org.openstreetmap.josm.plugins.validator.TestError;
-
-/**
- * Checks for untagged nodes that are in no way
- *
- * @author frsantos
- */
-public class UntaggedNode extends Test
-{
-    protected static int UNTAGGED_NODE = 201;
-
-    /** Bag of all nodes */
-    Set<Node> emptyNodes;
-
-    /**
-     * Constructor
-     */
-    public UntaggedNode()
-    {
-        super(tr("Untagged and unconnected nodes")+".",
-              tr("This test checks for untagged nodes that are not part of any way."));
-    }
-
-    @Override
-    public void startTest(ProgressMonitor monitor)
-    {
-    	super.startTest(monitor);
-        emptyNodes = new HashSet<Node>(100);
-    }
-
-    @Override
-    public void visit(Collection<OsmPrimitive> selection)
-    {
-        // If there is a partial selection, it may be false positives if a
-        // node is selected, but not the container way. So, in this
-        // case, we must visit all ways, selected or not.
-        if (partialSelection) {
-            for (OsmPrimitive p : selection) {
-                if (p.isUsable() && p instanceof Node) {
-                    p.visit(this);
-                }
-            }
-            for (Way w : Main.main.getCurrentDataSet().getWays()) {
-                visit(w);
-            }
-        } else {
-            for (OsmPrimitive p : selection) {
-                if (p.isUsable()) {
-                    p.visit(this);
-                }
-            }
-        }
-    }
-
-    @Override
-    public void visit(Node n)
-    {
-        if(n.isUsable() && !n.isTagged())
-            emptyNodes.add(n);
-    }
-
-    @Override
-    public void visit(Way w)
-    {
-        for (Node n : w.getNodes()) {
-            emptyNodes.remove(n);
-        }
-    }
-
-    @Override
-    public void endTest()
-    {
-        for(Node node : emptyNodes)
-        {
-            errors.add( new TestError(this, Severity.OTHER, tr("Untagged and unconnected nodes"), UNTAGGED_NODE, node) );
-        }
-        emptyNodes = null;
-        super.endTest();
-    }
-
-    @Override
-    public Command fixError(TestError testError)
-    {
-        return DeleteCommand.delete(Main.map.mapView.getEditLayer(), testError.getPrimitives());
-    }
-
-    @Override
-    public boolean isFixable(TestError testError)
-    {
-        return (testError.getTester() instanceof UntaggedNode);
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/tests/UntaggedWay.java b/validator/src/org/openstreetmap/josm/plugins/validator/tests/UntaggedWay.java
deleted file mode 100644
index 0f75208..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/tests/UntaggedWay.java
+++ /dev/null
@@ -1,157 +0,0 @@
-package org.openstreetmap.josm.plugins.validator.tests;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.Map;
-import java.util.Set;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.command.Command;
-import org.openstreetmap.josm.command.DeleteCommand;
-import org.openstreetmap.josm.data.osm.Relation;
-import org.openstreetmap.josm.data.osm.RelationMember;
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.gui.progress.ProgressMonitor;
-import org.openstreetmap.josm.plugins.validator.Severity;
-import org.openstreetmap.josm.plugins.validator.Test;
-import org.openstreetmap.josm.plugins.validator.TestError;
-
-/**
- * Checks for untagged ways
- *
- * @author frsantos
- */
-public class UntaggedWay extends Test
-{
-    /** Empty way error */
-    protected static final int EMPTY_WAY    = 301;
-    /** Untagged way error */
-    protected static final int UNTAGGED_WAY = 302;
-    /** Unnamed way error */
-    protected static final int UNNAMED_WAY  = 303;
-    /** One node way error */
-    protected static final int ONE_NODE_WAY = 304;
-    /** Unnamed junction error */
-    protected static final int UNNAMED_JUNCTION  = 305;
-
-    private LinkedList<Way> multipolygonways;
-
-    /** Ways that must have a name */
-    public static final Set<String> NAMED_WAYS = new HashSet<String>();
-    static
-    {
-        NAMED_WAYS.add( "motorway" );
-        NAMED_WAYS.add( "trunk" );
-        NAMED_WAYS.add( "primary" );
-        NAMED_WAYS.add( "secondary" );
-        NAMED_WAYS.add( "tertiary" );
-        NAMED_WAYS.add( "residential" );
-        NAMED_WAYS.add( "pedestrian" ); ;
-    }
-
-    /**
-     * Constructor
-     */
-    public UntaggedWay()
-    {
-        super(tr("Untagged, empty and one node ways."),
-              tr("This test checks for untagged, empty and one node ways."));
-    }
-
-    @Override
-    public void visit(Way w)
-    {
-        if (!w.isUsable()) return;
-
-        Map<String, String> tags = w.getKeys();
-        if( tags.size() != 0 )
-        {
-            String highway = tags.get("highway");
-            if(highway != null && NAMED_WAYS.contains(highway))
-            {
-                if( !tags.containsKey("name") && !tags.containsKey("ref") )
-                {
-                    boolean isRoundabout = false;
-                    boolean hasName = false;
-                    for( String key : w.keySet())
-                    {
-                        hasName = key.startsWith("name:") || key.endsWith("_name") || key.endsWith("_ref");
-                        if( hasName )
-                            break;
-                        if(key.equals("junction"))
-                        {
-                            isRoundabout = w.get("junction").equals("roundabout");
-                            break;
-                        }
-                    }
-
-                    if( !hasName && !isRoundabout)
-                        errors.add( new TestError(this, Severity.WARNING, tr("Unnamed ways"), UNNAMED_WAY, w) );
-                    else if(isRoundabout)
-                        errors.add( new TestError(this, Severity.WARNING, tr("Unnamed junction"), UNNAMED_JUNCTION, w) );
-                }
-            }
-        }
-
-        if(!w.isTagged() && !multipolygonways.contains(w))
-        {
-            errors.add( new TestError(this, Severity.WARNING, tr("Untagged ways"), UNTAGGED_WAY, w) );
-        }
-
-        if( w.getNodesCount() == 0 )
-        {
-            errors.add( new TestError(this, Severity.ERROR, tr("Empty ways"), EMPTY_WAY, w) );
-        }
-        else if( w.getNodesCount() == 1 )
-        {
-            errors.add( new TestError(this, Severity.ERROR, tr("One node ways"), ONE_NODE_WAY, w) );
-        }
-
-    }
-
-    @Override
-    public void startTest(ProgressMonitor monitor)
-    {
-        super.startTest(monitor);
-        multipolygonways = new LinkedList<Way>();
-        for (Relation r : Main.main.getCurrentDataSet().getRelations())
-        {
-            if(r.isUsable() && "multipolygon".equals(r.get("type")))
-            {
-                for (RelationMember m : r.getMembers())
-                {
-                    if(m.getMember() != null && m.getMember() instanceof Way &&
-                    m.getMember().isUsable() && !m.getMember().isTagged())
-                        multipolygonways.add((Way)m.getMember());
-                }
-            }
-        }
-    }
-
-    @Override
-    public void endTest()
-    {
-        multipolygonways = null;
-        super.endTest();
-    }
-
-    @Override
-    public boolean isFixable(TestError testError)
-    {
-        if( testError.getTester() instanceof UntaggedWay )
-        {
-            return testError.getCode() == EMPTY_WAY
-                || testError.getCode() == ONE_NODE_WAY;
-        }
-
-        return false;
-    }
-
-    @Override
-    public Command fixError(TestError testError)
-    {
-        return DeleteCommand.delete(Main.map.mapView.getEditLayer(), testError.getPrimitives());
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/tests/WronglyOrderedWays.java b/validator/src/org/openstreetmap/josm/plugins/validator/tests/WronglyOrderedWays.java
deleted file mode 100644
index 4614099..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/tests/WronglyOrderedWays.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package org.openstreetmap.josm.plugins.validator.tests;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.gui.progress.ProgressMonitor;
-import org.openstreetmap.josm.plugins.validator.Severity;
-import org.openstreetmap.josm.plugins.validator.Test;
-import org.openstreetmap.josm.plugins.validator.TestError;
-import org.openstreetmap.josm.plugins.validator.util.Bag;
-
-/**
- * Check cyclic ways for errors
- *
- * @author jrreid
- */
-public class WronglyOrderedWays extends Test  {
-    protected static int WRONGLY_ORDERED_COAST = 1001;
-    protected static int WRONGLY_ORDERED_WATER = 1002;
-    protected static int WRONGLY_ORDERED_LAND  = 1003;
-
-    /** The already detected errors */
-    Bag<Way, Way> _errorWays;
-
-    /**
-     * Constructor
-     */
-    public WronglyOrderedWays()
-    {
-        super(tr("Wrongly Ordered Ways."),
-              tr("This test checks the direction of water, land and coastline ways."));
-    }
-
-    @Override
-    public void startTest(ProgressMonitor monitor)
-    {
-    	super.startTest(monitor);
-        _errorWays = new Bag<Way, Way>();
-    }
-
-    @Override
-    public void endTest()
-    {
-        _errorWays = null;
-        super.endTest();
-    }
-
-    @Override
-    public void visit(Way w)
-    {
-        String errortype = "";
-        int type;
-
-        if( !w.isUsable() )
-            return;
-        if (w.getNodesCount() <= 0)
-            return;
-
-        String natural = w.get("natural");
-        if( natural == null)
-            return;
-
-        if( natural.equals("coastline") )
-        {
-            errortype = tr("Reversed coastline: land not on left side");
-            type= WRONGLY_ORDERED_COAST;
-        }
-        else if(natural.equals("water") )
-        {
-            errortype = tr("Reversed water: land not on left side");
-            type= WRONGLY_ORDERED_WATER;
-        }
-        else if( natural.equals("land") )
-        {
-            errortype = tr("Reversed land: land not on left side");
-            type= WRONGLY_ORDERED_LAND;
-        }
-        else
-            return;
-
-
-        /**
-         * Test the directionality of the way
-         *
-         * Assuming a closed non-looping way, compute twice the area
-         * of the polygon using the formula 2*a = sum (Xn * Yn+1 - Xn+1 * Yn)
-         * If the area is negative the way is ordered in a clockwise direction
-         *
-         */
-
-        if(w.getNode(0) == w.getNode(w.getNodesCount()-1))
-        {
-            double area2 = 0;
-
-            for (int node = 1; node < w.getNodesCount(); node++)
-            {
-                area2 += (w.getNode(node-1).getCoor().lon() * w.getNode(node).getCoor().lat()
-                - w.getNode(node).getCoor().lon() * w.getNode(node-1).getCoor().lat());
-            }
-
-            if(((natural.equals("coastline") || natural.equals("land")) && area2 < 0.)
-            || (natural.equals("water") && area2 > 0.))
-            {
-                List<OsmPrimitive> primitives = new ArrayList<OsmPrimitive>();
-                primitives.add(w);
-                errors.add( new TestError(this, Severity.OTHER, errortype, type, primitives) );
-                _errorWays.add(w,w);
-            }
-        }
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/util/AgregatePrimitivesVisitor.java b/validator/src/org/openstreetmap/josm/plugins/validator/util/AgregatePrimitivesVisitor.java
deleted file mode 100644
index 2965691..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/util/AgregatePrimitivesVisitor.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.openstreetmap.josm.plugins.validator.util;
-
-import java.util.Collection;
-import java.util.LinkedList;
-
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.Relation;
-import org.openstreetmap.josm.data.osm.RelationMember;
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.data.osm.visitor.AbstractVisitor;
-
-/**
- * A visitor that aggregates all primitives it visits.
- * <p>
- * The primitives are sorted according to their type: first nodes, then ways.
- *
- * @author frsantos
- */
-public class AgregatePrimitivesVisitor extends AbstractVisitor
-{
-    /** Aggregated data */
-    Collection<OsmPrimitive> aggregatedData;
-
-    /**
-     * Constructor
-     */
-    public AgregatePrimitivesVisitor()
-    {
-        aggregatedData = new LinkedList<OsmPrimitive>();
-    }
-
-    /**
-     * Visits a collection of primitives
-     * @param data The collection of primitives
-     * @return The aggregated primitives
-     */
-    public Collection<OsmPrimitive> visit(Collection<OsmPrimitive> data)
-    {
-        for (OsmPrimitive osm : data)
-        {
-            osm.visit(this);
-        }
-
-        return aggregatedData;
-    }
-
-    public void visit(Node n)
-    {
-        if(!aggregatedData.contains(n))
-            aggregatedData.add(n);
-    }
-
-    public void visit(Way w)
-    {
-        if(!aggregatedData.contains(w))
-        {
-            aggregatedData.add(w);
-            for (Node n : w.getNodes())
-                visit(n);
-        }
-    }
-
-    public void visit(Relation r) {
-        if (!aggregatedData.contains(r)) {
-            aggregatedData.add(r);
-            for (RelationMember m : r.getMembers()) {
-                m.getMember().visit(this);
-            }
-        }
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/util/Bag.java b/validator/src/org/openstreetmap/josm/plugins/validator/util/Bag.java
deleted file mode 100644
index cb64b20..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/util/Bag.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package org.openstreetmap.josm.plugins.validator.util;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- *
- * A very simple bag to store multiple occurences of a same key.
- * <p>
- * The bag will keep, for each key, a list of values.
- *
- * @author frsantos
- *
- * @param <K> The key class
- * @param <V> The value class
- */
-public class Bag<K,V> extends HashMap<K, List<V>>
-{
-    /** Serializable ID */
-    private static final long serialVersionUID = 5374049172859211610L;
-
-    /**
-     * Returns the list of elements with the same key
-     * @param key The key to obtain the elements
-     * @return the list of elements with the same key
-     */
-    public List<V> get(K key)
-    {
-        return super.get(key);
-    }
-
-    /**
-     * Adds an element to the bag
-     * @param key The key of the element
-     * @param value The element to add
-     */
-    public void add(K key, V value)
-    {
-        List<V> values = get(key);
-        if( values == null )
-        {
-            values = new ArrayList<V>();
-            put(key, values);
-        }
-        values.add(value);
-    }
-
-    /**
-     * Adds an element to the bag
-     * @param key The key of the element
-     * @param value The element to add
-     */
-    public void add(K key)
-    {
-        List<V> values = get(key);
-        if( values == null )
-        {
-            values = new ArrayList<V>();
-            put(key, values);
-        }
-    }
-
-    /**
-     * Constructor
-     */
-    public Bag()
-    {
-        super();
-    }
-
-    /**
-     * Constructor
-     *
-     * @param initialCapacity The initial capacity
-     */
-    public Bag(int initialCapacity)
-    {
-        super(initialCapacity);
-    }
-
-    /**
-     * Returns true if the bag contains a value for a key
-     * @param key The key
-     * @param value The value
-     * @return true if the key contains the value
-     */
-    public boolean contains(K key, V value)
-    {
-        List<V> values = get(key);
-        return (values == null) ? false : values.contains(value);
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/util/Entities.java b/validator/src/org/openstreetmap/josm/plugins/validator/util/Entities.java
deleted file mode 100644
index b07906e..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/util/Entities.java
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* Taken from: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/java/org/apache/commons/lang/Entities.java?revision=636641 */
-package org.openstreetmap.josm.plugins.validator.util;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * <p>
- * Provides HTML and XML entity utilities.
- * </p>
- * @see <a href="http://hotwired.lycos.com/webmonkey/reference/special_characters/">ISO Entities</a>
- * @see <a href="http://www.w3.org/TR/REC-html32#latin1">HTML 3.2 Character Entities for ISO Latin-1</a>
- * @see <a href="http://www.w3.org/TR/REC-html40/sgml/entities.html">HTML 4.0 Character entity references</a>
- * @see <a href="http://www.w3.org/TR/html401/charset.html#h-5.3">HTML 4.01 Character References</a>
- * @see <a href="http://www.w3.org/TR/html401/charset.html#code-position">HTML 4.01 Code positions</a>
- */
-public class Entities {
-    private static final String[][] ARRAY = {
-        /* BASIC */
-        {"quot", "34"}, // " - double-quote
-        {"amp", "38"}, // & - ampersand
-        {"lt", "60"}, // < - less-than
-        {"gt", "62"}, // > - greater-than
-        /* XML */
-        {"apos", "39"}, // XML apostrophe
-        /* ISO8859_1 */
-        {"nbsp", "160"}, // non-breaking space
-        {"iexcl", "161"}, // inverted exclamation mark
-        {"cent", "162"}, // cent sign
-        {"pound", "163"}, // pound sign
-        {"curren", "164"}, // currency sign
-        {"yen", "165"}, // yen sign = yuan sign
-        {"brvbar", "166"}, // broken bar = broken vertical bar
-        {"sect", "167"}, // section sign
-        {"uml", "168"}, // diaeresis = spacing diaeresis
-        {"copy", "169"}, // © - copyright sign
-        {"ordf", "170"}, // feminine ordinal indicator
-        {"laquo", "171"}, // left-pointing double angle quotation mark = left pointing guillemet
-        {"not", "172"}, // not sign
-        {"shy", "173"}, // soft hyphen = discretionary hyphen
-        {"reg", "174"}, // ® - registered trademark sign
-        {"macr", "175"}, // macron = spacing macron = overline = APL overbar
-        {"deg", "176"}, // degree sign
-        {"plusmn", "177"}, // plus-minus sign = plus-or-minus sign
-        {"sup2", "178"}, // superscript two = superscript digit two = squared
-        {"sup3", "179"}, // superscript three = superscript digit three = cubed
-        {"acute", "180"}, // acute accent = spacing acute
-        {"micro", "181"}, // micro sign
-        {"para", "182"}, // pilcrow sign = paragraph sign
-        {"middot", "183"}, // middle dot = Georgian comma = Greek middle dot
-        {"cedil", "184"}, // cedilla = spacing cedilla
-        {"sup1", "185"}, // superscript one = superscript digit one
-        {"ordm", "186"}, // masculine ordinal indicator
-        {"raquo", "187"}, // right-pointing double angle quotation mark = right pointing guillemet
-        {"frac14", "188"}, // vulgar fraction one quarter = fraction one quarter
-        {"frac12", "189"}, // vulgar fraction one half = fraction one half
-        {"frac34", "190"}, // vulgar fraction three quarters = fraction three quarters
-        {"iquest", "191"}, // inverted question mark = turned question mark
-        {"Agrave", "192"}, // À - uppercase A, grave accent
-        {"Aacute", "193"}, // Á - uppercase A, acute accent
-        {"Acirc", "194"}, // Â - uppercase A, circumflex accent
-        {"Atilde", "195"}, // Ã - uppercase A, tilde
-        {"Auml", "196"}, // Ä - uppercase A, umlaut
-        {"Aring", "197"}, // Å - uppercase A, ring
-        {"AElig", "198"}, // Æ - uppercase AE
-        {"Ccedil", "199"}, // Ç - uppercase C, cedilla
-        {"Egrave", "200"}, // È - uppercase E, grave accent
-        {"Eacute", "201"}, // É - uppercase E, acute accent
-        {"Ecirc", "202"}, // Ê - uppercase E, circumflex accent
-        {"Euml", "203"}, // Ë - uppercase E, umlaut
-        {"Igrave", "204"}, // Ì - uppercase I, grave accent
-        {"Iacute", "205"}, // Í - uppercase I, acute accent
-        {"Icirc", "206"}, // Î - uppercase I, circumflex accent
-        {"Iuml", "207"}, // Ï - uppercase I, umlaut
-        {"ETH", "208"}, // Ð - uppercase Eth, Icelandic
-        {"Ntilde", "209"}, // Ñ - uppercase N, tilde
-        {"Ograve", "210"}, // Ò - uppercase O, grave accent
-        {"Oacute", "211"}, // Ó - uppercase O, acute accent
-        {"Ocirc", "212"}, // Ô - uppercase O, circumflex accent
-        {"Otilde", "213"}, // Õ - uppercase O, tilde
-        {"Ouml", "214"}, // Ö - uppercase O, umlaut
-        {"times", "215"}, // multiplication sign
-        {"Oslash", "216"}, // Ø - uppercase O, slash
-        {"Ugrave", "217"}, // Ù - uppercase U, grave accent
-        {"Uacute", "218"}, // Ú - uppercase U, acute accent
-        {"Ucirc", "219"}, // Û - uppercase U, circumflex accent
-        {"Uuml", "220"}, // Ü - uppercase U, umlaut
-        {"Yacute", "221"}, // Ý - uppercase Y, acute accent
-        {"THORN", "222"}, // Þ - uppercase THORN, Icelandic
-        {"szlig", "223"}, // ß - lowercase sharps, German
-        {"agrave", "224"}, // à - lowercase a, grave accent
-        {"aacute", "225"}, // á - lowercase a, acute accent
-        {"acirc", "226"}, // â - lowercase a, circumflex accent
-        {"atilde", "227"}, // ã - lowercase a, tilde
-        {"auml", "228"}, // ä - lowercase a, umlaut
-        {"aring", "229"}, // å - lowercase a, ring
-        {"aelig", "230"}, // æ - lowercase ae
-        {"ccedil", "231"}, // ç - lowercase c, cedilla
-        {"egrave", "232"}, // è - lowercase e, grave accent
-        {"eacute", "233"}, // é - lowercase e, acute accent
-        {"ecirc", "234"}, // ê - lowercase e, circumflex accent
-        {"euml", "235"}, // ë - lowercase e, umlaut
-        {"igrave", "236"}, // ì - lowercase i, grave accent
-        {"iacute", "237"}, // í - lowercase i, acute accent
-        {"icirc", "238"}, // î - lowercase i, circumflex accent
-        {"iuml", "239"}, // ï - lowercase i, umlaut
-        {"eth", "240"}, // ð - lowercase eth, Icelandic
-        {"ntilde", "241"}, // ñ - lowercase n, tilde
-        {"ograve", "242"}, // ò - lowercase o, grave accent
-        {"oacute", "243"}, // ó - lowercase o, acute accent
-        {"ocirc", "244"}, // ô - lowercase o, circumflex accent
-        {"otilde", "245"}, // õ - lowercase o, tilde
-        {"ouml", "246"}, // ö - lowercase o, umlaut
-        {"divide", "247"}, // division sign
-        {"oslash", "248"}, // ø - lowercase o, slash
-        {"ugrave", "249"}, // ù - lowercase u, grave accent
-        {"uacute", "250"}, // ú - lowercase u, acute accent
-        {"ucirc", "251"}, // û - lowercase u, circumflex accent
-        {"uuml", "252"}, // ü - lowercase u, umlaut
-        {"yacute", "253"}, // ý - lowercase y, acute accent
-        {"thorn", "254"}, // þ - lowercase thorn, Icelandic
-        {"yuml", "255"}, // ÿ - lowercase y, umlaut
-        /* HTML 40 */
-        // <!-- Latin Extended-B -->
-        {"fnof", "402"}, // latin small f with hook = function= florin, U+0192 ISOtech -->
-        // <!-- Greek -->
-        {"Alpha", "913"}, // greek capital letter alpha, U+0391 -->
-        {"Beta", "914"}, // greek capital letter beta, U+0392 -->
-        {"Gamma", "915"}, // greek capital letter gamma,U+0393 ISOgrk3 -->
-        {"Delta", "916"}, // greek capital letter delta,U+0394 ISOgrk3 -->
-        {"Epsilon", "917"}, // greek capital letter epsilon, U+0395 -->
-        {"Zeta", "918"}, // greek capital letter zeta, U+0396 -->
-        {"Eta", "919"}, // greek capital letter eta, U+0397 -->
-        {"Theta", "920"}, // greek capital letter theta,U+0398 ISOgrk3 -->
-        {"Iota", "921"}, // greek capital letter iota, U+0399 -->
-        {"Kappa", "922"}, // greek capital letter kappa, U+039A -->
-        {"Lambda", "923"}, // greek capital letter lambda,U+039B ISOgrk3 -->
-        {"Mu", "924"}, // greek capital letter mu, U+039C -->
-        {"Nu", "925"}, // greek capital letter nu, U+039D -->
-        {"Xi", "926"}, // greek capital letter xi, U+039E ISOgrk3 -->
-        {"Omicron", "927"}, // greek capital letter omicron, U+039F -->
-        {"Pi", "928"}, // greek capital letter pi, U+03A0 ISOgrk3 -->
-        {"Rho", "929"}, // greek capital letter rho, U+03A1 -->
-        // <!-- there is no Sigmaf, and no U+03A2 character either -->
-        {"Sigma", "931"}, // greek capital letter sigma,U+03A3 ISOgrk3 -->
-        {"Tau", "932"}, // greek capital letter tau, U+03A4 -->
-        {"Upsilon", "933"}, // greek capital letter upsilon,U+03A5 ISOgrk3 -->
-        {"Phi", "934"}, // greek capital letter phi,U+03A6 ISOgrk3 -->
-        {"Chi", "935"}, // greek capital letter chi, U+03A7 -->
-        {"Psi", "936"}, // greek capital letter psi,U+03A8 ISOgrk3 -->
-        {"Omega", "937"}, // greek capital letter omega,U+03A9 ISOgrk3 -->
-        {"alpha", "945"}, // greek small letter alpha,U+03B1 ISOgrk3 -->
-        {"beta", "946"}, // greek small letter beta, U+03B2 ISOgrk3 -->
-        {"gamma", "947"}, // greek small letter gamma,U+03B3 ISOgrk3 -->
-        {"delta", "948"}, // greek small letter delta,U+03B4 ISOgrk3 -->
-        {"epsilon", "949"}, // greek small letter epsilon,U+03B5 ISOgrk3 -->
-        {"zeta", "950"}, // greek small letter zeta, U+03B6 ISOgrk3 -->
-        {"eta", "951"}, // greek small letter eta, U+03B7 ISOgrk3 -->
-        {"theta", "952"}, // greek small letter theta,U+03B8 ISOgrk3 -->
-        {"iota", "953"}, // greek small letter iota, U+03B9 ISOgrk3 -->
-        {"kappa", "954"}, // greek small letter kappa,U+03BA ISOgrk3 -->
-        {"lambda", "955"}, // greek small letter lambda,U+03BB ISOgrk3 -->
-        {"mu", "956"}, // greek small letter mu, U+03BC ISOgrk3 -->
-        {"nu", "957"}, // greek small letter nu, U+03BD ISOgrk3 -->
-        {"xi", "958"}, // greek small letter xi, U+03BE ISOgrk3 -->
-        {"omicron", "959"}, // greek small letter omicron, U+03BF NEW -->
-        {"pi", "960"}, // greek small letter pi, U+03C0 ISOgrk3 -->
-        {"rho", "961"}, // greek small letter rho, U+03C1 ISOgrk3 -->
-        {"sigmaf", "962"}, // greek small letter final sigma,U+03C2 ISOgrk3 -->
-        {"sigma", "963"}, // greek small letter sigma,U+03C3 ISOgrk3 -->
-        {"tau", "964"}, // greek small letter tau, U+03C4 ISOgrk3 -->
-        {"upsilon", "965"}, // greek small letter upsilon,U+03C5 ISOgrk3 -->
-        {"phi", "966"}, // greek small letter phi, U+03C6 ISOgrk3 -->
-        {"chi", "967"}, // greek small letter chi, U+03C7 ISOgrk3 -->
-        {"psi", "968"}, // greek small letter psi, U+03C8 ISOgrk3 -->
-        {"omega", "969"}, // greek small letter omega,U+03C9 ISOgrk3 -->
-        {"thetasym", "977"}, // greek small letter theta symbol,U+03D1 NEW -->
-        {"upsih", "978"}, // greek upsilon with hook symbol,U+03D2 NEW -->
-        {"piv", "982"}, // greek pi symbol, U+03D6 ISOgrk3 -->
-        // <!-- General Punctuation -->
-        {"bull", "8226"}, // bullet = black small circle,U+2022 ISOpub -->
-        // <!-- bullet is NOT the same as bullet operator, U+2219 -->
-        {"hellip", "8230"}, // horizontal ellipsis = three dot leader,U+2026 ISOpub -->
-        {"prime", "8242"}, // prime = minutes = feet, U+2032 ISOtech -->
-        {"Prime", "8243"}, // double prime = seconds = inches,U+2033 ISOtech -->
-        {"oline", "8254"}, // overline = spacing overscore,U+203E NEW -->
-        {"frasl", "8260"}, // fraction slash, U+2044 NEW -->
-        // <!-- Letterlike Symbols -->
-        {"weierp", "8472"}, // script capital P = power set= Weierstrass p, U+2118 ISOamso -->
-        {"image", "8465"}, // blackletter capital I = imaginary part,U+2111 ISOamso -->
-        {"real", "8476"}, // blackletter capital R = real part symbol,U+211C ISOamso -->
-        {"trade", "8482"}, // trade mark sign, U+2122 ISOnum -->
-        {"alefsym", "8501"}, // alef symbol = first transfinite cardinal,U+2135 NEW -->
-        // <!-- alef symbol is NOT the same as hebrew letter alef,U+05D0 although the
-        // same glyph could be used to depict both characters -->
-        // <!-- Arrows -->
-        {"larr", "8592"}, // leftwards arrow, U+2190 ISOnum -->
-        {"uarr", "8593"}, // upwards arrow, U+2191 ISOnum-->
-        {"rarr", "8594"}, // rightwards arrow, U+2192 ISOnum -->
-        {"darr", "8595"}, // downwards arrow, U+2193 ISOnum -->
-        {"harr", "8596"}, // left right arrow, U+2194 ISOamsa -->
-        {"crarr", "8629"}, // downwards arrow with corner leftwards= carriage return, U+21B5 NEW -->
-        {"lArr", "8656"}, // leftwards double arrow, U+21D0 ISOtech -->
-        // <!-- ISO 10646 does not say that lArr is the same as the 'is implied by'
-        // arrow but also does not have any other character for that function.
-        // So ? lArr canbe used for 'is implied by' as ISOtech suggests -->
-        {"uArr", "8657"}, // upwards double arrow, U+21D1 ISOamsa -->
-        {"rArr", "8658"}, // rightwards double arrow,U+21D2 ISOtech -->
-        // <!-- ISO 10646 does not say this is the 'implies' character but does not
-        // have another character with this function so ?rArr can be used for
-        // 'implies' as ISOtech suggests -->
-        {"dArr", "8659"}, // downwards double arrow, U+21D3 ISOamsa -->
-        {"hArr", "8660"}, // left right double arrow,U+21D4 ISOamsa -->
-        // <!-- Mathematical Operators -->
-        {"forall", "8704"}, // for all, U+2200 ISOtech -->
-        {"part", "8706"}, // partial differential, U+2202 ISOtech -->
-        {"exist", "8707"}, // there exists, U+2203 ISOtech -->
-        {"empty", "8709"}, // empty set = null set = diameter,U+2205 ISOamso -->
-        {"nabla", "8711"}, // nabla = backward difference,U+2207 ISOtech -->
-        {"isin", "8712"}, // element of, U+2208 ISOtech -->
-        {"notin", "8713"}, // not an element of, U+2209 ISOtech -->
-        {"ni", "8715"}, // contains as member, U+220B ISOtech -->
-        // <!-- should there be a more memorable name than 'ni'? -->
-        {"prod", "8719"}, // n-ary product = product sign,U+220F ISOamsb -->
-        // <!-- prod is NOT the same character as U+03A0 'greek capital letter pi'
-        // though the same glyph might be used for both -->
-        {"sum", "8721"}, // n-ary summation, U+2211 ISOamsb -->
-        // <!-- sum is NOT the same character as U+03A3 'greek capital letter sigma'
-        // though the same glyph might be used for both -->
-        {"minus", "8722"}, // minus sign, U+2212 ISOtech -->
-        {"lowast", "8727"}, // asterisk operator, U+2217 ISOtech -->
-        {"radic", "8730"}, // square root = radical sign,U+221A ISOtech -->
-        {"prop", "8733"}, // proportional to, U+221D ISOtech -->
-        {"infin", "8734"}, // infinity, U+221E ISOtech -->
-        {"ang", "8736"}, // angle, U+2220 ISOamso -->
-        {"and", "8743"}, // logical and = wedge, U+2227 ISOtech -->
-        {"or", "8744"}, // logical or = vee, U+2228 ISOtech -->
-        {"cap", "8745"}, // intersection = cap, U+2229 ISOtech -->
-        {"cup", "8746"}, // union = cup, U+222A ISOtech -->
-        {"int", "8747"}, // integral, U+222B ISOtech -->
-        {"there4", "8756"}, // therefore, U+2234 ISOtech -->
-        {"sim", "8764"}, // tilde operator = varies with = similar to,U+223C ISOtech -->
-        // <!-- tilde operator is NOT the same character as the tilde, U+007E,although
-        // the same glyph might be used to represent both -->
-        {"cong", "8773"}, // approximately equal to, U+2245 ISOtech -->
-        {"asymp", "8776"}, // almost equal to = asymptotic to,U+2248 ISOamsr -->
-        {"ne", "8800"}, // not equal to, U+2260 ISOtech -->
-        {"equiv", "8801"}, // identical to, U+2261 ISOtech -->
-        {"le", "8804"}, // less-than or equal to, U+2264 ISOtech -->
-        {"ge", "8805"}, // greater-than or equal to,U+2265 ISOtech -->
-        {"sub", "8834"}, // subset of, U+2282 ISOtech -->
-        {"sup", "8835"}, // superset of, U+2283 ISOtech -->
-        // <!-- note that nsup, 'not a superset of, U+2283' is not covered by the
-        // Symbol font encoding and is not included. Should it be, for symmetry?
-        // It is in ISOamsn --> <!ENTITY nsub", "8836"},
-        // not a subset of, U+2284 ISOamsn -->
-        {"sube", "8838"}, // subset of or equal to, U+2286 ISOtech -->
-        {"supe", "8839"}, // superset of or equal to,U+2287 ISOtech -->
-        {"oplus", "8853"}, // circled plus = direct sum,U+2295 ISOamsb -->
-        {"otimes", "8855"}, // circled times = vector product,U+2297 ISOamsb -->
-        {"perp", "8869"}, // up tack = orthogonal to = perpendicular,U+22A5 ISOtech -->
-        {"sdot", "8901"}, // dot operator, U+22C5 ISOamsb -->
-        // <!-- dot operator is NOT the same character as U+00B7 middle dot -->
-        // <!-- Miscellaneous Technical -->
-        {"lceil", "8968"}, // left ceiling = apl upstile,U+2308 ISOamsc -->
-        {"rceil", "8969"}, // right ceiling, U+2309 ISOamsc -->
-        {"lfloor", "8970"}, // left floor = apl downstile,U+230A ISOamsc -->
-        {"rfloor", "8971"}, // right floor, U+230B ISOamsc -->
-        {"lang", "9001"}, // left-pointing angle bracket = bra,U+2329 ISOtech -->
-        // <!-- lang is NOT the same character as U+003C 'less than' or U+2039 'single left-pointing angle quotation
-        // mark' -->
-        {"rang", "9002"}, // right-pointing angle bracket = ket,U+232A ISOtech -->
-        // <!-- rang is NOT the same character as U+003E 'greater than' or U+203A
-        // 'single right-pointing angle quotation mark' -->
-        // <!-- Geometric Shapes -->
-        {"loz", "9674"}, // lozenge, U+25CA ISOpub -->
-        // <!-- Miscellaneous Symbols -->
-        {"spades", "9824"}, // black spade suit, U+2660 ISOpub -->
-        // <!-- black here seems to mean filled as opposed to hollow -->
-        {"clubs", "9827"}, // black club suit = shamrock,U+2663 ISOpub -->
-        {"hearts", "9829"}, // black heart suit = valentine,U+2665 ISOpub -->
-        {"diams", "9830"}, // black diamond suit, U+2666 ISOpub -->
-
-        // <!-- Latin Extended-A -->
-        {"OElig", "338"}, // -- latin capital ligature OE,U+0152 ISOlat2 -->
-        {"oelig", "339"}, // -- latin small ligature oe, U+0153 ISOlat2 -->
-        // <!-- ligature is a misnomer, this is a separate character in some languages -->
-        {"Scaron", "352"}, // -- latin capital letter S with caron,U+0160 ISOlat2 -->
-        {"scaron", "353"}, // -- latin small letter s with caron,U+0161 ISOlat2 -->
-        {"Yuml", "376"}, // -- latin capital letter Y with diaeresis,U+0178 ISOlat2 -->
-        // <!-- Spacing Modifier Letters -->
-        {"circ", "710"}, // -- modifier letter circumflex accent,U+02C6 ISOpub -->
-        {"tilde", "732"}, // small tilde, U+02DC ISOdia -->
-        // <!-- General Punctuation -->
-        {"ensp", "8194"}, // en space, U+2002 ISOpub -->
-        {"emsp", "8195"}, // em space, U+2003 ISOpub -->
-        {"thinsp", "8201"}, // thin space, U+2009 ISOpub -->
-        {"zwnj", "8204"}, // zero width non-joiner,U+200C NEW RFC 2070 -->
-        {"zwj", "8205"}, // zero width joiner, U+200D NEW RFC 2070 -->
-        {"lrm", "8206"}, // left-to-right mark, U+200E NEW RFC 2070 -->
-        {"rlm", "8207"}, // right-to-left mark, U+200F NEW RFC 2070 -->
-        {"ndash", "8211"}, // en dash, U+2013 ISOpub -->
-        {"mdash", "8212"}, // em dash, U+2014 ISOpub -->
-        {"lsquo", "8216"}, // left single quotation mark,U+2018 ISOnum -->
-        {"rsquo", "8217"}, // right single quotation mark,U+2019 ISOnum -->
-        {"sbquo", "8218"}, // single low-9 quotation mark, U+201A NEW -->
-        {"ldquo", "8220"}, // left double quotation mark,U+201C ISOnum -->
-        {"rdquo", "8221"}, // right double quotation mark,U+201D ISOnum -->
-        {"bdquo", "8222"}, // double low-9 quotation mark, U+201E NEW -->
-        {"dagger", "8224"}, // dagger, U+2020 ISOpub -->
-        {"Dagger", "8225"}, // double dagger, U+2021 ISOpub -->
-        {"permil", "8240"}, // per mille sign, U+2030 ISOtech -->
-        {"lsaquo", "8249"}, // single left-pointing angle quotation mark,U+2039 ISO proposed -->
-        // <!-- lsaquo is proposed but not yet ISO standardized -->
-        {"rsaquo", "8250"}, // single right-pointing angle quotation mark,U+203A ISO proposed -->
-        // <!-- rsaquo is proposed but not yet ISO standardized -->
-        {"euro", "8364"}, // -- euro sign, U+20AC NEW -->
-    };
-
-    private static Map<String, String> mapNameToValue = null;
-
-    public String unescape(String str) {
-        int firstAmp = str.indexOf('&');
-        if (firstAmp < 0)
-            return str;
-        String res = new String(str.substring(0, firstAmp));
-        int len = str.length();
-        for (int i = firstAmp; i < len; i++) {
-            char c = str.charAt(i);
-            if (c == '&') {
-                int nextIdx = i + 1;
-                int semiColonIdx = str.indexOf(';', nextIdx);
-                if (semiColonIdx == -1) {
-                    res += c;
-                    continue;
-                }
-                int amphersandIdx = str.indexOf('&', i + 1);
-                if (amphersandIdx != -1 && amphersandIdx < semiColonIdx) {
-                    // Then the text looks like &...&...;
-                    res += c;
-                    continue;
-                }
-                String entityContent = str.substring(nextIdx, semiColonIdx);
-                int entityValue = -1;
-                int entityContentLen = entityContent.length();
-                if (entityContentLen > 0) {
-                    if (entityContent.charAt(0) == '#') { // escaped value content is an integer (decimal or
-                        // hexidecimal)
-                        if (entityContentLen > 1) {
-                            char isHexChar = entityContent.charAt(1);
-                            try {
-                                switch (isHexChar) {
-                                    case 'X' :
-                                    case 'x' : {
-                                        entityValue = Integer.parseInt(entityContent.substring(2), 16);
-                                        break;
-                                    }
-                                    default : {
-                                        entityValue = Integer.parseInt(entityContent.substring(1), 10);
-                                    }
-                                }
-                                if (entityValue > 0xFFFF) {
-                                    entityValue = -1;
-                                }
-                            } catch (NumberFormatException e) {
-                                entityValue = -1;
-                            }
-                        }
-                    } else { // escaped value content is an entity name
-                        if(mapNameToValue == null)
-                        {
-                            mapNameToValue = new HashMap<String, String>();
-                            for (int in = 0; in < ARRAY.length; ++in)
-                                mapNameToValue.put(ARRAY[in][0], ARRAY[in][1]);
-                        }
-                        String value = mapNameToValue.get(entityContent);
-                        entityValue = (value == null ? -1 : Integer.parseInt(value));
-                    }
-                }
-
-                if (entityValue == -1) {
-                    res += '&' + entityContent + ';';
-                } else {
-                    res += (char) entityValue;
-                }
-                i = semiColonIdx; // move index up to the semi-colon
-            } else {
-                res += c;
-            }
-        }
-        return res;
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/util/MultipleNameVisitor.java b/validator/src/org/openstreetmap/josm/plugins/validator/util/MultipleNameVisitor.java
deleted file mode 100644
index fdb7d07..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/util/MultipleNameVisitor.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package org.openstreetmap.josm.plugins.validator.util;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-import static org.openstreetmap.josm.tools.I18n.trn;
-
-import java.util.Collection;
-
-import javax.swing.Icon;
-import javax.swing.JLabel;
-
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.tools.ImageProvider;
-
-/**
- * Able to create a name and an icon for a collection of elements.
- *
- * @author frsantos
- */
-public class MultipleNameVisitor extends NameVisitor
-{
-    /** The class name of the combined primitives */
-    String multipleClassname;
-    /* name to be displayed */
-    String displayName;
-    /** Size of the collection */
-    int size;
-
-    /**
-     * Visits a collection of primitives
-     * @param data The collection of primitives
-     */
-    public void visit(Collection<? extends OsmPrimitive> data)
-    {
-        String multipleName = null;
-        String multiplePluralClassname = null;
-        String firstName = null;
-        boolean initializedname = false;
-        size = data.size();
-
-        multipleClassname = null;
-        for (OsmPrimitive osm : data)
-        {
-            String name = osm.get("name");
-            if(name == null) name = osm.get("ref");
-            if(!initializedname)
-            {
-                multipleName = name; initializedname = true;
-            }
-            else if(multipleName != null && (name == null  || !name.equals(multipleName)))
-            {
-                multipleName = null;
-            }
-
-            if(firstName == null && name != null)
-                firstName = name;
-            osm.visit(this);
-            if (multipleClassname == null)
-            {
-                multipleClassname = className;
-                multiplePluralClassname = classNamePlural;
-            }
-            else if (!multipleClassname.equals(className))
-            {
-                multipleClassname = "object";
-                multiplePluralClassname = trn("object", "objects", 2);
-            }
-        }
-
-        if( size == 1 )
-            displayName = name;
-        else if(multipleName != null)
-            displayName = size + " " + trn(multipleClassname, multiplePluralClassname, size) + ": " + multipleName;
-        else if(firstName != null)
-            displayName = size + " " + trn(multipleClassname, multiplePluralClassname, size) + ": " + tr("{0}, ...", firstName);
-        else
-            displayName = size + " " + trn(multipleClassname, multiplePluralClassname, size);
-    }
-
-    @Override
-    public JLabel toLabel()
-    {
-        return new JLabel(getText(), getIcon(), JLabel.HORIZONTAL);
-    }
-
-    /**
-     * Gets the name of the items
-     * @return the name of the items
-     */
-    public String getText()
-    {
-        return displayName;
-    }
-
-    /**
-     * Gets the icon of the items
-     * @return the icon of the items
-     */
-    public Icon getIcon()
-    {
-        if( size == 1 )
-            return icon;
-        else
-            return ImageProvider.get("data", multipleClassname);
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/util/NameVisitor.java b/validator/src/org/openstreetmap/josm/plugins/validator/util/NameVisitor.java
deleted file mode 100644
index 60733ea..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/util/NameVisitor.java
+++ /dev/null
@@ -1,84 +0,0 @@
-// License: GPL. Copyright 2007 by Immanuel Scholz and others
-package org.openstreetmap.josm.plugins.validator.util;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-import static org.openstreetmap.josm.tools.I18n.trn;
-
-import javax.swing.Icon;
-import javax.swing.JLabel;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.Relation;
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.data.osm.visitor.AbstractVisitor;
-import org.openstreetmap.josm.gui.DefaultNameFormatter;
-import org.openstreetmap.josm.tools.ImageProvider;
-
-/**
- * Able to create a name and an icon for each data element.
- *
- * @author imi
- */
-//TODO This class used to be in JOSM but it was removed. MultipleNameVisitor depends on it so I copied it here, but MultipleNameVisitor should be refactored instead of using this class
-public class NameVisitor extends AbstractVisitor {
-
-    /**
-     * The name of the item class
-     */
-    public String className;
-    public String classNamePlural;
-    /**
-     * The name of this item.
-     */
-    public String name;
-    /**
-     * The icon of this item.
-     */
-    public Icon icon;
-
-    /**
-     * If the node has a name-key or id-key, this is displayed. If not, (lat,lon)
-     * is displayed.
-     */
-    public void visit(Node n) {
-        name = n.getDisplayName(DefaultNameFormatter.getInstance());
-        addId(n);
-        icon = ImageProvider.get("data", "node");
-        className = "node";
-        classNamePlural = trn("node", "nodes", 2);
-    }
-
-    /**
-     * If the way has a name-key or id-key, this is displayed. If not, (x nodes)
-     * is displayed with x being the number of nodes in the way.
-     */
-    public void visit(Way w) {
-        name = w.getDisplayName(DefaultNameFormatter.getInstance());
-        addId(w);
-        icon = ImageProvider.get("data", "way");
-        className = "way";
-        classNamePlural = trn("way", "ways", 2);
-    }
-
-    /**
-     */
-    public void visit(Relation e) {
-        name = e.getDisplayName(DefaultNameFormatter.getInstance());
-        addId(e);
-        icon = ImageProvider.get("data", "relation");
-        className = "relation";
-        classNamePlural = trn("relation", "relations", 2);
-    }
-
-    public JLabel toLabel() {
-        return new JLabel(name, icon, JLabel.HORIZONTAL);
-    }
-
-
-    private void addId(OsmPrimitive osm) {
-        if (Main.pref.getBoolean("osm-primitives.showid"))
-            name += tr(" [id: {0}]", osm.getId());
-    }
-}
diff --git a/validator/src/org/openstreetmap/josm/plugins/validator/util/Util.java b/validator/src/org/openstreetmap/josm/plugins/validator/util/Util.java
deleted file mode 100644
index c4dbef0..0000000
--- a/validator/src/org/openstreetmap/josm/plugins/validator/util/Util.java
+++ /dev/null
@@ -1,175 +0,0 @@
-package org.openstreetmap.josm.plugins.validator.util;
-
-import java.awt.geom.Point2D;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.plugins.validator.OSMValidatorPlugin;
-
-/**
- * Utility class
- *
- * @author frsantos
- */
-public class Util
-{
-    /**
-     * Returns the plugin's directory of the plugin
-     *
-     * @return The directory of the plugin
-     */
-    public static String getPluginDir()
-    {
-        return Main.pref.getPreferencesDir() + "plugins/validator/";
-    }
-
-    /**
-     * Returns the start and end cells of a way.
-     * @param w The way
-     * @param cellWays The map with all cells
-     * @return A list with all the cells the way starts or ends
-     */
-    public static List<List<Way>> getWaysInCell(Way w, Map<Point2D,List<Way>> cellWays)
-    {
-        if (w.getNodesCount() == 0)
-            return Collections.emptyList();
-
-        Node n1 = w.getNode(0);
-        Node n2 = w.getNode(w.getNodesCount() - 1);
-
-        List<List<Way>> cells = new ArrayList<List<Way>>(2);
-        Set<Point2D> cellNodes = new HashSet<Point2D>();
-        Point2D cell;
-
-        // First, round coordinates
-        long x0 = Math.round(n1.getEastNorth().east()  * OSMValidatorPlugin.griddetail);
-        long y0 = Math.round(n1.getEastNorth().north() * OSMValidatorPlugin.griddetail);
-        long x1 = Math.round(n2.getEastNorth().east()  * OSMValidatorPlugin.griddetail);
-        long y1 = Math.round(n2.getEastNorth().north() * OSMValidatorPlugin.griddetail);
-
-        // Start of the way
-        cell = new Point2D.Double(x0, y0);
-        cellNodes.add(cell);
-        List<Way> ways = cellWays.get( cell );
-        if( ways == null )
-        {
-            ways = new ArrayList<Way>();
-            cellWays.put(cell, ways);
-        }
-        cells.add(ways);
-
-        // End of the way
-        cell = new Point2D.Double(x1, y1);
-        if( !cellNodes.contains(cell) )
-        {
-            cellNodes.add(cell);
-            ways = cellWays.get( cell );
-            if( ways == null )
-            {
-                ways = new ArrayList<Way>();
-                cellWays.put(cell, ways);
-            }
-            cells.add(ways);
-        }
-
-        // Then floor coordinates, in case the way is in the border of the cell.
-        x0 = (long)Math.floor(n1.getEastNorth().east()  * OSMValidatorPlugin.griddetail);
-        y0 = (long)Math.floor(n1.getEastNorth().north() * OSMValidatorPlugin.griddetail);
-        x1 = (long)Math.floor(n2.getEastNorth().east()  * OSMValidatorPlugin.griddetail);
-        y1 = (long)Math.floor(n2.getEastNorth().north() * OSMValidatorPlugin.griddetail);
-
-        // Start of the way
-        cell = new Point2D.Double(x0, y0);
-        if( !cellNodes.contains(cell) )
-        {
-            cellNodes.add(cell);
-            ways = cellWays.get( cell );
-            if( ways == null )
-            {
-                ways = new ArrayList<Way>();
-                cellWays.put(cell, ways);
-            }
-            cells.add(ways);
-        }
-
-        // End of the way
-        cell = new Point2D.Double(x1, y1);
-        if( !cellNodes.contains(cell) )
-        {
-            cellNodes.add(cell);
-            ways = cellWays.get( cell );
-            if( ways == null )
-            {
-                ways = new ArrayList<Way>();
-                cellWays.put(cell, ways);
-            }
-            cells.add(ways);
-        }
-
-        return cells;
-    }
-
-    /**
-     * Returns the coordinates of all cells in a grid that a line between 2
-     * nodes intersects with.
-     *
-     * @param n1 The first node.
-     * @param n2 The second node.
-     * @param gridDetail The detail of the grid. Bigger values give smaller
-     * cells, but a bigger number of them.
-     * @return A list with the coordinates of all cells
-     */
-    public static List<Point2D> getSegmentCells(Node n1, Node n2, double gridDetail)
-    {
-        List<Point2D> cells = new ArrayList<Point2D>();
-        double x0 = n1.getEastNorth().east() * gridDetail;
-        double x1 = n2.getEastNorth().east() * gridDetail;
-        double y0 = n1.getEastNorth().north() * gridDetail + 1;
-        double y1 = n2.getEastNorth().north() * gridDetail + 1;
-
-        if( x0 > x1 )
-        {
-            // Move to 1st-4th cuadrants
-            double aux;
-            aux = x0; x0 = x1; x1 = aux;
-            aux = y0; y0 = y1; y1 = aux;
-        }
-
-        double dx  = x1 - x0;
-        double dy  = y1 - y0;
-        long stepY = y0 <= y1 ? 1 : -1;
-        long gridX0 = (long)Math.floor(x0);
-        long gridX1 = (long)Math.floor(x1);
-        long gridY0 = (long)Math.floor(y0);
-        long gridY1 = (long)Math.floor(y1);
-
-        long maxSteps = (gridX1 - gridX0) + Math.abs(gridY1 - gridY0) + 1;
-        while( (gridX0 <= gridX1 && (gridY0 - gridY1)*stepY <= 0) && maxSteps-- > 0)
-        {
-            cells.add( new Point2D.Double(gridX0, gridY0) );
-
-            // Is the cross between the segment and next vertical line nearer than the cross with next horizontal line?
-            // Note: segment line formula: y=dy/dx(x-x1)+y1
-            // Note: if dy < 0, must use *bottom* line. If dy > 0, must use upper line
-            double scanY = dy/dx * (gridX0 + 1 - x1) + y1 + (dy < 0 ? -1 : 0);
-            double scanX = dx/dy * (gridY0 + (dy < 0 ? 0 : 1)*stepY - y1) + x1;
-
-            double distX = Math.pow(gridX0 + 1 - x0, 2) + Math.pow(scanY - y0, 2);
-            double distY = Math.pow(scanX - x0, 2) + Math.pow(gridY0 + stepY - y0, 2);
-
-            if( distX < distY)
-                gridX0 += 1;
-            else
-                gridY0 += stepY;
-        }
-
-        return cells;
-    }
-}
diff --git a/validator/tagchecker.cfg b/validator/tagchecker.cfg
deleted file mode 100644
index e16209d..0000000
--- a/validator/tagchecker.cfg
+++ /dev/null
@@ -1,79 +0,0 @@
-# JOSM TagChecker validator file
-
-# Format:
-# Each line specifies a certain error to be reported
-# <data type> : messagetype : <key><expression><value>
-#
-# Data type can be:
-#  node        - a node point
-#  way         - a way
-#  relation    - a relation
-#  *           - all data types
-#
-# Message type can be:
-# E            - an error
-# W            - a warning
-# I            - an low priority informational warning
-#
-# Key and value are expressions describing certain keys and values of these keys.
-# Regulator expressions are supported. In this case the expressions starts and
-# ends with // signs. If an 'i' is appended, the regular expression is
-# case insensitive.
-#
-# The * sign indicates any string.
-# The texts BOOLEAN_TRUE and BOOLEAN_FALSE in the value part indicate a special
-# handling for boolean values (yes, true, 0, false, no, ...).
-#
-# Expression can be:
-#  !=          - the key/value combination does not match
-#  ==          - the key/value combination does match
-#
-# To have more complicated expressions, multiple elements can be grouped together
-# with an logical and (&&).
-#
-# The comment at the end of a rule is displayed in validator description
-#
-# Empty lines and space signs are ignored
-
-way  : W : highway == * && name == /.* (Ave|Blvd|Cct|Cir|Cl|Cr|Crct|Cres|Crt|Ct|Dr|Drv|Esp|Espl|Hwy|Ln|Mw|Mwy|Pl|Rd|Qy|Qys|Sq|St|Str|Ter|Tce|Tr|Wy)\.?$/i               # abbreviated street name
-
-node : W : oneway == *                                         # oneway tag on a node
-node : W : bridge == BOOLEAN_TRUE                              # bridge tag on a node
-node : W : highway == tertiary                                 # wrong highway tag on a node
-node : W : highway == secondary                                # wrong highway tag on a node
-node : W : highway == residential                              # wrong highway tag on a node
-node : W : highway == unclassified                             # wrong highway tag on a node
-node : W : highway == track                                    # wrong highway tag on a node
-way  : W : highway == unclassified && name != *                # Unnamed unclassified highway
-way  : I : highway == secondary && ref != *                    # highway without a reference
-way  : I : highway == tertiary && ref != *                     # highway without a reference
-way  : I : highway == motorway && nat_ref != *                 # highway without a reference
-*    : W : highway == road                                     # temporary highway type
-*    : W : / *name */i == * && name != *                       # misspelled key name
-
-# The following could replace unnamed way check. Still at the moment we keep it as it is
-#way  : W : junction == roundabout && highway == /motorway|trunk|primary|secondary|tertiary|residential|pedestrian/ && /name|ref|(name:.*)|(.*_name)|(.*_ref)/ != * # Unnamed junction
-#way  : W : highway == /motorway|trunk|primary|secondary|tertiary|residential|pedestrian/ && /name|ref|(name:.*)|(.*_name)|(.*_ref)/ != * # Unnamed 
-
-way  : W : highway == cycleway && bicycle == BOOLEAN_FALSE     # cycleway with tag bicycle
-way  : W : highway == footway && foot == BOOLEAN_FALSE         # footway with tag foot
-#way  : I : highway == cycleway && bicycle == *                 # cycleway with tag bicycle
-#way  : I : highway == footway && foot == *                     # footway with tag foot
-way  : W : highway == cycleway && cycleway == lane             # separate cycleway as lane on a cycleway
-way  : W : highway == * && barrier == *                        # barrier used on a way
-
-#way  : I : waterway == * && layer != *                         # waterway without layer tag
-way  : I : highway == footway && maxspeed == *                 # maxspeed used for footway
-way  : I : highway == steps && maxspeed == *                   # maxspeed used for footway
-
-*    : W : layer == /\+.*/                                     # layer tag with + sign
-
-*    : I : name == /.*Strasse.*/i                              # street name contains ss
-
-relation : E : type != *                                       # relation without type
-
-node : I : amenity == /restaurant|cafe|fast_food/ && name != * # restaurant without name
-#way  : I : highway != * && railway != * && waterway != * && name == * # unusual named way type
-#*    : W : natural == water && waterway == *                   # unusual tag combination
-*    : W : highway == * && waterway == *                       # unusual tag combination
-*    : W : highway == * && natural == *                        # unusual tag combination
diff --git a/wmsplugin/.settings/org.eclipse.jdt.ui.prefs b/wmsplugin/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..def8a1f
--- /dev/null
+++ b/wmsplugin/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,54 @@
+#Mon Jan 25 21:25:55 CET 2010
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=true
+sp_cleanup.format_source_code=false
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=true
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/wmsplugin/Makefile b/wmsplugin/Makefile
index 302fb1a..2e87c35 100644
--- a/wmsplugin/Makefile
+++ b/wmsplugin/Makefile
@@ -1,16 +1,31 @@
 #!/usr/bin/make
 
-MOC=moc
-#MOC=/usr/share/qt4/bin/moc
-CFLAGS =
-LDFLAGS =
-LDLIBS = `pkg-config --libs --cflags QtCore QtGui QtWebKit`
+ifneq ($(windir),)
+MINGWPATH = C:\\PROGRA~1\\mingw\\bin\\
+QTPATH    = C:\\PROGRA~1\\qt\\
+
+CPP       = ${MINGWPATH}c++.exe
+MOC       = ${QTPATH}bin\\moc.exe
+RM        = del
+CFLAGS    = -W -O2 -I${QTPATH}include
+LDFLAGS   = -L${QTPATH}lib
+LDLIBS    = -lQtCore4 -lQtWebKit4 -lQtGui4 -lQtNetwork4
+else
+MOC       = moc
+#MOC       = /usr/share/qt4/bin/moc
+CPP       = gcc
+
+PACKAGES  = QtCore QtGui QtWebKit QtNetwork
+CFLAGS    = -W -O2 `pkg-config --cflags ${PACKAGES}`
+LDFLAGS   = `pkg-config --libs-only-L ${PACKAGES}`
+LDLIBS    = `pkg-config --libs-only-l ${PACKAGES}`
+endif
 
 webkit-image: webkit-image.cpp webkit-image.h
-	g++ -W -o $@ -O2 $(CFLAGS) $(LDFLAGS) webkit-image.cpp $(LDLIBS)
+	$(CPP) -o $@ $(CFLAGS) $(LDFLAGS) webkit-image.cpp $(LDLIBS)
 
 webkit-image.h: webkit-image.cpp
 	$(MOC) webkit-image.cpp >$@
 
 clean:
-	rm -f *.o webkit-image webkit-image.h
+	${RM} *.o webkit-image webkit-image.h
diff --git a/wmsplugin/build.xml b/wmsplugin/build.xml
index 67a3121..fb132ad 100644
--- a/wmsplugin/build.xml
+++ b/wmsplugin/build.xml
@@ -1,5 +1,5 @@
 <!--
-** This is a template build file for a JOSM  plugin.
+** This is the build file for the wmsplugin
 **
 ** Maintaining versions
 ** ====================
@@ -25,127 +25,128 @@
 **
 -->
 <project name="wmsplugin" default="dist" basedir=".">
-	
-	
-	<property name="commit.message" value="fixed JOSM issue #3940" />		
-	<property name="plugin.main.version" value="2450" />
-	
-	
-	<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">
-    	<echo message="building ${plugin.jar} with version ${version.entry.commit.revision} for JOSM version ${josm.reference.release} "/>
-        <copy todir="${plugin.build.dir}/images">
-            <fileset dir="images"/>
-        </copy>
-        <jar destfile="${plugin.jar}" basedir="${plugin.build.dir}">
-            <manifest>
-                <attribute name="Author" value="Tim Waters, Petr Dlouhý"/>
-                <attribute name="Plugin-Class" value="wmsplugin.WMSPlugin"/>
-                <attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
-                <attribute name="Plugin-Description" value="Display georeferenced images as background in JOSM (WMS servers, Yahoo, ...)."/>
-                <attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/wiki/JOSM/Plugins/WMSPlugin"/>
-                <attribute name="Plugin-Mainversion" value="${plugin.main.version}"/>
-                <attribute name="Plugin-Version" value="${version.entry.commit.revision}"/>
-                <attribute name="de_Plugin-Link" value="http://wiki.openstreetmap.org/wiki/DE:JOSM/Plugins/WMSPlugin"/>
-            </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>
+
+	<property name="commit.message" value="Uses new constructor for plugin" />
+	<property name="plugin.main.version" value="2830" />
+
+
+	<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">
+		<echo message="building ${plugin.jar} with version ${version.entry.commit.revision} for JOSM version ${josm.reference.release} " />
+		<copy todir="${plugin.build.dir}/images">
+			<fileset dir="images" />
+		</copy>
+		<jar destfile="${plugin.jar}" basedir="${plugin.build.dir}">
+			<manifest>
+				<attribute name="Author" value="Tim Waters, Petr Dlouhý" />
+				<attribute name="Plugin-Class" value="wmsplugin.WMSPlugin" />
+				<attribute name="Plugin-Date" value="${version.entry.commit.date}" />
+				<attribute name="Plugin-Description" value="Display georeferenced images as background in JOSM (WMS servers, Yahoo, ...)." />
+				<attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/wiki/JOSM/Plugins/WMSPlugin" />
+				<attribute name="Plugin-Mainversion" value="${plugin.main.version}" />
+				<attribute name="Plugin-Version" value="${version.entry.commit.revision}" />
+				<attribute name="de_Plugin-Link" value="http://wiki.openstreetmap.org/wiki/DE:JOSM/Plugins/WMSPlugin" />
+				<attribute name="ja_Plugin-Link" value="http://wiki.openstreetmap.org/wiki/Ja:JOSM/Plugins/WMSPlugin?uselang=ja" />
+			</manifest>
+		</jar>
+	</target>
+	<target name="revision">
+		<exec append="false" output="REVISION" executable="svn" failifexecutionfails="true" failonerror="true">
+			<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>
+
+	<!--
+	************************** Publishing the plugin *********************************** 
+	-->
+	<!--
+	** extracts the JOSM release for the JOSM version in ../core and saves it in the 
+	** property ${coreversion.info.entry.revision}
+	**
+	-->
+	<target name="core-info">
+		<exec append="false" output="core.info.xml" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C" />
+			<arg value="info" />
+			<arg value="--xml" />
+			<arg value="../../core" />
+		</exec>
+		<xmlproperty file="core.info.xml" prefix="coreversion" keepRoot="true" collapseAttributes="true" />
+		<echo>Building against core revision ${coreversion.info.entry.revision}.</echo>
+		<echo>Plugin-Mainversion is set to ${plugin.main.version}.</echo>
+		<delete file="core.info.xml" />
+	</target>
 
 	<!--
-		 ************************** Publishing the plugin *********************************** 
-		-->
-			<!--
-			  ** extracts the JOSM release for the JOSM version in ../core and saves it in the 
-			  ** property ${coreversion.info.entry.revision}
-			  **
-			-->
-			<target name="core-info">
-		        <exec append="false" output="core.info.xml" executable="svn" failifexecutionfails="false">
-		                    <env key="LANG" value="C"/>
-		                    <arg value="info"/>
-		                    <arg value="--xml"/>
-		                    <arg value="../../core"/>
-		        </exec>
-		        <xmlproperty file="core.info.xml" prefix="coreversion" keepRoot="true" collapseAttributes="true"/>
-				<echo>Building against core revision ${coreversion.info.entry.revision}.</echo>			
-				<echo>Plugin-Mainversion is set to ${plugin.main.version}.</echo>
-				<delete file="core.info.xml" />
-			</target>
+	** commits the source tree for this plugin
+	-->
+	<target name="commit-current">
+		<echo>Commiting the plugin source with message '${commit.message}' ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="true" failonerror="true">
+			<env key="LANG" value="C" />
+			<arg value="commit" />
+			<arg value="-m '${commit.message}'" />
+			<arg value="." />
+		</exec>
+	</target>
 
-			<!--
-			 ** commits the source tree for this plugin
-			-->
-			<target name="commit-current">
-				<echo>Commiting the plugin source with message '${commit.message}' ...</echo>
-			    <exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
-			                    <env key="LANG" value="C"/>
-			                    <arg value="commit"/>
-			                    <arg value="-m '${commit.message}'"/>
-			                    <arg value="."/>
-			    </exec>	    
-			</target>
+	<!--
+	** updates (svn up) the source tree for this plugin
+	-->
+	<target name="update-current">
+		<echo>Updating plugin source ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="true" failonerror="true">
+			<env key="LANG" value="C" />
+			<arg value="up" />
+			<arg value="." />
+		</exec>
+		<echo>Updating ${plugin.jar} ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="true" failonerror="true">
+			<env key="LANG" value="C" />
+			<arg value="up" />
+			<arg value="../dist/${plugin.jar}" />
+		</exec>
+	</target>
 
-			<!--
-			** updates (svn up) the source tree for this plugin
-			-->
-			<target name="update-current">
-				<echo>Updating plugin source ...</echo>
-			    <exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
-			                    <env key="LANG" value="C"/>
-			                    <arg value="up"/>
-			                    <arg value="."/>
-			    </exec>	    
-				<echo>Updating ${plugin.jar} ...</echo>
-			    <exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
-			                    <env key="LANG" value="C"/>
-			                    <arg value="up"/>
-			                    <arg value="../dist/${plugin.jar}"/>
-			    </exec>	    
-			</target>
-			
-			<!--
-			 ** commits the plugin.jar 
-			 -->
-			<target name="commit-dist">
-					<echo>
+	<!--
+	** commits the plugin.jar 
+	-->
+	<target name="commit-dist">
+		<echo>
 	***** Properties of published ${plugin.jar} *****
 	Commit message    : '${commit.message}'					
 	Plugin-Mainversion: ${plugin.main.version}
@@ -154,15 +155,29 @@
 	***** / Properties of published ${plugin.jar} *****					
 						
 	Now commiting ${plugin.jar} ...
-	</echo>					
-				    <exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
-				                    <env key="LANG" value="C"/>
-					    			<arg value="-m '${commit.message}'"/>
-				    				<arg value="commit"/>	                			
-	            			        <arg value="${plugin.jar}"/>
-				    </exec>	    
-		   	</target>
-					
-			<target name="publish" depends="core-info,commit-current,update-current,clean,dist,commit-dist">
-			</target>
+	</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="true" failonerror="true">
+			<env key="LANG" value="C" />
+			<arg value="-m '${commit.message}'" />
+			<arg value="commit" />
+			<arg value="${plugin.jar}" />
+		</exec>
+	</target>
+
+
+	<!-- ** make sure svn is present as a command line tool ** -->
+	<target name="ensure-svn-present">
+		<exec append="true" output="svn.log" executable="svn" failonerror="false" resultproperty="svn.exit.code">
+			<env key="LANG" value="C" />
+			<arg value="--version" />
+		</exec>
+		<fail message="Fatal: command 'svn' not found. Please make sure svn is installed on your system.">
+			<condition>
+				<isfailure code="${svn.exit.code}" />
+			</condition>
+		</fail>
+	</target>
+
+	<target name="publish" depends="ensure-svn-present,core-info,commit-current,update-current,clean,dist,commit-dist">
+	</target>
 </project>
diff --git a/wmsplugin/images/cursor/modifier/move.png b/wmsplugin/images/cursor/modifier/move.png
new file mode 100644
index 0000000..54a0b84
Binary files /dev/null and b/wmsplugin/images/cursor/modifier/move.png differ
diff --git a/validator/josm-validator.launch b/wmsplugin/josm-wmsplugin.launch
similarity index 91%
rename from validator/josm-validator.launch
rename to wmsplugin/josm-wmsplugin.launch
index fd6b2ff..0b4de4c 100644
--- a/validator/josm-validator.launch
+++ b/wmsplugin/josm-wmsplugin.launch
@@ -6,7 +6,7 @@
 <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
 <listEntry value="1"/>
 </listAttribute>
-<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JDK 6"/>
+<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JDK 5"/>
 <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.openstreetmap.josm.gui.MainApplication"/>
-<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="validator"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="wmsplugin"/>
 </launchConfiguration>
diff --git a/wmsplugin/sources.cfg b/wmsplugin/sources.cfg
index a0c11e3..e832913 100644
--- a/wmsplugin/sources.cfg
+++ b/wmsplugin/sources.cfg
@@ -3,7 +3,7 @@
 # NOTE: default items should be common and worldwide
 #
 true;Landsat;http://onearth.jpl.nasa.gov/wms.cgi?request=GetMap&layers=global_mosaic&styles=&format=image/jpeg&
-true;Open Aerial Map;http://openaerialmap.org/wms/?VERSION=1.0&request=GetMap&layers=world&styles=&format=image/jpeg&
+false;Open Aerial Map;http://openaerialmap.org/wms/?VERSION=1.0&request=GetMap&layers=world&styles=&format=image/jpeg&
 #
 # different forms for web access
 # must be html:<url>
diff --git a/wmsplugin/src/wmsplugin/GeorefImage.java b/wmsplugin/src/wmsplugin/GeorefImage.java
index 3f62193..85440bf 100644
--- a/wmsplugin/src/wmsplugin/GeorefImage.java
+++ b/wmsplugin/src/wmsplugin/GeorefImage.java
@@ -1,10 +1,10 @@
 package wmsplugin;
 
-import java.awt.Color;
 import java.awt.Dimension;
 import java.awt.Graphics;
 import java.awt.Image;
 import java.awt.Point;
+import java.awt.Transparency;
 import java.awt.image.BufferedImage;
 import java.io.IOException;
 import java.io.ObjectInputStream;
@@ -18,144 +18,137 @@ import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.gui.NavigatableComponent;
 
 public class GeorefImage implements Serializable {
-    public BufferedImage image = null;
-    private Image reImg = null;
-    private Dimension reImgHash = new Dimension(0, 0);
-    public EastNorth min, max;
-    public boolean downloadingStarted;
-    public boolean failed = false;
-
-    public GeorefImage(boolean downloadingStarted) {
-        this.downloadingStarted = downloadingStarted;
-    }
-
-    public boolean contains(EastNorth en, double dx, double dy) {
-        return min.east()+dx <= en.east() && en.east() <= max.east()+dx
-            && min.north()+dy <= en.north() && en.north() <= max.north()+dy;
-    }
-
-    public boolean isVisible(NavigatableComponent nc, double dx, double dy) {
-        EastNorth mi = new EastNorth(min.east()+dx, min.north()+dy);
-        EastNorth ma = new EastNorth(max.east()+dx, max.north()+dy);
-        Point minPt = nc.getPoint(mi), maxPt = nc.getPoint(ma);
-        Graphics g = nc.getGraphics();
-
-        return (g.hitClip(minPt.x, maxPt.y,
-                maxPt.x - minPt.x, minPt.y - maxPt.y));
-    }
-
-    public boolean paint(Graphics g, NavigatableComponent nc, double dx, double dy) {
-        if (image == null || min == null || max == null) return false;
-
-        EastNorth mi = new EastNorth(min.east()+dx, min.north()+dy);
-        EastNorth ma = new EastNorth(max.east()+dx, max.north()+dy);
-        Point minPt = nc.getPoint(mi), maxPt = nc.getPoint(ma);
-
-        if(!isVisible(nc, dx, dy)){
-            return false;
-        }
-
-        // Width and height flicker about 2 pixels due to rounding errors, typically only 1
-        int width = Math.abs(maxPt.x-minPt.x);
-        int height = Math.abs(minPt.y-maxPt.y);
-        int diffx, diffy;
-        try {
-            diffx = reImgHash.width - width;
-            diffy = reImgHash.height - height;
-        } catch(Exception e) {
-            reImgHash = new Dimension(0, 0);
-            diffx = 99;
-            diffy = 99;
-        }
-        // This happens if you zoom outside the world
-        if(width == 0 || height == 0)
-            return false;
-
-        // We still need to re-render if the requested size is larger (otherwise we'll have black lines)
-        // If it's only up to two pixels smaller, just draw the old image, the errors are minimal
-        // but the performance improvements when moving are huge
-        // Zooming is still slow because the images need to be resized
-        if(diffx >= 0 && diffx <= 2 && diffy >= 0 && diffy <= 2 && reImg != null) {
-            /*g.setColor(Color.RED);
+	public BufferedImage image = null;
+	private Image reImg = null;
+	private Dimension reImgHash = new Dimension(0, 0);
+	public EastNorth min, max;
+	public boolean downloadingStarted;
+	public boolean failed = false;
+
+	public GeorefImage(boolean downloadingStarted) {
+		this.downloadingStarted = downloadingStarted;
+	}
+
+	public boolean contains(EastNorth en, double dx, double dy) {
+		return min.east()+dx <= en.east() && en.east() <= max.east()+dx
+		&& min.north()+dy <= en.north() && en.north() <= max.north()+dy;
+	}
+
+	public boolean isVisible(NavigatableComponent nc, double dx, double dy) {
+		EastNorth mi = new EastNorth(min.east()+dx, min.north()+dy);
+		EastNorth ma = new EastNorth(max.east()+dx, max.north()+dy);
+		Point minPt = nc.getPoint(mi), maxPt = nc.getPoint(ma);
+		Graphics g = nc.getGraphics();
+
+		return (g.hitClip(minPt.x, maxPt.y,
+				maxPt.x - minPt.x, minPt.y - maxPt.y));
+	}
+
+	public boolean paint(Graphics g, NavigatableComponent nc, double dx, double dy) {
+		if (image == null || min == null || max == null) return false;
+
+		EastNorth mi = new EastNorth(min.east()+dx, min.north()+dy);
+		EastNorth ma = new EastNorth(max.east()+dx, max.north()+dy);
+		Point minPt = nc.getPoint(mi), maxPt = nc.getPoint(ma);
+
+		if(!isVisible(nc, dx, dy)){
+			return false;
+		}
+
+		// Width and height flicker about 2 pixels due to rounding errors, typically only 1
+		int width = Math.abs(maxPt.x-minPt.x);
+		int height = Math.abs(minPt.y-maxPt.y);
+		int diffx, diffy;
+
+		diffx = reImgHash.width - width;
+		diffy = reImgHash.height - height;
+		// This happens if you zoom outside the world
+		if(width == 0 || height == 0)
+			return false;
+
+		// We still need to re-render if the requested size is larger (otherwise we'll have black lines)
+		// If it's only up to two pixels smaller, just draw the old image, the errors are minimal
+		// but the performance improvements when moving are huge
+		// Zooming is still slow because the images need to be resized
+		if(diffx >= 0 && diffx <= 2 && diffy >= 0 && diffy <= 2 && reImg != null) {
+			/*g.setColor(Color.RED);
               g.drawRect(minPt.x, minPt.y-height, width, height);*/
-            g.drawImage(reImg, minPt.x, maxPt.y, null);
-            return true;
-        }
-
-        boolean alphaChannel = Main.pref.getBoolean("wmsplugin.alpha_channel");
-
-        try {
-            if(reImg != null) reImg.flush();
-            long freeMem = Runtime.getRuntime().maxMemory() - Runtime.getRuntime().totalMemory();
-            //System.out.println("Free Memory:           "+ (freeMem/1024/1024) +" MB");
-            // Notice that this value can get negative due to integer overflows
-            //System.out.println("Img Size:              "+ (width*height*3/1024/1024) +" MB");
-
-            int multipl = alphaChannel ? 4 : 3;
-            // This happens when requesting images while zoomed out and then zooming in
-            // Storing images this large in memory will certainly hang up JOSM. Luckily
-            // traditional rendering is as fast at these zoom levels, so it's no loss.
-            // Also prevent caching if we're out of memory soon
-            if(width > 2000 || height > 2000 || width*height*multipl > freeMem) {
-                fallbackDraw(g, image, minPt, maxPt);
-            } else {
-                // We haven't got a saved resized copy, so resize and cache it
-                reImg = new BufferedImage(width, height,
-                    alphaChannel
-                        ? BufferedImage.TYPE_INT_ARGB
-                        : BufferedImage.TYPE_3BYTE_BGR  // This removes alpha
-                    );
-                reImg.getGraphics().drawImage(image,
-                    0, 0, width, height, // dest
-                    0, 0, image.getWidth(null), image.getHeight(null), // src
-                    null);
-                reImg.getGraphics().dispose();
-
-                reImgHash.setSize(width, height);
-                /*g.setColor(Color.RED);
+			g.drawImage(reImg, minPt.x, maxPt.y, null);
+			return true;
+		}
+
+		boolean alphaChannel = Main.pref.getBoolean("wmsplugin.alpha_channel") && image.getTransparency() != Transparency.OPAQUE;
+
+		try {
+			if(reImg != null) reImg.flush();
+			long freeMem = Runtime.getRuntime().maxMemory() - Runtime.getRuntime().totalMemory();
+			//System.out.println("Free Memory:           "+ (freeMem/1024/1024) +" MB");
+			// Notice that this value can get negative due to integer overflows
+			//System.out.println("Img Size:              "+ (width*height*3/1024/1024) +" MB");
+
+			int multipl = alphaChannel ? 4 : 3;
+			// This happens when requesting images while zoomed out and then zooming in
+			// Storing images this large in memory will certainly hang up JOSM. Luckily
+			// traditional rendering is as fast at these zoom levels, so it's no loss.
+			// Also prevent caching if we're out of memory soon
+			if(width > 2000 || height > 2000 || width*height*multipl > freeMem) {
+				fallbackDraw(g, image, minPt, maxPt);
+			} else {
+				// We haven't got a saved resized copy, so resize and cache it
+				reImg = new BufferedImage(width, height, alphaChannel?BufferedImage.TYPE_INT_ARGB:BufferedImage.TYPE_3BYTE_BGR);
+				reImg.getGraphics().drawImage(image,
+						0, 0, width, height, // dest
+						0, 0, image.getWidth(null), image.getHeight(null), // src
+						null);
+				reImg.getGraphics().dispose();
+
+				reImgHash.setSize(width, height);
+				/*g.setColor(Color.RED);
                   g.drawRect(minPt.x, minPt.y-height, width, height);*/
-                g.drawImage(reImg, minPt.x, maxPt.y, null);
-            }
-        } catch(Exception e) {
-            fallbackDraw(g, image, minPt, maxPt);
-        }
-        return true;
-    }
-
-    private void fallbackDraw(Graphics g, Image img, Point min, Point max) {
-        if(reImg != null) reImg.flush();
-        reImg = null;
-        g.drawImage(img,
-            min.x, max.y, max.x, min.y, // dest
-            0, 0, img.getWidth(null), img.getHeight(null), // src
-            null);
-    }
-
-    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
-        max = (EastNorth) in.readObject();
-        min = (EastNorth) in.readObject();
-        boolean hasImage = in.readBoolean();
-        if (hasImage)
-            image = (BufferedImage) ImageIO.read(ImageIO.createImageInputStream(in));
-        else {
-            in.readObject(); // read null from input stream
-            image = null;
-        }
-    }
-
-    private void writeObject(ObjectOutputStream out) throws IOException {
-        out.writeObject(max);
-        out.writeObject(min);
-        if(image == null) {
-            out.writeBoolean(false);
-            out.writeObject(null);
-        } else {
-            out.writeBoolean(true);
-            ImageIO.write(image, "png", ImageIO.createImageOutputStream(out));
-        }
-    }
-
-    public void flushedResizedCachedInstance() {
-        reImg = null;
-    }
+				g.drawImage(reImg, minPt.x, maxPt.y, null);
+			}
+		} catch(Exception e) {
+			fallbackDraw(g, image, minPt, maxPt);
+		}
+		return true;
+	}
+
+	private void fallbackDraw(Graphics g, Image img, Point min, Point max) {
+		if(reImg != null) {
+			reImg.flush();
+			reImg = null;
+		}
+		g.drawImage(img,
+				min.x, max.y, max.x, min.y, // dest
+				0, 0, img.getWidth(null), img.getHeight(null), // src
+				null);
+	}
+
+	private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+		max = (EastNorth) in.readObject();
+		min = (EastNorth) in.readObject();
+		boolean hasImage = in.readBoolean();
+		if (hasImage)
+			image = ImageIO.read(ImageIO.createImageInputStream(in));
+		else {
+			in.readObject(); // read null from input stream
+			image = null;
+		}
+	}
+
+	private void writeObject(ObjectOutputStream out) throws IOException {
+		out.writeObject(max);
+		out.writeObject(min);
+		if(image == null) {
+			out.writeBoolean(false);
+			out.writeObject(null);
+		} else {
+			out.writeBoolean(true);
+			ImageIO.write(image, "png", ImageIO.createImageOutputStream(out));
+		}
+	}
+
+	public void flushedResizedCachedInstance() {
+		reImg = null;
+	}
 }
diff --git a/wmsplugin/src/wmsplugin/Grabber.java b/wmsplugin/src/wmsplugin/Grabber.java
index 66f21fe..14e4011 100644
--- a/wmsplugin/src/wmsplugin/Grabber.java
+++ b/wmsplugin/src/wmsplugin/Grabber.java
@@ -28,14 +28,14 @@ abstract public class Grabber extends Thread {
         if (b.min != null && b.max != null && WMSPlugin.doOverlap) { 
             double eastSize =  b.max.east() - b.min.east(); 
             double northSize =  b.max.north() - b.min.north(); 
-    
+
             double eastCoef = WMSPlugin.overlapEast / 100.0; 
             double northCoef = WMSPlugin.overlapNorth / 100.0; 
-             
-            this.b = new ProjectionBounds( new EastNorth(b.min.east(), 
+
+            this.b = new ProjectionBounds( new EastNorth(b.min.east(),
                                             b.min.north()), 
                                  new EastNorth(b.max.east() + eastCoef * eastSize, 
-                                            b.max.north() + northCoef * northSize));             
+                                            b.max.north() + northCoef * northSize));
         } else 
            this.b = b;
 
@@ -72,6 +72,24 @@ abstract public class Grabber extends Thread {
         image.image = img;
         image.flushedResizedCachedInstance();
         image.failed = true;
+        image.downloadingStarted = false;
+        g.setFont(font);
+    }
+
+    protected void grabNotInCache(){ // report not in cache
+        BufferedImage img = new BufferedImage(width(), height(), BufferedImage.TYPE_INT_ARGB);
+        Graphics g = img.getGraphics();
+        g.setColor(Color.GRAY);
+        g.fillRect(0, 0, width(), height());
+        Font font = g.getFont();
+        Font tempFont = font.deriveFont(Font.PLAIN).deriveFont(36.0f);
+        g.setFont(tempFont);
+        g.setColor(Color.BLACK);
+        g.drawString(tr("Not in cache"), 10, height()/2);
+        image.image = img;
+        image.flushedResizedCachedInstance();
+        image.failed = true;
+        image.downloadingStarted = false;
         g.setFont(font);
     }
 
@@ -94,4 +112,6 @@ abstract public class Grabber extends Thread {
     public static int random(int min, int max) {
         return (int)(Math.random() * ((max+1)-min) ) + min;
     }
+
+    abstract public boolean loadFromCache();
 }
diff --git a/wmsplugin/src/wmsplugin/HTMLGrabber.java b/wmsplugin/src/wmsplugin/HTMLGrabber.java
index e201506..5cc5789 100644
--- a/wmsplugin/src/wmsplugin/HTMLGrabber.java
+++ b/wmsplugin/src/wmsplugin/HTMLGrabber.java
@@ -26,9 +26,6 @@ public class HTMLGrabber extends WMSGrabber {
 
         System.out.println("Grabbing HTML " + url);
 
-        BufferedImage cached = cache.getImg(urlstring);
-        if(cached != null) return cached;
-
         ArrayList<String> cmdParams = new ArrayList<String>();
         StringTokenizer st = new StringTokenizer(MessageFormat.format(
         Main.pref.get("wmsplugin.browser", "webkit-image {0}"), urlstring));
diff --git a/wmsplugin/src/wmsplugin/Map_Rectifier_WMSmenuAction.java b/wmsplugin/src/wmsplugin/Map_Rectifier_WMSmenuAction.java
index 26e99d2..a034a90 100644
--- a/wmsplugin/src/wmsplugin/Map_Rectifier_WMSmenuAction.java
+++ b/wmsplugin/src/wmsplugin/Map_Rectifier_WMSmenuAction.java
@@ -2,6 +2,7 @@ package wmsplugin;
 
 import static org.openstreetmap.josm.tools.I18n.tr;
 
+import java.awt.GridBagConstraints;
 import java.awt.GridBagLayout;
 import java.awt.Toolkit;
 import java.awt.datatransfer.DataFlavor;
@@ -30,7 +31,7 @@ public class Map_Rectifier_WMSmenuAction extends JosmAction {
     /**
      * Class that bundles all required information of a rectifier service
      */
-    public class rectifierService {
+    public static class RectifierService {
         private final String name;
         private final String url;
         private final String wmsUrl;
@@ -44,7 +45,7 @@ public class Map_Rectifier_WMSmenuAction extends JosmAction {
          * @param urlRegEx: a regular expression that determines if a given URL is one of the service and returns the WMS id if so
          * @param idValidator: regular expression that checks if a given ID is syntactically valid
          */
-        public rectifierService(String name, String url, String wmsUrl, String urlRegEx, String idValidator) {
+        public RectifierService(String name, String url, String wmsUrl, String urlRegEx, String idValidator) {
             this.name = name;
             this.url = url;
             this.wmsUrl = wmsUrl;
@@ -60,7 +61,7 @@ public class Map_Rectifier_WMSmenuAction extends JosmAction {
     /**
      * List of available rectifier services. May be extended from the outside
      */
-    public ArrayList<rectifierService> services = new ArrayList<rectifierService>();
+    public ArrayList<RectifierService> services = new ArrayList<RectifierService>();
 
     public Map_Rectifier_WMSmenuAction() {
         super(tr("Rectified Image..."),
@@ -75,7 +76,7 @@ public class Map_Rectifier_WMSmenuAction extends JosmAction {
 
         // Add default services
         services.add(
-            new rectifierService("Metacarta Map Rectifier",
+            new RectifierService("Metacarta Map Rectifier",
                 "http://labs.metacarta.com/rectifier/",
                 "http://labs.metacarta.com/rectifier/wms.cgi?id=__s__&srs=EPSG:4326"
                 + "&Service=WMS&Version=1.1.0&Request=GetMap&format=image/png&",
@@ -88,7 +89,7 @@ public class Map_Rectifier_WMSmenuAction extends JosmAction {
             // TODO: Change all links to mapwarper.net once the project has moved.
             // The RegEx already matches the new URL and old URLs will be forwarded
             // to make the transition as smooth as possible for the users
-            new rectifierService("Geothings Map Warper",
+            new RectifierService("Geothings Map Warper",
                 "http://warper.geothings.net/",
                 "http://warper.geothings.net/maps/wms/__s__?request=GetMap&version=1.1.1"
                 + "&styles=&format=image/png&srs=epsg:4326&exceptions=application/vnd.ogc.se_inimage&",
@@ -103,7 +104,7 @@ public class Map_Rectifier_WMSmenuAction extends JosmAction {
 
         // Clipboard content gets trimmed, so matching whitespace only ensures that this
         // service will never be selected automatically.
-        services.add(new rectifierService(tr("Custom WMS Link"), "", "", "^\\s+$", ""));
+        services.add(new RectifierService(tr("Custom WMS Link"), "", "", "^\\s+$", ""));
     }
 
     public void actionPerformed(ActionEvent e) {
@@ -116,7 +117,7 @@ public class Map_Rectifier_WMSmenuAction extends JosmAction {
         ButtonGroup group = new ButtonGroup();
 
         JRadioButton firstBtn = null;
-        for(rectifierService s : services) {
+        for(RectifierService s : services) {
             JRadioButton serviceBtn = new JRadioButton(s.name);
             if(firstBtn == null)
                 firstBtn = serviceBtn;
@@ -132,9 +133,9 @@ public class Map_Rectifier_WMSmenuAction extends JosmAction {
             group.add(serviceBtn);
             if(!s.url.equals("")) {
                 panel.add(serviceBtn, GBC.std());
-                panel.add(new UrlLabel(s.url, tr("Visit Homepage")), GBC.eol().anchor(GBC.EAST));
+                panel.add(new UrlLabel(s.url, tr("Visit Homepage")), GBC.eol().anchor(GridBagConstraints.EAST));
             } else
-                panel.add(serviceBtn, GBC.eol().anchor(GBC.WEST));
+                panel.add(serviceBtn, GBC.eol().anchor(GridBagConstraints.WEST));
         }
 
         // Fallback in case no match was found
@@ -142,7 +143,7 @@ public class Map_Rectifier_WMSmenuAction extends JosmAction {
             firstBtn.setSelected(true);
 
         panel.add(new JLabel(tr("WMS URL or Image ID:")), GBC.eol());
-        panel.add(tfWmsUrl, GBC.eol().fill(GBC.HORIZONTAL));
+        panel.add(tfWmsUrl, GBC.eol().fill(GridBagConstraints.HORIZONTAL));
 
         ExtendedDialog diag = new ExtendedDialog(Main.parent,
                 tr("Add Rectified Image"),
@@ -162,7 +163,7 @@ public class Map_Rectifier_WMSmenuAction extends JosmAction {
 
             String text = tfWmsUrl.getText().trim();
             // Loop all services until we find the selected one
-            for(rectifierService s : services) {
+            for(RectifierService s : services) {
                 if(!s.isSelected())
                     continue;
 
diff --git a/wmsplugin/src/wmsplugin/WMSAdjustAction.java b/wmsplugin/src/wmsplugin/WMSAdjustAction.java
index 369041c..7a6576c 100644
--- a/wmsplugin/src/wmsplugin/WMSAdjustAction.java
+++ b/wmsplugin/src/wmsplugin/WMSAdjustAction.java
@@ -9,7 +9,6 @@ import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.awt.event.MouseMotionListener;
 import java.util.List;
-import java.util.logging.Logger;
 
 import javax.swing.DefaultComboBoxModel;
 import javax.swing.DefaultListCellRenderer;
@@ -31,8 +30,8 @@ import org.openstreetmap.josm.tools.ImageProvider;
 
 
 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;
     EastNorth prevEastNorth;
@@ -44,10 +43,10 @@ public class WMSAdjustAction extends MapMode implements MouseListener, MouseMoti
                         ImageProvider.getCursor("normal", "move"));
     }
 
-    
-    
+
+
     @Override public void enterMode() {
-        super.enterMode();       
+        super.enterMode();
         if (!hasWMSLayersToAdjust()) {
             warnNoWMSLayers();
             return;
@@ -107,15 +106,15 @@ public class WMSAdjustAction extends MapMode implements MouseListener, MouseMoti
         selectedImage = null;
         prevEastNorth = null;
     }
-    
+
     @Override
     public void mouseEntered(MouseEvent e) {
     }
-    
+
     @Override
     public void mouseExited(MouseEvent e) {
     }
-    
+
     @Override
     public void mouseMoved(MouseEvent e) {
     }
@@ -128,10 +127,10 @@ public class WMSAdjustAction extends MapMode implements MouseListener, MouseMoti
     @Override public boolean layerIsSupported(Layer l) {
         return (l instanceof WMSLayer) && l.isVisible();
     }
-    
+
     /**
     * the list cell renderer used to render layer list entries
-    * 
+    *
     */
    static public class LayerListCellRenderer extends DefaultListCellRenderer {
 
@@ -157,25 +156,25 @@ public class WMSAdjustAction extends MapMode implements MouseListener, MouseMoti
    }
 
    /**
-    * Prompts the user with a list of WMS layers which can be adjusted  
-    * 
-    * @param adjustableLayers the list of adjustable layers 
-    * @return  the selected layer; null, if no layer was selected 
+    * Prompts the user with a list of WMS layers which can be adjusted
+    *
+    * @param adjustableLayers the list of adjustable layers
+    * @return  the selected layer; null, if no layer was selected
     */
    protected Layer askAdjustLayer(List<? extends Layer> adjustableLayers) {
        JComboBox layerList = new JComboBox();
        layerList.setRenderer(new LayerListCellRenderer());
        layerList.setModel(new DefaultComboBoxModel(adjustableLayers.toArray()));
        layerList.setSelectedIndex(0);
-   
+
        JPanel pnl = new JPanel();
        pnl.setLayout(new GridBagLayout());
        pnl.add(new JLabel(tr("Please select the WMS layer to adjust.")), GBC.eol());
        pnl.add(layerList, GBC.eol());
-   
+
        ExtendedDialog diag = new ExtendedDialog(
-               Main.parent, 
-               tr("Select WMS layer"), 
+               Main.parent,
+               tr("Select WMS layer"),
                new String[] { tr("Start adjusting"),tr("Cancel") }
                );
        diag.setContent(pnl);
@@ -189,21 +188,21 @@ public class WMSAdjustAction extends MapMode implements MouseListener, MouseMoti
    }
 
    /**
-    * Displays a warning message if there are no WMS layers to adjust 
-    * 
+    * Displays a warning message if there are no WMS layers to adjust
+    *
     */
    protected void warnNoWMSLayers() {
        JOptionPane.showMessageDialog(
                Main.parent,
                tr("There are currently no WMS layer to adjust."),
-               tr("No layers to adjust"), 
+               tr("No layers to adjust"),
                JOptionPane.WARNING_MESSAGE
        );
    }
-   
+
    /**
-    * Replies true if there is at least one WMS layer 
-    * 
+    * Replies true if there is at least one WMS layer
+    *
     * @return true if there is at least one WMS layer
     */
    protected boolean hasWMSLayersToAdjust() {
@@ -215,5 +214,5 @@ public class WMSAdjustAction extends MapMode implements MouseListener, MouseMoti
     @Override
     protected void updateEnabledState() {
         setEnabled(hasWMSLayersToAdjust());
-    }   
+    }
 }
diff --git a/wmsplugin/src/wmsplugin/WMSGrabber.java b/wmsplugin/src/wmsplugin/WMSGrabber.java
index e157667..2fb7f2e 100644
--- a/wmsplugin/src/wmsplugin/WMSGrabber.java
+++ b/wmsplugin/src/wmsplugin/WMSGrabber.java
@@ -36,7 +36,7 @@ public class WMSGrabber extends Grabber {
     public static boolean isUrlWithPatterns(String url) {
         return url != null && url.contains("{") && url.contains("}");
     }
-    
+
     protected String baseURL;
     private final boolean urlWithPatterns;
 
@@ -47,7 +47,8 @@ public class WMSGrabber extends Grabber {
         urlWithPatterns = isUrlWithPatterns(baseURL);
     }
 
-    public void run() {
+    @Override
+	public void run() {
         attempt();
         mv.repaint();
     }
@@ -151,10 +152,34 @@ public class WMSGrabber extends Grabber {
         return res;
     }
 
-    protected BufferedImage grab(URL url) throws IOException, OsmTransferException {
+    @Override
+	public boolean loadFromCache(){
+        URL url = null;
+        try{
+           url = getURL(
+              b.min.east(), b.min.north(),
+              b.max.east(), b.max.north(),
+              width(), height());
+        } catch(Exception e) {
+           return false;
+        }
         BufferedImage cached = cache.getImg(url.toString());
-        if(cached != null) return cached;
+        if(!layer.hasAutoDownload() || cached != null){
+           image.min = b.min;
+           image.max = b.max;
+           if(cached == null){
+              grabNotInCache();
+              return true;
+           }
+           image.image = cached;
+           image.flushedResizedCachedInstance();
+           image.downloadingStarted = false;
+           return true;
+        }
+        return false;
+    }
 
+    protected BufferedImage grab(URL url) throws IOException, OsmTransferException {
         System.out.println("Grabbing WMS " + url);
 
         HttpURLConnection conn = (HttpURLConnection) url.openConnection();
diff --git a/wmsplugin/src/wmsplugin/WMSInfo.java b/wmsplugin/src/wmsplugin/WMSInfo.java
index 0469c64..4d4094f 100644
--- a/wmsplugin/src/wmsplugin/WMSInfo.java
+++ b/wmsplugin/src/wmsplugin/WMSInfo.java
@@ -32,7 +32,7 @@ public class WMSInfo implements Comparable<WMSInfo> {
 
     public int compareTo(WMSInfo in)
     {
-        Integer i = name.compareTo(in.name);
+        int i = name.compareTo(in.name);
         if(i == 0)
             i = url.compareTo(in.url);
         if(i == 0)
diff --git a/wmsplugin/src/wmsplugin/WMSLayer.java b/wmsplugin/src/wmsplugin/WMSLayer.java
index e9b8aff..b691ad7 100644
--- a/wmsplugin/src/wmsplugin/WMSLayer.java
+++ b/wmsplugin/src/wmsplugin/WMSLayer.java
@@ -43,424 +43,436 @@ import org.openstreetmap.josm.tools.ImageProvider;
  * 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;
-
-        // quick hack to predefine the PixelDensity to reuse the cache
-        int codeIndex = getName().indexOf("#PPD=");
-        if (codeIndex != -1) {
-            pixelPerDegree = Double.valueOf(getName().substring(codeIndex+5));
-        } else {
-            pixelPerDegree = getPPD();
-        }
-        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 initialized, 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 JMenuItem(new BookmarkWmsAction()),
-                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, 4096);
-
-            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;
-            }
-        }
-    }
-    /**
-     * This action will add a WMS layer menu entry with the current WMS layer URL and name extended by the current resolution.
-     * When using the menu entry again, the WMS cache will be used properly.
-     */
-    public class BookmarkWmsAction extends AbstractAction {
-        public BookmarkWmsAction() {
-            super(tr("Set WMS Bookmark"));
-        }
-        public void actionPerformed(ActionEvent ev) {
-            int i = 0;
-            while (Main.pref.hasKey("wmsplugin.url."+i+".url")) {
-                i++;
-            }
-            String baseName;
-            // cut old parameter
-            int parameterIndex = getName().indexOf("#PPD=");
-            if (parameterIndex != -1) {
-                baseName = getName().substring(0,parameterIndex);
-            }
-            else {
-                baseName = getName();
-            }
-            Main.pref.put("wmsplugin.url."+ i +".url",baseURL );
-            Main.pref.put("wmsplugin.url."+String.valueOf(i)+".name", baseName + "#" + getPPD() );
-            WMSPlugin.refreshMenu();
-        }
-    }
+	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;
+
+		// quick hack to predefine the PixelDensity to reuse the cache
+		int codeIndex = getName().indexOf("#PPD=");
+		if (codeIndex != -1) {
+			pixelPerDegree = Double.valueOf(getName().substring(codeIndex+5));
+		} else {
+			pixelPerDegree = getPPD();
+		}
+		resolution = mv.getDist100PixelText();
+
+		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 boolean hasAutoDownload(){
+		return startstop.isSelected();
+	}
+
+	public double getDx(){
+		return dx;
+	}
+
+	public double getDy(){
+		return dy;
+	}
+
+	@Override
+	public void destroy() {
+		try {
+			executor.shutdownNow();
+			// Might not be initialized, 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;
+	}
+
+	private boolean zoomIsTooBig() {
+		//don't download when it's too outzoomed
+		return pixelPerDegree / getPPD() > minZoom;
+	}
+
+	@Override public void paint(Graphics2D g, final MapView mv, Bounds bounds) {
+		if(baseURL == null) return;
+		if (usesInvalidUrl && !isInvalidUrlConfirmed) return;
+
+		if (zoomIsTooBig()) {
+			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 );
+
+		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);
+					if(!gr.loadFromCache()){
+						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().createActivateLayerAction(this)),
+				new JMenuItem(LayerListDialog.getInstance().createShowHideLayerAction(this)),
+				new JMenuItem(LayerListDialog.getInstance().createDeleteLayerAction(this)),
+				new JSeparator(),
+				new JMenuItem(new LoadWmsAction()),
+				new JMenuItem(new SaveWmsAction()),
+				new JMenuItem(new BookmarkWmsAction()),
+				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) {
+			if (zoomIsTooBig()) {
+				JOptionPane.showMessageDialog(
+						Main.parent,
+						tr("The requested area is too big. Please zoom in a little, or change resolution"),
+						tr("Error"),
+						JOptionPane.ERROR_MESSAGE
+				);
+			} else {
+				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, 4096);
+
+			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;
+			}
+		}
+	}
+	/**
+	 * This action will add a WMS layer menu entry with the current WMS layer URL and name extended by the current resolution.
+	 * When using the menu entry again, the WMS cache will be used properly.
+	 */
+	public class BookmarkWmsAction extends AbstractAction {
+		public BookmarkWmsAction() {
+			super(tr("Set WMS Bookmark"));
+		}
+		public void actionPerformed(ActionEvent ev) {
+			int i = 0;
+			while (Main.pref.hasKey("wmsplugin.url."+i+".url")) {
+				i++;
+			}
+			String baseName;
+			// cut old parameter
+			int parameterIndex = getName().indexOf("#PPD=");
+			if (parameterIndex != -1) {
+				baseName = getName().substring(0,parameterIndex);
+			}
+			else {
+				baseName = getName();
+			}
+			Main.pref.put("wmsplugin.url."+ i +".url",baseURL );
+			Main.pref.put("wmsplugin.url."+String.valueOf(i)+".name", baseName + "#PPD=" + getPPD() );
+			WMSPlugin.refreshMenu();
+		}
+	}
 }
diff --git a/wmsplugin/src/wmsplugin/WMSPlugin.java b/wmsplugin/src/wmsplugin/WMSPlugin.java
index 81732ed..4a462a2 100644
--- a/wmsplugin/src/wmsplugin/WMSPlugin.java
+++ b/wmsplugin/src/wmsplugin/WMSPlugin.java
@@ -35,6 +35,7 @@ import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
 import org.openstreetmap.josm.io.CacheFiles;
 import org.openstreetmap.josm.io.MirroredInputStream;
 import org.openstreetmap.josm.plugins.Plugin;
+import org.openstreetmap.josm.plugins.PluginInformation;
 
 import wmsplugin.io.WMSLayerExporter;
 import wmsplugin.io.WMSLayerImporter;
@@ -60,7 +61,8 @@ public class WMSPlugin extends Plugin {
         ExtensionFileFilter.importers.add(new WMSLayerImporter());
     }
 
-    public WMSPlugin() {
+    public WMSPlugin(PluginInformation info) {
+    	super(info);
         refreshMenu();
         cache.setExpire(CacheFiles.EXPIRE_MONTHLY, false);
         cache.setMaxSize(70, false);
@@ -247,6 +249,6 @@ public class WMSPlugin extends Plugin {
 
     static public String getPrefsPath()
     {
-        return Main.pref.getPluginsDirFile().getPath() + "/wmsplugin/";
+        return Main.pref.getPluginsDirectory().getPath() + "/wmsplugin/";
     }
 }
diff --git a/wmsplugin/src/wmsplugin/WMSPreferenceEditor.java b/wmsplugin/src/wmsplugin/WMSPreferenceEditor.java
index 9d21e3e..42c8b28 100644
--- a/wmsplugin/src/wmsplugin/WMSPreferenceEditor.java
+++ b/wmsplugin/src/wmsplugin/WMSPreferenceEditor.java
@@ -1,15 +1,10 @@
 package wmsplugin;
 
-import java.awt.BorderLayout;
-import java.awt.FlowLayout;
-import javax.swing.JCheckBox;
-import javax.swing.JSpinner;
-import javax.swing.SpinnerNumberModel;
-import org.openstreetmap.josm.Main;
 import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.Dimension;
 import java.awt.FlowLayout;
+import java.awt.GridBagConstraints;
 import java.awt.GridBagLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
@@ -18,18 +13,21 @@ import java.util.Map;
 
 import javax.swing.Box;
 import javax.swing.JButton;
+import javax.swing.JCheckBox;
 import javax.swing.JComboBox;
 import javax.swing.JLabel;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
+import javax.swing.JSpinner;
 import javax.swing.JTable;
 import javax.swing.JTextField;
+import javax.swing.SpinnerNumberModel;
 import javax.swing.table.DefaultTableModel;
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.gui.preferences.PreferenceDialog;
 import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
+import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
 import org.openstreetmap.josm.tools.GBC;
 
 public class WMSPreferenceEditor implements PreferenceSetting {
@@ -40,14 +38,14 @@ public class WMSPreferenceEditor implements PreferenceSetting {
     JCheckBox overlapCheckBox;
     JSpinner spinEast;
     JSpinner spinNorth;
-    
-    public void addGui(final PreferenceDialog gui) {
+
+    public void addGui(final PreferenceTabbedPane gui) {
         JPanel p = gui.createPreferenceTab("wms", tr("WMS Plugin Preferences"), tr("Modify list of WMS servers displayed in the WMS plugin menu"));
 
         model = new DefaultTableModel(new String[]{tr("Menu Name"), tr("WMS URL")}, 0);
         final JTable list = new JTable(model);
         JScrollPane scroll = new JScrollPane(list);
-        p.add(scroll, GBC.eol().fill(GBC.BOTH));
+        p.add(scroll, GBC.eol().fill(GridBagConstraints.BOTH));
         scroll.setPreferredSize(new Dimension(200,200));
 
         for (WMSInfo i : WMSPlugin.wmsList) {
@@ -80,12 +78,12 @@ public class WMSPreferenceEditor implements PreferenceSetting {
                 p.add(new JLabel(tr("Menu Name")), GBC.std().insets(0,0,5,0));
                 JTextField key = new JTextField(40);
                 JTextField value = new JTextField(40);
-                p.add(key, GBC.eop().insets(5,0,0,0).fill(GBC.HORIZONTAL));
+                p.add(key, GBC.eop().insets(5,0,0,0).fill(GridBagConstraints.HORIZONTAL));
                 p.add(new JLabel(tr("WMS URL")), GBC.std().insets(0,0,5,0));
-                p.add(value, GBC.eol().insets(5,0,0,0).fill(GBC.HORIZONTAL));
+                p.add(value, GBC.eol().insets(5,0,0,0).fill(GridBagConstraints.HORIZONTAL));
                 int answer = JOptionPane.showConfirmDialog(
-                        gui, p, 
-                        tr("Enter a menu name and WMS URL"), 
+                        gui, p,
+                        tr("Enter a menu name and WMS URL"),
                         JOptionPane.OK_CANCEL_OPTION,
                         JOptionPane.QUESTION_MESSAGE);
                 if (answer == JOptionPane.OK_OPTION) {
@@ -116,22 +114,22 @@ public class WMSPreferenceEditor implements PreferenceSetting {
                 int[] lines = listdef.getSelectedRows();
                 if (lines.length == 0) {
                     JOptionPane.showMessageDialog(
-                            gui, 
+                            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()) 
+                        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
@@ -140,7 +138,7 @@ public class WMSPreferenceEditor implements PreferenceSetting {
                             continue outer;
                         }
                     }
-                    
+
                     model.addRow(new String[] {c1, c2});
                     int lastLine = model.getRowCount() - 1;
                     list.getSelectionModel().setSelectionInterval(lastLine, lastLine);
@@ -150,10 +148,10 @@ public class WMSPreferenceEditor implements PreferenceSetting {
         });
 
         p.add(buttonPanel);
-        p.add(Box.createHorizontalGlue(), GBC.eol().fill(GBC.HORIZONTAL));
+        p.add(Box.createHorizontalGlue(), GBC.eol().fill(GridBagConstraints.HORIZONTAL));
         // Add default item list
-        p.add(scrolldef, GBC.eol().insets(0,5,0,0).fill(GBC.BOTH));       
-        
+        p.add(scrolldef, GBC.eol().insets(0,5,0,0).fill(GridBagConstraints.BOTH));
+
         browser = new JComboBox(new String[]{
         "webkit-image {0}",
         "gnome-web-photo --mode=photo --format=png {0} /dev/stdout",
@@ -161,27 +159,27 @@ public class WMSPreferenceEditor implements PreferenceSetting {
         "webkit-image-gtk {0}"});
         browser.setEditable(true);
         browser.setSelectedItem(Main.pref.get("wmsplugin.browser", "webkit-image {0}"));
-        p.add(new JLabel(tr("Downloader:")), GBC.eol().fill(GBC.HORIZONTAL));
+        p.add(new JLabel(tr("Downloader:")), GBC.eol().fill(GridBagConstraints.HORIZONTAL));
         p.add(browser);
 
 
         //Overlap
-        p.add(Box.createHorizontalGlue(), GBC.eol().fill(GBC.HORIZONTAL)); 
-         
-        overlapCheckBox = new JCheckBox(tr("Overlap tiles"), WMSPlugin.doOverlap ); 
-        JLabel labelEast = new JLabel(tr("% of east:")); 
-        JLabel labelNorth = new JLabel(tr("% of north:")); 
-        spinEast = new JSpinner(new SpinnerNumberModel(WMSPlugin.overlapEast, 1, 50, 1)); 
-        spinNorth = new JSpinner(new SpinnerNumberModel(WMSPlugin.overlapNorth, 1, 50, 1)); 
-         
-        JPanel overlapPanel = new JPanel(new FlowLayout()); 
-        overlapPanel.add(overlapCheckBox); 
-        overlapPanel.add(labelEast); 
-        overlapPanel.add(spinEast); 
-        overlapPanel.add(labelNorth); 
-        overlapPanel.add(spinNorth); 
-         
-        p.add(overlapPanel);    
+        p.add(Box.createHorizontalGlue(), GBC.eol().fill(GridBagConstraints.HORIZONTAL));
+
+        overlapCheckBox = new JCheckBox(tr("Overlap tiles"), WMSPlugin.doOverlap );
+        JLabel labelEast = new JLabel(tr("% of east:"));
+        JLabel labelNorth = new JLabel(tr("% of north:"));
+        spinEast = new JSpinner(new SpinnerNumberModel(WMSPlugin.overlapEast, 1, 50, 1));
+        spinNorth = new JSpinner(new SpinnerNumberModel(WMSPlugin.overlapNorth, 1, 50, 1));
+
+        JPanel overlapPanel = new JPanel(new FlowLayout());
+        overlapPanel.add(overlapCheckBox);
+        overlapPanel.add(labelEast);
+        overlapPanel.add(spinEast);
+        overlapPanel.add(labelNorth);
+        overlapPanel.add(spinNorth);
+
+        p.add(overlapPanel);
     }
 
     public boolean ok() {
@@ -221,13 +219,13 @@ public class WMSPreferenceEditor implements PreferenceSetting {
 
         if (change) WMSPlugin.refreshMenu();
 
-        WMSPlugin.doOverlap = overlapCheckBox.getModel().isSelected(); 
-        WMSPlugin.overlapEast = (Integer) spinEast.getModel().getValue(); 
-        WMSPlugin.overlapNorth = (Integer) spinNorth.getModel().getValue(); 
-         
-        Main.pref.put("wmsplugin.url.overlap",    String.valueOf(WMSPlugin.doOverlap)); 
-        Main.pref.put("wmsplugin.url.overlapEast", String.valueOf(WMSPlugin.overlapEast)); 
-        Main.pref.put("wmsplugin.url.overlapNorth", String.valueOf(WMSPlugin.overlapNorth)); 
+        WMSPlugin.doOverlap = overlapCheckBox.getModel().isSelected();
+        WMSPlugin.overlapEast = (Integer) spinEast.getModel().getValue();
+        WMSPlugin.overlapNorth = (Integer) spinNorth.getModel().getValue();
+
+        Main.pref.put("wmsplugin.url.overlap",    String.valueOf(WMSPlugin.doOverlap));
+        Main.pref.put("wmsplugin.url.overlapEast", String.valueOf(WMSPlugin.overlapEast));
+        Main.pref.put("wmsplugin.url.overlapNorth", String.valueOf(WMSPlugin.overlapNorth));
 
         Main.pref.put("wmsplugin.browser", browser.getEditor().getItem().toString());
         return false;
diff --git a/wmsplugin/webkit-image.cpp b/wmsplugin/webkit-image.cpp
index ae905b4..fddb51c 100644
--- a/wmsplugin/webkit-image.cpp
+++ b/wmsplugin/webkit-image.cpp
@@ -1,19 +1,16 @@
-/* compile with
-moc webkit-image.cpp >webkit-image.h
-g++ webkit-image.cpp -o webkit-image -lQtCore -lQtWebKit -lQtGui -s -O2
-or under Windows:
-g++ webkit-image.cpp -o webkit-image -lQtCore4 -lQtWebKit4 -lQtGui4 -s O2
-adding the correct directories with -L or -I:
--I C:\Progra~1\Qt\include -L C:\Progra~1\Qt\lib
-*/
 #include <QtGui/QApplication>
 #include <QtGui/QPainter>
 #include <QtCore/QFile>
 #include <QtCore/QString>
+#include <QtCore/QUrl>
 #include <QtWebKit/QWebPage>
 #include <QtWebKit/QWebFrame>
 #include <QtNetwork/QNetworkProxy>
 #include <QtCore/QProcess>
+#if QT_VERSION >= 0x040500
+#include <QtGui/QDesktopServices>
+#include <QtNetwork/QNetworkDiskCache>
+#endif
 
 /* using mingw to set binary mode */
 #ifdef WIN32
@@ -75,26 +72,82 @@ int main(int argc, char **argv)
   int idx = environment.indexOf(QRegExp("http_proxy=.*"));
   if(idx != -1)
   {
-     QString proxyHost;
-     int proxyPort = 8080;
-     QStringList tmpList = environment.at(idx).split("=");
-     QStringList host_port = tmpList.at(1).split(":");
-     proxyHost = host_port.at(0);
-     if(host_port.size() == 2)
-     {
-       bool ok;
-       int port = host_port.at(1).toInt(&ok);
-       if(ok)
-         proxyPort = port;
-     }
-
-     QNetworkProxy proxy;
-     proxy.setType(QNetworkProxy::HttpCachingProxy);
-     proxy.setHostName(proxyHost);
-     proxy.setPort(proxyPort);
-     page->networkAccessManager()->setProxy(proxy);
+    QString scheme = "http";   // default
+    QString proxyHost;
+
+    int proxyPort = 8080;
+    QStringList tmpList = environment.at(idx).split("=");
+
+#if QT_VERSION >= 0x040600  // Qt4.6: Use QUrl::fromUserInput
+    // set URL (and guess if proto scheme missing)
+    QUrl url (QUrl::fromUserInput(tmpList.at(1)));
+#else
+    // set URL
+    QUrl url (tmpList.at(1));
+#endif
+    if (url.isValid() && !url.host().isEmpty())
+    {
+      proxyHost = url.host();
+
+      if (url.port() != -1)
+        proxyPort = url.port();
+
+      if (!url.scheme().isEmpty())
+        scheme = url.scheme();
+
+      if (scheme == "http")   // we support only http
+      {
+        QNetworkProxy proxy;
+        proxy.setType(QNetworkProxy::HttpCachingProxy);
+        proxy.setHostName(proxyHost);
+        proxy.setPort(proxyPort);
+        if (!url.userName().isEmpty())
+          proxy.setUser(url.userName());
+        if (!url.password().isEmpty())
+          proxy.setPassword(url.password());
+        page->networkAccessManager()->setProxy(proxy);
+      }
+    }
+    else /* manual mode */
+    {
+      QStringList proto_host_port = tmpList.at(1).split("://");
+      QStringList host_port;
+      if (proto_host_port.size() == 2)  // string has proto
+      {
+        scheme = proto_host_port.at(0);
+        host_port = proto_host_port.at(1).split(":");
+      }
+      else  // no proto (or invalid format with several delimiters)
+      {
+        host_port = tmpList.at(1).split(":");
+      }
+      if (scheme == "http")   // we support only http
+      {
+        proxyHost = host_port.at(0);
+        if(host_port.size() == 2)
+        {
+          bool ok;
+          int port = host_port.at(1).toInt(&ok);
+          if(ok)
+            proxyPort = port;
+        }
+
+        QNetworkProxy proxy;
+        proxy.setType(QNetworkProxy::HttpCachingProxy);
+        proxy.setHostName(proxyHost);
+        proxy.setPort(proxyPort);
+        page->networkAccessManager()->setProxy(proxy);
+      }
+    }
   }
 
+#if QT_VERSION >= 0x040500
+  QNetworkDiskCache *diskCache = new QNetworkDiskCache(page);
+  QString location = QDesktopServices::storageLocation(QDesktopServices::CacheLocation);
+  diskCache->setCacheDirectory(location);
+  page->networkAccessManager()->setCache(diskCache);
+#endif
+
   QObject::connect(page, SIGNAL(loadFinished(bool)), s, SLOT(loaded(bool)));
   QObject::connect(s, SIGNAL(finish(void)), &a, SLOT(quit()));
   /* set some useful defaults for a webpage */

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/josm-plugins.git



More information about the Pkg-grass-devel mailing list