Index: src/uk/me/parabola/imgfmt/app/typ/ShapeStacking.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/typ/ShapeStacking.java	(revision 2063)
+++ src/uk/me/parabola/imgfmt/app/typ/ShapeStacking.java	(revision )
@@ -16,9 +16,49 @@
  */
 package uk.me.parabola.imgfmt.app.typ;
 
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import uk.me.parabola.imgfmt.app.ImgFileWriter;
+
 /**
+ * Holds the shape stacking section.
+ *
+ * Deals with sorting everything correctly, so no need to sort in the input file.
+ * 
  * @author Steve Ratcliffe
  */
 public class ShapeStacking {
-	// TODO give in content
+	private final SortedMap<Integer, DrawOrder> bar = new TreeMap<Integer, DrawOrder>();
+
+	public void addPolygon(int level, int type, int subtype) {
+		int levelType = (level << 16) + type;
+		DrawOrder order = bar.get(levelType);
+		if (order == null) {
+			order = new DrawOrder((byte) type);
+			bar.put(levelType, order);
-}
+		}
+		
+		order.addSubtype(subtype);
+	}
+
+	public void write(ImgFileWriter writer) {
+		int lastLevel = 1;
+
+		DrawOrder empty = new DrawOrder(0);
+
+		for (Map.Entry<Integer, DrawOrder> ent : bar.entrySet()) {
+			int level = (ent.getKey() >> 16) & 0xffff;
+			DrawOrder order = ent.getValue();
+
+			if (level != lastLevel) {
+				empty.write(writer);
+				lastLevel = level;
+			}
+
+			order.write(writer);
+		}
+	}
+
+}
Index: src/uk/me/parabola/mkgmap/typ/TypTextReader.java
===================================================================
--- src/uk/me/parabola/mkgmap/typ/TypTextReader.java	(revision )
+++ src/uk/me/parabola/mkgmap/typ/TypTextReader.java	(revision )
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2011.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 or
+ * 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.
+ */
+package uk.me.parabola.mkgmap.typ;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.io.Reader;
+import java.nio.channels.FileChannel;
+
+import uk.me.parabola.imgfmt.app.typ.ShapeStacking;
+import uk.me.parabola.imgfmt.app.typ.TYPFile;
+import uk.me.parabola.imgfmt.app.typ.TypParam;
+import uk.me.parabola.imgfmt.sys.FileImgChannel;
+import uk.me.parabola.mkgmap.scan.SyntaxException;
+import uk.me.parabola.mkgmap.scan.TokType;
+import uk.me.parabola.mkgmap.scan.Token;
+import uk.me.parabola.mkgmap.scan.TokenScanner;
+
+/**
+ * Read in a TYP file in the text format.
+ *
+ * @author Steve Ratcliffe
+ */
+public class TypTextReader {
+
+	private final TypParam param = new TypParam();
+	private final ShapeStacking stacking = new ShapeStacking();
+
+	public void read(String filename, Reader r) {
+		TokenScanner scanner = new TokenScanner(filename, r);
+
+		ProcessMethod currentSection = null;
+
+		while (!scanner.isEndOfFile()) {
+			Token tok = scanner.nextToken();
+
+			// We deal with whole line comments here
+			if (tok.isValue(";")) {
+				scanner.skipLine();
+				continue;
+			}
+
+			if (tok.getType() == TokType.SYMBOL) {
+				switch (tok.getValue().charAt(0)) {
+				case ';':
+					scanner.skipLine();
+					break;
+				case '[':
+					ProcessMethod newMethod = readSectionType(scanner);
+					if (currentSection != null)
+						currentSection.finish();
+					currentSection = newMethod;
+					break;
+				case '"':
+					scanner.skipLine();
+					break;
+				}
+			} else {
+				// Line inside a section
+				String name = tok.getValue();
+
+				String sep = scanner.nextValue();
+				if (!sep.equals("=") && !sep.equals(":"))
+					throw new SyntaxException(scanner, "Expecting '=' or ':' instead of " + sep);
+
+				String value = scanner.readLine();
+
+				if (currentSection == null)
+					throw new SyntaxException(scanner, "Missing section start");
+
+				currentSection.processLine(scanner, name, value);
+			}
+			scanner.skipSpace();
+		}
+	}
+
+	private ProcessMethod readSectionType(TokenScanner scanner) {
+		String sectionName = scanner.nextValue().toLowerCase();
+		scanner.validateNext("]"); // Check for closing bracket
+
+		if ("_id".equals(sectionName)) {
+			return new ProcessMethod() {
+				public void processLine(TokenScanner scanner, String name, String value) {
+					idSection(scanner, name, value);
+				}
+
+				public void finish() {
+				}
+			};
+
+		} else if ("_draworder".equals(sectionName)) {
+			return new ProcessMethod() {
+				public void processLine(TokenScanner scanner, String name, String value) {
+					drawOrderSection(scanner, name, value);
+				}
+
+				public void finish() {
+				}
+			};
+
+		} else if ("_point".equals(sectionName)) {
+			return new ProcessMethod() {
+				public void processLine(TokenScanner scanner, String name, String value) {
+					pointSection(scanner, name, value);
+				}
+
+				public void finish() {
+				}
+			};
+
+		} else if ("_line".equals(sectionName)) {
+			return new ProcessMethod() {
+				public void processLine(TokenScanner scanner, String name, String value) {
+					lineSection(scanner, name, value);
+				}
+
+				public void finish() {
+				}
+			};
+
+		} else if ("_polygon".equals(sectionName)) {
+			return new ProcessMethod() {
+				public void processLine(TokenScanner scanner, String name, String value) {
+					polygonSection(scanner, name, value);
+				}
+
+				public void finish() {
+				}
+			};
+
+		} else if ("end".equals(sectionName)) {
+			return null;
+		}
+
+		throw new SyntaxException(scanner, "Unrecognised section name: " + sectionName);
+	}
+
+	private void idSection(TokenScanner scanner, String name, String value) {
+		int ival;
+		try {
+			ival = Integer.parseInt(value);
+		} catch (NumberFormatException e) {
+			throw new SyntaxException(scanner, "Bad integer " + value);
+		}
+
+		if (name.equals("FID")) {
+			param.setFamilyId(ival);
+		} else if (name.equals("ProductCode")) {
+			param.setProductId(ival);
+		} else if (name.equals("CodePage")) {
+			param.setCodePage(ival);
+		} else {
+			throw new SyntaxException(scanner, "Unrecognised keyword in id section: " + name);
+		}
+
+	}
+
+	private void drawOrderSection(TokenScanner scanner, String name, String value) {
+		if (!name.equals("Type"))
+			throw new SyntaxException(scanner, "Unrecognised keyword in draw order section: " + name);
+
+		String[] foo = value.split(",");
+		if (foo.length != 2)
+			throw new SyntaxException(scanner, "Unrecognised drawOrder type " + value);
+
+		int fulltype = Integer.decode(foo[0]);
+		int type;
+		int subtype = 0;
+
+		if (fulltype > 0x10000) {
+			type = (fulltype >> 8) & 0xff;
+			subtype = fulltype & 0xff;
+		} else {
+			type = fulltype & 0xff;
+		}
+
+		int level = Integer.parseInt(foo[1]);
+		stacking.addPolygon(level, type, subtype);
+	}
+
+	private void pointSection(TokenScanner scanner, String name, String value) {
+		if (commonKey(scanner, name, value))
+			return;
+	}
+
+	private void lineSection(TokenScanner scanner, String name, String value) {
+		if (commonKey(scanner, name, value))
+			return;
+	}
+
+	private void polygonSection(TokenScanner scanner, String name, String value) {
+		if (commonKey(scanner, name, value))
+			return;
+	}
+
+	private boolean commonKey(TokenScanner scanner, String name, String value) {
+		return false;
+	}
+
+	public TypParam getParam() {
+		return param;
+	}
+
+	public ShapeStacking getStacking() {
+		return stacking;
+	}
+
+	interface ProcessMethod {
+		public void processLine(TokenScanner scanner, String name, String value);
+
+		public void finish();
+	}
+
+	public static void main(String[] args) throws IOException {
+		String in = "default.txt";
+		if (args.length > 0)
+			in = args[0];
+		String out = "OUT.TYP";
+		if (args.length > 1)
+			out = args[1];
+
+		Reader r = new BufferedReader(new FileReader(in));
+
+		TypTextReader tr = new TypTextReader();
+		try {
+			tr.read(in, r);
+		} catch (SyntaxException e) {
+			System.out.println(e.getMessage());
+		}
+
+		RandomAccessFile raf = new RandomAccessFile(out, "rw");
+		FileChannel channel = raf.getChannel();
+		channel.truncate(0);
+		
+		FileImgChannel w = new FileImgChannel(channel);
+		TYPFile typ = new TYPFile(w);
+		typ.setTypParam(tr.param);
+		typ.setStacking(tr.stacking);
+
+		typ.write();
+		typ.close();
+	}
+}
Index: test/func/lib/ArrayImgWriter.java
===================================================================
--- test/func/lib/ArrayImgWriter.java	(revision )
+++ test/func/lib/ArrayImgWriter.java	(revision )
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2011.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 or
+ * 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.
+ */
+package func.lib;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import uk.me.parabola.imgfmt.app.ImgFileWriter;
+
+/**
+ * A writer that just writes to an array for testing.
+ *
+ * @author Steve Ratcliffe
+ */
+public class ArrayImgWriter implements ImgFileWriter {
+	private final ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+	public void sync() throws IOException {
+	}
+
+	public int position() {
+		return out.size();
+	}
+
+	public void position(long pos) {
+		throw new UnsupportedOperationException();
+	}
+
+	public void put(byte b) {
+		out.write(b);
+	}
+
+	public void putChar(char c) {
+		out.write(c & 0xff);
+		out.write((c >> 8) & 0xff);
+	}
+
+	public void put3(int val) {
+		out.write(val & 0xff);
+		out.write((val >> 8) & 0xff);
+		out.write((val >> 16) & 0xff);
+	}
+
+	public void putInt(int val) {
+		out.write(val & 0xff);
+		out.write((val >> 8) & 0xff);
+		out.write((val >> 16) & 0xff);
+		out.write((val >> 24) & 0xff);
+	}
+
+	public void put(byte[] val) {
+		out.write(val, 0, val.length);
+	}
+
+	public void put(byte[] src, int start, int length) {
+		out.write(src, start, length);
+	}
+
+	public void put(ByteBuffer src) {
+		byte[] array = src.array();
+		out.write(array, 0, array.length);
+	}
+
+	public long getSize() {
+		return out.size();
+	}
+
+	public void close() throws IOException {
+		out.close();
+	}
+
+	public byte[] getBytes() {
+		return out.toByteArray();
+	}
+}
Index: src/uk/me/parabola/imgfmt/app/typ/TYPFile.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/typ/TYPFile.java	(revision 2063)
+++ src/uk/me/parabola/imgfmt/app/typ/TYPFile.java	(revision )
@@ -26,9 +26,11 @@
 import java.util.List;
 import java.util.Map;
 
