diff --git a/resources/styles/default/lines b/resources/styles/default/lines
index dee0024..da2e1f6 100644
--- a/resources/styles/default/lines
+++ b/resources/styles/default/lines
@@ -16,7 +16,7 @@ junction=roundabout & highway=unclassified [0x0c road_class=1 road_speed=2 resol
 junction=roundabout [0x0c road_class=0 road_speed=1 resolution 21]
 
 # Set highway names to include the reference if there is one
-highway=* {name '${name} (${ref})' | '${ref}' | '${name}' }
+#highway=* {name '${name} (${ref})' | '${ref}' | '${name}' }
 highway=bridleway {add access = no; add bicycle = yes; add foot = yes} [0x16 road_class=0 road_speed=0 resolution 23]
 highway=byway [0x16 road_class=0 road_speed=0 resolution 23]
 highway=cycleway {add access = no; add bicycle = yes; add foot = yes} [0x16 road_class=0 road_speed=1 resolution 23]
diff --git a/src/uk/me/parabola/imgfmt/app/Label.java b/src/uk/me/parabola/imgfmt/app/Label.java
index 3ac3a44..7ff47a9 100644
--- a/src/uk/me/parabola/imgfmt/app/Label.java
+++ b/src/uk/me/parabola/imgfmt/app/Label.java
@@ -32,7 +32,7 @@ import uk.me.parabola.log.Logger;
  *
  * @author Steve Ratcliffe
  */
-public class Label {
+public class Label implements Comparable {
 	private static final Logger log = Logger.getLogger(Label.class);
 
 	// The compressed form of the label text.
@@ -47,6 +47,14 @@ public class Label {
 		length = etext.getLength();
 	}
 
+	public byte[] getCtext() {
+		return ctext;
+	}
+
+	public int getLength() {
+		return length;
+	}
+
 	/**
 	 * The offset of this label in the LBL file.  The first byte of this file
 	 * is zero and an offset of zero means that the label has a zero length/is
@@ -107,4 +115,18 @@ public class Label {
 	public int hashCode() {
 		return offset;
 	}
+
+    	public int compareTo(Object other) {
+		Label o = (Label)other;
+		if(this == other)
+			return 0;
+		for(int i = 0; i < length && i < o.length; ++i) {
+			int diff = (ctext[i] & 0xff) - (o.ctext[i] & 0xff);
+			if(diff != 0)
+				return diff;
+		}
+		if(length == o.length)
+			return 0;
+		return (length > o.length)? 1 : -1;
+	}
 }
diff --git a/src/uk/me/parabola/imgfmt/app/lbl/City.java b/src/uk/me/parabola/imgfmt/app/lbl/City.java
index 69a7c4d..6338f68 100644
--- a/src/uk/me/parabola/imgfmt/app/lbl/City.java
+++ b/src/uk/me/parabola/imgfmt/app/lbl/City.java
@@ -26,7 +26,7 @@ import uk.me.parabola.imgfmt.app.trergn.Subdivision;
  * 
  * @author Steve Ratcliffe
  */
-public class City {
+public class City implements Comparable {
 	private static final int POINT_REF = 0x8000;
 	private static final int REGION_IS_COUNTRY = 0x4000;
 
@@ -104,4 +104,13 @@ public class City {
 		pointRef = true;
 		this.subdivision = subdivision;
 	}
+
+	public int compareTo(Object other) {
+		City o = (City)other;
+		if(o == this)
+			return 0;
+		if(label != null && o.label != null)
+			return label.compareTo(o.label);
+		return hashCode() - o.hashCode();
+	}
 }
diff --git a/src/uk/me/parabola/imgfmt/app/lbl/Country.java b/src/uk/me/parabola/imgfmt/app/lbl/Country.java
index 4c001e8..53d03e3 100644
--- a/src/uk/me/parabola/imgfmt/app/lbl/Country.java
+++ b/src/uk/me/parabola/imgfmt/app/lbl/Country.java
@@ -44,4 +44,8 @@ public class Country {
 	public void setLabel(Label label) {
 		this.label = label;
 	}
+
+	public Label getLabel() {
+		return label;
+	}
 }
diff --git a/src/uk/me/parabola/imgfmt/app/lbl/LBLFile.java b/src/uk/me/parabola/imgfmt/app/lbl/LBLFile.java
index f01389a..5a1373e 100644
--- a/src/uk/me/parabola/imgfmt/app/lbl/LBLFile.java
+++ b/src/uk/me/parabola/imgfmt/app/lbl/LBLFile.java
@@ -214,4 +214,20 @@ public class LBLFile extends ImgFile {
 	public PlacesHeader getPlaceHeader() {
 		return lblHeader.getPlaceHeader();
 	}
+
+	public int numCities() {
+		return places.numCities();
+	}
+
+	public int numZips() {
+		return places.numZips();
+	}
+
+	public int numHighways() {
+		return places.numHighways();
+	}
+
+	public int numExitFacilities() {
+		return places.numExitFacilities();
+	}
 }
diff --git a/src/uk/me/parabola/imgfmt/app/lbl/PlacesFile.java b/src/uk/me/parabola/imgfmt/app/lbl/PlacesFile.java
index 7f1329f..b84f6cf 100644
--- a/src/uk/me/parabola/imgfmt/app/lbl/PlacesFile.java
+++ b/src/uk/me/parabola/imgfmt/app/lbl/PlacesFile.java
@@ -24,10 +24,11 @@ import java.util.List;
 import java.util.Map;
 
 import uk.me.parabola.imgfmt.app.trergn.Subdivision;
-
 import uk.me.parabola.imgfmt.app.ImgFileWriter;
 import uk.me.parabola.imgfmt.app.Label;
 
+import uk.me.parabola.util.Sortable;
+
 import uk.me.parabola.mkgmap.general.Exit;
 
 /**
@@ -36,9 +37,13 @@ import uk.me.parabola.mkgmap.general.Exit;
  */
 public class PlacesFile {
 	private final Map<String, Country> countries = new LinkedHashMap<String, Country>();
+
 	private final Map<String, Region> regions = new LinkedHashMap<String, Region>();
+	private final List<Sortable<String, Region>> regionList = new ArrayList<Sortable<String, Region>>();
+
 	private final Map<String, City> cities = new LinkedHashMap<String, City>();
-	private final List<CitySort> cityList = new ArrayList<CitySort>();
+	private final List<Sortable<String, City>> cityList = new ArrayList<Sortable<String, City>>();
+
 	private final Map<String, Zip> postalCodes = new LinkedHashMap<String, Zip>();
 	private final List<Highway> highways = new ArrayList<Highway>();
 	private final List<ExitFacility> exitFacilities = new ArrayList<ExitFacility>();
@@ -69,12 +74,12 @@ public class PlacesFile {
 			c.write(writer);
 		placeHeader.endCountries(writer.position());
 
-		for (Region r : regions.values())
-			r.write(writer);
+		for (Sortable<String, Region> sr : regionList)
+			sr.getValue().write(writer);
 		placeHeader.endRegions(writer.position());
 
-		for (CitySort c : cityList)
-			c.getCity().write(writer);
+		for (Sortable<String, City> sc : cityList)
+			sc.getValue().write(writer);
 
 		placeHeader.endCity(writer.position());
 
@@ -147,15 +152,16 @@ public class PlacesFile {
 	
 		String s = abbr != null ? name + (char)0x1d + abbr : name;
 
-		String uniqueRegionName = s.toUpperCase().concat(Long.toString(country.getIndex()));	
+		String uniqueRegionName = s.toUpperCase() + "_C" + country.getLabel().getOffset();
 	
 		Region r = regions.get(uniqueRegionName);
 		
 		if(r == null)
 		{
-			r = new Region(country, regions.size()+1);
+			r = new Region(country);
 			Label l = lblFile.newLabel(s);
 			r.setLabel(l);
+			regionList.add(new Sortable<String, Region>(name, r));
 			regions.put(uniqueRegionName, r);
 		}
 		return r;
@@ -163,7 +169,7 @@ public class PlacesFile {
 
 	City createCity(Country country, String name, boolean unique) {
 		
-		String uniqueCityName = name.toUpperCase().concat("_C").concat(Long.toString(country.getIndex()));
+		String uniqueCityName = name.toUpperCase() + "_C" + country.getLabel().getOffset();
 		
 		City c = null;
 
@@ -177,16 +183,16 @@ public class PlacesFile {
 			Label l = lblFile.newLabel(name);
 			c.setLabel(l);
 
-			cityList.add(new CitySort(name, c));
+			cityList.add(new Sortable<String, City>(name, c));
 			cities.put(uniqueCityName, c);
 		}
 
 		return c;
-  }
+	}
 
 	City createCity(Region region, String name, boolean unique) {
 		
-		String uniqueCityName = name.toUpperCase().concat("_R").concat(Long.toString(region.getIndex()));
+		String uniqueCityName = name.toUpperCase() + "_R" + region.getLabel().getOffset();
 		
 		City c = null;
 
@@ -200,26 +206,13 @@ public class PlacesFile {
 			Label l = lblFile.newLabel(name);
 			c.setLabel(l);
 
-			cityList.add(new CitySort(name, c));
+			cityList.add(new Sortable<String, City>(name, c));
 			cities.put(uniqueCityName, c);
 		}
 
 		return c;
 	}
 
-	private void sortCities()
-	{
-		int index = 1;
-
-		Collections.sort(cityList, new Comparator<CitySort>() {
-			public int compare(CitySort o1, CitySort o2) {
-				return o1.getKey().compareTo(o2.getKey());
-			}
-		});
-		for (CitySort cs: cityList)
-			cs.getCity().setIndex(index++);
-	}
-
 	Zip createZip(String code) {
 	
 		Zip z = postalCodes.get(code);
@@ -293,7 +286,15 @@ public class PlacesFile {
 
 	void allPOIsDone() {
 
-		sortCities();
+		int index = 1;
+		Collections.sort(regionList);
+		for (Sortable<String, Region> sr: regionList)
+			sr.getValue().setIndex(index++);
+
+		index = 1;
+		Collections.sort(cityList);
+		for (Sortable<String, City> sc: cityList)
+			sc.getValue().setIndex(index++);
 
 		poisClosed = true;
 
@@ -308,21 +309,19 @@ public class PlacesFile {
 			ofs += p.calcOffset(ofs, poiFlags, cities.size(), postalCodes.size(), highways.size(), exitFacilities.size());
 	}
 
-	private class CitySort {
-		private final String key;
-		private final City city;
+	public int numCities() {
+		return cities.size();
+	}
 
-		private CitySort(String key, City city) {
-			this.key = key;
-			this.city = city;
-		}
+	public int numZips() {
+		return postalCodes.size();
+	}
 
-		public String getKey() {
-			return key;
-		}
+	public int numHighways() {
+		return highways.size();
+	}
 
-		public City getCity() {
-			return city;
-		}
+	public int numExitFacilities() {
+		return exitFacilities.size();
 	}
 }
diff --git a/src/uk/me/parabola/imgfmt/app/lbl/Region.java b/src/uk/me/parabola/imgfmt/app/lbl/Region.java
index 6c4c12f..36d7ede 100644
--- a/src/uk/me/parabola/imgfmt/app/lbl/Region.java
+++ b/src/uk/me/parabola/imgfmt/app/lbl/Region.java
@@ -25,14 +25,13 @@ import uk.me.parabola.imgfmt.app.ImgFileWriter;
  * @author Steve Ratcliffe
  */
 public class Region {
-	private final char index;
+	private char index;
 
 	private final Country country;
 	private Label label;
 
-	public Region(Country country, int index) {
+	public Region(Country country) {
 		this.country = country;
-		this.index = (char) index;
 	}
 
 	public void write(ImgFileWriter writer) {
@@ -41,10 +40,23 @@ public class Region {
 	}
 
 	public char getIndex() {
+		assert index > 0 : "Index not yet set";
 		return index;
 	}
 
+	public Country getCountry() {
+		return country;
+	}
+
+	public void setIndex(int index) {
+		this.index = (char)index;
+	}
+
 	public void setLabel(Label label) {
 		this.label = label;
 	}
+
+	public Label getLabel() {
+		return label;
+	}
 }
diff --git a/src/uk/me/parabola/imgfmt/app/net/NETFile.java b/src/uk/me/parabola/imgfmt/app/net/NETFile.java
index 2460271..0d74a37 100644
--- a/src/uk/me/parabola/imgfmt/app/net/NETFile.java
+++ b/src/uk/me/parabola/imgfmt/app/net/NETFile.java
@@ -16,6 +16,8 @@
  */
 package uk.me.parabola.imgfmt.app.net;
 
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 import uk.me.parabola.imgfmt.Utils;
@@ -23,7 +25,9 @@ import uk.me.parabola.imgfmt.app.BufferedImgFileReader;
 import uk.me.parabola.imgfmt.app.BufferedImgFileWriter;
 import uk.me.parabola.imgfmt.app.ImgFile;
 import uk.me.parabola.imgfmt.app.ImgFileWriter;
+import uk.me.parabola.imgfmt.app.Label;
 import uk.me.parabola.imgfmt.fs.ImgChannel;
+import uk.me.parabola.util.Sortable;
 
 /**
  * The NET file.  This consists of information about roads.  It is not clear
@@ -47,12 +51,12 @@ public class NETFile extends ImgFile {
 		}
 	}
 
-	public void write() {
+	public void write(int numCities, int numZips) {
 		// Write out the actual file body.
 		ImgFileWriter writer = netHeader.makeRoadWriter(getWriter());
 		try {
 			for (RoadDef rd : roads)
-				rd.writeNet1(writer);
+				rd.writeNet1(writer, numCities, numZips);
 
 		} finally {
 			Utils.closeFile(writer);
@@ -60,8 +64,23 @@ public class NETFile extends ImgFile {
 	}
 
 	public void writePost(ImgFileWriter rgn) {
-		for (RoadDef rd : roads)
+		List<Sortable<Label, RoadDef>> sortedRoads = new ArrayList<Sortable<Label, RoadDef>>(roads.size());
+
+		for (RoadDef rd : roads) {
 			rd.writeRgnOffsets(rgn);
+			Label[] l = rd.getLabels();
+			for(int i = 0; i < l.length && l[i] != null; ++i)
+				if(l[i].getLength() != 0)
+					sortedRoads.add(new Sortable<Label, RoadDef>(l[i], rd));
+		}
+
+		if(sortedRoads.size() > 0) {
+			Collections.sort(sortedRoads);
+			ImgFileWriter writer = netHeader.makeSortedRoadWriter(getWriter());
+			for(Sortable<Label, RoadDef> srd : sortedRoads)
+				srd.getValue().putSortedRoadEntry(writer, srd.getKey());
+			Utils.closeFile(writer);
+		}
 
 		getHeader().writeHeader(getWriter());
 	}
diff --git a/src/uk/me/parabola/imgfmt/app/net/NETHeader.java b/src/uk/me/parabola/imgfmt/app/net/NETHeader.java
index 3dd1bf0..c8a2b0d 100644
--- a/src/uk/me/parabola/imgfmt/app/net/NETHeader.java
+++ b/src/uk/me/parabola/imgfmt/app/net/NETHeader.java
@@ -95,4 +95,9 @@ public class NETHeader extends CommonHeader {
 		roadDefinitions.setPosition(writer.position());
 		return new SectionWriter(writer, roadDefinitions);
 	}
+
+	ImgFileWriter makeSortedRoadWriter(ImgFileWriter writer) {
+		sortedRoads.setPosition(writer.position());
+		return new SectionWriter(writer, sortedRoads);
+	}
 }
diff --git a/src/uk/me/parabola/imgfmt/app/net/RoadDef.java b/src/uk/me/parabola/imgfmt/app/net/RoadDef.java
index 4e6199a..7f08e57 100644
--- a/src/uk/me/parabola/imgfmt/app/net/RoadDef.java
+++ b/src/uk/me/parabola/imgfmt/app/net/RoadDef.java
@@ -23,6 +23,8 @@ import java.util.TreeMap;
 
 import uk.me.parabola.imgfmt.app.ImgFileWriter;
 import uk.me.parabola.imgfmt.app.Label;
+import uk.me.parabola.imgfmt.app.lbl.City;
+import uk.me.parabola.imgfmt.app.lbl.Zip;
 import uk.me.parabola.imgfmt.app.trergn.Polyline;
 import uk.me.parabola.log.Logger;
 
@@ -47,7 +49,7 @@ import uk.me.parabola.log.Logger;
  * @author Robert Vollmert
  */
 
-public class RoadDef {
+public class RoadDef implements Comparable {
 	private static final Logger log = Logger.getLogger(RoadDef.class);
 
 	// the offset in Nod2 of our Nod2 record
@@ -74,10 +76,10 @@ public class RoadDef {
 	 * Everything that's relevant for writing to NET1.
 	 */
 
-	private static final int NET_FLAG_NODINFO = 0x40;
-	private static final int NET_FLAG_UNK1 = 0x04; // lock on road?
-	private static final int NET_FLAG_ONEWAY = 0x02;
-	private static final int NET_FLAG_ADDRINFO = 0x01;
+	private static final int NET_FLAG_NODINFO  = 0x40;
+	private static final int NET_FLAG_ADDRINFO = 0x10;
+	private static final int NET_FLAG_UNK1     = 0x04; // lock on road?
+	private static final int NET_FLAG_ONEWAY   = 0x02;
 
 	private int netFlags = NET_FLAG_UNK1;
 
@@ -93,11 +95,14 @@ public class RoadDef {
 
 	private final SortedMap<Integer,List<RoadIndex>> roadIndexes = new TreeMap<Integer,List<RoadIndex>>();
 
+	private City city;
+	private Zip zip;
+
 	/**
 	 * This is for writing to NET1.
 	 * @param writer A writer that is positioned within NET1.
 	 */
-	void writeNet1(ImgFileWriter writer) {
+	void writeNet1(ImgFileWriter writer, int numCities, int numZips) {
 		if (numlabels == 0)
 			return;
 		assert numlabels > 0;
@@ -112,6 +117,30 @@ public class RoadDef {
 
 		writeLevelDivs(writer, maxlevel);
 
+		if((netFlags & NET_FLAG_ADDRINFO) != 0) {
+			writer.put((byte)0); // unknown (nearly always zero)
+			int code = 0xe8;     // zip and city present
+			if(city == null)
+				code |= 0x10; // no city
+			if(zip == null)
+				code |= 0x04; // no zip
+			writer.put((byte)code);
+			if(zip != null) {
+				char zipIndex = (char)zip.getIndex();
+				if(numZips > 255)
+					writer.putChar(zipIndex);
+				else
+					writer.put((byte)zipIndex);
+			}
+			if(city != null) {
+				char cityIndex = (char)city.getIndex();
+				if(numCities > 255)
+					writer.putChar(cityIndex);
+				else
+					writer.put((byte)cityIndex);
+			}
+		}
+
 		if (hasNodInfo()) {
 			// This is the offset of an entry in NOD2
 			int val = offsetNod2;
@@ -135,6 +164,15 @@ public class RoadDef {
 		}
 	}
 
+	public void putSortedRoadEntry(ImgFileWriter writer, Label label) {
+		for(int i = 0; i < labels.length && labels[i] != null; ++i) {
+			if(labels[i].equals(label)) {
+				writer.put3((i << 22) | offsetNet1);
+				return;
+			}
+		}
+	}
+
 	private int writeLevelCount(ImgFileWriter writer) {
 		int maxlevel = getMaxZoomLevel();
 		for (int i = 0; i <= maxlevel; i++) {
@@ -159,13 +197,30 @@ public class RoadDef {
 	}
 
 	public void addLabel(Label l) {
-		// XXX: apparently, just one label for now?
-		if (numlabels == 0)
-			labels[numlabels++] = l;
-		else if (!l.equals(labels[0]))
+		int i;
+		for (i = 0; i < MAX_LABELS && labels[i] != null; ++i) {
+			if (l.equals(labels[i])) {
+				// label already present
+				return;
+			}
+		}
+
+		if (i < MAX_LABELS) {
+			labels[i] = l;
+			++numlabels;
+		}
+		else
 			log.warn("discarding extra label", l);
 	}
 
+	public int getNumLabels() {
+		return numlabels;
+	}
+
+	public Label[] getLabels() {
+		return labels;
+	}
+
 	/**
 	 * Add a polyline to this road.
 	 *
@@ -458,4 +513,25 @@ public class RoadDef {
 		tabAInfo |= TABA_FLAG_ONEWAY;
 		netFlags |= NET_FLAG_ONEWAY;
 	}
+
+	public void setCity(City city) {
+		this.city = city;
+		netFlags |= NET_FLAG_ADDRINFO;
+	}
+
+	public void setZip(Zip zip) {
+		this.zip = zip;
+		netFlags |= NET_FLAG_ADDRINFO;
+	}
+
+	public int compareTo(Object other) {
+		// sort by city name - this is used to group together
+		// roads that have been split into segments
+		RoadDef o = (RoadDef)other;
+		if(o == this)
+			return 0;
+		if(city != null && o.city != null)
+			return city.compareTo(o.city);
+		return hashCode() - o.hashCode();
+	}
 }
diff --git a/src/uk/me/parabola/imgfmt/app/trergn/MapObject.java b/src/uk/me/parabola/imgfmt/app/trergn/MapObject.java
index 550a0bd..9a3c017 100644
--- a/src/uk/me/parabola/imgfmt/app/trergn/MapObject.java
+++ b/src/uk/me/parabola/imgfmt/app/trergn/MapObject.java
@@ -19,6 +19,9 @@ package uk.me.parabola.imgfmt.app.trergn;
 import uk.me.parabola.imgfmt.app.Label;
 import uk.me.parabola.imgfmt.app.ImgFileWriter;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * An object that appears in a map.  One of point, polyline, polygon or indexed
  * point.
@@ -35,8 +38,9 @@ public abstract class MapObject {
 	// the division.
 	private Subdivision subdiv;
 
-	// The lable for this object
+	// The label(s) for this object
 	private Label label;
+	private List<Label> refLabels;
 
 	// The type of road etc.
 	private int type;
@@ -65,6 +69,12 @@ public abstract class MapObject {
 		this.label = label;
 	}
 
+	public void addRefLabel(Label refLabel) {
+		if(refLabels == null)
+			refLabels = new ArrayList<Label>();
+		refLabels.add(refLabel);
+	}
+
 	protected int getType() {
 		return type;
 	}
@@ -126,4 +136,8 @@ public abstract class MapObject {
 	protected Label getLabel() {
 		return label;
 	}
+
+	public List<Label> getRefLabels() {
+		return refLabels;
+	}
 }
diff --git a/src/uk/me/parabola/imgfmt/app/trergn/Polyline.java b/src/uk/me/parabola/imgfmt/app/trergn/Polyline.java
index 6884dfa..8e0d244 100644
--- a/src/uk/me/parabola/imgfmt/app/trergn/Polyline.java
+++ b/src/uk/me/parabola/imgfmt/app/trergn/Polyline.java
@@ -22,6 +22,7 @@ import java.util.List;
 import uk.me.parabola.imgfmt.app.BitWriter;
 import uk.me.parabola.imgfmt.app.Coord;
 import uk.me.parabola.imgfmt.app.ImgFileWriter;
+import uk.me.parabola.imgfmt.app.Label;
 import uk.me.parabola.imgfmt.app.net.RoadDef;
 import uk.me.parabola.log.Logger;
 
@@ -110,6 +111,11 @@ public class Polyline extends MapObject {
 			roaddef.addLabel(getLabel());
 			roaddef.addOffsetTarget(file.position(),
 					FLAG_NETINFO | (loff & FLAG_EXTRABIT));
+			// also add ref label(s) if present
+			List<Label> refLabels = getRefLabels();
+			if(refLabels != null)
+				for(Label rl : refLabels)
+					roaddef.addLabel(rl);
 		}
 
 		file.put3(loff);
diff --git a/src/uk/me/parabola/imgfmt/app/trergn/Subdivision.java b/src/uk/me/parabola/imgfmt/app/trergn/Subdivision.java
index 94ac8e8..081ff7b 100644
--- a/src/uk/me/parabola/imgfmt/app/trergn/Subdivision.java
+++ b/src/uk/me/parabola/imgfmt/app/trergn/Subdivision.java
@@ -208,12 +208,23 @@ public class Subdivision {
 		return p;
 	}
 
-	public Polyline createLine(String name) {
+	public Polyline createLine(String name, String ref) {
 		assert hasPolylines;
 		Label label = lblFile.newLabel(name);
 		Polyline pl = new Polyline(this);
 
 		pl.setLabel(label);
+		if(ref != null) {
+			// ref may contain multiple ids separated by ";"
+			for(String r : ref.split(";")) {
+				String tr = r.trim();
+				if(tr.length() > 0) {
+					//System.err.println("Adding ref " + tr + " to road " + name);
+					pl.addRefLabel(lblFile.newLabel(tr));
+				}
+			}
+		}
+
 		numPolylines++;
 		pl.setNumber(numPolylines);
 		return pl;
diff --git a/src/uk/me/parabola/mkgmap/build/MapBuilder.java b/src/uk/me/parabola/mkgmap/build/MapBuilder.java
index 83a58ba..23bce9d 100644
--- a/src/uk/me/parabola/mkgmap/build/MapBuilder.java
+++ b/src/uk/me/parabola/mkgmap/build/MapBuilder.java
@@ -184,7 +184,7 @@ public class MapBuilder implements Configurable {
 				nodFile.setNetwork(network.getCenters(), network.getRoadDefs(), network.getBoundary());
 				nodFile.write();
 			}
-			netFile.write();
+			netFile.write(lblFile.numCities(), lblFile.numZips());
 
 			if (nodFile != null) {
 				nodFile.writePost();
@@ -223,7 +223,7 @@ public class MapBuilder implements Configurable {
 			{
 				Country thisCountry;
 				Region 	thisRegion;
-				City 		thisCity;
+				City	thisCity;
 
 				String CountryStr = p.getCountry();
 				String RegionStr  = p.getRegion();
@@ -248,6 +248,53 @@ public class MapBuilder implements Configurable {
 				cityMap.put(p, thisCity);
 			}
 		}
+
+		MapPoint tempPoint = new MapPoint();
+
+		for (MapLine line : src.getLines()) {
+			if(line.isRoad()) {
+				String cityName = line.getCity();
+				String cityCountryName = line.getCountry();
+				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) {
+
+					Country cc = (cityCountryName == null)? country : lbl.createCountry(cityCountryName, locator.getCountryCode(cityCountryName));
+
+					Region cr = (cityRegionName == null)? region : lbl.createRegion(cc, cityRegionName, null);
+
+					if(cr != null) {
+						((MapRoad)line).setRoadCity(lbl.createCity(cr, cityName, false));
+					}
+					else {
+						((MapRoad)line).setRoadCity(lbl.createCity(cc, cityName, false));
+					}
+				}
+
+				if(zipStr != null) {
+					((MapRoad)line).setRoadZip(lbl.createZip(zipStr));
+				}
+
+			}
+		}
 	}
 
 	private void processPOIs(Map map, MapDataSource src) {
@@ -886,7 +933,7 @@ public class MapBuilder implements Configurable {
 			MapLine line = (MapLine) element;
 			assert line.getPoints().size() < 255 : "too many points";
 
-			Polyline pl = div.createLine(line.getName());
+			Polyline pl = div.createLine(line.getName(), line.getRef());
 			pl.setDirection(line.isDirection());
 
 			for (Coord co : line.getPoints())
diff --git a/src/uk/me/parabola/mkgmap/general/MapElement.java b/src/uk/me/parabola/mkgmap/general/MapElement.java
index 5f8d9bd..1c0fb3c 100644
--- a/src/uk/me/parabola/mkgmap/general/MapElement.java
+++ b/src/uk/me/parabola/mkgmap/general/MapElement.java
@@ -28,6 +28,7 @@ import uk.me.parabola.imgfmt.app.Coord;
  */
 public abstract class MapElement {
 	private String name;
+	private String ref;
 	private int type;
 
 	private int minResolution = 24;
@@ -45,6 +46,7 @@ public abstract class MapElement {
 
 	protected MapElement(MapElement orig) {
 		name = orig.name;
+		ref = orig.ref;
 		type = orig.type;
 		minResolution = orig.minResolution;
 		maxResolution = orig.maxResolution;
@@ -62,11 +64,20 @@ public abstract class MapElement {
 		return name;
 	}
 
+	public String getRef() {
+		return ref;
+	}
+
 	public void setName(String name) {
 	  if(name != null)
 		this.name = name.toUpperCase();
 	}
 
+	public void setRef(String ref) {
+	  if(ref != null)
+		this.ref = ref.toUpperCase();
+	}
+
 	public String getCity() {
 		return city;
 	}
diff --git a/src/uk/me/parabola/mkgmap/general/MapRoad.java b/src/uk/me/parabola/mkgmap/general/MapRoad.java
index 0262e0d..bd0eac4 100644
--- a/src/uk/me/parabola/mkgmap/general/MapRoad.java
+++ b/src/uk/me/parabola/mkgmap/general/MapRoad.java
@@ -16,6 +16,8 @@
  */
 package uk.me.parabola.mkgmap.general;
 
+import uk.me.parabola.imgfmt.app.lbl.City;
+import uk.me.parabola.imgfmt.app.lbl.Zip;
 import uk.me.parabola.imgfmt.app.net.RoadDef;
 
 /**
@@ -101,4 +103,12 @@ public class MapRoad extends MapLine {
 	public RoadDef getRoadDef() {
 		return roadDef;
 	}
+
+	public void setRoadCity(City c) {
+		this.roadDef.setCity(c);
+	}
+
+	public void setRoadZip(Zip z) {
+		this.roadDef.setZip(z);
+	}
 }
diff --git a/src/uk/me/parabola/mkgmap/main/MakeTestLangMap.java b/src/uk/me/parabola/mkgmap/main/MakeTestLangMap.java
index 3eeaa26..a730a18 100644
--- a/src/uk/me/parabola/mkgmap/main/MakeTestLangMap.java
+++ b/src/uk/me/parabola/mkgmap/main/MakeTestLangMap.java
@@ -73,7 +73,7 @@ public class MakeTestLangMap extends AbstractTestMap {
 			}
 
 			String name = new String(out);
-			Polyline l = div.createLine(name);
+			Polyline l = div.createLine(name, null);
 			double baseLat = lat + y * space;
 			Coord co = new Coord(baseLat, lon);
 			l.addCoord(co);
diff --git a/src/uk/me/parabola/mkgmap/main/MapMaker.java b/src/uk/me/parabola/mkgmap/main/MapMaker.java
index b8c5cfa..60e24a3 100644
--- a/src/uk/me/parabola/mkgmap/main/MapMaker.java
+++ b/src/uk/me/parabola/mkgmap/main/MapMaker.java
@@ -207,12 +207,6 @@ public class MapMaker implements MapProcessor {
 				}
 			}
 
-			List<MapPoint> cities = new ArrayList<MapPoint>();
-			for(MapPoint mp : src.getPoints()) {
-				if(mp.isCity())
-					cities.add(mp);
-			}
-
 			// generate a POI for each named road
 			for(List<MapLine> lr : findConnectedRoadsWithSameName(namedRoads)) {
 				// connected roads are not ordered so just use first in list
@@ -315,11 +309,12 @@ public class MapMaker implements MapProcessor {
 			int i2 = numPoints / 2;
 			int i1 = i2 - 1;
 			coord = new Coord((points.get(i1).getLatitude() +
-					points.get(i2).getLatitude()) / 2,
-					(points.get(i1).getLongitude() +
-							points.get(i2).getLongitude()) / 2);
-		} else
+					   points.get(i2).getLatitude()) / 2,
+					  (points.get(i1).getLongitude() +
+					   points.get(i2).getLongitude()) / 2);
+		} else {
 			coord = points.get(numPoints / 2);
+		}
 
 		String name = road.getName();
 		MapPoint rnp = new MapPoint();
diff --git a/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java b/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
index 942522a..dc6da0a 100644
--- a/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
+++ b/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
@@ -322,8 +322,44 @@ public class StyledConverter implements OsmConverter {
 		collector.addPoint(mp);
 	}
 
+	private String combineRefs(Element element) {
+		String ref = element.getTag("ref");
+		String int_ref = element.getTag("int_ref");
+		if(int_ref != null) {
+			if(ref == null)
+				ref = int_ref;
+			else
+				ref += ";" + int_ref;
+		}
+		String nat_ref = element.getTag("nat_ref");
+		if(nat_ref != null) {
+			if(ref == null)
+				ref = nat_ref;
+			else
+				ref += ";" + nat_ref;
+		}
+		String reg_ref = element.getTag("reg_ref");
+		if(reg_ref != null) {
+			if(ref == null)
+				ref = reg_ref;
+			else
+				ref += ";" + reg_ref;
+		}
+
+		return ref;
+	}
+
 	private void elementSetup(MapElement ms, GType gt, Element element) {
-		ms.setName(element.getName());
+		String name = element.getName();
+		String refs = combineRefs(element);
+		if(name == null && refs != null) {
+			// use first ref as name
+			name = refs.split(";")[0].trim();
+		}
+		if(name != null)
+			ms.setName(name);
+		if(refs != null)
+			ms.setRef(refs);
 		ms.setType(gt.getType());
 		ms.setMinResolution(gt.getMinResolution());
 		ms.setMaxResolution(gt.getMaxResolution());
@@ -333,9 +369,9 @@ public class StyledConverter implements OsmConverter {
 		String city         = element.getTag("addr:city");
 		String zip          = element.getTag("addr:postcode");
 		String street 	    = element.getTag("addr:street");
-		String houseNumber  = element.getTag("addr:housenumber");		
-		String phone	 	    = element.getTag("phone");		
-		String isIn	        = element.getTag("is_in");
+		String houseNumber  = element.getTag("addr:housenumber");
+		String phone        = element.getTag("phone");
+		String isIn         = element.getTag("is_in");
 		String country      = element.getTag("is_in:country");
 		String region       = element.getTag("is_in:county");
 		
@@ -609,7 +645,7 @@ public class StyledConverter implements OsmConverter {
 		// if the way is a motorway and has a ref tag, we may
 		// be generating a Garmin "highway" record for it so
 		// save the ref tag for later
-		String ref = way.getTag("ref");
+		String ref = combineRefs(way);
 		if(ref != null) {
 			road.setRef(ref);
 		}
diff --git a/src/uk/me/parabola/util/Sortable.java b/src/uk/me/parabola/util/Sortable.java
new file mode 100644
index 0000000..f4d9d20
--- /dev/null
+++ b/src/uk/me/parabola/util/Sortable.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2007 Steve Ratcliffe
+ * 
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ * 
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ * 
+ * 
+ * Author: Mark Burton 
+ * Create date: 17-March-2009
+ */
+
+package uk.me.parabola.util;
+
+public class Sortable<K, V> implements Comparable {
+	private final K key;
+	private final V value;
+
+	public Sortable(K key, V value) {
+		this.key = key;
+		this.value = value;
+	}
+
+	public K getKey() {
+		return key;
+	}
+
+	public V getValue() {
+		return value;
+	}
+
+	public int compareTo(Object other) {
+		Sortable<K, V> o = (Sortable<K, V>)other;
+		int diff = ((Comparable)key).compareTo(o.key);
+		if(diff == 0 && value instanceof Comparable)
+			diff = ((Comparable)value).compareTo(o.value);
+		return diff;
+	}
+}
