Index: unk/src/org/openstreetmap/josm/data/projection/BelgianLambert1972.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/BelgianLambert1972.java	(revision 5547)
+++ 	(revision )
@@ -1,61 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.data.projection;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.projection.datum.SevenParameterDatum;
-import org.openstreetmap.josm.data.projection.proj.LambertConformalConic;
-import org.openstreetmap.josm.data.projection.proj.ProjParameters;
-
-/**
- * Belgian Lambert 72 projection as specified by the Belgian IGN
- * in this document: http://www.ngi.be/Common/Lambert2008/Transformation_Geographic_Lambert_FR.pdf
- * @author Don-vip
- *
- */
-public class BelgianLambert1972 extends AbstractProjection {
-
-    public BelgianLambert1972() {
-        ellps = Ellipsoid.hayford;
-        // 7 parameters transformation: http://www.eye4software.com/resources/datum/4313/
-        datum = new SevenParameterDatum("Belgium Datum 72", null, ellps, -99.06, 53.32, -112.49, 0.419, -0.830, 1.885, -1);
-        x_0 =  150000.013;
-        y_0 = 5400088.438;
-        lon_0 = convertDegreeMinuteSecond(4, 22, 2.952);
-        proj = new LambertConformalConic();
-        try {
-            proj.initialize(new ProjParameters() {{
-                ellps = BelgianLambert1972.this.ellps;
-                lat_0 = 90.0;
-                lat_1 = 49 + convertMinuteSecond(50, 0.00204);
-                lat_2 = 51 + convertMinuteSecond(10, 0.00204);
-            }});
-        } catch (ProjectionConfigurationException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    @Override
-    public String getCacheDirectoryName() {
-        return "belgianLambert1972";
-    }
-
-    @Override
-    public Bounds getWorldBoundsLatLon() {
-        return new Bounds(
-                new LatLon(49.51, 2.54),
-                new LatLon(51.50, 6.40), false);
-    }
-
-    @Override
-    public Integer getEpsgCode() {
-        return 31370;
-    }
-
-    @Override
-    public String toString() {
-        return tr("Belgian Lambert 1972");
-    }
-}
Index: unk/src/org/openstreetmap/josm/data/projection/BelgianLambert2008.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/BelgianLambert2008.java	(revision 5547)
+++ 	(revision )
@@ -1,60 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.data.projection;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.projection.datum.GRS80Datum;
-import org.openstreetmap.josm.data.projection.proj.LambertConformalConic;
-import org.openstreetmap.josm.data.projection.proj.ProjParameters;
-
-/**
- * Belgian Lambert 2008 projection as specified by the Belgian IGN
- * in this document: http://www.ngi.be/Common/Lambert2008/Transformation_Geographic_Lambert_FR.pdf
- * @author Don-vip
- *
- */
-public class BelgianLambert2008 extends AbstractProjection {
-
-    public BelgianLambert2008() {
-        ellps = Ellipsoid.GRS80;
-        datum = GRS80Datum.INSTANCE;
-        x_0 =  649328.0;
-        y_0 = 665262.0;
-        lon_0 = convertDegreeMinuteSecond(4, 21, 33.177);
-        proj = new LambertConformalConic();
-        try {
-            proj.initialize(new ProjParameters() {{
-                ellps = BelgianLambert2008.this.ellps;
-                lat_0 = convertDegreeMinuteSecond(50, 47, 52.134);
-                lat_1 = convertDegreeMinuteSecond(49, 50,  0);
-                lat_2 = convertDegreeMinuteSecond(51, 10,  0);
-            }});
-        } catch (ProjectionConfigurationException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    @Override
-    public String getCacheDirectoryName() {
-        return "belgianLambert2008";
-    }
-
-    @Override
-    public Bounds getWorldBoundsLatLon() {
-        return new Bounds(
-                new LatLon(49.51, 2.54),
-                new LatLon(51.50, 6.40), false);
-    }
-
-    @Override
-    public Integer getEpsgCode() {
-        return 3812;
-    }
-
-    @Override
-    public String toString() {
-        return tr("Belgian Lambert 2008");
-    }
-}
Index: /trunk/src/org/openstreetmap/josm/data/projection/CustomProjection.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/CustomProjection.java	(revision 5547)
+++ /trunk/src/org/openstreetmap/josm/data/projection/CustomProjection.java	(revision 5548)
@@ -21,4 +21,5 @@
 import org.openstreetmap.josm.data.projection.datum.ThreeParameterDatum;
 import org.openstreetmap.josm.data.projection.datum.WGS84Datum;
+import org.openstreetmap.josm.data.projection.proj.Mercator;
 import org.openstreetmap.josm.data.projection.proj.Proj;
 import org.openstreetmap.josm.data.projection.proj.ProjParameters;
@@ -38,4 +39,7 @@
      */
     protected String pref;
+    protected String name;
+    protected String code;
+    protected String cacheDir;
     protected Bounds bounds;
 
@@ -83,10 +87,24 @@
 
     public CustomProjection() {
-        this.pref = null;
     }
 
     public CustomProjection(String pref) {
+        this(null, null, pref, null);
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param name describe projection in one or two words
+     * @param code unique code for this projection - may be null
+     * @param pref the string that defines the custom projection
+     * @param cacheDir cache directory name
+     */
+    public CustomProjection(String name, String code, String pref, String cacheDir) {
+        this.name = name;
+        this.code = code;
+        this.pref = pref;
+        this.cacheDir = cacheDir;
         try {
-            this.pref = pref;
             update(pref);
         } catch (ProjectionConfigurationException ex) {
@@ -104,5 +122,5 @@
             ellps = Ellipsoid.WGS84;
             datum = WGS84Datum.INSTANCE;
-            proj = new org.openstreetmap.josm.data.projection.proj.Mercator();
+            proj = new Mercator();
             bounds = new Bounds(
                     new LatLon(-85.05112877980659, -180.0),
@@ -429,4 +447,9 @@
     @Override
     public Integer getEpsgCode() {
+        if (code != null && code.startsWith("EPSG:")) {
+            try {
+                return Integer.parseInt(code.substring(5));
+            } catch (NumberFormatException e) {}
+        }
         return null;
     }
@@ -434,10 +457,10 @@
     @Override
     public String toCode() {
-        return "proj:" + (pref == null ? "ERROR" : pref);
+        return code != null ? code : "proj:" + (pref == null ? "ERROR" : pref);
     }
 
     @Override
     public String getCacheDirectoryName() {
-        return "proj-"+Utils.md5Hex(pref == null ? "" : pref).substring(0, 4);
+        return cacheDir != null ? cacheDir : "proj-"+Utils.md5Hex(pref == null ? "" : pref).substring(0, 4);
     }
 
@@ -452,5 +475,5 @@
     @Override
     public String toString() {
-        return tr("Custom Projection");
+        return name != null ? name : tr("Custom Projection");
     }
 }
Index: unk/src/org/openstreetmap/josm/data/projection/Epsg3008.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/Epsg3008.java	(revision 5547)
+++ 	(revision )
@@ -1,60 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.data.projection;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.projection.datum.GRS80Datum;
-import org.openstreetmap.josm.data.projection.proj.ProjParameters;
-import org.openstreetmap.josm.data.projection.proj.TransverseMercator;
-
-/**
- * SWEREF99 13 30 projection. Based on data from spatialreference.org.
- * http://spatialreference.org/ref/epsg/3008/
- *
- * @author Hanno Hecker
- */
-public class Epsg3008 extends AbstractProjection {
-
-    public Epsg3008() {
-        ellps = Ellipsoid.GRS80;
-        proj = new org.openstreetmap.josm.data.projection.proj.TransverseMercator();
-        try {
-            proj.initialize(new ProjParameters() {{ ellps = Epsg3008.this.ellps; }});
-        } catch (ProjectionConfigurationException e) {
-            throw new RuntimeException(e);
-        }
-        datum = GRS80Datum.INSTANCE;
-        lon_0 = 13.5;
-        x_0 = 150000;
-    }
-
-    @Override
-    public String toString() {
-        return tr("SWEREF99 13 30 / EPSG:3008 (Sweden)");
-    }
-
-    @Override
-    public Integer getEpsgCode() {
-        return 3008;
-    }
-
-    @Override
-    public int hashCode() {
-        return toCode().hashCode();
-    }
-
-    @Override
-    public String getCacheDirectoryName() {
-        return "epsg"+ getEpsgCode();
-    }
-
-    @Override
-    public Bounds getWorldBoundsLatLon() {
-        return new Bounds(
-                new LatLon(55.2, 12.1),
-                new LatLon(62.26, 14.65), false);
-    }
-
-}
Index: unk/src/org/openstreetmap/josm/data/projection/Epsg4326.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/Epsg4326.java	(revision 5547)
+++ 	(revision )
@@ -1,53 +1,0 @@
-// License: GPL. Copyright 2007 by Immanuel Scholz and others
-package org.openstreetmap.josm.data.projection;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.coor.EastNorth;
-import org.openstreetmap.josm.data.coor.LatLon;
-
-/**
- * Directly use latitude / longitude values as x/y.
- *
- * @author imi
- */
-public class Epsg4326 implements Projection {
-
-    public EastNorth latlon2eastNorth(LatLon p) {
-        return new EastNorth(p.lon(), p.lat());
-    }
-
-    public LatLon eastNorth2latlon(EastNorth p) {
-        return new LatLon(p.north(), p.east());
-    }
-
-    @Override public String toString() {
-        return tr("WGS84 Geographic");
-    }
-
-    public String toCode() {
-        return "EPSG:4326";
-    }
-
-    @Override
-    public int hashCode() {
-        return getClass().getName().hashCode(); // we have no variables
-    }
-
-    public String getCacheDirectoryName() {
-        return "epsg4326";
-    }
-
-    public Bounds getWorldBoundsLatLon()
-    {
-        return new Bounds(
-                new LatLon(-90.0, -180.0),
-                new LatLon(90.0, 180.0), false);
-    }
-
-    public double getDefaultZoomInPPD() {
-        // This will set the scale bar to about 100 km
-        return 0.009;
-    }
-}
Index: unk/src/org/openstreetmap/josm/data/projection/GaussKrueger.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/GaussKrueger.java	(revision 5547)
+++ 	(revision )
@@ -1,69 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.data.projection;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.projection.datum.NTV2Datum;
-import org.openstreetmap.josm.data.projection.datum.NTV2GridShiftFileWrapper;
-import org.openstreetmap.josm.data.projection.proj.ProjParameters;
-import org.openstreetmap.josm.data.projection.proj.TransverseMercator;
-
-public class GaussKrueger extends AbstractProjection {
-
-    public static final int DEFAULT_ZONE = 2;
-    private final int zone;
-
-    private static Bounds[] bounds = {
-        new Bounds(new LatLon(-5, 3.5), new LatLon(85, 8.5), false),
-        new Bounds(new LatLon(-5, 6.5), new LatLon(85, 11.5), false),
-        new Bounds(new LatLon(-5, 9.5), new LatLon(85, 14.5), false),
-        new Bounds(new LatLon(-5, 12.5), new LatLon(85, 17.5), false),
-    };
-
-    public GaussKrueger() {
-        this(DEFAULT_ZONE);
-    }
-
-    public GaussKrueger(int zone) {
-        if (zone < 2 || zone > 5)
-            throw new IllegalArgumentException();
-        this.zone = zone;
-        ellps = Ellipsoid.Bessel1841;
-        datum = new NTV2Datum("BETA2007", null, ellps, NTV2GridShiftFileWrapper.BETA2007);
-        ////less acurrate datum (errors up to 3m):
-        //datum = new SevenParameterDatum(
-        //        tr("Deutsches Hauptdreiecksnetz"), null, ellps,
-        //        598.1, 73.7, 418.2, 0.202, 0.045, -2.455, 6.70);
-        proj = new TransverseMercator();
-        try {
-            proj.initialize(new ProjParameters() {{ ellps = GaussKrueger.this.ellps; }});
-        } catch (ProjectionConfigurationException e) {
-            throw new RuntimeException(e);
-        }
-        x_0 = 1000000 * zone + 500000;
-        lon_0 = 3 * zone;
-    }
-
-    @Override
-    public String toString() {
-        return tr("Gau\u00DF-Kr\u00FCger Zone {0}", zone);
-    }
-
-    @Override
-    public Integer getEpsgCode() {
-        return 31464 + zone;
-    }
-
-    @Override
-    public String getCacheDirectoryName() {
-        return "gausskrueger"+zone;
-    }
-
-    @Override
-    public Bounds getWorldBoundsLatLon() {
-        return bounds[zone-2];
-    }
-
-}
Index: unk/src/org/openstreetmap/josm/data/projection/Lambert.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/Lambert.java	(revision 5547)
+++ 	(revision )
@@ -1,145 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.data.projection;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.projection.datum.NTV2Datum;
-import org.openstreetmap.josm.data.projection.datum.NTV2GridShiftFileWrapper;
-import org.openstreetmap.josm.data.projection.proj.LambertConformalConic;
-import org.openstreetmap.josm.data.projection.proj.ProjParameters;
-
-/**
- * Lambert conic conform 4 zones using the French geodetic system NTF.
- * This newer version uses the grid translation NTF<->RGF93 provided by IGN for a submillimetric accuracy.
- * (RGF93 is the French geodetic system similar to WGS84 but not mathematically equal)
- *
- * Source: http://professionnels.ign.fr/DISPLAY/000/526/700/5267002/transformation.pdf
- * @author Pieren
- */
-public class Lambert extends AbstractProjection {
-
-    /**
-     * Lambert I, II, III, and IV latitude origin
-     */
-    private static final double lat_0s[] = { 49.5, 46.8, 44.1, 42.165 };
-    
-    /**
-     * Lambert I, II, III, and IV latitude of first standard parallel
-     */
-    private static final double lat_1s[] = { 
-            convertDegreeMinuteSecond(48, 35, 54.682), 
-            convertDegreeMinuteSecond(45, 53, 56.108),
-            convertDegreeMinuteSecond(43, 11, 57.449),
-            convertDegreeMinuteSecond(41, 33, 37.396)};
-    
-    /**
-     * Lambert I, II, III, and IV latitude of second standard parallel
-     */
-    private static final double lat_2s[] = {
-            convertDegreeMinuteSecond(50, 23, 45.282),
-            convertDegreeMinuteSecond(47, 41, 45.652),
-            convertDegreeMinuteSecond(44, 59, 45.938),
-            convertDegreeMinuteSecond(42, 46, 3.588)};
-
-    /**
-     * Lambert I, II, III, and IV false east
-     */
-    private static final double x_0s[] = { 600000.0, 600000.0, 600000.0, 234.358 };
-    
-    /**
-     * Lambert I, II, III, and IV false north
-     */
-    private static final double y_0s[] = { 200000.0, 200000.0, 200000.0, 185861.369 };
-    
-    /**
-     * France is divided in 4 Lambert projection zones (1,2,3 + 4th for Corsica)
-     */
-    public static final double cMaxLatZone1Radian = Math.toRadians(57 * 0.9);
-    public static final double cMinLatZone1Radian = Math.toRadians(46.1 * 0.9);// lowest latitude of Zone 4 (South Corsica)
-
-    public static final double[][] zoneLimitsDegree = {
-        {Math.toDegrees(cMaxLatZone1Radian), (53.5 * 0.9)}, // Zone 1  (reference values in grad *0.9)
-        {(53.5 * 0.9), (50.5 * 0.9)}, // Zone 2
-        {(50.5 * 0.9), (47.0 * 0.9)}, // Zone 3
-        {(47.51963 * 0.9), Math.toDegrees(cMinLatZone1Radian)} // Zone 4
-    };
-
-    public static final double cMinLonZonesRadian = Math.toRadians(-4.9074074074074059 * 0.9);
-
-    public static final double cMaxLonZonesRadian = Math.toRadians(10.2 * 0.9);
-
-    /**
-     *  Allow some extension beyond the theoretical limits
-     */
-    public static final double cMaxOverlappingZonesDegree = 1.5;
-
-    public static final int DEFAULT_ZONE = 0;
-
-    private int layoutZone;
-
-    public Lambert() {
-        this(DEFAULT_ZONE);
-    }
-
-    public Lambert(final int layoutZone) {
-        if (layoutZone < 0 || layoutZone >= 4)
-            throw new IllegalArgumentException();
-        this.layoutZone = layoutZone;
-        ellps = Ellipsoid.clarkeIGN;
-        datum = new NTV2Datum("ntf_rgf93Grid", null, ellps, NTV2GridShiftFileWrapper.ntf_rgf93);
-        x_0 = x_0s[layoutZone];
-        y_0 = y_0s[layoutZone];
-        lon_0 = 2.0 + 20.0 / 60 + 14.025 / 3600; // 0 grade Paris
-        if (proj == null) {
-            proj = new LambertConformalConic();
-        }
-        proj = new LambertConformalConic();
-        try {
-            proj.initialize(new ProjParameters() {{
-                ellps = Lambert.this.ellps;
-                lat_0 = lat_0s[layoutZone];
-                lat_1 = lat_1s[layoutZone];
-                lat_2 = lat_2s[layoutZone];
-            }});
-        } catch (ProjectionConfigurationException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    @Override
-    public String toString() {
-        return tr("Lambert 4 Zones (France)");
-    }
-
-    @Override
-    public Integer getEpsgCode() {
-        return 27561+layoutZone;
-    }
-
-    @Override
-    public int hashCode() {
-        return getClass().getName().hashCode()+layoutZone; // our only real variable
-    }
-
-    @Override
-    public String getCacheDirectoryName() {
-        return "lambert";
-    }
-
-    @Override
-    public Bounds getWorldBoundsLatLon()
-    {
-        Bounds b= new Bounds(
-                new LatLon(Math.max(zoneLimitsDegree[layoutZone][1] - cMaxOverlappingZonesDegree, Math.toDegrees(cMinLatZone1Radian)), Math.toDegrees(cMinLonZonesRadian)),
-                new LatLon(Math.min(zoneLimitsDegree[layoutZone][0] + cMaxOverlappingZonesDegree, Math.toDegrees(cMaxLatZone1Radian)), Math.toDegrees(cMaxLonZonesRadian)),
-                false);
-        return b;
-    }
-
-    public int getLayoutZone() {
-        return layoutZone;
-    }
-
-}
Index: unk/src/org/openstreetmap/josm/data/projection/Lambert93.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/Lambert93.java	(revision 5547)
+++ 	(revision )
@@ -1,59 +1,0 @@
-package org.openstreetmap.josm.data.projection;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.projection.datum.GRS80Datum;
-import org.openstreetmap.josm.data.projection.proj.LambertConformalConic;
-import org.openstreetmap.josm.data.projection.proj.ProjParameters;
-
-/**
- * Lambert 93 projection as specified by the IGN
- * in this document http://professionnels.ign.fr/DISPLAY/000/526/702/5267026/NTG_87.pdf
- * @author Don-vip
- *
- */
-public class Lambert93 extends AbstractProjection {
-
-    public Lambert93() {
-        ellps = Ellipsoid.GRS80;
-        datum = GRS80Datum.INSTANCE;
-        x_0 =  700000;
-        y_0 = 6600000;
-        lon_0 = 3;
-        proj = new LambertConformalConic();
-        try {
-            proj.initialize(new ProjParameters() {{
-                ellps = Lambert93.this.ellps;
-                lat_0 = 46.50;
-                lat_1 = 44.00;
-                lat_2 = 49.00;
-            }});
-        } catch (ProjectionConfigurationException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    @Override
-    public String getCacheDirectoryName() {
-        return "lambert93";
-    }
-
-    @Override
-    public Bounds getWorldBoundsLatLon() {
-        return new Bounds(
-                new LatLon(41.0, -5.5),
-                new LatLon(51.0, 10.2), false);
-    }
-
-    @Override
-    public Integer getEpsgCode() {
-        return 2154;
-    }
-
-    @Override
-    public String toString() {
-        return tr("Lambert 93 (France)");
-    }
-}
Index: unk/src/org/openstreetmap/josm/data/projection/LambertCC9Zones.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/LambertCC9Zones.java	(revision 5547)
+++ 	(revision )
@@ -1,100 +1,0 @@
-//License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.data.projection;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.projection.datum.GRS80Datum;
-import org.openstreetmap.josm.data.projection.proj.LambertConformalConic;
-import org.openstreetmap.josm.data.projection.proj.ProjParameters;
-
-/**
- * Lambert Conic Conform 9 Zones projection as specified by the IGN
- * in this document http://professionnels.ign.fr/DISPLAY/000/526/700/5267002/transformation.pdf
- * @author Pieren
- *
- */
-public class LambertCC9Zones extends AbstractProjection {
-
-    /**
-     * France is divided in 9 Lambert projection zones, CC42 to CC50.
-     */
-    public static final double cMaxLatZonesRadian = Math.toRadians(51.1);
-
-    public static final double cMinLatZonesDegree = 41.0;
-
-    public static final double cMaxOverlappingZones = 1.5;
-
-    public static final int DEFAULT_ZONE = 0;
-
-    private final int layoutZone;
-
-    public LambertCC9Zones() {
-        this(DEFAULT_ZONE);
-    }
-
-    public LambertCC9Zones(final int layoutZone) {
-        ellps = Ellipsoid.GRS80;
-        datum = GRS80Datum.INSTANCE;
-        this.layoutZone = layoutZone;
-        x_0 = 1700000;
-        y_0 = (layoutZone+1) * 1000000 + 200000;
-        lon_0 = 3;
-        if (proj == null) {
-            proj = new LambertConformalConic();
-        }
-        try {
-            proj.initialize(new ProjParameters() {{
-                ellps = LambertCC9Zones.this.ellps;
-                lat_0 = 42.0 + layoutZone;
-                lat_1 = 41.25 + layoutZone;
-                lat_2 = 42.75 + layoutZone;
-            }});
-        } catch (ProjectionConfigurationException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    @Override
-    public String toString() {
-        return tr("Lambert CC9 Zone (France)");
-    }
-
-    public static int north2ZoneNumber(double north) {
-        int nz = (int)(north /1000000) - 1;
-        if (nz < 0) return 0;
-        else if (nz > 8) return 8;
-        else return nz;
-    }
-
-    @Override
-    public Integer getEpsgCode() {
-        return 3942+layoutZone; //CC42 is EPSG:3942 (up to EPSG:3950 for CC50)
-    }
-
-    @Override
-    public int hashCode() {
-        return getClass().getName().hashCode()+layoutZone; // our only real variable
-    }
-
-    @Override
-    public String getCacheDirectoryName() {
-        return "lambert";
-    }
-
-    @Override
-    public Bounds getWorldBoundsLatLon()
-    {
-        double medLatZone = cMinLatZonesDegree + (layoutZone+1);
-        return new Bounds(
-                new LatLon(Math.max(medLatZone - 1.0 - cMaxOverlappingZones, cMinLatZonesDegree), -5.5),
-                new LatLon(Math.min(medLatZone + 1.0 + cMaxOverlappingZones, Math.toDegrees(cMaxLatZonesRadian)), 10.2),
-                false);
-    }
-
-    public int getLayoutZone() {
-        return layoutZone;
-    }
-
-}
Index: unk/src/org/openstreetmap/josm/data/projection/LambertEST.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/LambertEST.java	(revision 5547)
+++ 	(revision )
@@ -1,68 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.data.projection;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.projection.datum.GRS80Datum;
-import org.openstreetmap.josm.data.projection.proj.LambertConformalConic;
-import org.openstreetmap.josm.data.projection.proj.ProjParameters;
-
-/**
- * Estonian Coordinate System of 1997.
- *
- * Thanks to Johan Montagnat and its geoconv java converter application
- * (http://www.i3s.unice.fr/~johan/gps/ , published under GPL license)
- * from which some code and constants have been reused here.
- */
-public class LambertEST extends AbstractProjection {
-
-    public LambertEST() {
-        ellps = Ellipsoid.GRS80;
-        datum = GRS80Datum.INSTANCE;
-        lon_0 = 24;
-        x_0 = 500000;
-        y_0 = 6375000;
-        proj = new LambertConformalConic();
-        try {
-            proj.initialize(new ProjParameters() {{
-                ellps = LambertEST.this.ellps;
-                lat_0 = 57.517553930555555555555555555556;
-                lat_1 = 59.0 + 1.0/3.0;
-                lat_2 = 58.0;
-            }});
-        } catch (ProjectionConfigurationException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    @Override
-    public String toString() {
-        return tr("Lambert Zone (Estonia)");
-    }
-
-    @Override
-    public Integer getEpsgCode() {
-        return 3301;
-    }
-
-    @Override
-    public int hashCode() {
-        return getClass().getName().hashCode(); // we have no variables
-    }
-
-    @Override
-    public String getCacheDirectoryName() {
-        return "lambertest";
-    }
-
-    @Override
-    public Bounds getWorldBoundsLatLon()
-    {
-        return new Bounds(
-                new LatLon(56.05, 21.64),
-                new LatLon(61.13, 28.58), false);
-    }
-
-}
Index: unk/src/org/openstreetmap/josm/data/projection/Mercator.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/Mercator.java	(revision 5547)
+++ 	(revision )
@@ -1,65 +1,0 @@
-// License: GPL. Copyright 2007 by Immanuel Scholz and others
-package org.openstreetmap.josm.data.projection;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.projection.datum.WGS84Datum;
-import org.openstreetmap.josm.data.projection.proj.ProjParameters;
-
-/**
- * Mercator Projection
- *
- * The center of the mercator projection is always the 0 grad
- * coordinate.
- *
- * See also USGS Bulletin 1532
- * (http://egsc.usgs.gov/isb/pubs/factsheets/fs08799.html)
- *
- * @author imi
- */
-public class Mercator extends AbstractProjection {
-
-    public Mercator() {
-        ellps = Ellipsoid.WGS84;
-        datum = WGS84Datum.INSTANCE;
-        proj = new org.openstreetmap.josm.data.projection.proj.Mercator();
-        try {
-            proj.initialize(new ProjParameters());
-        } catch (ProjectionConfigurationException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    @Override
-    public String toString() {
-        return tr("Mercator");
-    }
-
-    @Override
-    public Integer getEpsgCode() {
-        /* initially they used 3785 but that has been superseded,
-         * see http://www.epsg-registry.org/ */
-        return 3857;
-    }
-
-    @Override
-    public int hashCode() {
-        return getClass().getName().hashCode(); // we have no variables
-    }
-
-    @Override
-    public String getCacheDirectoryName() {
-        return "mercator";
-    }
-
-    @Override
-    public Bounds getWorldBoundsLatLon()
-    {
-        return new Bounds(
-                new LatLon(-85.05112877980659, -180.0),
-                new LatLon(85.05112877980659, 180.0), false);
-    }
-
-}
Index: /trunk/src/org/openstreetmap/josm/data/projection/Projection.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/Projection.java	(revision 5547)
+++ /trunk/src/org/openstreetmap/josm/data/projection/Projection.java	(revision 5548)
@@ -1,3 +1,3 @@
-// License: GPL. Copyright 2007 by Immanuel Scholz and others
+// License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.data.projection;
 
@@ -7,51 +7,62 @@
 
 /**
- * Classes implementing this are able to convert lat/lon values to
- * planar screen coordinates.
+ * A projection, i.e.&nbsp;a class that supports conversion from lat/lon
+ * to east/north and back.
  *
- * @author imi
+ * The conversion from east/north to the screen coordinates is simply a scale
+ * factor and x/y offset.
  */
 public interface Projection {
     /**
-     * The default scale factor in east/north units per pixel ({@link #NavigatableComponent#scale}))
+     * The default scale factor in east/north units per pixel ({@link #NavigatableComponent#scale})).
      * FIXME: misnomer
+     * @return the scale factor
      */
     double getDefaultZoomInPPD();
 
     /**
-     * Convert from lat/lon to northing/easting.
+     * Convert from lat/lon to easting/northing.
      *
-     * @param p     The geo point to convert. x/y members of the point are filled.
+     * @param ll the geographical point to convert (in WGS84 lat/lon)
+     * @return the corresponding east/north coordinates
      */
-    EastNorth latlon2eastNorth(LatLon p);
+    EastNorth latlon2eastNorth(LatLon ll);
 
     /**
-     * Convert from norting/easting to lat/lon.
+     * Convert from easting/norting to lat/lon.
      *
-     * @param p     The geo point to convert. lat/lon members of the point are filled.
+     * @param en the geographical point to convert (in projected coordinates)
+     * @return the corresponding lat/lon (WGS84)
      */
-    LatLon eastNorth2latlon(EastNorth p);
+    LatLon eastNorth2latlon(EastNorth en);
 
     /**
-     * Describe the projection converter in one or two words.
+     * Describe the projection in one or two words.
+     * @return the name / description
      */
     String toString();
 
     /**
-     * Return projection code. This should be a unique identifier.
+     * Return projection code.
+     *
+     * This should be a unique identifier.
      * If projection supports parameters, return a different code
      * for each set of parameters.
      * 
      * The EPSG code can be used (if defined for the projection).
+     *
+     * @return the projection identifier
      */
     String toCode();
 
     /**
-     * Get a filename compatible string (for the cache directory)
+     * Get a filename compatible string (for the cache directory).
+     * @return the cache directory name (base name)
      */
     String getCacheDirectoryName();
 
     /**
-     * Get the bounds of the world
+     * Get the bounds of the world.
+     * @return the supported lat/lon rectangle for this projection
      */
     Bounds getWorldBoundsLatLon();
Index: /trunk/src/org/openstreetmap/josm/data/projection/Projections.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/Projections.java	(revision 5547)
+++ /trunk/src/org/openstreetmap/josm/data/projection/Projections.java	(revision 5548)
@@ -25,4 +25,5 @@
 import org.openstreetmap.josm.data.projection.proj.TransverseMercator;
 import org.openstreetmap.josm.io.MirroredInputStream;
+import org.openstreetmap.josm.tools.Pair;
 
 /**
@@ -47,9 +48,9 @@
      * should be compatible to PROJ.4
      */
-    public static Map<String, ProjFactory> projs = new HashMap<String, ProjFactory>();
-    public static Map<String, Ellipsoid> ellipsoids = new HashMap<String, Ellipsoid>();
-    public static Map<String, Datum> datums = new HashMap<String, Datum>();
-    public static Map<String, NTV2GridShiftFileWrapper> nadgrids = new HashMap<String, NTV2GridShiftFileWrapper>();
-    public static Map<String, String> inits = new HashMap<String, String>();
+    final public static Map<String, ProjFactory> projs = new HashMap<String, ProjFactory>();
+    final public static Map<String, Ellipsoid> ellipsoids = new HashMap<String, Ellipsoid>();
+    final public static Map<String, Datum> datums = new HashMap<String, Datum>();
+    final public static Map<String, NTV2GridShiftFileWrapper> nadgrids = new HashMap<String, NTV2GridShiftFileWrapper>();
+    final public static Map<String, Pair<String, String>> inits = new HashMap<String, Pair<String, String>>();
 
     static {
@@ -109,5 +110,5 @@
 
     public static String getInit(String id) {
-        return inits.get(id);
+        return inits.get(id.toLowerCase()).b;
     }
 
@@ -116,19 +117,22 @@
      */
     private static void loadInits() {
-        Pattern epsgPattern = Pattern.compile("\\A<(\\d+)>(.*)<>\\Z");
+        Pattern epsgPattern = Pattern.compile("<(\\d+)>(.*)<>");
         try {
             InputStream in = new MirroredInputStream("resource://data/epsg");
             BufferedReader r = new BufferedReader(new InputStreamReader(in));
-            String line;
+            String line, lastline = "";
             while ((line = r.readLine()) != null) {
                 line = line.trim();
                 if (!line.startsWith("#") && !line.isEmpty()) {
+                    if (!lastline.startsWith("#")) throw new AssertionError();
+                    String name = lastline.substring(1).trim();
                     Matcher m = epsgPattern.matcher(line);
                     if (m.matches()) {
-                        inits.put("epsg:" + m.group(1), m.group(2).trim());
+                        inits.put("epsg:" + m.group(1), Pair.create(name, m.group(2).trim()));
                     } else {
                         System.err.println("Warning: failed to parse line from the epsg projection definition: "+line);
                     }
                 }
+                lastline = line;
             }
         } catch (IOException ex) {
Index: unk/src/org/openstreetmap/josm/data/projection/Puwg.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/Puwg.java	(revision 5547)
+++ 	(revision )
@@ -1,209 +1,0 @@
-// License: GPL. Copyright 2007 by Immanuel Scholz and others
-//                         2009 by Łukasz Stelmach
-package org.openstreetmap.josm.data.projection;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.projection.datum.GRS80Datum;
-import org.openstreetmap.josm.data.projection.proj.ProjParameters;
-
-/**
- * PUWG 1992 and 2000 are the official cordinate systems in Poland.
- * They use the same math as UTM only with different constants.
- *
- * @author steelman
- */
-public class Puwg extends AbstractProjection {
-
-    public static final int DEFAULT_ZONE = 0;
-
-    private final int zone;
-
-    static public PuwgData[] zones = new PuwgData[] {
-        new Epsg2180(),
-        new Epsg2176(),
-        new Epsg2177(),
-        new Epsg2178(),
-        new Epsg2179()
-    };
-
-    public Puwg() {
-        this(DEFAULT_ZONE);
-    }
-
-    public Puwg(int zone) {
-        if (zone < 0 || zone >= zones.length)
-            throw new IllegalArgumentException();
-        ellps = Ellipsoid.GRS80;
-        proj = new org.openstreetmap.josm.data.projection.proj.TransverseMercator();
-        try {
-            proj.initialize(new ProjParameters() {{ ellps = Puwg.this.ellps; }});
-        } catch (ProjectionConfigurationException e) {
-            throw new RuntimeException(e);
-        }
-        datum = GRS80Datum.INSTANCE;
-        this.zone = zone;
-        PuwgData z = zones[zone];
-        x_0 = z.getPuwgFalseEasting();
-        y_0 = z.getPuwgFalseNorthing();
-        lon_0 = z.getPuwgCentralMeridianDeg();
-        k_0 = z.getPuwgScaleFactor();
-    }
-
-    @Override
-    public String toString() {
-        return tr("PUWG (Poland)");
-    }
-
-    @Override
-    public Integer getEpsgCode() {
-        return zones[zone].getEpsgCode();
-    }
-
-    @Override
-    public int hashCode() {
-        return getClass().getName().hashCode()+zone; // our only real variable
-    }
-
-    @Override
-    public String getCacheDirectoryName() {
-        return zones[zone].getCacheDirectoryName();
-    }
-
-    @Override
-    public Bounds getWorldBoundsLatLon() {
-        return zones[zone].getWorldBoundsLatLon();
-    }
-
-    public interface PuwgData {
-        double getPuwgCentralMeridianDeg();
-        double getPuwgCentralMeridian();
-        double getPuwgFalseEasting();
-        double getPuwgFalseNorthing();
-        double getPuwgScaleFactor();
-
-        // Projection methods
-        Integer getEpsgCode();
-        String toCode();
-        String getCacheDirectoryName();
-        Bounds getWorldBoundsLatLon();
-    }
-
-    public static class Epsg2180 implements PuwgData {
-
-        private static final double Epsg2180FalseEasting = 500000.0; /* y */
-        private static final double Epsg2180FalseNorthing = -5300000.0; /* x */
-        private static final double Epsg2180ScaleFactor = 0.9993;
-        private static final double Epsg2180CentralMeridian = 19.0;
-
-        @Override public String toString() {
-            return tr("PUWG 1992 (Poland)");
-        }
-
-        @Override
-        public Integer getEpsgCode() {
-            return 2180;
-        }
-
-        @Override
-        public String toCode() {
-            return "EPSG:" + getEpsgCode();
-        }
-
-        @Override
-        public String getCacheDirectoryName() {
-            return "epsg2180";
-        }
-
-        @Override
-        public Bounds getWorldBoundsLatLon()
-        {
-            return new Bounds(
-                    new LatLon(49.00, 14.12),
-                    new LatLon(54.84, 24.15), false);
-        }
-
-        @Override public double getPuwgCentralMeridianDeg() { return Epsg2180CentralMeridian; }
-        @Override public double getPuwgCentralMeridian() { return Math.toRadians(Epsg2180CentralMeridian); }
-        @Override public double getPuwgFalseEasting() { return Epsg2180FalseEasting; }
-        @Override public double getPuwgFalseNorthing() { return Epsg2180FalseNorthing; }
-        @Override public double getPuwgScaleFactor() { return Epsg2180ScaleFactor; }
-    }
-
-    abstract static class Puwg2000 implements PuwgData {
-
-        private static final double PuwgFalseEasting = 500000.0;
-        private static final double PuwgFalseNorthing = 0;
-        private static final double PuwgScaleFactor = 0.999923;
-        //final private double[] Puwg2000CentralMeridian = {15.0, 18.0, 21.0, 24.0};
-        final private Integer[] Puwg2000Code = { 2176,  2177, 2178, 2179 };
-        final private String[] Puwg2000CDName = { "epsg2176",  "epsg2177", "epsg2178", "epsg2179" };
-
-        @Override public String toString() {
-            return tr("PUWG 2000 Zone {0} (Poland)", Integer.toString(getZone()));
-        }
-
-        @Override
-        public Integer getEpsgCode() {
-            return Puwg2000Code[getZoneIndex()];
-        }
-
-        @Override
-        public String toCode() {
-            return "EPSG:" + getEpsgCode();
-        }
-
-        @Override
-        public String getCacheDirectoryName() {
-            return Puwg2000CDName[getZoneIndex()];
-        }
-
-        @Override
-        public Bounds getWorldBoundsLatLon()
-        {
-            return new Bounds(
-                    new LatLon(49.00, (3 * getZone()) - 1.5),
-                    new LatLon(54.84, (3 * getZone()) + 1.5), false);
-        }
-
-        @Override public double getPuwgCentralMeridianDeg() { return getZone() * 3.0; }
-        @Override public double getPuwgCentralMeridian() { return Math.toRadians(getZone() * 3.0); }
-        @Override public double getPuwgFalseNorthing() { return PuwgFalseNorthing;}
-        @Override public double getPuwgFalseEasting() { return 1e6 * getZone() + PuwgFalseEasting; }
-        @Override public double getPuwgScaleFactor() { return PuwgScaleFactor; }
-        public abstract int getZone();
-
-        public int getZoneIndex() { return getZone() - 5; }
-
-    }
-
-    public static class Epsg2176 extends Puwg2000 {
-        private static final int PuwgZone = 5;
-
-        @Override
-        public int getZone() { return PuwgZone; }
-    }
-
-    public static class Epsg2177 extends Puwg2000 {
-        private static final int PuwgZone = 6;
-
-        @Override
-        public int getZone() { return PuwgZone; }
-    }
-
-    public static class Epsg2178 extends Puwg2000 {
-        private static final int PuwgZone = 7;
-
-        @Override
-        public int getZone() { return PuwgZone; }
-    }
-
-    public static class Epsg2179 extends Puwg2000 {
-        private static final int PuwgZone = 8;
-
-        @Override
-        public int getZone() { return PuwgZone; }
-    }
-}
Index: unk/src/org/openstreetmap/josm/data/projection/SwissGrid.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/SwissGrid.java	(revision 5547)
+++ 	(revision )
@@ -1,68 +1,0 @@
-//License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.data.projection;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.projection.datum.ThreeParameterDatum;
-import org.openstreetmap.josm.data.projection.proj.ProjParameters;
-import org.openstreetmap.josm.data.projection.proj.SwissObliqueMercator;
-
-/**
- * SwissGrid CH1903 / L03, see http://de.wikipedia.org/wiki/Swiss_Grid.
- *
- * Actually, what we have here, is CH1903+ (EPSG:2056), but without
- * the additional false easting of 2000km and false northing 1000 km.
- *
- * To get to CH1903, a shift file is required. So currently, there are errors
- * up to 1.6m (depending on the location).
- *
- * This projection does not have any parameters, it only implements
- * ProjectionSubPrefs to show a warning that the grid file correction is not done.
- */
-public class SwissGrid extends AbstractProjection {
-
-    public SwissGrid() {
-        ellps = Ellipsoid.Bessel1841;
-        datum = new ThreeParameterDatum("SwissGrid Datum", null, ellps, 674.374, 15.056, 405.346);
-        x_0 = 600000;
-        y_0 = 200000;
-        lon_0 = 7.0 + 26.0/60 + 22.50/3600;
-        proj = new SwissObliqueMercator();
-        try {
-            proj.initialize(new ProjParameters() {{
-                ellps = SwissGrid.this.ellps;
-                lat_0 = 46.0 + 57.0/60 + 8.66/3600;
-            }});
-        } catch (ProjectionConfigurationException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    @Override
-    public String toString() {
-        return tr("Swiss Grid (Switzerland)");
-    }
-
-    @Override
-    public Integer getEpsgCode() {
-        return 21781;
-    }
-
-    @Override
-    public int hashCode() {
-        return getClass().getName().hashCode(); // we have no variables
-    }
-
-    @Override
-    public String getCacheDirectoryName() {
-        return "swissgrid";
-    }
-
-    @Override
-    public Bounds getWorldBoundsLatLon() {
-        return new Bounds(new LatLon(45.7, 5.7), new LatLon(47.9, 10.6), false);
-    }
-
-}
Index: unk/src/org/openstreetmap/josm/data/projection/TransverseMercatorLV.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/TransverseMercatorLV.java	(revision 5547)
+++ 	(revision )
@@ -1,60 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.data.projection;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.projection.datum.GRS80Datum;
-import org.openstreetmap.josm.data.projection.proj.ProjParameters;
-
-/**
- * LKS-92/ Latvia TM projection. Based on data from spatialreference.org.
- * http://spatialreference.org/ref/epsg/3059/
- *
- * @author Viesturs Zarins
- */
-public class TransverseMercatorLV extends AbstractProjection {
-
-    public TransverseMercatorLV() {
-        ellps = Ellipsoid.GRS80;
-        proj = new org.openstreetmap.josm.data.projection.proj.TransverseMercator();
-        try {
-            proj.initialize(new ProjParameters() {{ ellps = TransverseMercatorLV.this.ellps; }});
-        } catch (ProjectionConfigurationException e) {
-            throw new RuntimeException(e);
-        }
-        datum = GRS80Datum.INSTANCE;
-        lon_0 = 24;
-        x_0 = 500000;
-        y_0 = -6000000;
-        k_0 = 0.9996;
-    }
-
-    @Override
-    public String toString() {
-        return tr("LKS-92 (Latvia TM)");
-    }
-
-    @Override
-    public Integer getEpsgCode() {
-        return 3059;
-    }
-
-    @Override
-    public int hashCode() {
-        return toCode().hashCode();
-    }
-
-    @Override
-    public String getCacheDirectoryName() {
-        return "epsg"+ getEpsgCode();
-    }
-
-    @Override
-    public Bounds getWorldBoundsLatLon() {
-        return new Bounds(
-                new LatLon(-90.0, -180.0),
-                new LatLon(90.0, 180.0), false);
-    }
-}
Index: unk/src/org/openstreetmap/josm/data/projection/UTM.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/UTM.java	(revision 5547)
+++ 	(revision )
@@ -1,105 +1,0 @@
-// License: GPL. Copyright 2007 by Immanuel Scholz and others
-package org.openstreetmap.josm.data.projection;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.projection.datum.WGS84Datum;
-import org.openstreetmap.josm.data.projection.proj.ProjParameters;
-
-/**
- *
- * @author Dirk Stöcker
- * code based on JavaScript from Chuck Taylor
- *
- */
-public class UTM extends AbstractProjection {
-
-    private static final int DEFAULT_ZONE = 30;
-    private int zone;
-
-    public enum Hemisphere { North, South }
-    private static final Hemisphere DEFAULT_HEMISPHERE = Hemisphere.North;
-    private Hemisphere hemisphere;
-
-    public UTM() {
-        this(DEFAULT_ZONE, DEFAULT_HEMISPHERE);
-    }
-
-    public UTM(int zone, Hemisphere hemisphere) {
-        if (zone < 1 || zone > 60)
-            throw new IllegalArgumentException();
-        ellps = Ellipsoid.WGS84;
-        proj = new org.openstreetmap.josm.data.projection.proj.TransverseMercator();
-        try {
-            proj.initialize(new ProjParameters() {{ ellps = UTM.this.ellps; }});
-        } catch (ProjectionConfigurationException e) {
-            throw new RuntimeException(e);
-        }
-        datum = WGS84Datum.INSTANCE;
-        this.zone = zone;
-        this.hemisphere = hemisphere;
-        x_0 = 500000;
-        y_0 = hemisphere == Hemisphere.North ? 0 : 10000000;
-        lon_0 = getUtmCentralMeridianDeg(zone);
-        k_0 = 0.9996;
-    }
-
-    /*
-     * UTMCentralMeridian
-     *
-     * Determines the central meridian for the given UTM zone.
-     *
-     * Inputs:
-     *     zone - An integer value designating the UTM zone, range [1,60].
-     *
-     * Returns:
-     *   The central meridian for the given UTM zone, in radians, or zero
-     *   if the UTM zone parameter is outside the range [1,60].
-     *   Range of the central meridian is the radian equivalent of [-177,+177].
-     *
-     */
-    private double getUtmCentralMeridianDeg(int zone)
-    {
-        return -183.0 + (zone * 6.0);
-    }
-
-    public int getzone() {
-        return zone;
-    }
-
-    @Override
-    public String toString() {
-        return tr("UTM");
-    }
-
-    @Override
-    public Integer getEpsgCode() {
-        return (32600 + getzone() + (hemisphere == Hemisphere.South?100:0));
-    }
-
-    @Override
-    public int hashCode() {
-        return toCode().hashCode();
-    }
-
-    @Override
-    public String getCacheDirectoryName() {
-        return "epsg"+ getEpsgCode();
-    }
-
-    @Override
-    public Bounds getWorldBoundsLatLon()
-    {
-        if (hemisphere == Hemisphere.North)
-            return new Bounds(
-                    new LatLon(-5.0, getUtmCentralMeridianDeg(getzone())-5.0),
-                    new LatLon(85.0, getUtmCentralMeridianDeg(getzone())+5.0), false);
-        else
-            return new Bounds(
-                    new LatLon(-85.0, getUtmCentralMeridianDeg(getzone())-5.0),
-                    new LatLon(5.0, getUtmCentralMeridianDeg(getzone())+5.0), false);
-    }
-
-}
Index: unk/src/org/openstreetmap/josm/data/projection/UTM_France_DOM.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/UTM_France_DOM.java	(revision 5547)
+++ 	(revision )
@@ -1,111 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.data.projection;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.projection.datum.Datum;
-import org.openstreetmap.josm.data.projection.datum.GRS80Datum;
-import org.openstreetmap.josm.data.projection.datum.SevenParameterDatum;
-import org.openstreetmap.josm.data.projection.datum.ThreeParameterDatum;
-import org.openstreetmap.josm.data.projection.proj.ProjParameters;
-
-/**
- * This class implements all projections for French departements in the Caribbean Sea and
- * Indian Ocean using the UTM transvers Mercator projection and specific geodesic settings.
- *
- */
-public class UTM_France_DOM extends AbstractProjection {
-
-    private final static Bounds FortMarigotBounds = new Bounds( new LatLon(17.6,-63.25), new LatLon(18.5,-62.5), false);
-    private final static Bounds SainteAnneBounds = new Bounds( new LatLon(15.8,-61.9), new LatLon(16.6,-60.9), false);
-    private final static Bounds MartiniqueBounds = new Bounds( new LatLon(14.25,-61.25), new LatLon(15.025,-60.725), false);
-    private final static Bounds ReunionBounds = new Bounds( new LatLon(-25.92,37.58), new LatLon(-10.6, 58.27), false);
-    private final static Bounds GuyaneBounds = new Bounds( new LatLon(2.16 , -54.0), new LatLon(9.06 , -49.62), false);
-    private final static Bounds[] utmBounds = { FortMarigotBounds, SainteAnneBounds, MartiniqueBounds, ReunionBounds, GuyaneBounds };
-
-    private final static Integer FortMarigotEPSG = 2969;
-    private final static Integer SainteAnneEPSG = 2970;
-    private final static Integer MartiniqueEPSG = 2973;
-    private final static Integer ReunionEPSG = 2975;
-    private final static Integer GuyaneEPSG = 2972;
-    public final static Integer[] utmEPSGs = { FortMarigotEPSG, SainteAnneEPSG, MartiniqueEPSG, ReunionEPSG, GuyaneEPSG };
-
-    private final static Datum FortMarigotDatum = new ThreeParameterDatum("FortMarigot Datum", null, Ellipsoid.hayford, 136.596, 248.148, -429.789);
-    private final static Datum SainteAnneDatum = new SevenParameterDatum("SainteAnne Datum", null, Ellipsoid.hayford, -472.29, -5.63, -304.12, 0.4362, -0.8374, 0.2563, 1.8984);
-    private final static Datum MartiniqueDatum = new SevenParameterDatum("Martinique Datum", null, Ellipsoid.hayford, 126.926, 547.939, 130.409, -2.78670, 5.16124, -0.85844, 13.82265);
-    private final static Datum ReunionDatum = GRS80Datum.INSTANCE;
-    private final static Datum GuyaneDatum = GRS80Datum.INSTANCE;
-    private final static Datum[] utmDatums = { FortMarigotDatum, SainteAnneDatum, MartiniqueDatum, ReunionDatum, GuyaneDatum };
-
-    private final static int[] utmZones = { 20, 20, 20, 40, 22 };
-
-    /**
-     * UTM zone (from 1 to 60)
-     */
-    private static int zone;
-    /**
-     * whether north or south hemisphere
-     */
-    private boolean isNorth;
-
-    public static final int DEFAULT_GEODESIC = 0;
-
-    public int currentGeodesic;
-
-
-    public UTM_France_DOM() {
-        this(DEFAULT_GEODESIC);
-    }
-
-    public UTM_France_DOM(int currentGeodesic) {
-        if (currentGeodesic < 0 || currentGeodesic >= 5)
-            throw new IllegalArgumentException();
-        this.currentGeodesic = currentGeodesic;
-        datum = utmDatums[currentGeodesic];
-        ellps = datum.getEllipsoid();
-        proj = new org.openstreetmap.josm.data.projection.proj.TransverseMercator();
-        try {
-            proj.initialize(new ProjParameters() {{ ellps = UTM_France_DOM.this.ellps; }});
-        } catch (ProjectionConfigurationException e) {
-            throw new RuntimeException(e);
-        }
-        isNorth = currentGeodesic != 3;
-        zone = utmZones[currentGeodesic];
-        x_0 = 500000;
-        y_0 = isNorth ? 0.0 : 10000000.0;
-        lon_0 = 6 * zone - 183;
-        k_0 = 0.9996;
-    }
-
-    public int getCurrentGeodesic() {
-        return currentGeodesic;
-    }
-
-    @Override
-    public String toString() {
-        return tr("UTM France (DOM)");
-    }
-
-    @Override
-    public String getCacheDirectoryName() {
-        return this.toString();
-    }
-
-    @Override
-    public Bounds getWorldBoundsLatLon() {
-        return utmBounds[currentGeodesic];
-    }
-
-    @Override
-    public Integer getEpsgCode() {
-        return utmEPSGs[currentGeodesic];
-    }
-
-    @Override
-    public int hashCode() {
-        return getClass().getName().hashCode()+currentGeodesic; // our only real variable
-    }
-
-}
Index: /trunk/src/org/openstreetmap/josm/data/validation/OsmValidator.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/validation/OsmValidator.java	(revision 5547)
+++ /trunk/src/org/openstreetmap/josm/data/validation/OsmValidator.java	(revision 5548)
@@ -12,4 +12,5 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
@@ -23,7 +24,4 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.ValidateAction;
-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.data.validation.tests.BuildingInBuilding;
 import org.openstreetmap.josm.data.validation.tests.Coastlines;
@@ -57,4 +55,5 @@
 import org.openstreetmap.josm.gui.layer.ValidatorLayer;
 import org.openstreetmap.josm.gui.preferences.ValidatorPreference;
+import org.openstreetmap.josm.gui.preferences.projection.ProjectionPreference;
 
 /**
@@ -253,9 +252,10 @@
      */
     public void initializeGridDetail() {
-        if (Main.getProjection().toString().equals(new Epsg4326().toString())) {
+        String code = Main.getProjection().toCode();
+        if (Arrays.asList(ProjectionPreference.wgs84.allCodes()).contains(code)) {
             OsmValidator.griddetail = 10000;
-        } else if (Main.getProjection().toString().equals(new Mercator().toString())) {
+        } else if (Arrays.asList(ProjectionPreference.mercator.allCodes()).contains(code)) {
             OsmValidator.griddetail = 0.01;
-        } else if (Main.getProjection().toString().equals(new Lambert().toString())) {
+        } else if (Arrays.asList(ProjectionPreference.lambert.allCodes()).contains(code)) {
             OsmValidator.griddetail = 0.1;
         } else {
Index: /trunk/src/org/openstreetmap/josm/gui/preferences/projection/AbstractProjectionChoice.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/projection/AbstractProjectionChoice.java	(revision 5547)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/projection/AbstractProjectionChoice.java	(revision 5548)
@@ -2,17 +2,48 @@
 package org.openstreetmap.josm.gui.preferences.projection;
 
+import org.openstreetmap.josm.data.projection.CustomProjection;
+import org.openstreetmap.josm.data.projection.Projection;
+import org.openstreetmap.josm.data.projection.Projections;
+
 abstract public class AbstractProjectionChoice implements ProjectionChoice {
-    private String id;
-    private String name;
+    
+    protected String name;
+    protected String id;
+    protected String cacheDir;
 
-    public AbstractProjectionChoice(String id, String name) {
+    /**
+     * Constructor.
+     *
+     * @param name short name of the projection choice as shown in the GUI
+     * @param id unique identifier for the projection choice
+     * @param cacheDir a cache directory name
+     */
+    public AbstractProjectionChoice(String name, String id, String cacheDir) {
+        this.name = name;
         this.id = id;
-        this.name = name;
+        this.cacheDir = cacheDir;
     }
+
+    /**
+     * Constructor (without cacheDir argument).
+     *
+     * Only for core projection choices, where chacheDir is the same as
+     * the second part of the id.
+     */
+    public AbstractProjectionChoice(String name, String id) {
+        this(name, id, null);
+        if (!id.startsWith("core:")) throw new IllegalArgumentException();
+        this.cacheDir = id.substring(5);
+    }
+
     @Override
     public String getId() {
         return id;
     }
-    
+
+    public String getCacheDir() {
+        return cacheDir;
+    }
+
     @Override
     public String toString() {
@@ -20,3 +51,16 @@
     }
 
+    abstract public String getCurrentCode();
+    
+    abstract public String getProjectionName();
+
+    @Override
+    public Projection getProjection() {
+        String code = getCurrentCode();
+        String pref = Projections.getInit(code);
+        if (pref == null)
+            throw new AssertionError("Error: Unkown projection code");
+        return new CustomProjection(getProjectionName(), code, pref, getCacheDir());
+    }
+
 }
Index: /trunk/src/org/openstreetmap/josm/gui/preferences/projection/CustomProjectionChoice.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/projection/CustomProjectionChoice.java	(revision 5547)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/projection/CustomProjectionChoice.java	(revision 5548)
@@ -43,5 +43,5 @@
 
     public CustomProjectionChoice() {
-        super("core:custom", tr("Custom Projection"));
+        super(tr("Custom Projection"), "core:custom");
     }
 
@@ -207,4 +207,16 @@
 
     @Override
+    public String getCurrentCode() {
+        // not needed - getProjection() is overridden
+        throw new UnsupportedOperationException(); 
+    }
+
+    @Override
+    public String getProjectionName() {
+        // not needed - getProjection() is overridden
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public JPanel getPreferencePanel(ActionListener listener) {
         return new PreferencePanel(pref, listener);
Index: /trunk/src/org/openstreetmap/josm/gui/preferences/projection/GaussKruegerProjectionChoice.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/projection/GaussKruegerProjectionChoice.java	(revision 5547)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/projection/GaussKruegerProjectionChoice.java	(revision 5548)
@@ -7,7 +7,4 @@
 import java.util.Collections;
 
-import org.openstreetmap.josm.data.projection.GaussKrueger;
-import org.openstreetmap.josm.data.projection.Projection;
-
 public class GaussKruegerProjectionChoice extends ListProjectionChoice {
 
@@ -15,10 +12,10 @@
 
     public GaussKruegerProjectionChoice() {
-        super("core:gauss-krueger", tr("Gau\u00DF-Kr\u00FCger"), zones, tr("GK Zone"));
+        super(tr("Gau\u00DF-Kr\u00FCger"), "core:gauss-krueger", zones, tr("GK Zone"));
     }
 
     @Override
-    public Projection getProjection() {
-        return new GaussKrueger(index + 2);
+    public String getCurrentCode() {
+        return "EPSG:"+Integer.toString(31466 + index);
     }
 
@@ -57,3 +54,8 @@
     }
     
+    @Override
+    public String getProjectionName() {
+        return tr("Gau\u00DF-Kr\u00FCger Zone {0}", index + 2);
+    }
+
 }
Index: /trunk/src/org/openstreetmap/josm/gui/preferences/projection/LambertCC9ZonesProjectionChoice.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/projection/LambertCC9ZonesProjectionChoice.java	(revision 5547)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/projection/LambertCC9ZonesProjectionChoice.java	(revision 5548)
@@ -11,6 +11,4 @@
 import javax.swing.JPanel;
 
-import org.openstreetmap.josm.data.projection.LambertCC9Zones;
-import org.openstreetmap.josm.data.projection.Projection;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -31,5 +29,5 @@
 
     public LambertCC9ZonesProjectionChoice() {
-        super("core:lambertcc9", tr("Lambert CC9 Zone (France)"), lambert9zones, tr("Lambert CC Zone"));
+        super(tr("Lambert CC9 Zone (France)"), "core:lambertcc9", lambert9zones, tr("Lambert CC Zone"));
     }
 
@@ -48,6 +46,11 @@
 
     @Override
-    public Projection getProjection() {
-        return new LambertCC9Zones(index);
+    public String getCurrentCode() {
+        return "EPSG:" + Integer.toString(3942+index); //CC42 is EPSG:3942 (up to EPSG:3950 for CC50)
+    }
+
+    @Override
+    public String getProjectionName() {
+        return tr("Lambert CC9 Zone (France)");
     }
 
Index: /trunk/src/org/openstreetmap/josm/gui/preferences/projection/LambertProjectionChoice.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/projection/LambertProjectionChoice.java	(revision 5547)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/projection/LambertProjectionChoice.java	(revision 5548)
@@ -11,6 +11,4 @@
 import javax.swing.JPanel;
 
-import org.openstreetmap.josm.data.projection.Lambert;
-import org.openstreetmap.josm.data.projection.Projection;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -26,5 +24,5 @@
 
     public LambertProjectionChoice() {
-        super("core:lambert", tr("Lambert 4 Zones (France)"), lambert4zones, tr("Lambert CC Zone"));
+        super(tr("Lambert 4 Zones (France)"), "core:lambert", lambert4zones, tr("Lambert CC Zone"));
     }
 
@@ -43,6 +41,11 @@
 
     @Override
-    public Projection getProjection() {
-        return new Lambert(index);
+    public String getCurrentCode() {
+        return "EPSG:" + Integer.toString(27561+index);
+    }
+
+    @Override
+    public String getProjectionName() {
+        return tr("Lambert 4 Zones (France)");
     }
 
Index: /trunk/src/org/openstreetmap/josm/gui/preferences/projection/ListProjectionChoice.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/projection/ListProjectionChoice.java	(revision 5547)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/projection/ListProjectionChoice.java	(revision 5548)
@@ -18,27 +18,27 @@
 abstract public class ListProjectionChoice extends AbstractProjectionChoice {
 
-    protected int index;
+    protected int index;        // 0-based index
     protected int defaultIndex;
     protected Object[] entries;
     protected String label;
 
-    public ListProjectionChoice(String id, String name, Object[] entries, String label) {
-        this(id, name, entries, label, 0);
-    }
-
     /**
      * Constructor
      *
+     * @param name the display name
      * @param id the unique id for this ProjectionChoice
-     * @param name the display name
      * @param entries the list of display entries for the combo-box
      * @param label a label shown left to the combo-box
      * @param defaultIndex the default index for the combo-box
      */
-    public ListProjectionChoice(String id, String name, Object[] entries, String label, int defaultIndex) {
-        super(id, name);
+    public ListProjectionChoice(String name, String id, Object[] entries, String label, int defaultIndex) {
+        super(name, id);
         this.entries = entries;
         this.label = label;
         this.defaultIndex = defaultIndex;
+    }
+
+    public ListProjectionChoice(String name, String id, Object[] entries, String label) {
+        this(name, id, entries, label, 0);
     }
 
Index: /trunk/src/org/openstreetmap/josm/gui/preferences/projection/ProjectionChoice.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/projection/ProjectionChoice.java	(revision 5547)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/projection/ProjectionChoice.java	(revision 5548)
@@ -18,4 +18,8 @@
     /**
      * Get a unique id for the projection choice.
+     *
+     * Will be used to save the user selection to the preference file.
+     * 
+     * @return the string identifier
      */
     String getId();
@@ -27,5 +31,6 @@
      * listener from getPreferencePanel is invoked.
      *
-     * Argument may be null to reset everything.
+     * @param args preferences as a list of strings; may be null
+     * to reset everything.
      */
     void setPreferences(Collection<String> args);
@@ -56,5 +61,5 @@
 
     /**
-     * Return all projection codes supported by this projection class.
+     * Return all projection codes supported by this projection choice.
      */
     String[] allCodes();
@@ -69,3 +74,10 @@
     Collection<String> getPreferencesFromCode(String code);
 
+    /**
+     * Short name of the projection choice as shown in the GUI (combo box).
+     * 
+     * @return the name
+     */
+    String toString();
+
 }
Index: /trunk/src/org/openstreetmap/josm/gui/preferences/projection/ProjectionPreference.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/projection/ProjectionPreference.java	(revision 5547)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/projection/ProjectionPreference.java	(revision 5548)
@@ -27,13 +27,6 @@
 import org.openstreetmap.josm.data.preferences.CollectionProperty;
 import org.openstreetmap.josm.data.preferences.StringProperty;
-import org.openstreetmap.josm.data.projection.BelgianLambert1972;
-import org.openstreetmap.josm.data.projection.BelgianLambert2008;
-import org.openstreetmap.josm.data.projection.Epsg3008;
-import org.openstreetmap.josm.data.projection.Epsg4326;
-import org.openstreetmap.josm.data.projection.Lambert93;
-import org.openstreetmap.josm.data.projection.LambertEST;
-import org.openstreetmap.josm.data.projection.Mercator;
+import org.openstreetmap.josm.data.projection.CustomProjection;
 import org.openstreetmap.josm.data.projection.Projection;
-import org.openstreetmap.josm.data.projection.TransverseMercatorLV;
 import org.openstreetmap.josm.gui.NavigatableComponent;
 import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
@@ -45,4 +38,20 @@
 import org.openstreetmap.josm.tools.GBC;
 
+/**
+ * Projection preferences.
+ *
+ * How to add new Projections:
+ *  - Find EPSG code for the projection.
+ *  - Look up the parameter string for Proj4, e.g. on http://spatialreference.org/
+ *      and add it to the file 'data/epsg' in JOSM trunk
+ *  - Search for official references and verify the parameter values. These
+ *      documents are often available in the local language only.
+ *  - Use {@link #registerProjectionChoice()}, to make the entry known to JOSM.
+ *
+ * In case there is no EPSG code:
+ *  - override {@link AbstractProjectionChoice#getProjection()} and provide
+ *    a manual implementation of the projection. Use {@link CustomProjection}
+ *    if possible.
+ */
 public class ProjectionPreference implements SubPreferenceSetting {
 
@@ -56,23 +65,145 @@
     private static Map<String, ProjectionChoice> projectionChoicesById = new HashMap<String, ProjectionChoice>();
 
-    public static ProjectionChoice mercator = new SingleProjectionChoice("core:mercator", new Mercator());
+    public static final ProjectionChoice wgs84;
+    public static final ProjectionChoice mercator;
+    public static final ProjectionChoice lambert;
     static {
-        // global projections
-        registerProjectionChoice("core:wgs84", new Epsg4326());
-        registerProjectionChoice(mercator);
+
+        /************************
+         * Global projections.
+         */
+
+        /**
+         * WGS84: Directly use latitude / longitude values as x/y.
+         */
+        wgs84 = registerProjectionChoice(tr("WGS84 Geographic"), "core:wgs84", 4326, "epsg4326");
+
+        /**
+         * Mercator Projection.
+         *
+         * The center of the mercator projection is always the 0 grad
+         * coordinate.
+         *
+         * See also USGS Bulletin 1532
+         * (http://egsc.usgs.gov/isb/pubs/factsheets/fs08799.html)
+         * initially EPSG used 3785 but that has been superseded by 3857,
+         * see http://www.epsg-registry.org/
+         */
+        mercator = registerProjectionChoice(tr("Mercator"), "core:mercator", 
+                3857);
+        
+        /**
+         * UTM.
+         */
         registerProjectionChoice(new UTMProjectionChoice());
-        // regional - alphabetical order by country code
-        registerProjectionChoice("core:belambert1972", new BelgianLambert1972());   // BE
-        registerProjectionChoice("core:belambert2008", new BelgianLambert2008());   // BE
-        registerProjectionChoice(new SwissGridProjectionChoice());                  // CH
-        registerProjectionChoice(new GaussKruegerProjectionChoice());               // DE
-        registerProjectionChoice("core:lambertest", new LambertEST());              // EE
-        registerProjectionChoice(new LambertProjectionChoice());                    // FR
-        registerProjectionChoice("core:lambert93", new Lambert93());                // FR
-        registerProjectionChoice(new LambertCC9ZonesProjectionChoice());            // FR
-        registerProjectionChoice(new UTM_France_DOM_ProjectionChoice());            // FR
-        registerProjectionChoice("core:tmerclv", new TransverseMercatorLV());       // LV
-        registerProjectionChoice(new PuwgProjectionChoice());                       // PL
-        registerProjectionChoice("core:sweref99", new Epsg3008());                  // SE
+
+        /************************
+         * Regional - alphabetical order by country code.
+         */
+
+        /**
+         * Belgian Lambert 72 projection.
+         *
+         * As specified by the Belgian IGN in this document:
+         * http://www.ngi.be/Common/Lambert2008/Transformation_Geographic_Lambert_FR.pdf
+         *
+         * @author Don-vip
+         */
+        registerProjectionChoice(tr("Belgian Lambert 1972"), "core:belgianLambert1972", 31370);     // BE
+        /**
+         * Belgian Lambert 2008 projection.
+         *
+         * As specified by the Belgian IGN in this document:
+         * http://www.ngi.be/Common/Lambert2008/Transformation_Geographic_Lambert_FR.pdf
+         *
+         * @author Don-vip
+         */
+        registerProjectionChoice(tr("Belgian Lambert 2008"), "core:belgianLambert2008", 3812);      // BE
+
+        /**
+         * SwissGrid CH1903 / L03, see http://de.wikipedia.org/wiki/Swiss_Grid.
+         *
+         * Actually, what we have here, is CH1903+ (EPSG:2056), but without
+         * the additional false easting of 2000km and false northing 1000 km.
+         *
+         * To get to CH1903, a shift file is required. So currently, there are errors
+         * up to 1.6m (depending on the location).
+         */
+        registerProjectionChoice(new SwissGridProjectionChoice());                                  // CH
+
+        registerProjectionChoice(new GaussKruegerProjectionChoice());                               // DE
+
+        /**
+         * Estonian Coordinate System of 1997.
+         *
+         * Thanks to Johan Montagnat and its geoconv java converter application
+         * (http://www.i3s.unice.fr/~johan/gps/ , published under GPL license)
+         * from which some code and constants have been reused here.
+         */
+        registerProjectionChoice(tr("Lambert Zone (Estonia)"), "core:lambertest", 3301);            // EE
+
+        /**
+         * Lambert conic conform 4 zones using the French geodetic system NTF.
+         *
+         * This newer version uses the grid translation NTF<->RGF93 provided by IGN for a submillimetric accuracy.
+         * (RGF93 is the French geodetic system similar to WGS84 but not mathematically equal)
+         *
+         * Source: http://professionnels.ign.fr/DISPLAY/000/526/700/5267002/transformation.pdf
+         * @author Pieren
+         */
+        registerProjectionChoice(lambert = new LambertProjectionChoice());                          // FR
+        /**
+         * Lambert 93 projection.
+         * 
+         * As specified by the IGN in this document
+         * http://professionnels.ign.fr/DISPLAY/000/526/702/5267026/NTG_87.pdf
+         * @author Don-vip
+         */
+        registerProjectionChoice(tr("Lambert 93 (France)"), "core:lambert93", 2154);                // FR
+        /**
+         * Lambert Conic Conform 9 Zones projection.
+         *
+         * As specified by the IGN in this document
+         * http://professionnels.ign.fr/DISPLAY/000/526/700/5267002/transformation.pdf
+         * @author Pieren
+         */
+        registerProjectionChoice(new LambertCC9ZonesProjectionChoice());                            // FR
+        /**
+         * French departements in the Caribbean Sea and Indian Ocean.
+         *
+         * Using the UTM transvers Mercator projection and specific geodesic settings.
+         */
+        registerProjectionChoice(new UTM_France_DOM_ProjectionChoice());                            // FR
+
+        /**
+         * LKS-92/ Latvia TM projection.
+         *
+         * Based on data from spatialreference.org.
+         * http://spatialreference.org/ref/epsg/3059/
+         *
+         * @author Viesturs Zarins
+         */
+        registerProjectionChoice(tr("LKS-92 (Latvia TM)"), "core:tmerclv", 3059);                   // LV
+
+        /**
+         * PUWG 1992 and 2000 are the official cordinate systems in Poland.
+         *
+         * They use the same math as UTM only with different constants.
+         *
+         * @author steelman
+         */
+        registerProjectionChoice(new PuwgProjectionChoice());                                       // PL
+
+        /**
+         * SWEREF99 13 30 projection. Based on data from spatialreference.org.
+         * http://spatialreference.org/ref/epsg/3008/
+         *
+         * @author Hanno Hecker
+         */
+        registerProjectionChoice(tr("SWEREF99 13 30 / EPSG:3008 (Sweden)"), "core:sweref99", 3008); // SE
+
+        /************************
+         * Custom projection.
+         */
         registerProjectionChoice(new CustomProjectionChoice());
     }
@@ -83,6 +214,14 @@
     }
 
-    public static void registerProjectionChoice(String id, Projection projection) {
-        registerProjectionChoice(new SingleProjectionChoice(id, projection));
+    public static ProjectionChoice registerProjectionChoice(String name, String id, Integer epsg, String cacheDir) {
+        ProjectionChoice pc = new SingleProjectionChoice(name, id, "EPSG:"+epsg, cacheDir);
+        registerProjectionChoice(pc);
+        return pc;
+    }
+
+    private static ProjectionChoice registerProjectionChoice(String name, String id, Integer epsg) {
+        ProjectionChoice pc = new SingleProjectionChoice(name, id, "EPSG:"+epsg);
+        registerProjectionChoice(pc);
+        return pc;
     }
 
Index: /trunk/src/org/openstreetmap/josm/gui/preferences/projection/PuwgProjectionChoice.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/projection/PuwgProjectionChoice.java	(revision 5547)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/projection/PuwgProjectionChoice.java	(revision 5548)
@@ -7,23 +7,41 @@
 import java.util.Collections;
 
-import org.openstreetmap.josm.data.projection.Projection;
-import org.openstreetmap.josm.data.projection.Puwg;
-
 public class PuwgProjectionChoice extends ListProjectionChoice {
 
+    public static final String[] CODES = {
+        "EPSG:2180",
+        "EPSG:2176",
+        "EPSG:2177",
+        "EPSG:2178",
+        "EPSG:2179"
+    };
+    public static final String[] NAMES = {
+        tr("PUWG 1992 (Poland)"),
+        tr("PUWG 2000 Zone {0} (Poland)", 5),
+        tr("PUWG 2000 Zone {0} (Poland)", 6),
+        tr("PUWG 2000 Zone {0} (Poland)", 7),
+        tr("PUWG 2000 Zone {0} (Poland)", 8)
+    };
+
     public PuwgProjectionChoice() {
-        super("core:puwg", tr("PUWG (Poland)"), Puwg.zones, tr("PUWG Zone"));
+        super(tr("PUWG (Poland)"), "core:puwg", NAMES, tr("PUWG Zone"));
     }
 
     @Override
-    public Projection getProjection() {
-        return new Puwg(index);
+    public String getCurrentCode() {
+        return CODES[index];
     }
 
     @Override
+    public String getProjectionName() {
+        return NAMES[index];
+    }
+
+
+    @Override
     public String[] allCodes() {
-        String[] zones = new String[Puwg.zones.length];
-        for (int index = 0; index < Puwg.zones.length; index++) {
-            zones[index] = Puwg.zones[index].toCode();
+        String[] zones = new String[CODES.length];
+        for (int idx = 0; idx < CODES.length; idx++) {
+            zones[idx] = CODES[idx];
         }
         return zones;
@@ -32,7 +50,7 @@
     @Override
     public Collection<String> getPreferencesFromCode(String code) {
-        for (Puwg.PuwgData p : Puwg.zones) {
-            if (code.equals(p.toCode()))
-                return Collections.singleton(code);
+        for (String code2 : CODES) {
+            if (code.equals(code2))
+                return Collections.singleton(code2);
         }
         return null;
@@ -41,11 +59,11 @@
     @Override
     protected String indexToZone(int index) {
-        return Puwg.zones[index].toCode();
+        return CODES[index];
     }
 
     @Override
     protected int zoneToIndex(String zone) {
-        for (int i=0; i<Puwg.zones.length; i++) {
-            if (zone.equals(Puwg.zones[i].toCode())) {
+        for (int i=0; i<CODES.length; i++) {
+            if (zone.equals(CODES[i])) {
                 return i;
             }
Index: /trunk/src/org/openstreetmap/josm/gui/preferences/projection/SingleProjectionChoice.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/projection/SingleProjectionChoice.java	(revision 5547)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/projection/SingleProjectionChoice.java	(revision 5548)
@@ -8,6 +8,4 @@
 import javax.swing.JPanel;
 
-import org.openstreetmap.josm.data.projection.Projection;
-
 /**
  * ProjectionChoice, that offers just one projection as choice.
@@ -15,18 +13,24 @@
  * The GUI is an empty panel.
  */
-public class SingleProjectionChoice implements ProjectionChoice {
+public class SingleProjectionChoice extends AbstractProjectionChoice {
 
-    private String id;
-    private String name;
-    private Projection projection;
+    protected String code;
 
-    public SingleProjectionChoice(String id, String name, Projection projection) {
-        this.id = id;
-        this.name = name;
-        this.projection = projection;
+    /**
+     * Constructor.
+     *
+     * @param name short name of the projection choice as shown in the GUI
+     * @param id unique identifier for the projection choice, e.g. "core:thisproj"
+     * @param code the unique identifier for the projection, e.g. "EPSG:1234"
+     * @param cacheDir a cache directory name
+     */
+    public SingleProjectionChoice(String name, String id, String code, String cacheDir) {
+        super(name, id, cacheDir);
+        this.code = code;
     }
 
-    public SingleProjectionChoice(String id, Projection projection) {
-        this(id, projection.toString(), projection);
+    public SingleProjectionChoice(String name, String id, String code) {
+        super(name, id);
+        this.code = code;
     }
 
@@ -37,11 +41,6 @@
 
     @Override
-    public String getId() {
-        return id;
-    }
-
-    @Override
     public String[] allCodes() {
-        return new String[] { projection.toCode() };
+        return new String[] { code };
     }
 
@@ -56,9 +55,4 @@
 
     @Override
-    public Projection getProjection() {
-        return projection;
-    }
-
-    @Override
     public String toString() {
         return name;
@@ -67,8 +61,19 @@
     @Override
     public Collection<String> getPreferencesFromCode(String code) {
-        if (code.equals(projection.toCode()))
+        if (code.equals(this.code))
             return Collections.emptyList();
         else
             return null;
     }
+
+    @Override
+    public String getCurrentCode() {
+        return code;
+    }
+
+    @Override
+    public String getProjectionName() {
+        return name; // the same name as the projection choice
+    }
+
 }
Index: /trunk/src/org/openstreetmap/josm/gui/preferences/projection/SwissGridProjectionChoice.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/projection/SwissGridProjectionChoice.java	(revision 5547)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/projection/SwissGridProjectionChoice.java	(revision 5548)
@@ -10,5 +10,4 @@
 import javax.swing.JPanel;
 
-import org.openstreetmap.josm.data.projection.SwissGrid;
 import org.openstreetmap.josm.gui.widgets.HtmlPanel;
 import org.openstreetmap.josm.tools.GBC;
@@ -17,5 +16,5 @@
 
     public SwissGridProjectionChoice() {
-        super("core:swissgrid", tr("Swiss Grid (Switzerland)"), new SwissGrid());
+        super(tr("Swiss Grid (Switzerland)"), "core:swissgrid", "EPSG:21781");
     }
 
Index: /trunk/src/org/openstreetmap/josm/gui/preferences/projection/UTMProjectionChoice.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/projection/UTMProjectionChoice.java	(revision 5547)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/projection/UTMProjectionChoice.java	(revision 5548)
@@ -16,23 +16,23 @@
 import javax.swing.JRadioButton;
 
-import org.openstreetmap.josm.data.projection.Projection;
-import org.openstreetmap.josm.data.projection.UTM;
 import org.openstreetmap.josm.tools.GBC;
 
 public class UTMProjectionChoice extends ListProjectionChoice {
 
-    private static final UTM.Hemisphere DEFAULT_HEMISPHERE = UTM.Hemisphere.North;
+    public enum Hemisphere { North, South }
 
-    private UTM.Hemisphere hemisphere;
+    private static final Hemisphere DEFAULT_HEMISPHERE = Hemisphere.North;
+
+    private Hemisphere hemisphere;
     
     private final static List<String> cbEntries = new ArrayList<String>();
     static {
         for (int i = 1; i <= 60; i++) {
-                cbEntries.add(Integer.toString(i));
+            cbEntries.add(Integer.toString(i));
         }
     }
 
     public UTMProjectionChoice() {
-        super("core:utm", tr("UTM"), cbEntries.toArray(), tr("UTM Zone"));
+        super(tr("UTM"), "core:utm", cbEntries.toArray(), tr("UTM Zone"));
     }
 
@@ -46,7 +46,7 @@
             //Hemisphere
             north = new JRadioButton();
-            north.setSelected(hemisphere == UTM.Hemisphere.North);
+            north.setSelected(hemisphere == Hemisphere.North);
             south = new JRadioButton();
-            south.setSelected(hemisphere == UTM.Hemisphere.South);
+            south.setSelected(hemisphere == Hemisphere.South);
 
             ButtonGroup group = new ButtonGroup();
@@ -82,7 +82,15 @@
 
     @Override
-    public Projection getProjection() {
-        return new UTM(index + 1, hemisphere);
+    public String getCurrentCode() {
+        int zone = index + 1;
+        int code = 32600 + zone + (hemisphere == Hemisphere.South ? 100 : 0);
+        return "EPSG:" + Integer.toString(code);
     }
+
+    @Override
+    public String getProjectionName() {
+        return tr("UTM");
+    }
+
 
     @Override
@@ -90,5 +98,5 @@
         UTMPanel p = (UTMPanel) panel;
         int index = p.prefcb.getSelectedIndex();
-        UTM.Hemisphere hemisphere = p.south.isSelected()?UTM.Hemisphere.South:UTM.Hemisphere.North;
+        Hemisphere hemisphere = p.south.isSelected()?Hemisphere.South:Hemisphere.North;
         return Arrays.asList(indexToZone(index), hemisphere.toString());
     }
@@ -98,6 +106,6 @@
         ArrayList<String> projections = new ArrayList<String>(60*4);
         for (int zone = 1;zone <= 60; zone++) {
-            for (UTM.Hemisphere hemisphere : UTM.Hemisphere.values()) {
-                projections.add("EPSG:" + (32600 + zone + (hemisphere == UTM.Hemisphere.South?100:0)));
+            for (Hemisphere hemisphere : Hemisphere.values()) {
+                projections.add("EPSG:" + (32600 + zone + (hemisphere == Hemisphere.South?100:0)));
             }
         }
@@ -110,5 +118,5 @@
         if (code.startsWith("EPSG:326") || code.startsWith("EPSG:327")) {
             try {
-                UTM.Hemisphere hemisphere = code.charAt(7)=='6'?UTM.Hemisphere.North:UTM.Hemisphere.South;
+                Hemisphere hemisphere = code.charAt(7)=='6'?Hemisphere.North:Hemisphere.South;
                 String zonestring = code.substring(8);
                 int zoneval = Integer.parseInt(zonestring);
@@ -123,5 +131,5 @@
     public void setPreferences(Collection<String> args) {
         super.setPreferences(args);
-        UTM.Hemisphere hemisphere = DEFAULT_HEMISPHERE;
+        Hemisphere hemisphere = DEFAULT_HEMISPHERE;
 
         if(args != null) {
@@ -129,5 +137,5 @@
 
             if (array.length > 1) {
-                hemisphere = UTM.Hemisphere.valueOf(array[1]);
+                hemisphere = Hemisphere.valueOf(array[1]);
             }
         }
Index: /trunk/src/org/openstreetmap/josm/gui/preferences/projection/UTM_France_DOM_ProjectionChoice.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/projection/UTM_France_DOM_ProjectionChoice.java	(revision 5547)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/projection/UTM_France_DOM_ProjectionChoice.java	(revision 5548)
@@ -6,7 +6,4 @@
 import java.util.Collection;
 import java.util.Collections;
-
-import org.openstreetmap.josm.data.projection.Projection;
-import org.openstreetmap.josm.data.projection.UTM_France_DOM;
 
 public class UTM_France_DOM_ProjectionChoice extends ListProjectionChoice {
@@ -19,6 +16,13 @@
     private final static String[] utmGeodesicsNames = { FortMarigotName, SainteAnneName, MartiniqueName, Reunion92Name, Guyane92Name};
 
+    private final static Integer FortMarigotEPSG = 2969;
+    private final static Integer SainteAnneEPSG = 2970;
+    private final static Integer MartiniqueEPSG = 2973;
+    private final static Integer ReunionEPSG = 2975;
+    private final static Integer GuyaneEPSG = 2972;
+    private final static Integer[] utmEPSGs = { FortMarigotEPSG, SainteAnneEPSG, MartiniqueEPSG, ReunionEPSG, GuyaneEPSG };
+
     public UTM_France_DOM_ProjectionChoice() {
-        super("core:utmfrancedom", tr("UTM France (DOM)"), utmGeodesicsNames, tr("UTM Geodesic system"));
+        super(tr("UTM France (DOM)"), "core:utmfrancedom", utmGeodesicsNames, tr("UTM Geodesic system"));
     }
 
@@ -37,13 +41,18 @@
 
     @Override
-    public Projection getProjection() {
-        return new UTM_France_DOM(index);
+    public String getProjectionName() {
+        return utmGeodesicsNames[index];
+    }
+
+    @Override
+    public String getCurrentCode() {
+        return "EPSG:" + utmEPSGs[index];
     }
 
     @Override
     public String[] allCodes() {
-        String[] res = new String[UTM_France_DOM.utmEPSGs.length];
-        for (int i=0; i<UTM_France_DOM.utmEPSGs.length; ++i) {
-            res[i] = "EPSG:"+UTM_France_DOM.utmEPSGs[i];
+        String[] res = new String[utmEPSGs.length];
+        for (int i=0; i<utmEPSGs.length; ++i) {
+            res[i] = "EPSG:" + utmEPSGs[i];
         }
         return res;
@@ -52,6 +61,6 @@
     @Override
     public Collection<String> getPreferencesFromCode(String code) {
-        for (int i=0; i < UTM_France_DOM.utmEPSGs.length; i++ )
-            if (("EPSG:"+UTM_France_DOM.utmEPSGs[i]).equals(code))
+        for (int i=0; i < utmEPSGs.length; i++ )
+            if (("EPSG:" + utmEPSGs[i]).equals(code))
                 return Collections.singleton(Integer.toString(i+1));
         return null;