-import uk.me.parabola.imgfmt.app.BufferedImgFileReader;
+import uk.me.parabola.imgfmt.Utils;
 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.SectionWriter;
 import uk.me.parabola.imgfmt.app.Writeable;
 import uk.me.parabola.imgfmt.fs.ImgChannel;
 import uk.me.parabola.log.Logger;
@@ -46,59 +48,56 @@
 	private final List<BitmapImage> images = new LinkedList<BitmapImage>();
 	private final List<PointInfo> pointInfo = new LinkedList<PointInfo>();
 	private final List<DrawOrder> drawOrder = new LinkedList<DrawOrder>();
+	private ShapeStacking stacking;
 
-	public TYPFile(ImgChannel chan, boolean write) {
+	public TYPFile(ImgChannel chan) {
 		setHeader(header);
-		if (write) {
-			setWriter(new BufferedImgFileWriter(chan));
-			position(TYPHeader.HEADER_LEN);
+		setWriter(new BufferedImgFileWriter(chan));
+		position(TYPHeader.HEADER_LEN);
-		} else {
-			setReader(new BufferedImgFileReader(chan));
-			header.readHeader(getReader());
-		}
+	}
-	}
 
-	public void setCodePage(char code) {
-		header.setCodePage(code);
+	public void setCodePage(int code) {
+		header.setCodePage((char) code);
 	}
 
-	public void setFamilyId(char code) {
-		header.setFamilyId(code);
+	public void setFamilyId(int code) {
+		header.setFamilyId((char) code);
 	}
 
-	public void setProductId(char code) {
-		header.setProductId(code);
+	public void setProductId(int code) {
+		header.setProductId((char) code);
 	}
 
 	public void write() {
 		// HEADER_LEN => 1. Image
 		Collections.sort(images, BitmapImage.comperator());
 
-		getWriter().position(TYPHeader.HEADER_LEN);
+		ImgFileWriter writer = getWriter();
+		writer.position(TYPHeader.HEADER_LEN);
 
-		int pos = getWriter().position();
+		int pos = writer.position();
 		header.getPointData().setPosition(pos);
 
 		for (Writeable w : images)
-			w.write(getWriter());
-		int len = getWriter().position() - pos;
+			w.write(writer);
+		int len = writer.position() - pos;
 		header.getPointData().setSize(len);
 
 		if (len < 0x100)
 			header.getPointIndex().setItemSize((char) 3);
-		pos = getWriter().position();
+		pos = writer.position();
 		for (PointInfo w : pointInfo)
-			w.write(getWriter(), header.getPointData().getSize());
-		header.getPointIndex().setSize(getWriter().position() - pos);
+			w.write(writer, header.getPointData().getSize());
+		header.getPointIndex().setSize(writer.position() - pos);
 
-		pos = getWriter().position();
-		for (Writeable w : drawOrder)
-			w.write(getWriter());
-		header.getShapeStacking().setSize(getWriter().position() - pos);
-
+		SectionWriter subWriter = null;
+		try {
+			subWriter = header.getShapeStacking().makeSectionWriter(writer);
+			stacking.write(subWriter);
+		} finally {
+			Utils.closeFile(subWriter);
-	}
+		}
 
-	public void writePost() {
 		log.debug("syncing TYP file");
 		position(0);
 		getHeader().writeHeader(getWriter());
@@ -134,19 +133,13 @@
 		}
 	}
 
-	public void createDrawOrder(byte typ, byte sub) {
-		drawOrder.add(new DrawOrder((char) (typ | sub << 8), (char) 0, (byte) 0));
+	public void setTypParam(TypParam param) {
+		setFamilyId(param.getFamilyId());
+		setProductId(param.getProductId());
+		setCodePage(param.getCodePage());
 	}
 
-	public List<BitmapImage> getImages() {
-		return images;
+	public void setStacking(ShapeStacking stacking) {
+		this.stacking = stacking;
 	}
-
-	public List<PointInfo> getPointInfo() {
-		return pointInfo;
-	}
+}
-
-	public List<DrawOrder> getDrawOrder() {
-		return drawOrder;
-	}
-}
Index: src/uk/me/parabola/imgfmt/app/typ/DrawOrder.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/typ/DrawOrder.java	(revision 2063)
+++ src/uk/me/parabola/imgfmt/app/typ/DrawOrder.java	(revision )
@@ -3,20 +3,27 @@
 import uk.me.parabola.imgfmt.app.ImgFileWriter;
 import uk.me.parabola.imgfmt.app.Writeable;
 
+/**
+ * The drawing order for a type and a set of subtypes.
+ *
+ * The drawing order is specified by the order of these within the file, rather than anything
+ * actually in the item.
+ */
 public class DrawOrder implements Writeable {
-	private final char typ;
-	private final char unk1;
-	private final byte unk2;
+	private final byte typ;
+	private int subTypes;
 
-	public DrawOrder(char typ, char unk1, byte unk2) {
-		this.typ = typ;
-		this.unk1 = unk1;
-		this.unk2 = unk2;
+	public DrawOrder(int typ) {
+		this.typ = (byte) typ;
 	}
 
 	public void write(ImgFileWriter writer) {
-		writer.putChar(typ);
-		writer.putChar(unk1);
-		writer.put(unk2);
+		writer.put(typ);
+		writer.putInt(subTypes);
 	}
+
+	public void addSubtype(int subtype) {
+		if (subtype > 0)
+			subTypes |= 1 << subtype;
-}
+	}
+}
Index: src/uk/me/parabola/mkgmap/scan/TokenScanner.java
===================================================================
--- src/uk/me/parabola/mkgmap/scan/TokenScanner.java	(revision 2063)
+++ src/uk/me/parabola/mkgmap/scan/TokenScanner.java	(revision )
@@ -332,8 +332,9 @@
 		skipSpace();
 		Token tok = nextToken();
 		if (val == null || !val.equals(tok.getValue()))
-			throw new SyntaxException("Expecting " + val);
+			throw new SyntaxException(this, "Expecting " + val);
 	}
+
 	public int getLinenumber() {
 		return linenumber;
 	}
Index: test/uk/me/parabola/imgfmt/app/typ/TYPFileTest.java
===================================================================
--- test/uk/me/parabola/imgfmt/app/typ/TYPFileTest.java	(revision 2063)
+++ test/uk/me/parabola/imgfmt/app/typ/TYPFileTest.java	(revision )
@@ -16,23 +16,23 @@
  */
 package uk.me.parabola.imgfmt.app.typ;
 
-import uk.me.parabola.imgfmt.FileExistsException;
-import uk.me.parabola.imgfmt.FileNotWritableException;
 import uk.me.parabola.imgfmt.FileSystemParam;
 import uk.me.parabola.imgfmt.fs.FileSystem;
 import uk.me.parabola.imgfmt.fs.ImgChannel;
 import uk.me.parabola.imgfmt.sys.ImgFS;
 
-import static org.junit.Assert.*;
 import org.junit.Test;
 
+import static org.junit.Assert.*;
+
 public class TYPFileTest {
+	
 	@Test
-	public void testWrite() throws FileNotWritableException, FileExistsException {
+	public void testWrite() throws Exception {
 		FileSystemParam params = new FileSystemParam();
 		FileSystem fs = ImgFS.createFs("test.typ", params);
 		ImgChannel channel = fs.create("XXX.TYP");
-		TYPFile typFile = new TYPFile(channel, true);
+		TYPFile typFile = new TYPFile(channel);
 		assertNotNull("typ file is created", typFile);
 	}
 }
Index: test/uk/me/parabola/mkgmap/typ/TypTextReaderTest.java
===================================================================
--- test/uk/me/parabola/mkgmap/typ/TypTextReaderTest.java	(revision )
+++ test/uk/me/parabola/mkgmap/typ/TypTextReaderTest.java	(revision )
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2011.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 or
+ * 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.
+ */
+package uk.me.parabola.mkgmap.typ;
+
+import java.io.Reader;
+import java.io.StringReader;
+
+import uk.me.parabola.imgfmt.app.typ.ShapeStacking;
+import uk.me.parabola.imgfmt.app.typ.TypParam;
+
+import func.lib.ArrayImgWriter;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class TypTextReaderTest {
+	private TypTextReader tr;
+	private static final int ORDER_SIZE = 5;
+
+	@Before
+	public void setUp() {
+	}
+
+	@Test
+	public void testIdSection() {
+		tr = makeTyp("[_id]\n" +
+				"FID=24\n" +
+				"ProductCode=2\n" +
+				"CodePage=99\n" +
+				"[End]");
+
+		TypParam param = tr.getParam();
+		assertEquals(24, param.getFamilyId());
+		assertEquals(2, param.getProductId());
+		assertEquals(99, param.getCodePage());
+	}
+
+	@Test
+	public void testStacking() {
+
+		tr = makeTyp("[_drawOrder]\n" +
+				"Type=0x3,1\n" +
+				"Type=0x2,2\n" +
+				"Type=0x1,4\n" +
+				"Type=0x4,2\n" +
+				"Type=0x10402,2\n" +
+				"Type=0x10405,2\n" +
+				"[End]\n");
+
+		ShapeStacking stacking = tr.getStacking();
+
+		ArrayImgWriter out = new ArrayImgWriter();
+		stacking.write(out);
+
+		byte[] buf = out.getBytes();
+		assertEquals(3, buf[0]);
+
+		assertEquals(0, buf[1 * ORDER_SIZE]);
+		assertEquals(2, buf[2 * ORDER_SIZE]);
+		assertEquals(4, buf[3 * ORDER_SIZE]);
+		assertEquals((1<<2) + (1<<5), buf[3 * ORDER_SIZE + 1]);
+	}
+
+	private TypTextReader makeTyp(String in) {
+		Reader r = new StringReader(in);
+
+		TypTextReader tr = new TypTextReader();
+		tr.read("string", r);
+		return tr;
+	}
+}
Index: src/uk/me/parabola/imgfmt/app/typ/TYPHeader.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/typ/TYPHeader.java	(revision 2063)
+++ src/uk/me/parabola/imgfmt/app/typ/TYPHeader.java	(revision )
@@ -36,9 +36,11 @@
 	private final Section pointData = new Section();
 	private final Section lineData = new Section(pointData);
 	private final Section polygonData = new Section(lineData);
+
 	private final Section pointIndex = new Section(polygonData, (char) 4);
 	private final Section lineIndex = new Section(pointIndex, (char) 3);
 	private final Section polygonIndex = new Section(lineIndex, (char) 3);
+
 	private final Section shapeStacking = new Section(polygonIndex, (char) 5);
 
 	public TYPHeader() {
@@ -92,39 +94,30 @@
 	 * @param writer The header is written here.
 	 */
 	protected void writeFileHeader(ImgFileWriter writer) {
-		System.out.println("in file header write");
 		writer.putChar(codePage);
-		writer.putInt(pointData.getPosition());
-		writer.putInt(pointData.getSize());
 
-		writer.putInt(lineData.getPosition());
-		writer.putInt(lineData.getSize());
+		pointData.writeSectionInfo(writer);
+		lineData.writeSectionInfo(writer);
+		polygonData.writeSectionInfo(writer);
 
-		writer.putInt(polygonData.getPosition());
-		writer.putInt(polygonData.getSize());
-
 		writer.putChar(familyId);
 		writer.putChar(productId);
 
-		writer.putInt(pointIndex.getPosition());
-		writer.putChar(pointIndex.getItemSize());
-		writer.putInt(pointIndex.getSize());
-
-		writer.putInt(lineIndex.getPosition());
-		writer.putChar(lineIndex.getItemSize());
-		writer.putInt(lineIndex.getSize());
-
-		writer.putInt(polygonIndex.getPosition());
-		writer.putChar(polygonIndex.getItemSize());
-		writer.putInt(polygonIndex.getSize());
-
-		writer.putInt(shapeStacking.getPosition());
-		writer.putChar(shapeStacking.getItemSize());
-		writer.putInt(shapeStacking.getSize());
+		// Can't use Section.writeSectionInfo here as there is an unusual layout.
+		writeSectionInfo(writer, pointIndex);
+		writeSectionInfo(writer, lineIndex);
+		writeSectionInfo(writer, polygonIndex);
+		writeSectionInfo(writer, shapeStacking);
 	}
 
-	char getCodePage() {
-		return codePage;
+	/**
+	 * There is an unusual layout of the section pointers in the TYP file for the sections
+	 * that have an item size.
+	 */
+	private void writeSectionInfo(ImgFileWriter writer, Section section) {
+		writer.putInt(section.getPosition());
+		writer.putChar(section.getItemSize());
+		writer.putInt(section.getSize());
 	}
 
 	void setCodePage(char codePage) {
@@ -135,18 +128,10 @@
 		return pointData;
 	}
 
-	char getFamilyId() {
-		return familyId;
-	}
-
 	void setFamilyId(char familyId) {
 		this.familyId = familyId;
 	}
 
-	char getProductId() {
-		return productId;
-	}
-
 	void setProductId(char productId) {
 		this.productId = productId;
 	}
Index: src/uk/me/parabola/imgfmt/app/typ/TypParam.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/typ/TypParam.java	(revision )
+++ src/uk/me/parabola/imgfmt/app/typ/TypParam.java	(revision )
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2011.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 or
+ * 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.
+ */
+package uk.me.parabola.imgfmt.app.typ;
+
+/**
+ * General TYP file parameters.
+ *
+ * @author Steve Ratcliffe
+ */
+public class TypParam {
+	private int familyId;
+	private int productId;
+	private int codePage;
+
+	public int getFamilyId() {
+		return familyId;
+	}
+
+	public void setFamilyId(int familyId) {
+		this.familyId = familyId;
+	}
+
+	public int getProductId() {
+		return productId;
+	}
+
+	public void setProductId(int productId) {
+		this.productId = productId;
+	}
+
+	public int getCodePage() {
+		return codePage;
+	}
+
+	public void setCodePage(int codePage) {
+		this.codePage = codePage;
+	}
+}
Index: src/uk/me/parabola/imgfmt/app/Section.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/Section.java	(revision 2063)
+++ src/uk/me/parabola/imgfmt/app/Section.java	(revision )
@@ -123,6 +123,11 @@
 			setItemSize(reader.getChar());
 	}
 
+	public SectionWriter makeSectionWriter(ImgFileWriter writer) {
+		setPosition(writer.position());
+		return new SectionWriter(writer, this);
+	}
+
 	public void writeSectionInfo(ImgFileWriter writer) {
 		writeSectionInfo(writer, false);
 	}
