Index: src/uk/me/parabola/util/ElementQuadTree.java
===================================================================
--- src/uk/me/parabola/util/ElementQuadTree.java	(revision 1860)
+++ src/uk/me/parabola/util/ElementQuadTree.java	(working copy)
@@ -2,69 +2,72 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
-import java.util.ListIterator;
 
 import uk.me.parabola.imgfmt.app.Area;
 import uk.me.parabola.imgfmt.app.Coord;
-import uk.me.parabola.util.QuadTreeNode.QuadTreePolygon;
+import uk.me.parabola.mkgmap.reader.osm.Element;
+import uk.me.parabola.util.ElementQuadTreeNode.QuadTreePolygon;
 
-public class QuadTree {
+public class ElementQuadTree {
 
-	private final QuadTreeNode root;
+	private final ElementQuadTreeNode root;
 	private long itemCount;
 
-	public QuadTree(Area bbox) {
-		this.root = new QuadTreeNode(bbox);
+	public ElementQuadTree(Area bbox) {
+		this.root = new ElementQuadTreeNode(bbox);
 		this.itemCount = 0;
 	}
 
-	public boolean addAll(Collection<Coord> coordList) {
+	public ElementQuadTree(Collection<Element> elements) {
+		this.root = new ElementQuadTreeNode(elements);
+		this.itemCount = 0;
+	}
+	
+	public boolean addAll(Collection<Element> elements) {
 		boolean oneAdded = false;
-		for (Coord c : coordList) {
-			oneAdded = add(c) | oneAdded;
+		for (Element element : elements) {
+			oneAdded = add(element) | oneAdded;
 		}
 		return oneAdded;
 	}
 
-	public boolean add(Coord c) {
+	public boolean add(Element element) {
 
-		boolean added = root.add(c);
+		boolean added = root.add(element);
 		if (added) {
 			itemCount++;
 		}
 		return added;
 	}
 
-	public List<Coord> get(Area bbox) {
-		return root.get(bbox, new ArrayList<Coord>(2000));
+	public MultiHashMap<Coord, Element> get(Area bbox) {
+		return root.get(bbox, new MultiHashMap<Coord, Element>());
 	}
 
-	public List<Coord> get(Collection<List<Coord>> polygons) {
-		return root.get(new QuadTreePolygon(polygons), new ArrayList<Coord>(
-				2000));
+	public MultiHashMap<Coord, Element> get(Collection<List<Coord>> polygons) {
+		return root.get(new QuadTreePolygon(polygons),
+				new MultiHashMap<Coord, Element>());
 	}
 
-	public List<Coord> get(List<Coord> polygon) {
+	public MultiHashMap<Coord, Element> get(List<Coord> polygon) {
 		return get(polygon, 0);
 	}
 
-	public List<Coord> get(List<Coord> polygon, int offset) {
+	public MultiHashMap<Coord, Element> get(List<Coord> polygon, int offset) {
 		if (polygon.size() < 3) {
-			return Collections.emptyList();
+			return new MultiHashMap<Coord, Element>();
 		}
 		if (polygon.get(0).equals(polygon.get(polygon.size() - 1)) == false) {
 			return null;
 		}
-		ArrayList<Coord> points = root.get(new QuadTreePolygon(polygon),
-				new ArrayList<Coord>(2000));
+		MultiHashMap<Coord, Element> points = root.get(new QuadTreePolygon(polygon),
+				new MultiHashMap<Coord, Element>());
 		if (offset > 0) {
-			ListIterator<Coord> pointIter = points.listIterator();
-			while (pointIter.hasNext()) {
-				if (isCloseToPolygon(pointIter.next(), polygon, offset)) {
-					pointIter.remove();
+			for (Coord c : new ArrayList<Coord>(points.keySet())) {
+				if (isCloseToPolygon(c, polygon, offset)) {
+					points.remove(c);
 				}
 			}
 		}
@@ -76,7 +79,8 @@
 		root.clear();
 	}
 
-	public long getSize() {
+	// TODO itemCount is not a good counter (coords or elements?)
+	private long getSize() {
 		return itemCount;
 	}
 

Property changes on: src\uk\me\parabola\util\ElementQuadTree.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: src/uk/me/parabola/util/ElementQuadTreeNode.java
===================================================================
--- src/uk/me/parabola/util/ElementQuadTreeNode.java	(revision 1860)
+++ src/uk/me/parabola/util/ElementQuadTreeNode.java	(working copy)
@@ -1,20 +1,26 @@
 package uk.me.parabola.util;
 
-import java.awt.*;
-import java.util.ArrayList;
+import java.awt.Rectangle;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
+import java.util.Map.Entry;
 
 import uk.me.parabola.imgfmt.app.Area;
 import uk.me.parabola.imgfmt.app.Coord;
+import uk.me.parabola.log.Logger;
+import uk.me.parabola.mkgmap.reader.osm.Element;
+import uk.me.parabola.mkgmap.reader.osm.Node;
+import uk.me.parabola.mkgmap.reader.osm.Relation;
+import uk.me.parabola.mkgmap.reader.osm.Way;
+
+public class ElementQuadTreeNode {
 
-public class QuadTreeNode {
+	private static final Logger log = Logger.getLogger(ElementQuadTreeNode.class);
 
 	private static final int MAX_POINTS = 20;
 
-	private Collection<Coord> points;
+	private MultiHashMap<Coord, Element> points;
 	private final Area bounds;
 	private Area coveredBounds;
 
@@ -22,7 +28,7 @@
 		return coveredBounds;
 	}
 
-	private QuadTreeNode[] children;
+	private ElementQuadTreeNode[] children;
 
 	public static final class QuadTreePolygon {
 		private final java.awt.geom.Area javaArea;
@@ -59,47 +65,114 @@
 		}
 	}
 
-	public QuadTreeNode(Area bounds) {
-		this(bounds, Collections.<Coord>emptyList());
+	public ElementQuadTreeNode(Area bounds) {
+		this(bounds, Collections.<Element> emptyList());
 	}
 
-	public QuadTreeNode(Area bounds, Collection<Coord> points) {
-		this.bounds = bounds;
+	
+	public ElementQuadTreeNode(Collection<Element> elements) {
 		this.children = null;
 
 		int minLat = Integer.MAX_VALUE;
 		int maxLat = Integer.MIN_VALUE;
 		int minLong = Integer.MAX_VALUE;
 		int maxLong = Integer.MIN_VALUE;
-		for (Coord c : points) {
-			if (c.getLatitude() < minLat) {
-				minLat = c.getLatitude();
+
+		this.points = new MultiHashMap<Coord, Element>();
+		for (Element el : elements) {
+			Collection<Coord> coords = null;
+			if (el instanceof Relation) {
+				continue;
+			} else if (el instanceof Way) {
+				Way w = (Way) el;
+				if (w.isClosed()) {
+					coords = w.getPoints().subList(0, w.getPoints().size()-1);	
+				} else {
+					coords = w.getPoints();
+				}
+			} else if (el instanceof Node) {
+				coords = Collections.singleton(((Node) el).getLocation());
 			}
-			if (c.getLatitude() > maxLat) {
-				maxLat = c.getLatitude();
+			
+			for (Coord c : coords) {
+				if (c.getLatitude() < minLat) {
+					minLat = c.getLatitude();
+				}
+				if (c.getLatitude() > maxLat) {
+					maxLat = c.getLatitude();
+				}
+				if (c.getLongitude() < minLong) {
+					minLong = c.getLongitude();
+				}
+				if (c.getLongitude() > maxLong) {
+					maxLong = c.getLongitude();
+				}
+				points.add(c, el);
 			}
-			if (c.getLongitude() < minLong) {
-				minLong = c.getLongitude();
+
+		}
+		coveredBounds = new Area(minLat, minLong, maxLat, maxLong);
+		this.bounds = coveredBounds;
+		
+		if (points.size() > MAX_POINTS) {
+			split();
+		} 
+	}
+
+	public ElementQuadTreeNode(Area bounds, Collection<Element> elements) {
+		this.bounds = bounds;
+		this.children = null;
+
+		int minLat = Integer.MAX_VALUE;
+		int maxLat = Integer.MIN_VALUE;
+		int minLong = Integer.MAX_VALUE;
+		int maxLong = Integer.MIN_VALUE;
+
+		this.points = new MultiHashMap<Coord, Element>();
+		for (Element el : elements) {
+			Collection<Coord> coords = null;
+			if (el instanceof Relation) {
+				continue;
+			} else if (el instanceof Way) {
+				Way w = (Way) el;
+				if (w.isClosed()) {
+					coords = w.getPoints().subList(0, w.getPoints().size()-1);	
+				} else {
+					coords = w.getPoints();
+				}
+			} else if (el instanceof Node) {
+				coords = Collections.singleton(((Node) el).getLocation());
 			}
-			if (c.getLongitude() > maxLong) {
-				maxLong = c.getLongitude();
+			
+			for (Coord c : coords) {
+				if (c.getLatitude() < minLat) {
+					minLat = c.getLatitude();
+				}
+				if (c.getLatitude() > maxLat) {
+					maxLat = c.getLatitude();
+				}
+				if (c.getLongitude() < minLong) {
+					minLong = c.getLongitude();
+				}
+				if (c.getLongitude() > maxLong) {
+					maxLong = c.getLongitude();
+				}
+				points.add(c, el);
 			}
+
 		}
 		coveredBounds = new Area(minLat, minLong, maxLat, maxLong);
 
 		if (points.size() > MAX_POINTS) {
-			this.points = points;
 			split();
-		} else {
-			this.points = new HashSet<Coord>(points);
-		}
+		} 
 	}
 
 	public Area getBounds() {
 		return this.bounds;
 	}
 
-	public boolean add(Coord c) {
+	private boolean add(Coord c, Element element) {
 		if (coveredBounds == null) {
 			coveredBounds = new Area(c.getLatitude(), c.getLongitude(),
 					c.getLatitude(), c.getLongitude());
@@ -111,21 +184,49 @@
 					c.getLongitude()));
 		}
 		if (isLeaf()) {
-			boolean added = points.add(c);
+			points.add(c,element);
 			if (points.size() > MAX_POINTS)
 				split();
-			return added;
+			return true;
 		} else {
-			for (QuadTreeNode nodes : children) {
+			for (ElementQuadTreeNode nodes : children) {
 				if (nodes.getBounds().contains(c)) {
-					return nodes.add(c);
+					return nodes.add(c, element);
 				}
 			}
 			return false;
 		}
 	}
 
-	public List<Coord> get(Area bbox, List<Coord> resultList) {
+	public boolean add(Element c) {
+		if (c instanceof Relation) {
+			log.error("Relations are not supported by this quadtree implementation. Skipping relation "
+					+ c.toBrowseURL());
+			return false;
+		} else if (c instanceof Way) {
+			// add all points to the tree
+			Way w = (Way) c;
+			List<Coord> points;
+			if (w.isClosed()) {
+				points = w.getPoints().subList(0, w.getPoints().size()-1);	
+			} else {
+				points = w.getPoints();
+			}
+			
+			boolean allOk = true;
+			for (Coord cp : points) {
+				allOk = add(cp, c) && allOk;
+			}
+			return allOk;
+		} else if (c instanceof Node) {
+			return add(((Node) c).getLocation(), c);
+		} else {
+			log.error("Unsupported element type: "+c);
+			return false;
+		}
+	}
+
+	public MultiHashMap<Coord, Element> get(Area bbox, MultiHashMap<Coord, Element> resultList) {
 		if (isLeaf()) {
 			if (bbox.getMinLat() <= coveredBounds.getMinLat()
 					&& bbox.getMaxLat() >= coveredBounds.getMaxLat()
@@ -134,17 +235,18 @@
 
 				// the bounding box is contained completely in the bbox
 				// => add all points without further check
-				resultList.addAll(points);
+				resultList.putAll(points);
 			} else {
 				// check each point
-				for (Coord c : points) {
-					if (bbox.contains(c)) {
-						resultList.add(c);
+				for (Entry<Coord, List<Element>> e : points.entrySet()) {
+					if (bbox.contains(e.getKey())) {
+						for (Element el : e.getValue())
+							resultList.add(e.getKey(), el);
 					}
 				}
 			}
 		} else {
-			for (QuadTreeNode child : children) {
+			for (ElementQuadTreeNode child : children) {
 				if (bbox.intersects(child.getCoveredBounds())) {
 					resultList = child.get(bbox, resultList);
 				}
@@ -153,17 +255,19 @@
 		return resultList;
 	}
 
-	public ArrayList<Coord> get(QuadTreePolygon polygon, ArrayList<Coord> resultList) {
+	public MultiHashMap<Coord, Element> get(QuadTreePolygon polygon,
+			MultiHashMap<Coord, Element> resultList) {
 		if (polygon.getBbox().intersects(getBounds())) {
 			if (isLeaf()) {
-				for (Coord c : points) {
-					if (polygon.getArea().contains(c.getLongitude(),
-							c.getLatitude())) {
-						resultList.add(c);
+				for (Entry<Coord, List<Element>> e : points.entrySet()) {
+					if (polygon.getArea().contains(e.getKey().getLongitude(),
+							e.getKey().getLatitude())) {
+						for (Element el : e.getValue())
+							resultList.add(e.getKey(),el);
 					}
 				}
 			} else {
-				for (QuadTreeNode child : children) {
+				for (ElementQuadTreeNode child : children) {
 					if (polygon.getBbox().intersects(child.getBounds())) {
 						java.awt.geom.Area subArea = (java.awt.geom.Area) polygon
 								.getArea().clone();
@@ -193,7 +297,7 @@
 
 		int halfLat = (bounds.getMinLat() + bounds.getMaxLat()) / 2;
 		int halfLong = (bounds.getMinLong() + bounds.getMaxLong()) / 2;
-		children = new QuadTreeNode[4];
+		children = new ElementQuadTreeNode[4];
 
 		Area swBounds = new Area(bounds.getMinLat(), bounds.getMinLong(),
 				halfLat, halfLong);
@@ -204,21 +308,22 @@
 		Area neBounds = new Area(halfLat + 1, halfLong + 1, bounds.getMaxLat(),
 				bounds.getMaxLong());
 
-		children[0] = new QuadTreeNode(swBounds);
-		children[1] = new QuadTreeNode(nwBounds);
-		children[2] = new QuadTreeNode(seBounds);
-		children[3] = new QuadTreeNode(neBounds);
+		children[0] = new ElementQuadTreeNode(swBounds);
+		children[1] = new ElementQuadTreeNode(nwBounds);
+		children[2] = new ElementQuadTreeNode(seBounds);
+		children[3] = new ElementQuadTreeNode(neBounds);
 
-		Collection<Coord> copyPoints = points;
+		MultiHashMap<Coord, Element> copyPoints = points;
 		points = null;
-		for (Coord c : copyPoints) {
-			add(c);
+		for (Entry<Coord, List<Element>> c : copyPoints.entrySet()) {
+			for (Element el : c.getValue())
+				add(c.getKey(), el);
 		}
 	}
 
 	public void clear() {
 		this.children = null;
-		points = new HashSet<Coord>();
+		points = new MultiHashMap<Coord, Element>();
 		coveredBounds = new Area(Integer.MAX_VALUE, Integer.MAX_VALUE,
 				Integer.MIN_VALUE, Integer.MIN_VALUE);
 	}

Property changes on: src\uk\me\parabola\util\ElementQuadTreeNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: src/uk/me/parabola/mkgmap/general/MapElement.java
===================================================================
--- src/uk/me/parabola/mkgmap/general/MapElement.java	(revision 1865)
+++ src/uk/me/parabola/mkgmap/general/MapElement.java	(working copy)
@@ -50,6 +50,7 @@
 		minResolution = orig.minResolution;
 		maxResolution = orig.maxResolution;
 		extTypeAttributes = orig.extTypeAttributes;
+		attributes.putAll(orig.attributes);
 	}
 
 	/**
Index: src/uk/me/parabola/mkgmap/reader/osm/AddressHook.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/AddressHook.java	(revision 0)
+++ src/uk/me/parabola/mkgmap/reader/osm/AddressHook.java	(revision 0)
@@ -0,0 +1,129 @@
+package uk.me.parabola.mkgmap.reader.osm;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.TreeMap;
+
+import uk.me.parabola.imgfmt.app.Coord;
+import uk.me.parabola.log.Logger;
+import uk.me.parabola.util.ElementQuadTree;
+import uk.me.parabola.util.EnhancedProperties;
+import uk.me.parabola.util.MultiHashMap;
+
+public class AddressHook extends OsmReadingHooksAdaptor {
+	private static final Logger log = Logger.getLogger(AddressHook.class);
+
+	private ElementSaver saver;
+
+	private final TreeMap<Integer, String> levelTags = new TreeMap<Integer, String>() {
+		{
+			put(2,"mkgmap:country");
+			put(3,"mkgmap:province");
+			put(4,"mkgmap:province");
+			put(5,"mkgmap:district");
+			put(6,"mkgmap:subdistrict");
+			put(7,"mkgmap:subdistrict");
+			put(8,"mkgmap:city");
+			put(9,"mkgmap:city");
+			put(10,"mkgmap:city");
+	}
+	};
+	
+	public boolean init(ElementSaver saver, EnhancedProperties props) {
+		this.saver = saver;
+		return true;
+	}
+
+	@Override
+	public void end() {
+		log.error("Starting with address hook");
+		List<Element> elements = new ArrayList<Element>(saver.getWays().size()
+				+ saver.getNodes().size());
+
+		MultiHashMap<Integer, Way> boundaries = new MultiHashMap<Integer, Way>();
+
+		for (Node node : saver.getNodes().values()) {
+			if (node.getTagCount() > 0) {
+				elements.add(node);
+			}
+		}
+		for (Way way : saver.getWays().values()) {
+			if (way.getTagCount() == 0) {
+				continue;
+			}
+			if (way.isClosed()
+					&& "administrative".equals(way.getTag("boundary"))
+					&& way.getTag("admin_level") != null
+					&& "polyline".equals(way.getTag("mkgmap:stylefilter")) == false) {
+				{
+					try {
+						int adminlevel = Integer.valueOf(way
+								.getTag("admin_level"));
+						if (adminlevel >= 0 && adminlevel <= 10) {
+							boundaries.add(adminlevel, way);
+						}
+					} catch (NumberFormatException nfe) {
+						log.error(nfe, nfe);
+					}
+				}
+			}
+
+			// in any case add it to the element list
+			elements.add(way);
+
+		}
+
+		log.info("Creating quadtree for",elements.size(),"elements");
+		ElementQuadTree quadTree = new ElementQuadTree(elements);
+		log.info("Quadtree created");
+		elements.clear();
+
+		// first add the tags to the boundaries itself
+		for (Integer adminlevel : levelTags.keySet()) {
+			String tag = levelTags.get(adminlevel);
+			log.info("Preparing admin level",adminlevel,"with tag",tag);
+			List<Way> levelBoundaries = boundaries.get(adminlevel);
+			log.info(levelBoundaries.size(),"boundaries");
+			for (Way boundary : levelBoundaries) {
+				if (boundary.getTag("name") == null) {
+					continue;
+				}
+
+				boundary.addTag(tag, boundary.getTag("name"));
+			}
+		}
+		
+		for (Integer adminlevel : levelTags.keySet()) {
+			String tag = levelTags.get(adminlevel);
+			log.info("Processing admin level",adminlevel,"with tag",tag);
+			List<Way> levelBoundaries = boundaries.get(adminlevel);
+			log.info(levelBoundaries.size(),"boundaries");
+			for (Way boundary : levelBoundaries) {
+				if (boundary.getTag("name") == null) {
+					continue;
+				}
+
+				log.info("Checking",boundary.toTagString());
+				
+				MultiHashMap<Coord, Element> elems = quadTree.get(boundary
+						.getPoints());
+				log.info(elems.size(),"elements found");
+				HashSet<Element> uniqueElems = new HashSet<Element>();
+				for (List<Element> elemList : elems.values()) {
+					uniqueElems.addAll(elemList);
+				}
+				
+				for (Element elem : uniqueElems) {
+					if (elem.getTag(tag) == null) {
+						if (log.isDebugEnabled())
+						log.debug("Add tag",tag+"="+boundary.getTag("name"),"to",elem.toTagString());
+						elem.addTag(tag, boundary.getTag("name"));
+					}
+				}
+			}
+		}
+		log.info("Address hook finished");
+	}
+
+}
Index: src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonFinishHook.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonFinishHook.java	(revision 0)
+++ src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonFinishHook.java	(revision 0)
@@ -0,0 +1,46 @@
+package uk.me.parabola.mkgmap.reader.osm;
+
+import java.util.Arrays;
+
+import uk.me.parabola.log.Logger;
+import uk.me.parabola.util.EnhancedProperties;
+
+public class MultiPolygonFinishHook extends OsmReadingHooksAdaptor {
+	private static final Logger log = Logger.getLogger(MultiPolygonFinishHook.class);
+	
+	private ElementSaver saver;
+	
+	public MultiPolygonFinishHook() {
+	}
+
+	@Override
+	public boolean init(ElementSaver saver, EnhancedProperties props) {
+		this.saver = saver;
+		return true;
+	}
+
+	@Override
+	public void end() {
+		log.error("Finish multipolygons");
+		for (Way way : saver.getWays().values()) {
+			String removeTag = way.getTag(ElementSaver.MKGMAP_REMOVE_TAG);
+			if (removeTag == null) {
+				continue;
+			}
+			if (ElementSaver.MKGMAP_REMOVE_TAG_ALL_KEY.equals(removeTag)) {
+				if (log.isDebugEnabled())
+					log.debug("Remove all tags from way",way.getId(),way.toTagString());
+				way.removeAllTags();
+			} else {
+				String[] tagsToRemove = removeTag.split(";");
+				if (log.isDebugEnabled())
+					log.debug("Remove tags",Arrays.toString(tagsToRemove),"from way",way.getId(),way.toTagString());
+				for (String rTag : tagsToRemove) {
+					way.deleteTag(rTag);
+				}
+				way.deleteTag(ElementSaver.MKGMAP_REMOVE_TAG);
+			}
+		}	
+	}
+
+}
Index: src/uk/me/parabola/mkgmap/reader/osm/ElementSaver.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/ElementSaver.java	(revision 1865)
+++ src/uk/me/parabola/mkgmap/reader/osm/ElementSaver.java	(working copy)
@@ -14,7 +14,6 @@
 
 import java.util.AbstractMap;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.IdentityHashMap;
 import java.util.LinkedHashMap;
@@ -206,7 +205,6 @@
 	
 	public void finishLoading() {
 		coordMap = null;
-		finishMultiPolygons();
 	}
 
 	/**
@@ -244,29 +242,6 @@
 		relationMap = null;
 	}
 
-
-	private void finishMultiPolygons() {
-		for (Way way : wayMap.values()) {
-			String removeTag = way.getTag(MKGMAP_REMOVE_TAG);
-			if (removeTag == null) {
-				continue;
-			}
-			if (MKGMAP_REMOVE_TAG_ALL_KEY.equals(removeTag)) {
-				if (log.isDebugEnabled())
-					log.debug("Remove all tags from way",way.getId(),way.toTagString());
-				way.removeAllTags();
-			} else {
-				String[] tagsToRemove = removeTag.split(";");
-				if (log.isDebugEnabled())
-					log.debug("Remove tags",Arrays.toString(tagsToRemove),"from way",way.getId(),way.toTagString());
-				for (String rTag : tagsToRemove) {
-					way.deleteTag(rTag);
-				}
-				way.deleteTag(MKGMAP_REMOVE_TAG);
-			}
-		}
-	}
-
 	/**
 	 *
 	 * "soft clip" each way that crosses a boundary by adding a point
@@ -564,6 +539,10 @@
 		map.put(p, inc);
 	}
 
+	public Map<Long, Node> getNodes() {
+		return nodeMap;
+	}
+	
 	public Map<Long, Way> getWays() {
 		return wayMap;
 	}
Index: src/uk/me/parabola/mkgmap/reader/osm/OsmMapDataSource.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/OsmMapDataSource.java	(revision 1865)
+++ src/uk/me/parabola/mkgmap/reader/osm/OsmMapDataSource.java	(working copy)
@@ -52,7 +52,9 @@
 	private Style style;
 	private final OsmReadingHooks[] POSSIBLE_HOOKS = {
 			new SeaGenerator(),
+			new MultiPolygonFinishHook(),
 			new HighwayHooks(),
+			new AddressHook(),
 	};
 	private OsmConverter converter;
 	private final Set<String> usedTags = new HashSet<String>();
Index: src/uk/me/parabola/mkgmap/reader/osm/Element.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/Element.java	(revision 1865)
+++ src/uk/me/parabola/mkgmap/reader/osm/Element.java	(working copy)
@@ -27,6 +27,10 @@
 	private String name;
 	private long id;
 
+	public int getTagCount() {
+		return (tags == null ? 0 : tags.size());
+	}
+	
 	/**
 	 * Add a tag to the way.  Some tags are recognised separately and saved in
 	 * separate fields.
Index: src/uk/me/parabola/mkgmap/build/Locator.java
===================================================================
--- src/uk/me/parabola/mkgmap/build/Locator.java	(revision 1865)
+++ src/uk/me/parabola/mkgmap/build/Locator.java	(working copy)
@@ -62,7 +62,7 @@
 public class Locator {
 
 	private final MapPointFastFindMap cityMap  					= new MapPointFastFindMap();
-	private final MapPointMultiMap  	fuzzyCityMap			= new MapPointMultiMap();
+//	private final MapPointMultiMap  	fuzzyCityMap			= new MapPointMultiMap();
 	private final List<MapPoint> placesMap  =  new ArrayList<MapPoint>();
 
 	private final LocatorConfig locConfig = new LocatorConfig();
@@ -73,22 +73,23 @@
 
 	public void addLocation(MapPoint p) 
 	{
-		resolveIsInInfo(p); // Pre-process the is_in field
+//		if (true) return;
+//		resolveIsInInfo(p); // Pre-process the is_in field
 		
-		if(autoFillLevel < 1 &&  p.getCity() == null)
-		{			
-			// Without auto-fill city name is the name of the tag
-			p.setCity(p.getName());
-		}
+//		if(autoFillLevel < 1 &&  p.getCity() == null)
+//		{			
+//			// Without auto-fill city name is the name of the tag
+//			p.setCity(p.getName());
+//		}
 		
 		if(p.getCity() != null)
 		{
 			cityMap.put(p.getCity(), p);
 			
-			fuzzyCityMap.put(fuzzyDecode(p.getCity()),p);
-
-			if(p.getName() != null && !p.getCity().equals(p.getName())) // Name variants ?
-				fuzzyCityMap.put(fuzzyDecode(p.getName()),p);
+//			fuzzyCityMap.put(fuzzyDecode(p.getCity()),p);
+//
+//			if(p.getName() != null && !p.getCity().equals(p.getName())) // Name variants ?
+//				fuzzyCityMap.put(fuzzyDecode(p.getName()),p);
 		}
 		else
 		{
@@ -259,21 +260,21 @@
 			}
 	 	}
 		
-		nextCityList = fuzzyCityMap.getList(fuzzyDecode(p.getCity()));
-		
-		if(nextCityList != null)
-		{
-			for (MapPoint nextCity: nextCityList)		
-			{
-				Double dist = p.getLocation().distance(nextCity.getLocation());
-
-				if(dist < minDist)
-				{
-					minDist = dist;
-					near = nextCity;
-				}
-			}
-	 	}
+//		nextCityList = fuzzyCityMap.getList(fuzzyDecode(p.getCity()));
+//		
+//		if(nextCityList != null)
+//		{
+//			for (MapPoint nextCity: nextCityList)		
+//			{
+//				Double dist = p.getLocation().distance(nextCity.getLocation());
+//
+//				if(dist < minDist)
+//				{
+//					minDist = dist;
+//					near = nextCity;
+//				}
+//			}
+//	 	}
 		
 		if(near != null && minDist < 30000) // Wrong hit more the 30 km away ?
 			return near;
@@ -300,9 +301,9 @@
 				String biggerCityName = aCityList.trim();
 
 
-				if (fuzzy)
-					nextCityList = fuzzyCityMap.getList(fuzzyDecode(biggerCityName));
-				else
+//				if (fuzzy)
+//					nextCityList = fuzzyCityMap.getList(fuzzyDecode(biggerCityName));
+//				else
 					nextCityList = cityMap.getList(biggerCityName);
 
 				if (nextCityList != null) {
@@ -340,7 +341,7 @@
 	}
 
 	public void resolve() {
-
+		if (true) return;
 		if(autoFillLevel < 0)
 			return;			// Nothing to do if auto-fill is fully disabled
 
@@ -420,7 +421,7 @@
 					if( place.getCity() != null)
 					{
 						cityMap.put(place.getName(),place);
-						fuzzyCityMap.put(fuzzyDecode(place.getName()),place);
+//						fuzzyCityMap.put(fuzzyDecode(place.getName()),place);
 						placesMap.set(i, null);
 					}
 					else if(autoFillLevel < 2 && (runCount + 1) == maxRuns)
@@ -442,21 +443,21 @@
 		
 	}
 
-	private String fuzzyDecode(String stringToDecode)
-	{
-
-		if(stringToDecode == null)
-			return stringToDecode;
-
-		String decodeString = stringToDecode.toUpperCase().trim();
-
-		// German umlaut resolution
-		//decodeString = decodeString.replaceAll("��","AE").replaceAll("��","UE").replaceAll("��","OE");
-		
-		//if(decodeString.equals(stringToDecode) == false)
-		//	System.out.println(stringToDecode + " -> " + decodeString);
-
-		return (decodeString);
-	}
+//	private String fuzzyDecode(String stringToDecode)
+//	{
+//
+//		if(stringToDecode == null)
+//			return stringToDecode;
+//
+//		String decodeString = stringToDecode.toUpperCase().trim();
+//
+//		// German umlaut resolution
+//		//decodeString = decodeString.replaceAll("��","AE").replaceAll("��","UE").replaceAll("��","OE");
+//		
+//		//if(decodeString.equals(stringToDecode) == false)
+//		//	System.out.println(stringToDecode + " -> " + decodeString);
+//
+//		return (decodeString);
+//	}
 }
 
Index: src/uk/me/parabola/mkgmap/build/MapBuilder.java
===================================================================
--- src/uk/me/parabola/mkgmap/build/MapBuilder.java	(revision 1865)
+++ src/uk/me/parabola/mkgmap/build/MapBuilder.java	(working copy)
@@ -286,22 +286,22 @@
 				String cityRegionName  = line.getRegion();
 				String zipStr = line.getZip();
 
-				if(cityName == null) {
-					// Get name of next city if untagged
-
-					tempPoint.setLocation(line.getLocation());
-					MapPoint nextCity = locator.findNextPoint(tempPoint);
-
-					if(nextCity != null) {
-						cityName = nextCity.getCity();
-						if(cityCountryName == null)
-							cityCountryName = nextCity.getCountry();
-						if(cityRegionName == null)
-							cityRegionName = nextCity.getRegion();
-						if(zipStr == null)
-							zipStr = nextCity.getZip();
-					}
-				}
+//				if(cityName == null) {
+//					// Get name of next city if untagged
+//
+//					tempPoint.setLocation(line.getLocation());
+//					MapPoint nextCity = locator.findNextPoint(tempPoint);
+//
+//					if(nextCity != null) {
+//						cityName = nextCity.getCity();
+//						if(cityCountryName == null)
+//							cityCountryName = nextCity.getCountry();
+//						if(cityRegionName == null)
+//							cityRegionName = nextCity.getRegion();
+//						if(zipStr == null)
+//							zipStr = nextCity.getZip();
+//					}
+//				}
 
 				if(cityName != null) {
 
Index: src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java	(revision 1865)
+++ src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java	(working copy)
@@ -662,6 +662,23 @@
 		
 		if(city == null)
 			city = element.getTag("openGeoDB:name");
+
+		// set the results of the address hook
+		if(country == null)
+			country = element.getTag("mkgmap:country");
+
+		if(zip == null)
+			zip = element.getTag("mkgmap:postcode");
+		
+		if(city == null)
+			city = element.getTag("mkgmap:city");
+		
+		if (region == null)
+			region = element.getTag("mkgmap:subdistrict");
+		if (region == null)
+			region = element.getTag("mkgmap:district");
+		if (region == null)
+			region = element.getTag("mkgmap:province");
 		
 		if(city != null)
 			ms.setCity(city);
