Index: src/uk/me/parabola/mkgmap/build/MapBuilder.java
===================================================================
--- src/uk/me/parabola/mkgmap/build/MapBuilder.java	(revision 1862)
+++ src/uk/me/parabola/mkgmap/build/MapBuilder.java	(working copy)
@@ -702,6 +702,9 @@
 		map.addInfo("Map data licenced under Creative Commons Attribution ShareAlike 2.0");
 		map.addInfo("http://creativecommons.org/licenses/by-sa/2.0/");
 
+		map.addInfo("GeoNames data attribution: http://www.geonames.org/");
+
+
 		// Pad the version number with spaces so that version
 		// strings that are different lengths do not change the size and
 		// offsets of the following sections.
Index: src/uk/me/parabola/mkgmap/reader/osm/SeaGenerator.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/SeaGenerator.java	(revision 1862)
+++ src/uk/me/parabola/mkgmap/reader/osm/SeaGenerator.java	(working copy)
@@ -26,6 +26,11 @@
 import java.util.SortedMap;
 import java.util.TreeMap;
 
+import java.net.*;
+import java.io.*;
+import uk.me.parabola.imgfmt.Utils;
+
+
 import uk.me.parabola.imgfmt.MapFailedException;
 import uk.me.parabola.imgfmt.app.Area;
 import uk.me.parabola.imgfmt.app.Coord;
@@ -55,6 +60,8 @@
 	private int fbThreshold = 20;
 	private boolean fbDebug;
 
+	private String geonamesUser;
+
 	private ElementSaver saver;
 
 	private List<Way> shoreline = new ArrayList<Way>();
@@ -101,6 +108,12 @@
 					fbThreshold = (int)Double.parseDouble(o.substring("fbthres=".length()));
 				else if("fbdebug".equals(o)) 
 					fbDebug = true;
+
+				else if(o.startsWith("geonames-user="))
+					geonamesUser = o.substring(14);
+
+
+
 				else {
 					if(!"help".equals(o))
 						System.err.println("Unknown sea generation option '" + o + "'");
@@ -115,6 +128,10 @@
 					System.err.println("  fbgap=NUM           points closer to the coastline are ignored for flood blocking (default 40)");
 					System.err.println("  fbthres=NUM         min points contained in a polygon to be flood blocked (default 20)");
 					System.err.println("  fbratio=NUM         min ratio (points/area size) for flood blocking (default 0.5)");
+
+					System.err.println("  geonames-user=VAL   geonames.org user to use for sea name lookups");
+
+
 				}
 			}
 			
@@ -323,6 +340,9 @@
 			seaRelation = new GeneralRelation(multiId);
 			seaRelation.addTag("type", "multipolygon");
 			seaRelation.addTag("natural", "sea");
+			if (geonamesUser != null) {
+                        	setSeaName(seaRelation, seaBounds);
+			}
 		}
 
 		List<Way> islands = new ArrayList<Way>();
@@ -439,7 +459,130 @@
 		}
 	}
 
+
 	/**
+	 * Get the name of the sea.
+	 * @param seaPoint The coordinates of the sea.
+	 */
+	private String getSeaName(Coord seaPoint) {
+
+		boolean foundName = false;
+		String seaName = null; String apiLine;
+
+		try {
+
+			String url = "http://api.geonames.org/oceanJSON?lat=" + Utils.toDegrees(seaPoint.getLatitude()) +
+			     	"&lng=" + Utils.toDegrees(seaPoint.getLongitude()) + "&username=" + geonamesUser;
+
+			log.info("Requesting URL " + url);
+
+			URL seaApiUrl = new URL(url);
+
+			BufferedReader httpIn = new BufferedReader(new InputStreamReader(seaApiUrl.openStream()));
+
+
+			while ((apiLine = httpIn.readLine()) != null && !foundName) {
+				log.info("HTTP line returned: " + apiLine);
+
+				seaName = apiLine.replaceFirst("\\{\"ocean\":\\{\"name\":\"(.*)\"\\}\\}", "$1");
+
+				if (seaName != null && ! seaName.equals(apiLine)) {
+					foundName = true;
+				}
+
+			}
+
+			httpIn.close();
+
+		} catch (MalformedURLException URLe) {
+			log.warn("Malformed URL: " + URLe.toString());
+		} catch(IOException IOe) { 
+			log.warn("IO Exception reading HTTP data: " + IOe.toString());
+		}
+
+
+		if (foundName && seaName != null) { return seaName; }
+		else { return null; }
+
+	}
+
+
+	/**
+	 * Set the name of the sea.
+	 * @param relation The sea relation.
+	 * @param bounds The sea bounds.
+	 */
+	private void setSeaName(Relation relation, Area bounds) {
+
+		String seaName = null;
+
+		if (shoreline != null && !shoreline.isEmpty()) {
+
+
+			// First try with the coordinates at the center of gravity of the 
+			// first way in the polygon:
+
+			Way shoreWay = shoreline.get(0);
+		 
+			seaName = getSeaName(shoreWay.getCofG());
+
+			// Make a second attempt with the first coordinate in the polygon:
+			if (seaName == null) {
+			
+				List<Coord> firstCoords = shoreWay.getPoints();
+
+				if (firstCoords != null && !firstCoords.isEmpty()) {
+					log.info("Second attempt to determine sea name");
+					seaName = getSeaName(firstCoords.get(0));
+
+				}
+
+			}
+
+		}
+
+		// Make further attempts with the bounding box:
+		if (seaName == null) {
+
+			log.info("Third try for sea name, using bounding box (SW)");
+		
+			seaName = getSeaName(new Coord(bounds.getMinLat(), bounds.getMinLong()));
+
+			if (seaName == null) {
+				log.info("Fourth try (NW):");
+				seaName = getSeaName(new Coord(bounds.getMaxLat(), bounds.getMinLong()));
+
+				if (seaName == null) {
+					log.info("Fifth try (SE):");
+					seaName = getSeaName(new Coord(bounds.getMinLat(), bounds.getMaxLong()));
+
+					if (seaName == null) {
+						log.info("Sixth try (NE):");		
+						seaName = getSeaName(new Coord(bounds.getMaxLat(), bounds.getMaxLong()));
+
+						if (seaName == null) {
+							log.info("Seventh try (center):");
+							seaName = getSeaName(bounds.getCenter());
+		
+						}
+
+					}
+
+				}
+
+			}
+
+		}
+
+		if (seaName != null) {
+			relation.addTag("name", seaName);
+			log.info("Determined sea name: " + seaName);
+
+		}
+		
+	}
+
+	/**
 	 * Clip the shoreline ways to the bounding box of the map.
 	 * @param shoreline All the the ways making up the coast.
 	 * @param bounds The map bounds.
Index: resources/help/en/options
===================================================================
--- resources/help/en/options	(revision 1862)
+++ resources/help/en/options	(working copy)
@@ -358,6 +358,28 @@
 		generates GPX files for each polygon checked by
 		the flood blocker
 
+	geonames-user=VAL
+	        Name of geonames.org account to use for the
+		ocean / sea reverse geocoding web service.
+		When you set this, mkgmap calls the web service and
+		attempts to determine the name of the sea
+		polygon being generated. The sea names are only in
+		English.
+
+		Further details:
+
+		http://www.geonames.org/export/web-services.html#ocean
+
+		Create a free account:
+
+		http://www.geonames.org/login
+
+		(After you create an account, you must also enable the 
+                free web services. Currently free accounts are limited
+                to 2000 requests/hour. Use user "demo" to test.)
+
+		Geonames data are cc-by licence.
+
 --make-poi-index
 	Generate the POI index (not yet useful).
 
