Created a new library directory called "FreeLib". All OpenSource RFMKII components will reside there, fontTools being the flagship.


git-svn-id: svn://svn.code.sf.net/p/fonttools/code/trunk@2 4cde692c-a291-49d1-8350-778aa11640f8
diff --git a/Lib/fontTools/__init__.py b/Lib/fontTools/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Lib/fontTools/__init__.py
diff --git a/Lib/fontTools/afmLib.py b/Lib/fontTools/afmLib.py
new file mode 100644
index 0000000..a725e83
--- /dev/null
+++ b/Lib/fontTools/afmLib.py
@@ -0,0 +1,265 @@
+"""Module for reading and writing AFM files."""
+
+# XXX reads AFM's generated by Fog, not tested with much else.
+# It does not implement the full spec (Adobe Technote 5004, Adobe Font Metrics
+# File Format Specification). Still, it should read most "common" AFM files.
+
+import re
+import string
+import types
+
+__version__ = "$Id: afmLib.py,v 1.1 1999-12-16 21:34:51 Just Exp $"
+
+
+# every single line starts with a "word"
+identifierRE = re.compile("^([A-Za-z]+).*")
+
+# regular expression to parse char lines
+charRE = re.compile(
+		"(-?\d+)"			# charnum
+		"\s*;\s*WX\s+"		# ; WX 
+		"(\d+)"			# width
+		"\s*;\s*N\s+"		# ; N 
+		"(\.?[A-Za-z0-9_]+)"	# charname
+		"\s*;\s*B\s+"		# ; B 
+		"(-?\d+)"			# left
+		"\s+"				# 
+		"(-?\d+)"			# bottom
+		"\s+"				# 
+		"(-?\d+)"			# right
+		"\s+"				# 
+		"(-?\d+)"			# top
+		"\s*;\s*"			# ; 
+		)
+
+# regular expression to parse kerning lines
+kernRE = re.compile(
+		"([.A-Za-z0-9_]+)"	# leftchar
+		"\s+"				# 
+		"([.A-Za-z0-9_]+)"	# rightchar
+		"\s+"				# 
+		"(-?\d+)"			# value
+		"\s*"				# 
+		)
+
+error = "AFM.error"
+
+class AFM:
+	
+	_keywords = ['StartFontMetrics',
+			'EndFontMetrics',
+			'StartCharMetrics',
+			'EndCharMetrics',
+			'StartKernData',
+			'StartKernPairs',
+			'EndKernPairs',
+			'EndKernData', ]
+	
+	def __init__(self, path = None):
+		self._attrs = {}
+		self._chars = {}
+		self._kerning = {}
+		self._index = {}
+		self._comments = []
+		if path is not None:
+			self.read(path)
+	
+	def read(self, path):
+		lines = readlines(path)
+		for line in lines:
+			if not string.strip(line):
+				continue
+			m = identifierRE.match(line)
+			if m is None:
+				raise error, "syntax error in AFM file: " + `line`
+			
+			pos = m.regs[1][1]
+			word = line[:pos]
+			rest = string.strip(line[pos:])
+			if word in self._keywords:
+				continue
+			if word == 'C':
+				self.parsechar(rest)
+			elif word == "KPX":
+				self.parsekernpair(rest)
+			else:
+				self.parseattr(word, rest)
+	
+	def parsechar(self, rest):
+		m = charRE.match(rest)
+		if m is None:
+			raise error, "syntax error in AFM file: " + `rest`
+		things = []
+		for fr, to in m.regs[1:]:
+			things.append(rest[fr:to])
+		charname = things[2]
+		del things[2]
+		charnum, width, l, b, r, t = map(string.atoi, things)
+		self._chars[charname] = charnum, width, (l, b, r, t)
+	
+	def parsekernpair(self, rest):
+		m = kernRE.match(rest)
+		if m is None:
+			raise error, "syntax error in AFM file: " + `rest`
+		things = []
+		for fr, to in m.regs[1:]:
+			things.append(rest[fr:to])
+		leftchar, rightchar, value = things
+		value = string.atoi(value)
+		self._kerning[(leftchar, rightchar)] = value
+	
+	def parseattr(self, word, rest):
+		if word == "FontBBox":
+			l, b, r, t = map(string.atoi, string.split(rest))
+			self._attrs[word] = l, b, r, t
+		elif word == "Comment":
+			self._comments.append(rest)
+		else:
+			try:
+				value = string.atoi(rest)
+			except (ValueError, OverflowError):
+				self._attrs[word] = rest
+			else:
+				self._attrs[word] = value
+	
+	def write(self, path, sep = '\r'):
+		import time
+		lines = [	"StartFontMetrics 2.0",
+				"Comment Generated by afmLib, version %s; at %s" % 
+						(string.split(__version__)[2],
+						time.strftime("%m/%d/%Y %H:%M:%S", 
+						time.localtime(time.time())))]
+		
+		# write attributes
+		items = self._attrs.items()
+		items.sort()		# XXX proper ordering???
+		for attr, value in items:
+			if attr == "FontBBox":
+				value = string.join(map(str, value), " ")
+			lines.append(attr + " " + str(value))
+		
+		# write char metrics
+		lines.append("StartCharMetrics " + `len(self._chars)`)
+		items = map(lambda (charname, (charnum, width, box)):
+			(charnum, (charname, width, box)),
+			self._chars.items())
+		
+		def myCmp(a, b):
+			"""Custom compare function to make sure unencoded chars (-1) 
+			end up at the end of the list after sorting."""
+			if a[0] == -1:
+				a = (0xffff,) + a[1:]  # 0xffff is an arbitrary large number
+			if b[0] == -1:
+				b = (0xffff,) + b[1:]
+			return cmp(a, b)
+		items.sort(myCmp)
+		
+		for charnum, (charname, width, (l, b, r, t)) in items:
+			lines.append("C %d ; WX %d ; N %s ; B %d %d %d %d ;" %
+					(charnum, width, charname, l, b, r, t))
+		lines.append("EndCharMetrics")
+		
+		# write kerning info
+		lines.append("StartKernData")
+		lines.append("StartKernPairs " + `len(self._kerning)`)
+		items = self._kerning.items()
+		items.sort()		# XXX is order important?
+		for (leftchar, rightchar), value in items:
+			lines.append("KPX %s %s %d" % (leftchar, rightchar, value))
+		
+		lines.append("EndKernPairs")
+		lines.append("EndKernData")
+		lines.append("EndFontMetrics")
+		
+		writelines(path, lines, sep)
+	
+	def has_kernpair(self, pair):
+		return self._kerning.has_key(pair)
+	
+	def kernpairs(self):
+		return self._kerning.keys()
+	
+	def has_char(self, char):
+		return self._chars.has_key(char)
+	
+	def chars(self):
+		return self._chars.keys()
+	
+	def comments(self):
+		return self._comments
+	
+	def __getattr__(self, attr):
+		if self._attrs.has_key(attr):
+			return self._attrs[attr]
+		else:
+			raise AttributeError, attr
+	
+	def __setattr__(self, attr, value):
+		# all attrs *not* starting with "_" are consider to be AFM keywords
+		if attr[:1] == "_":
+			self.__dict__[attr] = value
+		else:
+			self._attrs[attr] = value
+	
+	def __getitem__(self, key):
+		if type(key) == types.TupleType:
+			# key is a tuple, return the kernpair
+			if self._kerning.has_key(key):
+				return self._kerning[key]
+			else:
+				raise KeyError, "no kerning pair: " + str(key)
+		else:
+			# return the metrics instead
+			if self._chars.has_key(key):
+				return self._chars[key]
+			else:
+				raise KeyError, "metrics index " + str(key) + " out of range"
+	
+	def __repr__(self):
+		if hasattr(self, "FullName"):
+			return '<AFM object for %s>' % self.FullName
+		else:
+			return '<AFM object at %x>' % id(self)
+
+
+def readlines(path):
+	f = open(path, 'rb')
+	data = f.read()
+	f.close()
+	# read any text file, regardless whether it's formatted for Mac, Unix or Dos
+	sep = ""
+	if '\r' in data:
+		sep = sep + '\r'	# mac or dos
+	if '\n' in data:
+		sep = sep + '\n'	# unix or dos
+	return string.split(data, sep)
+
+def writelines(path, lines, sep = '\r'):
+	f = open(path, 'wb')
+	for line in lines:
+		f.write(line + sep)
+	f.close()
+	
+	
+
+if __name__ == "__main__":
+	import macfs
+	fss, ok = macfs.StandardGetFile('TEXT')
+	if ok:
+		path = fss.as_pathname()
+		afm = AFM(path)
+		char = 'A'
+		if afm.has_char(char):
+			print afm[char]	# print charnum, width and boundingbox
+		pair = ('A', 'V')
+		if afm.has_kernpair(pair):
+			print afm[pair]	# print kerning value for pair
+		print afm.Version	# various other afm entries have become attributes
+		print afm.Weight
+		# afm.comments() returns a list of all Comment lines found in the AFM
+		print afm.comments()
+		#print afm.chars()
+		#print afm.kernpairs()
+		print afm
+		afm.write(path + ".xxx")
+
diff --git a/Lib/fontTools/agl.py b/Lib/fontTools/agl.py
new file mode 100644
index 0000000..6ddc1e7
--- /dev/null
+++ b/Lib/fontTools/agl.py
@@ -0,0 +1,1189 @@
+_aglText = """\
+#
+# Name:          Adobe Glyph List
+# Table version: 1.2
+# Date:          22 Oct 1998
+#
+# Description:
+#
+#   The Adobe Glyph List (AGL) list relates Unicode values (UVs) to glyph
+#   names, and should be used only as described in the document "Unicode and
+#   Glyph Names," at
+#   http://www.adobe.com/supportservice/devrelations/typeforum/unicodegn.html .
+#
+#   The glyph name to UV relation is one to many. 12 glyph names are mapped to
+#   two UVs each; each UV has a separate entry. All other glyph names are
+#   mapped to one UV each.
+#
+#   The Unicode Standard version 2.1 is used for all UVs outside of the Private
+#   Use area, except for 4 entries (see Revision History for 1.2 below).
+#
+#   There are 1051 entries in this list, 171 of which are in the Corporate Use
+#   subarea (CUS). Refer to the document "Unicode Corporate Use Subarea as used
+#   by Adobe Systems," at
+#   http://www.adobe.com/supportservice/devrelations/typeforum/corporateuse.txt
+#   for compatibility decompositions for these characters, and to the document
+#   "Unicode and Glyph Names" for more information the CUS.
+#
+# Format: Semicolon-delimited fields:
+#
+#   (1) Standard UV or CUS UV. (4 uppercase hexadecimal digits)
+#
+#   (2) Glyph name. (upper- and lowercase letters, digits)
+#
+#   (3) Character names: Unicode character names for standard UVs, and
+#       descriptive names for CUS UVs. (uppercase letters, hyphen, space)
+#
+#   (4) [optional] Comment. A comment of "Duplicate" indicates one of two
+#       UVs of a double-mapping. It is the UV that may be given a uni<CODE>
+#       override, or the UV that is in the CUS, as described in the document
+#       "Unicode and Glyph Names."
+#
+#   The entries are sorted by glyph name in increasing ASCII order; entries
+#   with the same glyph name are sorted in decreasing priority order.
+#
+#   Lines starting with "#" are comments; blank lines should be ignored.
+#
+# Revision History:
+#
+#   1.2  [22 Oct 1998]
+#
+#     Some Central European glyph names were remapped and the glyph "dotlessj"
+#     was added. Some entries in the table below have not changed but are
+#     included to provide a complete context for other glyphs that have been
+#     remapped or double-mapped. "-" means that the entry for that UV does not
+#     exist in the AGL.
+#
+#       -------- ---------------------- ---------------- --------------
+#       UV       Character name         AGL 1.1          AGL 1.2
+#                (shortened)            glyph name       glyph name
+#       -------- ---------------------- ---------------- --------------
+#       015E/F   S/s with cedilla       S/scommaaccent   S/scedilla
+#       0162/3   T/t with cedilla       T/tcommaaccent   T/tcommaaccent
+#       0218/9   S/s with comma below   -                S/scommaaccent
+#       021A/B   T/t with comma below   -                T/tcommaaccent
+#       1E9E/F   S/s with comma below   S/scedilla       -
+#       F6C1/2   S/s with cedilla       S/scedilla       S/scedilla
+#       F6BE     dotless j              -                dotlessj
+#       -------- ---------------------- ---------------- --------------
+#
+#     The characters at U+1E9E/F in AGL 1.1, LATIN CAPITAL/SMALL LETTER S WITH
+#     COMMA BELOW, which are proposed new characters (see (b) in the notes for
+#     AGL 1.1 below), have since been reassigned by the Unicode Standard to new
+#     proposed values of U+0218/9. These characters, as well as U+021A/B, LATIN
+#     CAPITAL/SMALL LETTER T WITH COMMA BELOW, are not in the Unicode Standard
+#     2.1.
+#
+#     Entries with the same glyph name are now sorted in decreasing priority
+#     order instead of in increasing UV order.
+#
+#   1.1  [24 Nov 1997]
+#
+#     a. The "Euro" glyph's UV assignment is changed from U+20A0 (EURO-CURRENCY
+#        SIGN) to U+20AC (EURO SIGN). While U+20AC is not defined in the
+#        Unicode Standard 2.0, it has been accepted by the Unicode Technical
+#        Committee for the next version of the Standard; it has not yet passed
+#        the ISO approval process as of 7 November '97.
+#
+#     b. Glyphs "Scedilla" and "scedilla", which were assigned in the Corporate
+#        Use Subarea in AGL 1.0, are now additionally mapped to U+1E9E and
+#        U+1E9F respectively. These two UVs share the same Unicode approval
+#        status as the Euro glyph (see a. above).
+#
+#     c. The "fraction" glyph is now additionally mapped to U+2215, to match
+#        Windows Glyph List 4.
+#
+#     d. The descriptive name for glyph "onefitted", in the Corporate Use
+#        subarea, is changed from "TABULAR DIGIT ONE" to "PROPORTIONAL DIGIT
+#        ONE".
+#
+#   1.0  [17 Jul 1997]  Original version
+#
+0041;A;LATIN CAPITAL LETTER A
+00C6;AE;LATIN CAPITAL LETTER AE
+01FC;AEacute;LATIN CAPITAL LETTER AE WITH ACUTE
+F7E6;AEsmall;LATIN SMALL CAPITAL LETTER AE
+00C1;Aacute;LATIN CAPITAL LETTER A WITH ACUTE
+F7E1;Aacutesmall;LATIN SMALL CAPITAL LETTER A WITH ACUTE
+0102;Abreve;LATIN CAPITAL LETTER A WITH BREVE
+00C2;Acircumflex;LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+F7E2;Acircumflexsmall;LATIN SMALL CAPITAL LETTER A WITH CIRCUMFLEX
+F6C9;Acute;CAPITAL ACUTE ACCENT
+F7B4;Acutesmall;SMALL CAPITAL ACUTE ACCENT
+00C4;Adieresis;LATIN CAPITAL LETTER A WITH DIAERESIS
+F7E4;Adieresissmall;LATIN SMALL CAPITAL LETTER A WITH DIAERESIS
+00C0;Agrave;LATIN CAPITAL LETTER A WITH GRAVE
+F7E0;Agravesmall;LATIN SMALL CAPITAL LETTER A WITH GRAVE
+0391;Alpha;GREEK CAPITAL LETTER ALPHA
+0386;Alphatonos;GREEK CAPITAL LETTER ALPHA WITH TONOS
+0100;Amacron;LATIN CAPITAL LETTER A WITH MACRON
+0104;Aogonek;LATIN CAPITAL LETTER A WITH OGONEK
+00C5;Aring;LATIN CAPITAL LETTER A WITH RING ABOVE
+01FA;Aringacute;LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE
+F7E5;Aringsmall;LATIN SMALL CAPITAL LETTER A WITH RING ABOVE
+F761;Asmall;LATIN SMALL CAPITAL LETTER A
+00C3;Atilde;LATIN CAPITAL LETTER A WITH TILDE
+F7E3;Atildesmall;LATIN SMALL CAPITAL LETTER A WITH TILDE
+0042;B;LATIN CAPITAL LETTER B
+0392;Beta;GREEK CAPITAL LETTER BETA
+F6F4;Brevesmall;SMALL CAPITAL BREVE
+F762;Bsmall;LATIN SMALL CAPITAL LETTER B
+0043;C;LATIN CAPITAL LETTER C
+0106;Cacute;LATIN CAPITAL LETTER C WITH ACUTE
+F6CA;Caron;CAPITAL CARON
+F6F5;Caronsmall;SMALL CAPITAL CARON
+010C;Ccaron;LATIN CAPITAL LETTER C WITH CARON
+00C7;Ccedilla;LATIN CAPITAL LETTER C WITH CEDILLA
+F7E7;Ccedillasmall;LATIN SMALL CAPITAL LETTER C WITH CEDILLA
+0108;Ccircumflex;LATIN CAPITAL LETTER C WITH CIRCUMFLEX
+010A;Cdotaccent;LATIN CAPITAL LETTER C WITH DOT ABOVE
+F7B8;Cedillasmall;SMALL CAPITAL CEDILLA
+03A7;Chi;GREEK CAPITAL LETTER CHI
+F6F6;Circumflexsmall;SMALL CAPITAL MODIFIER LETTER CIRCUMFLEX ACCENT
+F763;Csmall;LATIN SMALL CAPITAL LETTER C
+0044;D;LATIN CAPITAL LETTER D
+010E;Dcaron;LATIN CAPITAL LETTER D WITH CARON
+0110;Dcroat;LATIN CAPITAL LETTER D WITH STROKE
+2206;Delta;INCREMENT
+0394;Delta;GREEK CAPITAL LETTER DELTA;Duplicate
+F6CB;Dieresis;CAPITAL DIAERESIS
+F6CC;DieresisAcute;CAPITAL DIAERESIS ACUTE ACCENT
+F6CD;DieresisGrave;CAPITAL DIAERESIS GRAVE ACCENT
+F7A8;Dieresissmall;SMALL CAPITAL DIAERESIS
+F6F7;Dotaccentsmall;SMALL CAPITAL DOT ABOVE
+F764;Dsmall;LATIN SMALL CAPITAL LETTER D
+0045;E;LATIN CAPITAL LETTER E
+00C9;Eacute;LATIN CAPITAL LETTER E WITH ACUTE
+F7E9;Eacutesmall;LATIN SMALL CAPITAL LETTER E WITH ACUTE
+0114;Ebreve;LATIN CAPITAL LETTER E WITH BREVE
+011A;Ecaron;LATIN CAPITAL LETTER E WITH CARON
+00CA;Ecircumflex;LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+F7EA;Ecircumflexsmall;LATIN SMALL CAPITAL LETTER E WITH CIRCUMFLEX
+00CB;Edieresis;LATIN CAPITAL LETTER E WITH DIAERESIS
+F7EB;Edieresissmall;LATIN SMALL CAPITAL LETTER E WITH DIAERESIS
+0116;Edotaccent;LATIN CAPITAL LETTER E WITH DOT ABOVE
+00C8;Egrave;LATIN CAPITAL LETTER E WITH GRAVE
+F7E8;Egravesmall;LATIN SMALL CAPITAL LETTER E WITH GRAVE
+0112;Emacron;LATIN CAPITAL LETTER E WITH MACRON
+014A;Eng;LATIN CAPITAL LETTER ENG
+0118;Eogonek;LATIN CAPITAL LETTER E WITH OGONEK
+0395;Epsilon;GREEK CAPITAL LETTER EPSILON
+0388;Epsilontonos;GREEK CAPITAL LETTER EPSILON WITH TONOS
+F765;Esmall;LATIN SMALL CAPITAL LETTER E
+0397;Eta;GREEK CAPITAL LETTER ETA
+0389;Etatonos;GREEK CAPITAL LETTER ETA WITH TONOS
+00D0;Eth;LATIN CAPITAL LETTER ETH
+F7F0;Ethsmall;LATIN SMALL CAPITAL LETTER ETH
+20AC;Euro;EURO SIGN
+0046;F;LATIN CAPITAL LETTER F
+F766;Fsmall;LATIN SMALL CAPITAL LETTER F
+0047;G;LATIN CAPITAL LETTER G
+0393;Gamma;GREEK CAPITAL LETTER GAMMA
+011E;Gbreve;LATIN CAPITAL LETTER G WITH BREVE
+01E6;Gcaron;LATIN CAPITAL LETTER G WITH CARON
+011C;Gcircumflex;LATIN CAPITAL LETTER G WITH CIRCUMFLEX
+0122;Gcommaaccent;LATIN CAPITAL LETTER G WITH CEDILLA
+0120;Gdotaccent;LATIN CAPITAL LETTER G WITH DOT ABOVE
+F6CE;Grave;CAPITAL GRAVE ACCENT
+F760;Gravesmall;SMALL CAPITAL GRAVE ACCENT
+F767;Gsmall;LATIN SMALL CAPITAL LETTER G
+0048;H;LATIN CAPITAL LETTER H
+25CF;H18533;BLACK CIRCLE
+25AA;H18543;BLACK SMALL SQUARE
+25AB;H18551;WHITE SMALL SQUARE
+25A1;H22073;WHITE SQUARE
+0126;Hbar;LATIN CAPITAL LETTER H WITH STROKE
+0124;Hcircumflex;LATIN CAPITAL LETTER H WITH CIRCUMFLEX
+F768;Hsmall;LATIN SMALL CAPITAL LETTER H
+F6CF;Hungarumlaut;CAPITAL DOUBLE ACUTE ACCENT
+F6F8;Hungarumlautsmall;SMALL CAPITAL DOUBLE ACUTE ACCENT
+0049;I;LATIN CAPITAL LETTER I
+0132;IJ;LATIN CAPITAL LIGATURE IJ
+00CD;Iacute;LATIN CAPITAL LETTER I WITH ACUTE
+F7ED;Iacutesmall;LATIN SMALL CAPITAL LETTER I WITH ACUTE
+012C;Ibreve;LATIN CAPITAL LETTER I WITH BREVE
+00CE;Icircumflex;LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+F7EE;Icircumflexsmall;LATIN SMALL CAPITAL LETTER I WITH CIRCUMFLEX
+00CF;Idieresis;LATIN CAPITAL LETTER I WITH DIAERESIS
+F7EF;Idieresissmall;LATIN SMALL CAPITAL LETTER I WITH DIAERESIS
+0130;Idotaccent;LATIN CAPITAL LETTER I WITH DOT ABOVE
+2111;Ifraktur;BLACK-LETTER CAPITAL I
+00CC;Igrave;LATIN CAPITAL LETTER I WITH GRAVE
+F7EC;Igravesmall;LATIN SMALL CAPITAL LETTER I WITH GRAVE
+012A;Imacron;LATIN CAPITAL LETTER I WITH MACRON
+012E;Iogonek;LATIN CAPITAL LETTER I WITH OGONEK
+0399;Iota;GREEK CAPITAL LETTER IOTA
+03AA;Iotadieresis;GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+038A;Iotatonos;GREEK CAPITAL LETTER IOTA WITH TONOS
+F769;Ismall;LATIN SMALL CAPITAL LETTER I
+0128;Itilde;LATIN CAPITAL LETTER I WITH TILDE
+004A;J;LATIN CAPITAL LETTER J
+0134;Jcircumflex;LATIN CAPITAL LETTER J WITH CIRCUMFLEX
+F76A;Jsmall;LATIN SMALL CAPITAL LETTER J
+004B;K;LATIN CAPITAL LETTER K
+039A;Kappa;GREEK CAPITAL LETTER KAPPA
+0136;Kcommaaccent;LATIN CAPITAL LETTER K WITH CEDILLA
+F76B;Ksmall;LATIN SMALL CAPITAL LETTER K
+004C;L;LATIN CAPITAL LETTER L
+F6BF;LL;LATIN CAPITAL LETTER LL
+0139;Lacute;LATIN CAPITAL LETTER L WITH ACUTE
+039B;Lambda;GREEK CAPITAL LETTER LAMDA
+013D;Lcaron;LATIN CAPITAL LETTER L WITH CARON
+013B;Lcommaaccent;LATIN CAPITAL LETTER L WITH CEDILLA
+013F;Ldot;LATIN CAPITAL LETTER L WITH MIDDLE DOT
+0141;Lslash;LATIN CAPITAL LETTER L WITH STROKE
+F6F9;Lslashsmall;LATIN SMALL CAPITAL LETTER L WITH STROKE
+F76C;Lsmall;LATIN SMALL CAPITAL LETTER L
+004D;M;LATIN CAPITAL LETTER M
+F6D0;Macron;CAPITAL MACRON
+F7AF;Macronsmall;SMALL CAPITAL MACRON
+F76D;Msmall;LATIN SMALL CAPITAL LETTER M
+039C;Mu;GREEK CAPITAL LETTER MU
+004E;N;LATIN CAPITAL LETTER N
+0143;Nacute;LATIN CAPITAL LETTER N WITH ACUTE
+0147;Ncaron;LATIN CAPITAL LETTER N WITH CARON
+0145;Ncommaaccent;LATIN CAPITAL LETTER N WITH CEDILLA
+F76E;Nsmall;LATIN SMALL CAPITAL LETTER N
+00D1;Ntilde;LATIN CAPITAL LETTER N WITH TILDE
+F7F1;Ntildesmall;LATIN SMALL CAPITAL LETTER N WITH TILDE
+039D;Nu;GREEK CAPITAL LETTER NU
+004F;O;LATIN CAPITAL LETTER O
+0152;OE;LATIN CAPITAL LIGATURE OE
+F6FA;OEsmall;LATIN SMALL CAPITAL LIGATURE OE
+00D3;Oacute;LATIN CAPITAL LETTER O WITH ACUTE
+F7F3;Oacutesmall;LATIN SMALL CAPITAL LETTER O WITH ACUTE
+014E;Obreve;LATIN CAPITAL LETTER O WITH BREVE
+00D4;Ocircumflex;LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+F7F4;Ocircumflexsmall;LATIN SMALL CAPITAL LETTER O WITH CIRCUMFLEX
+00D6;Odieresis;LATIN CAPITAL LETTER O WITH DIAERESIS
+F7F6;Odieresissmall;LATIN SMALL CAPITAL LETTER O WITH DIAERESIS
+F6FB;Ogoneksmall;SMALL CAPITAL OGONEK
+00D2;Ograve;LATIN CAPITAL LETTER O WITH GRAVE
+F7F2;Ogravesmall;LATIN SMALL CAPITAL LETTER O WITH GRAVE
+01A0;Ohorn;LATIN CAPITAL LETTER O WITH HORN
+0150;Ohungarumlaut;LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+014C;Omacron;LATIN CAPITAL LETTER O WITH MACRON
+2126;Omega;OHM SIGN
+03A9;Omega;GREEK CAPITAL LETTER OMEGA;Duplicate
+038F;Omegatonos;GREEK CAPITAL LETTER OMEGA WITH TONOS
+039F;Omicron;GREEK CAPITAL LETTER OMICRON
+038C;Omicrontonos;GREEK CAPITAL LETTER OMICRON WITH TONOS
+00D8;Oslash;LATIN CAPITAL LETTER O WITH STROKE
+01FE;Oslashacute;LATIN CAPITAL LETTER O WITH STROKE AND ACUTE
+F7F8;Oslashsmall;LATIN SMALL CAPITAL LETTER O WITH STROKE
+F76F;Osmall;LATIN SMALL CAPITAL LETTER O
+00D5;Otilde;LATIN CAPITAL LETTER O WITH TILDE
+F7F5;Otildesmall;LATIN SMALL CAPITAL LETTER O WITH TILDE
+0050;P;LATIN CAPITAL LETTER P
+03A6;Phi;GREEK CAPITAL LETTER PHI
+03A0;Pi;GREEK CAPITAL LETTER PI
+03A8;Psi;GREEK CAPITAL LETTER PSI
+F770;Psmall;LATIN SMALL CAPITAL LETTER P
+0051;Q;LATIN CAPITAL LETTER Q
+F771;Qsmall;LATIN SMALL CAPITAL LETTER Q
+0052;R;LATIN CAPITAL LETTER R
+0154;Racute;LATIN CAPITAL LETTER R WITH ACUTE
+0158;Rcaron;LATIN CAPITAL LETTER R WITH CARON
+0156;Rcommaaccent;LATIN CAPITAL LETTER R WITH CEDILLA
+211C;Rfraktur;BLACK-LETTER CAPITAL R
+03A1;Rho;GREEK CAPITAL LETTER RHO
+F6FC;Ringsmall;SMALL CAPITAL RING ABOVE
+F772;Rsmall;LATIN SMALL CAPITAL LETTER R
+0053;S;LATIN CAPITAL LETTER S
+250C;SF010000;BOX DRAWINGS LIGHT DOWN AND RIGHT
+2514;SF020000;BOX DRAWINGS LIGHT UP AND RIGHT
+2510;SF030000;BOX DRAWINGS LIGHT DOWN AND LEFT
+2518;SF040000;BOX DRAWINGS LIGHT UP AND LEFT
+253C;SF050000;BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+252C;SF060000;BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+2534;SF070000;BOX DRAWINGS LIGHT UP AND HORIZONTAL
+251C;SF080000;BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+2524;SF090000;BOX DRAWINGS LIGHT VERTICAL AND LEFT
+2500;SF100000;BOX DRAWINGS LIGHT HORIZONTAL
+2502;SF110000;BOX DRAWINGS LIGHT VERTICAL
+2561;SF190000;BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+2562;SF200000;BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+2556;SF210000;BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+2555;SF220000;BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+2563;SF230000;BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+2551;SF240000;BOX DRAWINGS DOUBLE VERTICAL
+2557;SF250000;BOX DRAWINGS DOUBLE DOWN AND LEFT
+255D;SF260000;BOX DRAWINGS DOUBLE UP AND LEFT
+255C;SF270000;BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+255B;SF280000;BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+255E;SF360000;BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+255F;SF370000;BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+255A;SF380000;BOX DRAWINGS DOUBLE UP AND RIGHT
+2554;SF390000;BOX DRAWINGS DOUBLE DOWN AND RIGHT
+2569;SF400000;BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+2566;SF410000;BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+2560;SF420000;BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+2550;SF430000;BOX DRAWINGS DOUBLE HORIZONTAL
+256C;SF440000;BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+2567;SF450000;BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+2568;SF460000;BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+2564;SF470000;BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+2565;SF480000;BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+2559;SF490000;BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+2558;SF500000;BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+2552;SF510000;BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+2553;SF520000;BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+256B;SF530000;BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+256A;SF540000;BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+015A;Sacute;LATIN CAPITAL LETTER S WITH ACUTE
+0160;Scaron;LATIN CAPITAL LETTER S WITH CARON
+F6FD;Scaronsmall;LATIN SMALL CAPITAL LETTER S WITH CARON
+015E;Scedilla;LATIN CAPITAL LETTER S WITH CEDILLA
+F6C1;Scedilla;LATIN CAPITAL LETTER S WITH CEDILLA;Duplicate
+015C;Scircumflex;LATIN CAPITAL LETTER S WITH CIRCUMFLEX
+0218;Scommaaccent;LATIN CAPITAL LETTER S WITH COMMA BELOW
+03A3;Sigma;GREEK CAPITAL LETTER SIGMA
+F773;Ssmall;LATIN SMALL CAPITAL LETTER S
+0054;T;LATIN CAPITAL LETTER T
+03A4;Tau;GREEK CAPITAL LETTER TAU
+0166;Tbar;LATIN CAPITAL LETTER T WITH STROKE
+0164;Tcaron;LATIN CAPITAL LETTER T WITH CARON
+0162;Tcommaaccent;LATIN CAPITAL LETTER T WITH CEDILLA
+021A;Tcommaaccent;LATIN CAPITAL LETTER T WITH COMMA BELOW;Duplicate
+0398;Theta;GREEK CAPITAL LETTER THETA
+00DE;Thorn;LATIN CAPITAL LETTER THORN
+F7FE;Thornsmall;LATIN SMALL CAPITAL LETTER THORN
+F6FE;Tildesmall;SMALL CAPITAL SMALL TILDE
+F774;Tsmall;LATIN SMALL CAPITAL LETTER T
+0055;U;LATIN CAPITAL LETTER U
+00DA;Uacute;LATIN CAPITAL LETTER U WITH ACUTE
+F7FA;Uacutesmall;LATIN SMALL CAPITAL LETTER U WITH ACUTE
+016C;Ubreve;LATIN CAPITAL LETTER U WITH BREVE
+00DB;Ucircumflex;LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+F7FB;Ucircumflexsmall;LATIN SMALL CAPITAL LETTER U WITH CIRCUMFLEX
+00DC;Udieresis;LATIN CAPITAL LETTER U WITH DIAERESIS
+F7FC;Udieresissmall;LATIN SMALL CAPITAL LETTER U WITH DIAERESIS
+00D9;Ugrave;LATIN CAPITAL LETTER U WITH GRAVE
+F7F9;Ugravesmall;LATIN SMALL CAPITAL LETTER U WITH GRAVE
+01AF;Uhorn;LATIN CAPITAL LETTER U WITH HORN
+0170;Uhungarumlaut;LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+016A;Umacron;LATIN CAPITAL LETTER U WITH MACRON
+0172;Uogonek;LATIN CAPITAL LETTER U WITH OGONEK
+03A5;Upsilon;GREEK CAPITAL LETTER UPSILON
+03D2;Upsilon1;GREEK UPSILON WITH HOOK SYMBOL
+03AB;Upsilondieresis;GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+038E;Upsilontonos;GREEK CAPITAL LETTER UPSILON WITH TONOS
+016E;Uring;LATIN CAPITAL LETTER U WITH RING ABOVE
+F775;Usmall;LATIN SMALL CAPITAL LETTER U
+0168;Utilde;LATIN CAPITAL LETTER U WITH TILDE
+0056;V;LATIN CAPITAL LETTER V
+F776;Vsmall;LATIN SMALL CAPITAL LETTER V
+0057;W;LATIN CAPITAL LETTER W
+1E82;Wacute;LATIN CAPITAL LETTER W WITH ACUTE
+0174;Wcircumflex;LATIN CAPITAL LETTER W WITH CIRCUMFLEX
+1E84;Wdieresis;LATIN CAPITAL LETTER W WITH DIAERESIS
+1E80;Wgrave;LATIN CAPITAL LETTER W WITH GRAVE
+F777;Wsmall;LATIN SMALL CAPITAL LETTER W
+0058;X;LATIN CAPITAL LETTER X
+039E;Xi;GREEK CAPITAL LETTER XI
+F778;Xsmall;LATIN SMALL CAPITAL LETTER X
+0059;Y;LATIN CAPITAL LETTER Y
+00DD;Yacute;LATIN CAPITAL LETTER Y WITH ACUTE
+F7FD;Yacutesmall;LATIN SMALL CAPITAL LETTER Y WITH ACUTE
+0176;Ycircumflex;LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
+0178;Ydieresis;LATIN CAPITAL LETTER Y WITH DIAERESIS
+F7FF;Ydieresissmall;LATIN SMALL CAPITAL LETTER Y WITH DIAERESIS
+1EF2;Ygrave;LATIN CAPITAL LETTER Y WITH GRAVE
+F779;Ysmall;LATIN SMALL CAPITAL LETTER Y
+005A;Z;LATIN CAPITAL LETTER Z
+0179;Zacute;LATIN CAPITAL LETTER Z WITH ACUTE
+017D;Zcaron;LATIN CAPITAL LETTER Z WITH CARON
+F6FF;Zcaronsmall;LATIN SMALL CAPITAL LETTER Z WITH CARON
+017B;Zdotaccent;LATIN CAPITAL LETTER Z WITH DOT ABOVE
+0396;Zeta;GREEK CAPITAL LETTER ZETA
+F77A;Zsmall;LATIN SMALL CAPITAL LETTER Z
+0061;a;LATIN SMALL LETTER A
+00E1;aacute;LATIN SMALL LETTER A WITH ACUTE
+0103;abreve;LATIN SMALL LETTER A WITH BREVE
+00E2;acircumflex;LATIN SMALL LETTER A WITH CIRCUMFLEX
+00B4;acute;ACUTE ACCENT
+0301;acutecomb;COMBINING ACUTE ACCENT
+00E4;adieresis;LATIN SMALL LETTER A WITH DIAERESIS
+00E6;ae;LATIN SMALL LETTER AE
+01FD;aeacute;LATIN SMALL LETTER AE WITH ACUTE
+2015;afii00208;HORIZONTAL BAR
+0410;afii10017;CYRILLIC CAPITAL LETTER A
+0411;afii10018;CYRILLIC CAPITAL LETTER BE
+0412;afii10019;CYRILLIC CAPITAL LETTER VE
+0413;afii10020;CYRILLIC CAPITAL LETTER GHE
+0414;afii10021;CYRILLIC CAPITAL LETTER DE
+0415;afii10022;CYRILLIC CAPITAL LETTER IE
+0401;afii10023;CYRILLIC CAPITAL LETTER IO
+0416;afii10024;CYRILLIC CAPITAL LETTER ZHE
+0417;afii10025;CYRILLIC CAPITAL LETTER ZE
+0418;afii10026;CYRILLIC CAPITAL LETTER I
+0419;afii10027;CYRILLIC CAPITAL LETTER SHORT I
+041A;afii10028;CYRILLIC CAPITAL LETTER KA
+041B;afii10029;CYRILLIC CAPITAL LETTER EL
+041C;afii10030;CYRILLIC CAPITAL LETTER EM
+041D;afii10031;CYRILLIC CAPITAL LETTER EN
+041E;afii10032;CYRILLIC CAPITAL LETTER O
+041F;afii10033;CYRILLIC CAPITAL LETTER PE
+0420;afii10034;CYRILLIC CAPITAL LETTER ER
+0421;afii10035;CYRILLIC CAPITAL LETTER ES
+0422;afii10036;CYRILLIC CAPITAL LETTER TE
+0423;afii10037;CYRILLIC CAPITAL LETTER U
+0424;afii10038;CYRILLIC CAPITAL LETTER EF
+0425;afii10039;CYRILLIC CAPITAL LETTER HA
+0426;afii10040;CYRILLIC CAPITAL LETTER TSE
+0427;afii10041;CYRILLIC CAPITAL LETTER CHE
+0428;afii10042;CYRILLIC CAPITAL LETTER SHA
+0429;afii10043;CYRILLIC CAPITAL LETTER SHCHA
+042A;afii10044;CYRILLIC CAPITAL LETTER HARD SIGN
+042B;afii10045;CYRILLIC CAPITAL LETTER YERU
+042C;afii10046;CYRILLIC CAPITAL LETTER SOFT SIGN
+042D;afii10047;CYRILLIC CAPITAL LETTER E
+042E;afii10048;CYRILLIC CAPITAL LETTER YU
+042F;afii10049;CYRILLIC CAPITAL LETTER YA
+0490;afii10050;CYRILLIC CAPITAL LETTER GHE WITH UPTURN
+0402;afii10051;CYRILLIC CAPITAL LETTER DJE
+0403;afii10052;CYRILLIC CAPITAL LETTER GJE
+0404;afii10053;CYRILLIC CAPITAL LETTER UKRAINIAN IE
+0405;afii10054;CYRILLIC CAPITAL LETTER DZE
+0406;afii10055;CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+0407;afii10056;CYRILLIC CAPITAL LETTER YI
+0408;afii10057;CYRILLIC CAPITAL LETTER JE
+0409;afii10058;CYRILLIC CAPITAL LETTER LJE
+040A;afii10059;CYRILLIC CAPITAL LETTER NJE
+040B;afii10060;CYRILLIC CAPITAL LETTER TSHE
+040C;afii10061;CYRILLIC CAPITAL LETTER KJE
+040E;afii10062;CYRILLIC CAPITAL LETTER SHORT U
+F6C4;afii10063;CYRILLIC SMALL LETTER GHE VARIANT
+F6C5;afii10064;CYRILLIC SMALL LETTER BE VARIANT
+0430;afii10065;CYRILLIC SMALL LETTER A
+0431;afii10066;CYRILLIC SMALL LETTER BE
+0432;afii10067;CYRILLIC SMALL LETTER VE
+0433;afii10068;CYRILLIC SMALL LETTER GHE
+0434;afii10069;CYRILLIC SMALL LETTER DE
+0435;afii10070;CYRILLIC SMALL LETTER IE
+0451;afii10071;CYRILLIC SMALL LETTER IO
+0436;afii10072;CYRILLIC SMALL LETTER ZHE
+0437;afii10073;CYRILLIC SMALL LETTER ZE
+0438;afii10074;CYRILLIC SMALL LETTER I
+0439;afii10075;CYRILLIC SMALL LETTER SHORT I
+043A;afii10076;CYRILLIC SMALL LETTER KA
+043B;afii10077;CYRILLIC SMALL LETTER EL
+043C;afii10078;CYRILLIC SMALL LETTER EM
+043D;afii10079;CYRILLIC SMALL LETTER EN
+043E;afii10080;CYRILLIC SMALL LETTER O
+043F;afii10081;CYRILLIC SMALL LETTER PE
+0440;afii10082;CYRILLIC SMALL LETTER ER
+0441;afii10083;CYRILLIC SMALL LETTER ES
+0442;afii10084;CYRILLIC SMALL LETTER TE
+0443;afii10085;CYRILLIC SMALL LETTER U
+0444;afii10086;CYRILLIC SMALL LETTER EF
+0445;afii10087;CYRILLIC SMALL LETTER HA
+0446;afii10088;CYRILLIC SMALL LETTER TSE
+0447;afii10089;CYRILLIC SMALL LETTER CHE
+0448;afii10090;CYRILLIC SMALL LETTER SHA
+0449;afii10091;CYRILLIC SMALL LETTER SHCHA
+044A;afii10092;CYRILLIC SMALL LETTER HARD SIGN
+044B;afii10093;CYRILLIC SMALL LETTER YERU
+044C;afii10094;CYRILLIC SMALL LETTER SOFT SIGN
+044D;afii10095;CYRILLIC SMALL LETTER E
+044E;afii10096;CYRILLIC SMALL LETTER YU
+044F;afii10097;CYRILLIC SMALL LETTER YA
+0491;afii10098;CYRILLIC SMALL LETTER GHE WITH UPTURN
+0452;afii10099;CYRILLIC SMALL LETTER DJE
+0453;afii10100;CYRILLIC SMALL LETTER GJE
+0454;afii10101;CYRILLIC SMALL LETTER UKRAINIAN IE
+0455;afii10102;CYRILLIC SMALL LETTER DZE
+0456;afii10103;CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+0457;afii10104;CYRILLIC SMALL LETTER YI
+0458;afii10105;CYRILLIC SMALL LETTER JE
+0459;afii10106;CYRILLIC SMALL LETTER LJE
+045A;afii10107;CYRILLIC SMALL LETTER NJE
+045B;afii10108;CYRILLIC SMALL LETTER TSHE
+045C;afii10109;CYRILLIC SMALL LETTER KJE
+045E;afii10110;CYRILLIC SMALL LETTER SHORT U
+040F;afii10145;CYRILLIC CAPITAL LETTER DZHE
+0462;afii10146;CYRILLIC CAPITAL LETTER YAT
+0472;afii10147;CYRILLIC CAPITAL LETTER FITA
+0474;afii10148;CYRILLIC CAPITAL LETTER IZHITSA
+F6C6;afii10192;CYRILLIC SMALL LETTER DE VARIANT
+045F;afii10193;CYRILLIC SMALL LETTER DZHE
+0463;afii10194;CYRILLIC SMALL LETTER YAT
+0473;afii10195;CYRILLIC SMALL LETTER FITA
+0475;afii10196;CYRILLIC SMALL LETTER IZHITSA
+F6C7;afii10831;CYRILLIC SMALL LETTER PE VARIANT
+F6C8;afii10832;CYRILLIC SMALL LETTER TE VARIANT
+04D9;afii10846;CYRILLIC SMALL LETTER SCHWA
+200E;afii299;LEFT-TO-RIGHT MARK
+200F;afii300;RIGHT-TO-LEFT MARK
+200D;afii301;ZERO WIDTH JOINER
+066A;afii57381;ARABIC PERCENT SIGN
+060C;afii57388;ARABIC COMMA
+0660;afii57392;ARABIC-INDIC DIGIT ZERO
+0661;afii57393;ARABIC-INDIC DIGIT ONE
+0662;afii57394;ARABIC-INDIC DIGIT TWO
+0663;afii57395;ARABIC-INDIC DIGIT THREE
+0664;afii57396;ARABIC-INDIC DIGIT FOUR
+0665;afii57397;ARABIC-INDIC DIGIT FIVE
+0666;afii57398;ARABIC-INDIC DIGIT SIX
+0667;afii57399;ARABIC-INDIC DIGIT SEVEN
+0668;afii57400;ARABIC-INDIC DIGIT EIGHT
+0669;afii57401;ARABIC-INDIC DIGIT NINE
+061B;afii57403;ARABIC SEMICOLON
+061F;afii57407;ARABIC QUESTION MARK
+0621;afii57409;ARABIC LETTER HAMZA
+0622;afii57410;ARABIC LETTER ALEF WITH MADDA ABOVE
+0623;afii57411;ARABIC LETTER ALEF WITH HAMZA ABOVE
+0624;afii57412;ARABIC LETTER WAW WITH HAMZA ABOVE
+0625;afii57413;ARABIC LETTER ALEF WITH HAMZA BELOW
+0626;afii57414;ARABIC LETTER YEH WITH HAMZA ABOVE
+0627;afii57415;ARABIC LETTER ALEF
+0628;afii57416;ARABIC LETTER BEH
+0629;afii57417;ARABIC LETTER TEH MARBUTA
+062A;afii57418;ARABIC LETTER TEH
+062B;afii57419;ARABIC LETTER THEH
+062C;afii57420;ARABIC LETTER JEEM
+062D;afii57421;ARABIC LETTER HAH
+062E;afii57422;ARABIC LETTER KHAH
+062F;afii57423;ARABIC LETTER DAL
+0630;afii57424;ARABIC LETTER THAL
+0631;afii57425;ARABIC LETTER REH
+0632;afii57426;ARABIC LETTER ZAIN
+0633;afii57427;ARABIC LETTER SEEN
+0634;afii57428;ARABIC LETTER SHEEN
+0635;afii57429;ARABIC LETTER SAD
+0636;afii57430;ARABIC LETTER DAD
+0637;afii57431;ARABIC LETTER TAH
+0638;afii57432;ARABIC LETTER ZAH
+0639;afii57433;ARABIC LETTER AIN
+063A;afii57434;ARABIC LETTER GHAIN
+0640;afii57440;ARABIC TATWEEL
+0641;afii57441;ARABIC LETTER FEH
+0642;afii57442;ARABIC LETTER QAF
+0643;afii57443;ARABIC LETTER KAF
+0644;afii57444;ARABIC LETTER LAM
+0645;afii57445;ARABIC LETTER MEEM
+0646;afii57446;ARABIC LETTER NOON
+0648;afii57448;ARABIC LETTER WAW
+0649;afii57449;ARABIC LETTER ALEF MAKSURA
+064A;afii57450;ARABIC LETTER YEH
+064B;afii57451;ARABIC FATHATAN
+064C;afii57452;ARABIC DAMMATAN
+064D;afii57453;ARABIC KASRATAN
+064E;afii57454;ARABIC FATHA
+064F;afii57455;ARABIC DAMMA
+0650;afii57456;ARABIC KASRA
+0651;afii57457;ARABIC SHADDA
+0652;afii57458;ARABIC SUKUN
+0647;afii57470;ARABIC LETTER HEH
+06A4;afii57505;ARABIC LETTER VEH
+067E;afii57506;ARABIC LETTER PEH
+0686;afii57507;ARABIC LETTER TCHEH
+0698;afii57508;ARABIC LETTER JEH
+06AF;afii57509;ARABIC LETTER GAF
+0679;afii57511;ARABIC LETTER TTEH
+0688;afii57512;ARABIC LETTER DDAL
+0691;afii57513;ARABIC LETTER RREH
+06BA;afii57514;ARABIC LETTER NOON GHUNNA
+06D2;afii57519;ARABIC LETTER YEH BARREE
+06D5;afii57534;ARABIC LETTER AE
+20AA;afii57636;NEW SHEQEL SIGN
+05BE;afii57645;HEBREW PUNCTUATION MAQAF
+05C3;afii57658;HEBREW PUNCTUATION SOF PASUQ
+05D0;afii57664;HEBREW LETTER ALEF
+05D1;afii57665;HEBREW LETTER BET
+05D2;afii57666;HEBREW LETTER GIMEL
+05D3;afii57667;HEBREW LETTER DALET
+05D4;afii57668;HEBREW LETTER HE
+05D5;afii57669;HEBREW LETTER VAV
+05D6;afii57670;HEBREW LETTER ZAYIN
+05D7;afii57671;HEBREW LETTER HET
+05D8;afii57672;HEBREW LETTER TET
+05D9;afii57673;HEBREW LETTER YOD
+05DA;afii57674;HEBREW LETTER FINAL KAF
+05DB;afii57675;HEBREW LETTER KAF
+05DC;afii57676;HEBREW LETTER LAMED
+05DD;afii57677;HEBREW LETTER FINAL MEM
+05DE;afii57678;HEBREW LETTER MEM
+05DF;afii57679;HEBREW LETTER FINAL NUN
+05E0;afii57680;HEBREW LETTER NUN
+05E1;afii57681;HEBREW LETTER SAMEKH
+05E2;afii57682;HEBREW LETTER AYIN
+05E3;afii57683;HEBREW LETTER FINAL PE
+05E4;afii57684;HEBREW LETTER PE
+05E5;afii57685;HEBREW LETTER FINAL TSADI
+05E6;afii57686;HEBREW LETTER TSADI
+05E7;afii57687;HEBREW LETTER QOF
+05E8;afii57688;HEBREW LETTER RESH
+05E9;afii57689;HEBREW LETTER SHIN
+05EA;afii57690;HEBREW LETTER TAV
+FB2A;afii57694;HEBREW LETTER SHIN WITH SHIN DOT
+FB2B;afii57695;HEBREW LETTER SHIN WITH SIN DOT
+FB4B;afii57700;HEBREW LETTER VAV WITH HOLAM
+FB1F;afii57705;HEBREW LIGATURE YIDDISH YOD YOD PATAH
+05F0;afii57716;HEBREW LIGATURE YIDDISH DOUBLE VAV
+05F1;afii57717;HEBREW LIGATURE YIDDISH VAV YOD
+05F2;afii57718;HEBREW LIGATURE YIDDISH DOUBLE YOD
+FB35;afii57723;HEBREW LETTER VAV WITH DAGESH
+05B4;afii57793;HEBREW POINT HIRIQ
+05B5;afii57794;HEBREW POINT TSERE
+05B6;afii57795;HEBREW POINT SEGOL
+05BB;afii57796;HEBREW POINT QUBUTS
+05B8;afii57797;HEBREW POINT QAMATS
+05B7;afii57798;HEBREW POINT PATAH
+05B0;afii57799;HEBREW POINT SHEVA
+05B2;afii57800;HEBREW POINT HATAF PATAH
+05B1;afii57801;HEBREW POINT HATAF SEGOL
+05B3;afii57802;HEBREW POINT HATAF QAMATS
+05C2;afii57803;HEBREW POINT SIN DOT
+05C1;afii57804;HEBREW POINT SHIN DOT
+05B9;afii57806;HEBREW POINT HOLAM
+05BC;afii57807;HEBREW POINT DAGESH OR MAPIQ
+05BD;afii57839;HEBREW POINT METEG
+05BF;afii57841;HEBREW POINT RAFE
+05C0;afii57842;HEBREW PUNCTUATION PASEQ
+02BC;afii57929;MODIFIER LETTER APOSTROPHE
+2105;afii61248;CARE OF
+2113;afii61289;SCRIPT SMALL L
+2116;afii61352;NUMERO SIGN
+202C;afii61573;POP DIRECTIONAL FORMATTING
+202D;afii61574;LEFT-TO-RIGHT OVERRIDE
+202E;afii61575;RIGHT-TO-LEFT OVERRIDE
+200C;afii61664;ZERO WIDTH NON-JOINER
+066D;afii63167;ARABIC FIVE POINTED STAR
+02BD;afii64937;MODIFIER LETTER REVERSED COMMA
+00E0;agrave;LATIN SMALL LETTER A WITH GRAVE
+2135;aleph;ALEF SYMBOL
+03B1;alpha;GREEK SMALL LETTER ALPHA
+03AC;alphatonos;GREEK SMALL LETTER ALPHA WITH TONOS
+0101;amacron;LATIN SMALL LETTER A WITH MACRON
+0026;ampersand;AMPERSAND
+F726;ampersandsmall;SMALL CAPITAL AMPERSAND
+2220;angle;ANGLE
+2329;angleleft;LEFT-POINTING ANGLE BRACKET
+232A;angleright;RIGHT-POINTING ANGLE BRACKET
+0387;anoteleia;GREEK ANO TELEIA
+0105;aogonek;LATIN SMALL LETTER A WITH OGONEK
+2248;approxequal;ALMOST EQUAL TO
+00E5;aring;LATIN SMALL LETTER A WITH RING ABOVE
+01FB;aringacute;LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE
+2194;arrowboth;LEFT RIGHT ARROW
+21D4;arrowdblboth;LEFT RIGHT DOUBLE ARROW
+21D3;arrowdbldown;DOWNWARDS DOUBLE ARROW
+21D0;arrowdblleft;LEFTWARDS DOUBLE ARROW
+21D2;arrowdblright;RIGHTWARDS DOUBLE ARROW
+21D1;arrowdblup;UPWARDS DOUBLE ARROW
+2193;arrowdown;DOWNWARDS ARROW
+F8E7;arrowhorizex;HORIZONTAL ARROW EXTENDER
+2190;arrowleft;LEFTWARDS ARROW
+2192;arrowright;RIGHTWARDS ARROW
+2191;arrowup;UPWARDS ARROW
+2195;arrowupdn;UP DOWN ARROW
+21A8;arrowupdnbse;UP DOWN ARROW WITH BASE
+F8E6;arrowvertex;VERTICAL ARROW EXTENDER
+005E;asciicircum;CIRCUMFLEX ACCENT
+007E;asciitilde;TILDE
+002A;asterisk;ASTERISK
+2217;asteriskmath;ASTERISK OPERATOR
+F6E9;asuperior;SUPERSCRIPT LATIN SMALL LETTER A
+0040;at;COMMERCIAL AT
+00E3;atilde;LATIN SMALL LETTER A WITH TILDE
+0062;b;LATIN SMALL LETTER B
+005C;backslash;REVERSE SOLIDUS
+007C;bar;VERTICAL LINE
+03B2;beta;GREEK SMALL LETTER BETA
+2588;block;FULL BLOCK
+F8F4;braceex;CURLY BRACKET EXTENDER
+007B;braceleft;LEFT CURLY BRACKET
+F8F3;braceleftbt;LEFT CURLY BRACKET BOTTOM
+F8F2;braceleftmid;LEFT CURLY BRACKET MID
+F8F1;bracelefttp;LEFT CURLY BRACKET TOP
+007D;braceright;RIGHT CURLY BRACKET
+F8FE;bracerightbt;RIGHT CURLY BRACKET BOTTOM
+F8FD;bracerightmid;RIGHT CURLY BRACKET MID
+F8FC;bracerighttp;RIGHT CURLY BRACKET TOP
+005B;bracketleft;LEFT SQUARE BRACKET
+F8F0;bracketleftbt;LEFT SQUARE BRACKET BOTTOM
+F8EF;bracketleftex;LEFT SQUARE BRACKET EXTENDER
+F8EE;bracketlefttp;LEFT SQUARE BRACKET TOP
+005D;bracketright;RIGHT SQUARE BRACKET
+F8FB;bracketrightbt;RIGHT SQUARE BRACKET BOTTOM
+F8FA;bracketrightex;RIGHT SQUARE BRACKET EXTENDER
+F8F9;bracketrighttp;RIGHT SQUARE BRACKET TOP
+02D8;breve;BREVE
+00A6;brokenbar;BROKEN BAR
+F6EA;bsuperior;SUPERSCRIPT LATIN SMALL LETTER B
+2022;bullet;BULLET
+0063;c;LATIN SMALL LETTER C
+0107;cacute;LATIN SMALL LETTER C WITH ACUTE
+02C7;caron;CARON
+21B5;carriagereturn;DOWNWARDS ARROW WITH CORNER LEFTWARDS
+010D;ccaron;LATIN SMALL LETTER C WITH CARON
+00E7;ccedilla;LATIN SMALL LETTER C WITH CEDILLA
+0109;ccircumflex;LATIN SMALL LETTER C WITH CIRCUMFLEX
+010B;cdotaccent;LATIN SMALL LETTER C WITH DOT ABOVE
+00B8;cedilla;CEDILLA
+00A2;cent;CENT SIGN
+F6DF;centinferior;SUBSCRIPT CENT SIGN
+F7A2;centoldstyle;OLDSTYLE CENT SIGN
+F6E0;centsuperior;SUPERSCRIPT CENT SIGN
+03C7;chi;GREEK SMALL LETTER CHI
+25CB;circle;WHITE CIRCLE
+2297;circlemultiply;CIRCLED TIMES
+2295;circleplus;CIRCLED PLUS
+02C6;circumflex;MODIFIER LETTER CIRCUMFLEX ACCENT
+2663;club;BLACK CLUB SUIT
+003A;colon;COLON
+20A1;colonmonetary;COLON SIGN
+002C;comma;COMMA
+F6C3;commaaccent;COMMA BELOW
+F6E1;commainferior;SUBSCRIPT COMMA
+F6E2;commasuperior;SUPERSCRIPT COMMA
+2245;congruent;APPROXIMATELY EQUAL TO
+00A9;copyright;COPYRIGHT SIGN
+F8E9;copyrightsans;COPYRIGHT SIGN SANS SERIF
+F6D9;copyrightserif;COPYRIGHT SIGN SERIF
+00A4;currency;CURRENCY SIGN
+F6D1;cyrBreve;CAPITAL CYRILLIC BREVE
+F6D2;cyrFlex;CAPITAL CYRILLIC CIRCUMFLEX
+F6D4;cyrbreve;CYRILLIC BREVE
+F6D5;cyrflex;CYRILLIC CIRCUMFLEX
+0064;d;LATIN SMALL LETTER D
+2020;dagger;DAGGER
+2021;daggerdbl;DOUBLE DAGGER
+F6D3;dblGrave;CAPITAL DOUBLE GRAVE ACCENT
+F6D6;dblgrave;DOUBLE GRAVE ACCENT
+010F;dcaron;LATIN SMALL LETTER D WITH CARON
+0111;dcroat;LATIN SMALL LETTER D WITH STROKE
+00B0;degree;DEGREE SIGN
+03B4;delta;GREEK SMALL LETTER DELTA
+2666;diamond;BLACK DIAMOND SUIT
+00A8;dieresis;DIAERESIS
+F6D7;dieresisacute;DIAERESIS ACUTE ACCENT
+F6D8;dieresisgrave;DIAERESIS GRAVE ACCENT
+0385;dieresistonos;GREEK DIALYTIKA TONOS
+00F7;divide;DIVISION SIGN
+2593;dkshade;DARK SHADE
+2584;dnblock;LOWER HALF BLOCK
+0024;dollar;DOLLAR SIGN
+F6E3;dollarinferior;SUBSCRIPT DOLLAR SIGN
+F724;dollaroldstyle;OLDSTYLE DOLLAR SIGN
+F6E4;dollarsuperior;SUPERSCRIPT DOLLAR SIGN
+20AB;dong;DONG SIGN
+02D9;dotaccent;DOT ABOVE
+0323;dotbelowcomb;COMBINING DOT BELOW
+0131;dotlessi;LATIN SMALL LETTER DOTLESS I
+F6BE;dotlessj;LATIN SMALL LETTER DOTLESS J
+22C5;dotmath;DOT OPERATOR
+F6EB;dsuperior;SUPERSCRIPT LATIN SMALL LETTER D
+0065;e;LATIN SMALL LETTER E
+00E9;eacute;LATIN SMALL LETTER E WITH ACUTE
+0115;ebreve;LATIN SMALL LETTER E WITH BREVE
+011B;ecaron;LATIN SMALL LETTER E WITH CARON
+00EA;ecircumflex;LATIN SMALL LETTER E WITH CIRCUMFLEX
+00EB;edieresis;LATIN SMALL LETTER E WITH DIAERESIS
+0117;edotaccent;LATIN SMALL LETTER E WITH DOT ABOVE
+00E8;egrave;LATIN SMALL LETTER E WITH GRAVE
+0038;eight;DIGIT EIGHT
+2088;eightinferior;SUBSCRIPT EIGHT
+F738;eightoldstyle;OLDSTYLE DIGIT EIGHT
+2078;eightsuperior;SUPERSCRIPT EIGHT
+2208;element;ELEMENT OF
+2026;ellipsis;HORIZONTAL ELLIPSIS
+0113;emacron;LATIN SMALL LETTER E WITH MACRON
+2014;emdash;EM DASH
+2205;emptyset;EMPTY SET
+2013;endash;EN DASH
+014B;eng;LATIN SMALL LETTER ENG
+0119;eogonek;LATIN SMALL LETTER E WITH OGONEK
+03B5;epsilon;GREEK SMALL LETTER EPSILON
+03AD;epsilontonos;GREEK SMALL LETTER EPSILON WITH TONOS
+003D;equal;EQUALS SIGN
+2261;equivalence;IDENTICAL TO
+212E;estimated;ESTIMATED SYMBOL
+F6EC;esuperior;SUPERSCRIPT LATIN SMALL LETTER E
+03B7;eta;GREEK SMALL LETTER ETA
+03AE;etatonos;GREEK SMALL LETTER ETA WITH TONOS
+00F0;eth;LATIN SMALL LETTER ETH
+0021;exclam;EXCLAMATION MARK
+203C;exclamdbl;DOUBLE EXCLAMATION MARK
+00A1;exclamdown;INVERTED EXCLAMATION MARK
+F7A1;exclamdownsmall;SMALL CAPITAL INVERTED EXCLAMATION MARK
+F721;exclamsmall;SMALL CAPITAL EXCLAMATION MARK
+2203;existential;THERE EXISTS
+0066;f;LATIN SMALL LETTER F
+2640;female;FEMALE SIGN
+FB00;ff;LATIN SMALL LIGATURE FF
+FB03;ffi;LATIN SMALL LIGATURE FFI
+FB04;ffl;LATIN SMALL LIGATURE FFL
+FB01;fi;LATIN SMALL LIGATURE FI
+2012;figuredash;FIGURE DASH
+25A0;filledbox;BLACK SQUARE
+25AC;filledrect;BLACK RECTANGLE
+0035;five;DIGIT FIVE
+215D;fiveeighths;VULGAR FRACTION FIVE EIGHTHS
+2085;fiveinferior;SUBSCRIPT FIVE
+F735;fiveoldstyle;OLDSTYLE DIGIT FIVE
+2075;fivesuperior;SUPERSCRIPT FIVE
+FB02;fl;LATIN SMALL LIGATURE FL
+0192;florin;LATIN SMALL LETTER F WITH HOOK
+0034;four;DIGIT FOUR
+2084;fourinferior;SUBSCRIPT FOUR
+F734;fouroldstyle;OLDSTYLE DIGIT FOUR
+2074;foursuperior;SUPERSCRIPT FOUR
+2044;fraction;FRACTION SLASH
+2215;fraction;DIVISION SLASH;Duplicate
+20A3;franc;FRENCH FRANC SIGN
+0067;g;LATIN SMALL LETTER G
+03B3;gamma;GREEK SMALL LETTER GAMMA
+011F;gbreve;LATIN SMALL LETTER G WITH BREVE
+01E7;gcaron;LATIN SMALL LETTER G WITH CARON
+011D;gcircumflex;LATIN SMALL LETTER G WITH CIRCUMFLEX
+0123;gcommaaccent;LATIN SMALL LETTER G WITH CEDILLA
+0121;gdotaccent;LATIN SMALL LETTER G WITH DOT ABOVE
+00DF;germandbls;LATIN SMALL LETTER SHARP S
+2207;gradient;NABLA
+0060;grave;GRAVE ACCENT
+0300;gravecomb;COMBINING GRAVE ACCENT
+003E;greater;GREATER-THAN SIGN
+2265;greaterequal;GREATER-THAN OR EQUAL TO
+00AB;guillemotleft;LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+00BB;guillemotright;RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+2039;guilsinglleft;SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+203A;guilsinglright;SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+0068;h;LATIN SMALL LETTER H
+0127;hbar;LATIN SMALL LETTER H WITH STROKE
+0125;hcircumflex;LATIN SMALL LETTER H WITH CIRCUMFLEX
+2665;heart;BLACK HEART SUIT
+0309;hookabovecomb;COMBINING HOOK ABOVE
+2302;house;HOUSE
+02DD;hungarumlaut;DOUBLE ACUTE ACCENT
+002D;hyphen;HYPHEN-MINUS
+00AD;hyphen;SOFT HYPHEN;Duplicate
+F6E5;hypheninferior;SUBSCRIPT HYPHEN-MINUS
+F6E6;hyphensuperior;SUPERSCRIPT HYPHEN-MINUS
+0069;i;LATIN SMALL LETTER I
+00ED;iacute;LATIN SMALL LETTER I WITH ACUTE
+012D;ibreve;LATIN SMALL LETTER I WITH BREVE
+00EE;icircumflex;LATIN SMALL LETTER I WITH CIRCUMFLEX
+00EF;idieresis;LATIN SMALL LETTER I WITH DIAERESIS
+00EC;igrave;LATIN SMALL LETTER I WITH GRAVE
+0133;ij;LATIN SMALL LIGATURE IJ
+012B;imacron;LATIN SMALL LETTER I WITH MACRON
+221E;infinity;INFINITY
+222B;integral;INTEGRAL
+2321;integralbt;BOTTOM HALF INTEGRAL
+F8F5;integralex;INTEGRAL EXTENDER
+2320;integraltp;TOP HALF INTEGRAL
+2229;intersection;INTERSECTION
+25D8;invbullet;INVERSE BULLET
+25D9;invcircle;INVERSE WHITE CIRCLE
+263B;invsmileface;BLACK SMILING FACE
+012F;iogonek;LATIN SMALL LETTER I WITH OGONEK
+03B9;iota;GREEK SMALL LETTER IOTA
+03CA;iotadieresis;GREEK SMALL LETTER IOTA WITH DIALYTIKA
+0390;iotadieresistonos;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+03AF;iotatonos;GREEK SMALL LETTER IOTA WITH TONOS
+F6ED;isuperior;SUPERSCRIPT LATIN SMALL LETTER I
+0129;itilde;LATIN SMALL LETTER I WITH TILDE
+006A;j;LATIN SMALL LETTER J
+0135;jcircumflex;LATIN SMALL LETTER J WITH CIRCUMFLEX
+006B;k;LATIN SMALL LETTER K
+03BA;kappa;GREEK SMALL LETTER KAPPA
+0137;kcommaaccent;LATIN SMALL LETTER K WITH CEDILLA
+0138;kgreenlandic;LATIN SMALL LETTER KRA
+006C;l;LATIN SMALL LETTER L
+013A;lacute;LATIN SMALL LETTER L WITH ACUTE
+03BB;lambda;GREEK SMALL LETTER LAMDA
+013E;lcaron;LATIN SMALL LETTER L WITH CARON
+013C;lcommaaccent;LATIN SMALL LETTER L WITH CEDILLA
+0140;ldot;LATIN SMALL LETTER L WITH MIDDLE DOT
+003C;less;LESS-THAN SIGN
+2264;lessequal;LESS-THAN OR EQUAL TO
+258C;lfblock;LEFT HALF BLOCK
+20A4;lira;LIRA SIGN
+F6C0;ll;LATIN SMALL LETTER LL
+2227;logicaland;LOGICAL AND
+00AC;logicalnot;NOT SIGN
+2228;logicalor;LOGICAL OR
+017F;longs;LATIN SMALL LETTER LONG S
+25CA;lozenge;LOZENGE
+0142;lslash;LATIN SMALL LETTER L WITH STROKE
+F6EE;lsuperior;SUPERSCRIPT LATIN SMALL LETTER L
+2591;ltshade;LIGHT SHADE
+006D;m;LATIN SMALL LETTER M
+00AF;macron;MACRON
+02C9;macron;MODIFIER LETTER MACRON;Duplicate
+2642;male;MALE SIGN
+2212;minus;MINUS SIGN
+2032;minute;PRIME
+F6EF;msuperior;SUPERSCRIPT LATIN SMALL LETTER M
+00B5;mu;MICRO SIGN
+03BC;mu;GREEK SMALL LETTER MU;Duplicate
+00D7;multiply;MULTIPLICATION SIGN
+266A;musicalnote;EIGHTH NOTE
+266B;musicalnotedbl;BEAMED EIGHTH NOTES
+006E;n;LATIN SMALL LETTER N
+0144;nacute;LATIN SMALL LETTER N WITH ACUTE
+0149;napostrophe;LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
+0148;ncaron;LATIN SMALL LETTER N WITH CARON
+0146;ncommaaccent;LATIN SMALL LETTER N WITH CEDILLA
+0039;nine;DIGIT NINE
+2089;nineinferior;SUBSCRIPT NINE
+F739;nineoldstyle;OLDSTYLE DIGIT NINE
+2079;ninesuperior;SUPERSCRIPT NINE
+2209;notelement;NOT AN ELEMENT OF
+2260;notequal;NOT EQUAL TO
+2284;notsubset;NOT A SUBSET OF
+207F;nsuperior;SUPERSCRIPT LATIN SMALL LETTER N
+00F1;ntilde;LATIN SMALL LETTER N WITH TILDE
+03BD;nu;GREEK SMALL LETTER NU
+0023;numbersign;NUMBER SIGN
+006F;o;LATIN SMALL LETTER O
+00F3;oacute;LATIN SMALL LETTER O WITH ACUTE
+014F;obreve;LATIN SMALL LETTER O WITH BREVE
+00F4;ocircumflex;LATIN SMALL LETTER O WITH CIRCUMFLEX
+00F6;odieresis;LATIN SMALL LETTER O WITH DIAERESIS
+0153;oe;LATIN SMALL LIGATURE OE
+02DB;ogonek;OGONEK
+00F2;ograve;LATIN SMALL LETTER O WITH GRAVE
+01A1;ohorn;LATIN SMALL LETTER O WITH HORN
+0151;ohungarumlaut;LATIN SMALL LETTER O WITH DOUBLE ACUTE
+014D;omacron;LATIN SMALL LETTER O WITH MACRON
+03C9;omega;GREEK SMALL LETTER OMEGA
+03D6;omega1;GREEK PI SYMBOL
+03CE;omegatonos;GREEK SMALL LETTER OMEGA WITH TONOS
+03BF;omicron;GREEK SMALL LETTER OMICRON
+03CC;omicrontonos;GREEK SMALL LETTER OMICRON WITH TONOS
+0031;one;DIGIT ONE
+2024;onedotenleader;ONE DOT LEADER
+215B;oneeighth;VULGAR FRACTION ONE EIGHTH
+F6DC;onefitted;PROPORTIONAL DIGIT ONE
+00BD;onehalf;VULGAR FRACTION ONE HALF
+2081;oneinferior;SUBSCRIPT ONE
+F731;oneoldstyle;OLDSTYLE DIGIT ONE
+00BC;onequarter;VULGAR FRACTION ONE QUARTER
+00B9;onesuperior;SUPERSCRIPT ONE
+2153;onethird;VULGAR FRACTION ONE THIRD
+25E6;openbullet;WHITE BULLET
+00AA;ordfeminine;FEMININE ORDINAL INDICATOR
+00BA;ordmasculine;MASCULINE ORDINAL INDICATOR
+221F;orthogonal;RIGHT ANGLE
+00F8;oslash;LATIN SMALL LETTER O WITH STROKE
+01FF;oslashacute;LATIN SMALL LETTER O WITH STROKE AND ACUTE
+F6F0;osuperior;SUPERSCRIPT LATIN SMALL LETTER O
+00F5;otilde;LATIN SMALL LETTER O WITH TILDE
+0070;p;LATIN SMALL LETTER P
+00B6;paragraph;PILCROW SIGN
+0028;parenleft;LEFT PARENTHESIS
+F8ED;parenleftbt;LEFT PAREN BOTTOM
+F8EC;parenleftex;LEFT PAREN EXTENDER
+208D;parenleftinferior;SUBSCRIPT LEFT PARENTHESIS
+207D;parenleftsuperior;SUPERSCRIPT LEFT PARENTHESIS
+F8EB;parenlefttp;LEFT PAREN TOP
+0029;parenright;RIGHT PARENTHESIS
+F8F8;parenrightbt;RIGHT PAREN BOTTOM
+F8F7;parenrightex;RIGHT PAREN EXTENDER
+208E;parenrightinferior;SUBSCRIPT RIGHT PARENTHESIS
+207E;parenrightsuperior;SUPERSCRIPT RIGHT PARENTHESIS
+F8F6;parenrighttp;RIGHT PAREN TOP
+2202;partialdiff;PARTIAL DIFFERENTIAL
+0025;percent;PERCENT SIGN
+002E;period;FULL STOP
+00B7;periodcentered;MIDDLE DOT
+2219;periodcentered;BULLET OPERATOR;Duplicate
+F6E7;periodinferior;SUBSCRIPT FULL STOP
+F6E8;periodsuperior;SUPERSCRIPT FULL STOP
+22A5;perpendicular;UP TACK
+2030;perthousand;PER MILLE SIGN
+20A7;peseta;PESETA SIGN
+03C6;phi;GREEK SMALL LETTER PHI
+03D5;phi1;GREEK PHI SYMBOL
+03C0;pi;GREEK SMALL LETTER PI
+002B;plus;PLUS SIGN
+00B1;plusminus;PLUS-MINUS SIGN
+211E;prescription;PRESCRIPTION TAKE
+220F;product;N-ARY PRODUCT
+2282;propersubset;SUBSET OF
+2283;propersuperset;SUPERSET OF
+221D;proportional;PROPORTIONAL TO
+03C8;psi;GREEK SMALL LETTER PSI
+0071;q;LATIN SMALL LETTER Q
+003F;question;QUESTION MARK
+00BF;questiondown;INVERTED QUESTION MARK
+F7BF;questiondownsmall;SMALL CAPITAL INVERTED QUESTION MARK
+F73F;questionsmall;SMALL CAPITAL QUESTION MARK
+0022;quotedbl;QUOTATION MARK
+201E;quotedblbase;DOUBLE LOW-9 QUOTATION MARK
+201C;quotedblleft;LEFT DOUBLE QUOTATION MARK
+201D;quotedblright;RIGHT DOUBLE QUOTATION MARK
+2018;quoteleft;LEFT SINGLE QUOTATION MARK
+201B;quotereversed;SINGLE HIGH-REVERSED-9 QUOTATION MARK
+2019;quoteright;RIGHT SINGLE QUOTATION MARK
+201A;quotesinglbase;SINGLE LOW-9 QUOTATION MARK
+0027;quotesingle;APOSTROPHE
+0072;r;LATIN SMALL LETTER R
+0155;racute;LATIN SMALL LETTER R WITH ACUTE
+221A;radical;SQUARE ROOT
+F8E5;radicalex;RADICAL EXTENDER
+0159;rcaron;LATIN SMALL LETTER R WITH CARON
+0157;rcommaaccent;LATIN SMALL LETTER R WITH CEDILLA
+2286;reflexsubset;SUBSET OF OR EQUAL TO
+2287;reflexsuperset;SUPERSET OF OR EQUAL TO
+00AE;registered;REGISTERED SIGN
+F8E8;registersans;REGISTERED SIGN SANS SERIF
+F6DA;registerserif;REGISTERED SIGN SERIF
+2310;revlogicalnot;REVERSED NOT SIGN
+03C1;rho;GREEK SMALL LETTER RHO
+02DA;ring;RING ABOVE
+F6F1;rsuperior;SUPERSCRIPT LATIN SMALL LETTER R
+2590;rtblock;RIGHT HALF BLOCK
+F6DD;rupiah;RUPIAH SIGN
+0073;s;LATIN SMALL LETTER S
+015B;sacute;LATIN SMALL LETTER S WITH ACUTE
+0161;scaron;LATIN SMALL LETTER S WITH CARON
+015F;scedilla;LATIN SMALL LETTER S WITH CEDILLA
+F6C2;scedilla;LATIN SMALL LETTER S WITH CEDILLA;Duplicate
+015D;scircumflex;LATIN SMALL LETTER S WITH CIRCUMFLEX
+0219;scommaaccent;LATIN SMALL LETTER S WITH COMMA BELOW
+2033;second;DOUBLE PRIME
+00A7;section;SECTION SIGN
+003B;semicolon;SEMICOLON
+0037;seven;DIGIT SEVEN
+215E;seveneighths;VULGAR FRACTION SEVEN EIGHTHS
+2087;seveninferior;SUBSCRIPT SEVEN
+F737;sevenoldstyle;OLDSTYLE DIGIT SEVEN
+2077;sevensuperior;SUPERSCRIPT SEVEN
+2592;shade;MEDIUM SHADE
+03C3;sigma;GREEK SMALL LETTER SIGMA
+03C2;sigma1;GREEK SMALL LETTER FINAL SIGMA
+223C;similar;TILDE OPERATOR
+0036;six;DIGIT SIX
+2086;sixinferior;SUBSCRIPT SIX
+F736;sixoldstyle;OLDSTYLE DIGIT SIX
+2076;sixsuperior;SUPERSCRIPT SIX
+002F;slash;SOLIDUS
+263A;smileface;WHITE SMILING FACE
+0020;space;SPACE
+00A0;space;NO-BREAK SPACE;Duplicate
+2660;spade;BLACK SPADE SUIT
+F6F2;ssuperior;SUPERSCRIPT LATIN SMALL LETTER S
+00A3;sterling;POUND SIGN
+220B;suchthat;CONTAINS AS MEMBER
+2211;summation;N-ARY SUMMATION
+263C;sun;WHITE SUN WITH RAYS
+0074;t;LATIN SMALL LETTER T
+03C4;tau;GREEK SMALL LETTER TAU
+0167;tbar;LATIN SMALL LETTER T WITH STROKE
+0165;tcaron;LATIN SMALL LETTER T WITH CARON
+0163;tcommaaccent;LATIN SMALL LETTER T WITH CEDILLA
+021B;tcommaaccent;LATIN SMALL LETTER T WITH COMMA BELOW;Duplicate
+2234;therefore;THEREFORE
+03B8;theta;GREEK SMALL LETTER THETA
+03D1;theta1;GREEK THETA SYMBOL
+00FE;thorn;LATIN SMALL LETTER THORN
+0033;three;DIGIT THREE
+215C;threeeighths;VULGAR FRACTION THREE EIGHTHS
+2083;threeinferior;SUBSCRIPT THREE
+F733;threeoldstyle;OLDSTYLE DIGIT THREE
+00BE;threequarters;VULGAR FRACTION THREE QUARTERS
+F6DE;threequartersemdash;THREE QUARTERS EM DASH
+00B3;threesuperior;SUPERSCRIPT THREE
+02DC;tilde;SMALL TILDE
+0303;tildecomb;COMBINING TILDE
+0384;tonos;GREEK TONOS
+2122;trademark;TRADE MARK SIGN
+F8EA;trademarksans;TRADE MARK SIGN SANS SERIF
+F6DB;trademarkserif;TRADE MARK SIGN SERIF
+25BC;triagdn;BLACK DOWN-POINTING TRIANGLE
+25C4;triaglf;BLACK LEFT-POINTING POINTER
+25BA;triagrt;BLACK RIGHT-POINTING POINTER
+25B2;triagup;BLACK UP-POINTING TRIANGLE
+F6F3;tsuperior;SUPERSCRIPT LATIN SMALL LETTER T
+0032;two;DIGIT TWO
+2025;twodotenleader;TWO DOT LEADER
+2082;twoinferior;SUBSCRIPT TWO
+F732;twooldstyle;OLDSTYLE DIGIT TWO
+00B2;twosuperior;SUPERSCRIPT TWO
+2154;twothirds;VULGAR FRACTION TWO THIRDS
+0075;u;LATIN SMALL LETTER U
+00FA;uacute;LATIN SMALL LETTER U WITH ACUTE
+016D;ubreve;LATIN SMALL LETTER U WITH BREVE
+00FB;ucircumflex;LATIN SMALL LETTER U WITH CIRCUMFLEX
+00FC;udieresis;LATIN SMALL LETTER U WITH DIAERESIS
+00F9;ugrave;LATIN SMALL LETTER U WITH GRAVE
+01B0;uhorn;LATIN SMALL LETTER U WITH HORN
+0171;uhungarumlaut;LATIN SMALL LETTER U WITH DOUBLE ACUTE
+016B;umacron;LATIN SMALL LETTER U WITH MACRON
+005F;underscore;LOW LINE
+2017;underscoredbl;DOUBLE LOW LINE
+222A;union;UNION
+2200;universal;FOR ALL
+0173;uogonek;LATIN SMALL LETTER U WITH OGONEK
+2580;upblock;UPPER HALF BLOCK
+03C5;upsilon;GREEK SMALL LETTER UPSILON
+03CB;upsilondieresis;GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+03B0;upsilondieresistonos;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+03CD;upsilontonos;GREEK SMALL LETTER UPSILON WITH TONOS
+016F;uring;LATIN SMALL LETTER U WITH RING ABOVE
+0169;utilde;LATIN SMALL LETTER U WITH TILDE
+0076;v;LATIN SMALL LETTER V
+0077;w;LATIN SMALL LETTER W
+1E83;wacute;LATIN SMALL LETTER W WITH ACUTE
+0175;wcircumflex;LATIN SMALL LETTER W WITH CIRCUMFLEX
+1E85;wdieresis;LATIN SMALL LETTER W WITH DIAERESIS
+2118;weierstrass;SCRIPT CAPITAL P
+1E81;wgrave;LATIN SMALL LETTER W WITH GRAVE
+0078;x;LATIN SMALL LETTER X
+03BE;xi;GREEK SMALL LETTER XI
+0079;y;LATIN SMALL LETTER Y
+00FD;yacute;LATIN SMALL LETTER Y WITH ACUTE
+0177;ycircumflex;LATIN SMALL LETTER Y WITH CIRCUMFLEX
+00FF;ydieresis;LATIN SMALL LETTER Y WITH DIAERESIS
+00A5;yen;YEN SIGN
+1EF3;ygrave;LATIN SMALL LETTER Y WITH GRAVE
+007A;z;LATIN SMALL LETTER Z
+017A;zacute;LATIN SMALL LETTER Z WITH ACUTE
+017E;zcaron;LATIN SMALL LETTER Z WITH CARON
+017C;zdotaccent;LATIN SMALL LETTER Z WITH DOT ABOVE
+0030;zero;DIGIT ZERO
+2080;zeroinferior;SUBSCRIPT ZERO
+F730;zerooldstyle;OLDSTYLE DIGIT ZERO
+2070;zerosuperior;SUPERSCRIPT ZERO
+03B6;zeta;GREEK SMALL LETTER ZETA
+"""
+
+
+AGLError = "AGLError"
+
+AGL2UV = {}
+UV2AGL = {}
+
+def _builddicts():
+	import re
+	import string
+	
+	lines = string.split(_aglText, "\n")
+	
+	parseAGL_RE = re.compile("([0-9A-F]{4});([A-Za-z_0-9.]+);.*?$")
+	
+	for line in lines:
+		if not line:
+			break
+		if line[:1] == '#':
+			continue
+		m = parseAGL_RE.match(line)
+		if not m:
+			raise AGLError, "syntax error in glyphlist.txt: %s" % repr(line[:20])
+		unicode = m.group(1)
+		assert len(unicode) == 4
+		unicode = string.atoi(unicode, 16)
+		glyphName = m.group(2)
+		if AGL2UV.has_key(glyphName):
+			assert type(AGL2UV[glyphName]) == type(0)
+			AGL2UV[glyphName] = AGL2UV[glyphName], unicode
+		else:
+			AGL2UV[glyphName] = unicode
+		UV2AGL[unicode] = glyphName
+	
+_builddicts()
+
diff --git a/Lib/fontTools/cffLib.py b/Lib/fontTools/cffLib.py
new file mode 100644
index 0000000..76476c3
--- /dev/null
+++ b/Lib/fontTools/cffLib.py
@@ -0,0 +1,459 @@
+"""cffLib.py -- read/write tools for Adobe CFF fonts."""
+
+__version__ = "1.0b1"
+__author__ = "jvr"
+
+import struct, sstruct
+import string
+import types
+import psCharStrings
+
+
+cffHeaderFormat = """
+	major:   B
+	minor:   B
+	hdrSize: B
+	offSize: B
+"""
+
+class CFFFontSet:
+	
+	def __init__(self):
+		self.fonts = {}
+	
+	def decompile(self, data):
+		sstruct.unpack(cffHeaderFormat, data[:4], self)
+		assert self.major == 1 and self.minor == 0, \
+				"unknown CFF format: %d.%d" % (self.major, self.minor)
+		restdata = data[self.hdrSize:]
+		
+		self.fontNames, restdata = readINDEX(restdata)
+		topDicts, restdata = readINDEX(restdata)
+		strings, restdata = readINDEX(restdata)
+		strings = IndexedStrings(strings)
+		globalSubrs, restdata = readINDEX(restdata)
+		self.GlobalSubrs = map(psCharStrings.T2CharString, globalSubrs)
+		
+		for i in range(len(topDicts)):
+			font = self.fonts[self.fontNames[i]] = CFFFont()
+			font.GlobalSubrs = self.GlobalSubrs  # Hmm.
+			font.decompile(data, topDicts[i], strings, self)  # maybe only 'on demand'?
+			
+	
+	def compile(self):
+		strings = IndexedStrings()
+		XXXX
+	
+	def toXML(self, xmlWriter, progress=None):
+		xmlWriter.newline()
+		for fontName in self.fontNames:
+			xmlWriter.begintag("CFFFont", name=fontName)
+			xmlWriter.newline()
+			font = self.fonts[fontName]
+			font.toXML(xmlWriter, progress)
+			xmlWriter.endtag("CFFFont")
+			xmlWriter.newline()
+		xmlWriter.newline()
+		xmlWriter.begintag("GlobalSubrs")
+		xmlWriter.newline()
+		for i in range(len(self.GlobalSubrs)):
+			xmlWriter.newline()
+			xmlWriter.begintag("CharString", id=i)
+			xmlWriter.newline()
+			self.GlobalSubrs[i].toXML(xmlWriter)
+			xmlWriter.endtag("CharString")
+			xmlWriter.newline()
+		xmlWriter.newline()
+		xmlWriter.endtag("GlobalSubrs")
+		xmlWriter.newline()
+		xmlWriter.newline()
+	
+	def fromXML(self, (name, attrs, content)):
+		xxx
+
+
+class IndexedStrings:
+	
+	def __init__(self, strings=None):
+		if strings is None:
+			strings = []
+		self.strings = strings
+	
+	def __getitem__(self, SID):
+		if SID < cffStandardStringCount:
+			return cffStandardStrings[SID]
+		else:
+			return self.strings[SID - cffStandardStringCount]
+	
+	def getSID(self, s):
+		if not hasattr(self, "stringMapping"):
+			self.buildStringMapping()
+		if cffStandardStringMapping.has_key(s):
+			SID = cffStandardStringMapping[s]
+		if self.stringMapping.has_key(s):
+			SID = self.stringMapping[s]
+		else:
+			SID = len(self.strings) + cffStandardStringCount
+			self.strings.append(s)
+			self.stringMapping[s] = SID
+		return SID
+	
+	def getStrings(self):
+		return self.strings
+	
+	def buildStringMapping(self):
+		self.stringMapping = {}
+		for index in range(len(self.strings)):
+			self.stringMapping[self.strings[index]] = index + cffStandardStringCount
+
+
+class CFFFont:
+	
+	defaults = psCharStrings.topDictDefaults
+	
+	def __init__(self):
+		pass
+	
+	def __getattr__(self, attr):
+		if not self.defaults.has_key(attr):
+			raise AttributeError, attr
+		return self.defaults[attr]
+	
+	def fromDict(self, dict):
+		self.__dict__.update(dict)
+	
+	def decompile(self, data, topDictData, strings, fontSet):
+		top = psCharStrings.TopDictDecompiler(strings)
+		top.decompile(topDictData)
+		self.fromDict(top.getDict())
+		
+		# get private dict
+		size, offset = self.Private
+		#print "YYY Private (size, offset):", size, offset
+		privateData = data[offset:offset+size]
+		self.Private = PrivateDict()
+		self.Private.decompile(data[offset:], privateData, strings)
+		
+		# get raw charstrings
+		#print "YYYY CharStrings offset:", self.CharStrings
+		rawCharStrings, restdata = readINDEX(data[self.CharStrings:])
+		nGlyphs = len(rawCharStrings)
+		
+		# get charset (or rather: get glyphNames)
+		charsetOffset = self.charset
+		if charsetOffset == 0:
+			xxx  # standard charset
+		else:
+			#print "YYYYY charsetOffset:", charsetOffset
+			format = ord(data[charsetOffset])
+			if format == 0:
+				xxx
+			elif format == 1:
+				charSet = parseCharsetFormat1(nGlyphs, 
+						data[charsetOffset+1:], strings)
+			elif format == 2:
+				charSet = parseCharsetFormat2(nGlyphs, 
+						data[charsetOffset+1:], strings)
+			elif format == 3:
+				xxx
+			else:
+				xxx
+		self.charset = charSet
+		
+		assert len(charSet) == nGlyphs
+		self.CharStrings = charStrings = {}
+		if self.CharstringType == 2:
+			# Type 2 CharStrings
+			charStringClass = psCharStrings.T2CharString
+		else:
+			# Type 1 CharStrings
+			charStringClass = psCharStrings.T1CharString
+		for i in range(nGlyphs):
+			charStrings[charSet[i]] = charStringClass(rawCharStrings[i])
+		assert len(charStrings) == nGlyphs
+		
+		# XXX Encoding!
+		encoding = self.Encoding
+		if encoding not in (0, 1):
+			# encoding is an _offset_ from the beginning of 'data' to an encoding subtable
+			XXX
+			self.Encoding = encoding
+	
+	def getGlyphOrder(self):
+		return self.charset
+	
+	def setGlyphOrder(self, glyphOrder):
+		self.charset = glyphOrder
+	
+	def decompileAllCharStrings(self):
+		if self.CharstringType == 2:
+			# Type 2 CharStrings
+			decompiler = psCharStrings.SimpleT2Decompiler(self.Private.Subrs, self.GlobalSubrs)
+			for charString in self.CharStrings.values():
+				if charString.needsDecompilation():
+					decompiler.reset()
+					decompiler.execute(charString)
+		else:
+			# Type 1 CharStrings
+			for charString in self.CharStrings.values():
+				charString.decompile()
+	
+	def toXML(self, xmlWriter, progress=None):
+		xmlWriter.newline()
+		# first dump the simple values
+		self.toXMLSimpleValues(xmlWriter)
+		
+		# dump charset
+		# XXX
+		
+		# decompile all charstrings
+		if progress:
+			progress.setlabel("Decompiling CharStrings...")
+		self.decompileAllCharStrings()
+		
+		# dump private dict
+		xmlWriter.begintag("Private")
+		xmlWriter.newline()
+		self.Private.toXML(xmlWriter)
+		xmlWriter.endtag("Private")
+		xmlWriter.newline()
+		
+		self.toXMLCharStrings(xmlWriter, progress)
+	
+	def toXMLSimpleValues(self, xmlWriter):
+		keys = self.__dict__.keys()
+		keys.remove("CharStrings")
+		keys.remove("Private")
+		keys.remove("charset")
+		keys.remove("GlobalSubrs")
+		keys.sort()
+		for key in keys:
+			value = getattr(self, key)
+			if key == "Encoding":
+				if value == 0:
+					# encoding is (Adobe) Standard Encoding
+					value = "StandardEncoding"
+				elif value == 1:
+					# encoding is Expert Encoding
+					value = "ExpertEncoding"
+			if type(value) == types.ListType:
+				value = string.join(map(str, value), " ")
+			else:
+				value = str(value)
+			xmlWriter.begintag(key)
+			if hasattr(value, "toXML"):
+				xmlWriter.newline()
+				value.toXML(xmlWriter)
+				xmlWriter.newline()
+			else:
+				xmlWriter.write(value)
+			xmlWriter.endtag(key)
+			xmlWriter.newline()
+		xmlWriter.newline()
+	
+	def toXMLCharStrings(self, xmlWriter, progress=None):
+		charStrings = self.CharStrings
+		xmlWriter.newline()
+		xmlWriter.begintag("CharStrings")
+		xmlWriter.newline()
+		glyphNames = charStrings.keys()
+		glyphNames.sort()
+		for glyphName in glyphNames:
+			if progress:
+				progress.setlabel("Dumping 'CFF ' table... (%s)" % glyphName)
+				progress.increment()
+			xmlWriter.newline()
+			charString = charStrings[glyphName]
+			xmlWriter.begintag("CharString", name=glyphName)
+			xmlWriter.newline()
+			charString.toXML(xmlWriter)
+			xmlWriter.endtag("CharString")
+			xmlWriter.newline()
+		xmlWriter.newline()
+		xmlWriter.endtag("CharStrings")
+		xmlWriter.newline()
+
+
+class PrivateDict:
+	
+	defaults = psCharStrings.privateDictDefaults
+	
+	def __init__(self):
+		pass
+	
+	def decompile(self, data, privateData, strings):
+		p = psCharStrings.PrivateDictDecompiler(strings)
+		p.decompile(privateData)
+		self.fromDict(p.getDict())
+		
+		# get local subrs
+		#print "YYY Private.Subrs:", self.Subrs
+		chunk = data[self.Subrs:]
+		localSubrs, restdata = readINDEX(chunk)
+		self.Subrs = map(psCharStrings.T2CharString, localSubrs)
+	
+	def toXML(self, xmlWriter):
+		xmlWriter.newline()
+		keys = self.__dict__.keys()
+		keys.remove("Subrs")
+		for key in keys:
+			value = getattr(self, key)
+			if type(value) == types.ListType:
+				value = string.join(map(str, value), " ")
+			else:
+				value = str(value)
+			xmlWriter.begintag(key)
+			xmlWriter.write(value)
+			xmlWriter.endtag(key)
+			xmlWriter.newline()
+		# write subroutines
+		xmlWriter.newline()
+		xmlWriter.begintag("Subrs")
+		xmlWriter.newline()
+		for i in range(len(self.Subrs)):
+			xmlWriter.newline()
+			xmlWriter.begintag("CharString", id=i)
+			xmlWriter.newline()
+			self.Subrs[i].toXML(xmlWriter)
+			xmlWriter.endtag("CharString")
+			xmlWriter.newline()
+		xmlWriter.newline()
+		xmlWriter.endtag("Subrs")
+		xmlWriter.newline()
+		xmlWriter.newline()
+	
+	def __getattr__(self, attr):
+		if not self.defaults.has_key(attr):
+			raise AttributeError, attr
+		return self.defaults[attr]
+	
+	def fromDict(self, dict):
+		self.__dict__.update(dict)
+
+
+def readINDEX(data):
+	count, = struct.unpack(">H", data[:2])
+	count = int(count)
+	offSize = ord(data[2])
+	data = data[3:]
+	offsets = []
+	for index in range(count+1):
+		chunk = data[index * offSize: (index+1) * offSize]
+		chunk = '\0' * (4 - offSize) + chunk
+		offset, = struct.unpack(">L", chunk)
+		offset = int(offset)
+		offsets.append(offset)
+	data = data[(count+1) * offSize:]
+	prev = offsets[0]
+	stuff = []
+	for next in offsets[1:]:
+		chunk = data[prev-1:next-1]
+		assert len(chunk) == next - prev
+		stuff.append(chunk)
+		prev = next
+	data = data[next-1:]
+	return stuff, data
+
+
+def parseCharsetFormat1(nGlyphs, data, strings):
+	charSet = ['.notdef']
+	count = 1
+	while count < nGlyphs:
+		first = int(struct.unpack(">H", data[:2])[0])
+		nLeft = ord(data[2])
+		data = data[3:]
+		for SID in range(first, first+nLeft+1):
+			charSet.append(strings[SID])
+		count = count + nLeft + 1
+	return charSet
+
+
+def parseCharsetFormat2(nGlyphs, data, strings):
+	charSet = ['.notdef']
+	count = 1
+	while count < nGlyphs:
+		first = int(struct.unpack(">H", data[:2])[0])
+		nLeft = int(struct.unpack(">H", data[2:4])[0])
+		data = data[4:]
+		for SID in range(first, first+nLeft+1):
+			charSet.append(strings[SID])
+		count = count + nLeft + 1
+	return charSet
+
+
+# The 391 Standard Strings as used in the CFF format.
+# from Adobe Technical None #5176, version 1.0, 18 March 1998
+
+cffStandardStrings = ['.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 
+		'dollar', 'percent', 'ampersand', 'quoteright', 'parenleft', 'parenright', 
+		'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 
+		'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 
+		'semicolon', 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 
+		'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 
+		'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 
+		'bracketright', 'asciicircum', 'underscore', 'quoteleft', 'a', 'b', 'c', 
+		'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 
+		's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 
+		'asciitilde', 'exclamdown', 'cent', 'sterling', 'fraction', 'yen', 'florin', 
+		'section', 'currency', 'quotesingle', 'quotedblleft', 'guillemotleft', 
+		'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 
+		'daggerdbl', 'periodcentered', 'paragraph', 'bullet', 'quotesinglbase', 
+		'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis', 'perthousand', 
+		'questiondown', 'grave', 'acute', 'circumflex', 'tilde', 'macron', 'breve', 
+		'dotaccent', 'dieresis', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron', 
+		'emdash', 'AE', 'ordfeminine', 'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae', 
+		'dotlessi', 'lslash', 'oslash', 'oe', 'germandbls', 'onesuperior', 
+		'logicalnot', 'mu', 'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', 
+		'onequarter', 'divide', 'brokenbar', 'degree', 'thorn', 'threequarters', 
+		'twosuperior', 'registered', 'minus', 'eth', 'multiply', 'threesuperior', 
+		'copyright', 'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', 
+		'Atilde', 'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave', 
+		'Iacute', 'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', 
+		'Ocircumflex', 'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', 
+		'Ucircumflex', 'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron', 
+		'aacute', 'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla', 
+		'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex', 
+		'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex', 'odieresis', 
+		'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis', 'ugrave', 
+		'yacute', 'ydieresis', 'zcaron', 'exclamsmall', 'Hungarumlautsmall', 
+		'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', 'Acutesmall', 
+		'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', 'onedotenleader', 
+		'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 
+		'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 
+		'nineoldstyle', 'commasuperior', 'threequartersemdash', 'periodsuperior', 
+		'questionsmall', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior', 
+		'esuperior', 'isuperior', 'lsuperior', 'msuperior', 'nsuperior', 'osuperior', 
+		'rsuperior', 'ssuperior', 'tsuperior', 'ff', 'ffi', 'ffl', 'parenleftinferior', 
+		'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 
+		'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 
+		'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall', 
+		'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall', 'Xsmall', 
+		'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', 
+		'exclamdownsmall', 'centoldstyle', 'Lslashsmall', 'Scaronsmall', 'Zcaronsmall', 
+		'Dieresissmall', 'Brevesmall', 'Caronsmall', 'Dotaccentsmall', 'Macronsmall', 
+		'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall', 'Cedillasmall', 
+		'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 
+		'onethird', 'twothirds', 'zerosuperior', 'foursuperior', 'fivesuperior', 
+		'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', 'zeroinferior', 
+		'oneinferior', 'twoinferior', 'threeinferior', 'fourinferior', 'fiveinferior', 
+		'sixinferior', 'seveninferior', 'eightinferior', 'nineinferior', 'centinferior', 
+		'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall', 
+		'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall', 
+		'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 
+		'Edieresissmall', 'Igravesmall', 'Iacutesmall', 'Icircumflexsmall', 
+		'Idieresissmall', 'Ethsmall', 'Ntildesmall', 'Ogravesmall', 'Oacutesmall', 
+		'Ocircumflexsmall', 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 
+		'Ugravesmall', 'Uacutesmall', 'Ucircumflexsmall', 'Udieresissmall', 
+		'Yacutesmall', 'Thornsmall', 'Ydieresissmall', '001.000', '001.001', '001.002', 
+		'001.003', 'Black', 'Bold', 'Book', 'Light', 'Medium', 'Regular', 'Roman', 
+		'Semibold'
+]
+
+cffStandardStringCount = 391
+assert len(cffStandardStrings) == cffStandardStringCount
+# build reverse mapping
+cffStandardStringMapping = {}
+for _i in range(cffStandardStringCount):
+	cffStandardStringMapping[cffStandardStrings[_i]] = _i
+
+
diff --git a/Lib/fontTools/fondLib.py b/Lib/fontTools/fondLib.py
new file mode 100644
index 0000000..94468cb
--- /dev/null
+++ b/Lib/fontTools/fondLib.py
@@ -0,0 +1,553 @@
+import os
+import Res
+import struct, sstruct
+import string
+
+__version__ = "1.0b2"
+__author__ = "jvr"
+
+error = "fondLib.error"
+
+DEBUG = 0
+
+headerformat = """
+	ffFlags:	h
+	ffFamID:	h
+	ffFirstChar:	h
+	ffLastChar:	h
+	ffAscent:	h
+	ffDescent:	h
+	ffLeading:	h
+	ffWidMax:	h
+	ffWTabOff:	l
+	ffKernOff:	l
+	ffStylOff:	l
+"""
+
+FONDheadersize = 52
+
+class FontFamily:
+	
+	def __init__(self, theRes, mode = 'r'):
+		self.ID, type, self.name = theRes.GetResInfo()
+		if type <> 'FOND':
+			raise ValueError, "FOND resource required"
+		self.FOND = theRes
+		self.mode = mode
+		self.changed = 0
+		
+		if DEBUG:
+			self.parsedthings = []
+	
+	def parse(self):
+		self._getheader()
+		self._getfontassociationtable()
+		self._getoffsettable()
+		self._getboundingboxtable()
+		self._getglyphwidthtable()
+		self._getstylemappingtable()
+		self._getglyphencodingsubtable()
+		self._getkerningtables()
+	
+	def minimalparse(self):
+		self._getheader()
+		self._getglyphwidthtable()
+		self._getstylemappingtable()
+	
+	def __repr__(self):
+		return "<FontFamily instance of %s>" % self.name
+	
+	def getflags(self):
+		return self.fondClass
+	
+	def setflags(self, flags):
+		self.changed = 1
+		self.fondClass = flags
+	
+	def save(self, destresfile = None):
+		if self.mode <> 'w':
+			raise error, "can't save font: no write permission"
+		self._buildfontassociationtable()
+		self._buildoffsettable()
+		self._buildboundingboxtable()
+		self._buildglyphwidthtable()
+		self._buildkerningtables()
+		self._buildstylemappingtable()
+		self._buildglyphencodingsubtable()
+		rawnames = [	"_rawheader", 
+					"_rawfontassociationtable", 
+					"_rawoffsettable", 
+					"_rawglyphwidthtable", 
+					"_rawstylemappingtable", 
+					"_rawglyphencodingsubtable",
+					"_rawkerningtables"
+				]
+		for name in rawnames[1:]:	# skip header
+			data = getattr(self, name)
+			if len(data) & 1:
+				setattr(self, name, data + '\0')
+		
+		self.ffWTabOff = FONDheadersize + len(self._rawfontassociationtable) + len(self._rawoffsettable)
+		self.ffStylOff = self.ffWTabOff + len(self._rawglyphwidthtable)
+		self.ffKernOff = self.ffStylOff + len(self._rawstylemappingtable) + len(self._rawglyphencodingsubtable)
+		self.glyphTableOffset = len(self._rawstylemappingtable)
+		
+		if not self._rawglyphwidthtable:
+			self.ffWTabOff = 0
+		if not self._rawstylemappingtable:
+			self.ffStylOff = 0
+		if not self._rawglyphencodingsubtable:
+			self.glyphTableOffset = 0
+		if not self._rawkerningtables:
+			self.ffKernOff = 0
+		
+		self._buildheader()
+		
+		# glyphTableOffset has only just been calculated
+		self._updatestylemappingtable()
+		
+		newdata = ""
+		for name in rawnames:
+			newdata = newdata + getattr(self, name)
+		if destresfile is None:
+			self.FOND.data = newdata
+			self.FOND.ChangedResource()
+			self.FOND.WriteResource()
+		else:
+			ID, type, name = self.FOND.GetResInfo()
+			self.FOND.DetachResource()
+			self.FOND.data = newdata
+			saveref = Res.CurResFile()
+			Res.UseResFile(destresfile)
+			self.FOND.AddResource(type, ID, name)
+			Res.UseResFile(saveref)
+		self.changed = 0
+	
+	def _getheader(self):
+		data = self.FOND.data
+		sstruct.unpack(headerformat, data[:28], self)
+		self.ffProperty = struct.unpack("9h", data[28:46])
+		self.ffIntl = struct.unpack("hh", data[46:50])
+		self.ffVersion, = struct.unpack("h", data[50:FONDheadersize])
+		
+		if DEBUG:
+			self._rawheader = data[:FONDheadersize]
+			self.parsedthings.append((0, FONDheadersize, 'header'))
+	
+	def _buildheader(self):
+		header = sstruct.pack(headerformat, self)
+		header = header + apply(struct.pack, ("9h",) + self.ffProperty)
+		header = header + apply(struct.pack, ("hh",) + self.ffIntl)
+		header = header + struct.pack("h", self.ffVersion)
+		if DEBUG:
+			print "header is the same?", self._rawheader == header and 'yes.' or 'no.'
+			if self._rawheader <> header:
+				print len(self._rawheader), len(header)
+		self._rawheader = header
+	
+	def _getfontassociationtable(self):
+		data = self.FOND.data
+		offset = FONDheadersize
+		numberofentries, = struct.unpack("h", data[offset:offset+2])
+		numberofentries = numberofentries + 1
+		size = numberofentries * 6
+		self.fontAssoc = []
+		for i in range(offset + 2, offset + size, 6):
+			self.fontAssoc.append(struct.unpack("3h", data[i:i+6]))
+		
+		self._endoffontassociationtable = offset + size + 2
+		if DEBUG:
+			self._rawfontassociationtable = data[offset:self._endoffontassociationtable]
+			self.parsedthings.append((offset, self._endoffontassociationtable, 'fontassociationtable'))
+	
+	def _buildfontassociationtable(self):
+		data = struct.pack("h", len(self.fontAssoc) - 1)
+		for size, stype, ID in self.fontAssoc:
+			data = data + struct.pack("3h", size, stype, ID)
+		
+		if DEBUG:
+			print "font association table is the same?", self._rawfontassociationtable == data and 'yes.' or 'no.'
+			if self._rawfontassociationtable <> data:
+				print len(self._rawfontassociationtable), len(data)
+		self._rawfontassociationtable = data
+	
+	def _getoffsettable(self):
+		if self.ffWTabOff == 0:
+			self._rawoffsettable = ""
+			return
+		data = self.FOND.data
+		# Quick'n'Dirty. What's the spec anyway? Can't find it...
+		offset = self._endoffontassociationtable
+		count = self.ffWTabOff
+		self._rawoffsettable = data[offset:count]
+		if DEBUG:
+			self.parsedthings.append((offset, count, 'offsettable&bbtable'))
+	
+	def _buildoffsettable(self):
+		if not hasattr(self, "_rawoffsettable"):
+			self._rawoffsettable = ""
+	
+	def _getboundingboxtable(self):
+		self.boundingBoxes = None
+		if self._rawoffsettable[:6] <> '\0\0\0\0\0\6':  # XXX ????
+			return
+		boxes = {}
+		data = self._rawoffsettable[6:]
+		numstyles = struct.unpack("h", data[:2])[0] + 1
+		data = data[2:]
+		for i in range(numstyles):
+			style, l, b, r, t = struct.unpack("hhhhh", data[:10])
+			boxes[style] = (l, b, r, t)
+			data = data[10:]
+		self.boundingBoxes = boxes
+	
+	def _buildboundingboxtable(self):
+		if self.boundingBoxes and self._rawoffsettable[:6] == '\0\0\0\0\0\6':
+			boxes = self.boundingBoxes.items()
+			boxes.sort()
+			data = '\0\0\0\0\0\6' + struct.pack("h", len(boxes) - 1)
+			for style, (l, b, r, t) in boxes:
+				data = data + struct.pack("hhhhh", style, l, b, r, t)
+			self._rawoffsettable = data
+	
+	def _getglyphwidthtable(self):
+		self.widthTables = {}
+		if self.ffWTabOff == 0:
+			return
+		data = self.FOND.data
+		offset = self.ffWTabOff
+		numberofentries, = struct.unpack("h", data[offset:offset+2])
+		numberofentries = numberofentries + 1
+		count = offset + 2
+		for i in range(numberofentries):
+			stylecode, = struct.unpack("h", data[count:count+2])
+			widthtable = self.widthTables[stylecode] = []
+			count = count + 2
+			for j in range(3 + self.ffLastChar - self.ffFirstChar):
+				width, = struct.unpack("h", data[count:count+2])
+				widthtable.append(width)
+				count = count + 2
+		
+		if DEBUG:
+			self._rawglyphwidthtable = data[offset:count]
+			self.parsedthings.append((offset, count, 'glyphwidthtable'))
+	
+	def _buildglyphwidthtable(self):
+		if not self.widthTables:
+			self._rawglyphwidthtable = ""
+			return
+		numberofentries = len(self.widthTables)
+		data = struct.pack('h', numberofentries - 1)
+		tables = self.widthTables.items()
+		tables.sort()
+		for stylecode, table in tables:
+			data = data + struct.pack('h', stylecode)
+			if len(table) <> (3 + self.ffLastChar - self.ffFirstChar):
+				raise error, "width table has wrong length"
+			for width in table:
+				data = data + struct.pack('h', width)
+		if DEBUG:
+			print "glyph width table is the same?", self._rawglyphwidthtable == data and 'yes.' or 'no.'
+		self._rawglyphwidthtable = data
+	
+	def _getkerningtables(self):
+		self.kernTables = {}
+		if self.ffKernOff == 0:
+			return
+		data = self.FOND.data
+		offset = self.ffKernOff
+		numberofentries, = struct.unpack("h", data[offset:offset+2])
+		numberofentries = numberofentries + 1
+		count = offset + 2
+		for i in range(numberofentries):
+			stylecode, = struct.unpack("h", data[count:count+2])
+			count = count + 2
+			numberofpairs, = struct.unpack("h", data[count:count+2])
+			count = count + 2
+			kerntable = self.kernTables[stylecode] = []
+			for j in range(numberofpairs):
+				firstchar, secondchar, kerndistance = struct.unpack("cch", data[count:count+4])
+				kerntable.append((ord(firstchar), ord(secondchar), kerndistance))
+				count = count + 4
+		
+		if DEBUG:
+			self._rawkerningtables = data[offset:count]
+			self.parsedthings.append((offset, count, 'kerningtables'))
+	
+	def _buildkerningtables(self):
+		if self.kernTables == {}:
+			self._rawkerningtables = ""
+			self.ffKernOff = 0
+			return
+		numberofentries = len(self.kernTables)
+		data = [struct.pack('h', numberofentries - 1)]
+		tables = self.kernTables.items()
+		tables.sort()
+		for stylecode, table in tables:
+			data.append(struct.pack('h', stylecode))
+			data.append(struct.pack('h', len(table)))  # numberofpairs
+			for firstchar, secondchar, kerndistance in table:
+				data.append(struct.pack("cch", chr(firstchar), chr(secondchar), kerndistance))
+		
+		data = string.join(data, '')
+		
+		if DEBUG:
+			print "kerning table is the same?", self._rawkerningtables == data and 'yes.' or 'no.'
+			if self._rawkerningtables <> data:
+				print len(self._rawkerningtables), len(data)
+		self._rawkerningtables = data
+	
+	def _getstylemappingtable(self):
+		offset = self.ffStylOff
+		self.styleStrings = []
+		self.styleIndices = ()
+		self.glyphTableOffset = 0
+		self.fondClass = 0
+		if offset == 0:
+			return
+		data = self.FOND.data
+		self.fondClass, self.glyphTableOffset, self.styleMappingReserved, = \
+				struct.unpack("hll", data[offset:offset+10])
+		self.styleIndices = struct.unpack('48b', data[offset + 10:offset + 58])
+		stringcount, = struct.unpack('h', data[offset+58:offset+60])
+		
+		count = offset + 60
+		for i in range(stringcount):
+			str_len = ord(data[count])
+			self.styleStrings.append(data[count + 1:count + 1 + str_len])
+			count = count + 1 + str_len
+		
+		self._unpackstylestrings()
+		
+		data = data[offset:count]
+		if len(data) % 2:
+			data = data + '\0'
+		if DEBUG:
+			self._rawstylemappingtable = data
+			self.parsedthings.append((offset, count, 'stylemappingtable'))
+	
+	def _buildstylemappingtable(self):
+		if not self.styleIndices:
+			self._rawstylemappingtable = ""
+			return
+		data = struct.pack("hll", self.fondClass, self.glyphTableOffset, 
+					self.styleMappingReserved)
+		
+		self._packstylestrings()
+		data = data + apply(struct.pack, ("48b",) + self.styleIndices)
+		
+		stringcount = len(self.styleStrings)
+		data = data + struct.pack("h", stringcount)
+		for string in self.styleStrings:
+			data = data + chr(len(string)) + string
+		
+		if len(data) % 2:
+			data = data + '\0'
+		
+		if DEBUG:
+			print "style mapping table is the same?", self._rawstylemappingtable == data and 'yes.' or 'no.'
+		self._rawstylemappingtable = data
+	
+	def _unpackstylestrings(self):
+		psNames = {}
+		self.ffFamilyName = self.styleStrings[0]
+		for i in self.widthTables.keys():
+			index = self.styleIndices[i]
+			if index == 1:
+				psNames[i] = self.styleStrings[0]
+			else:
+				style = self.styleStrings[0]
+				codes = map(ord, self.styleStrings[index - 1])
+				for code in codes:
+					style = style + self.styleStrings[code - 1]
+				psNames[i] = style
+		self.psNames = psNames
+	
+	def _packstylestrings(self):
+		nameparts = {}
+		splitnames = {}
+		for style, name in self.psNames.items():
+			split = splitname(name, self.ffFamilyName)
+			splitnames[style] = split
+			for part in split:
+				nameparts[part] = None
+		del nameparts[self.ffFamilyName]
+		nameparts = nameparts.keys()
+		nameparts.sort()
+		items = splitnames.items()
+		items.sort()
+		numindices = 0
+		for style, split in items:
+			if len(split) > 1:
+				numindices = numindices + 1
+		styleStrings = [self.ffFamilyName] + numindices * [None] + nameparts
+		# XXX the next bit goes wrong for MM fonts.
+		for style, split in items:
+			if len(split) == 1:
+				continue
+			indices = ""
+			for part in split[1:]:
+				indices = indices + chr(nameparts.index(part) + numindices + 2)
+			styleStrings[self.styleIndices[style] - 1] = indices
+		self.styleStrings = styleStrings
+	
+	def _updatestylemappingtable(self):
+		# Update the glyphTableOffset field.
+		# This is neccesary since we have to build this table to 
+		# know what the glyphTableOffset will be.
+		# And we don't want to build it twice, do we?
+		data = self._rawstylemappingtable
+		if not data:
+			return
+		data = data[:2] + struct.pack("l", self.glyphTableOffset) + data[6:]
+		self._rawstylemappingtable = data
+	
+	def _getglyphencodingsubtable(self):
+		glyphEncoding = self.glyphEncoding = {}
+		if not self.glyphTableOffset:
+			return
+		offset = self.ffStylOff + self.glyphTableOffset
+		data = self.FOND.data
+		numberofentries, = struct.unpack("h", data[offset:offset+2])
+		count = offset + 2
+		for i in range(numberofentries):
+			glyphcode = ord(data[count])
+			count = count + 1
+			strlen = ord(data[count])
+			count = count + 1
+			glyphname = data[count:count+strlen]
+			glyphEncoding[glyphcode] = glyphname
+			count = count + strlen
+		
+		if DEBUG:
+			self._rawglyphencodingsubtable = data[offset:count]
+			self.parsedthings.append((offset, count, 'glyphencodingsubtable'))
+	
+	def _buildglyphencodingsubtable(self):
+		if not self.glyphEncoding:
+			self._rawglyphencodingsubtable = ""
+			return
+		numberofentries = len(self.glyphEncoding)
+		data = struct.pack("h", numberofentries)
+		items = self.glyphEncoding.items()
+		items.sort()
+		for glyphcode, glyphname in items:
+			data = data + chr(glyphcode) + chr(len(glyphname)) + glyphname
+		self._rawglyphencodingsubtable = data
+	
+
+uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+
+def splitname(name, famname = None):
+	# XXX this goofs up MM font names: but how should it be done??
+	if famname:
+		if name[:len(famname)] <> famname:
+			raise error, "first part of name should be same as family name"
+		name = name[len(famname):]
+		split = [famname]
+	else:
+		split = []
+	current = ""
+	for c in name:
+		if c == '-' or c in uppercase:
+			if current:
+				split.append(current)
+				current = ""
+		current = current + c
+	if current:
+		split.append(current)
+	return split
+
+def makeLWFNfilename(name):
+	split = splitname(name)
+	lwfnname = split[0][:5]
+	for part in split[1:]:
+		if part <> '-':
+			lwfnname = lwfnname + part[:3]
+	return lwfnname
+
+class BitmapFontFile:
+	
+	def __init__(self, path, mode = 'r'):
+		import macfs
+		
+		if mode == 'r':
+			permission = 1	# read only
+		elif mode == 'w':
+			permission = 3	# exclusive r/w
+		else:
+			raise error, 'mode should be either "r" or "w"'
+		self.mode = mode
+		fss = macfs.FSSpec(path)
+		self.resref = Res.FSpOpenResFile(fss, permission)
+		Res.UseResFile(self.resref)
+		self.path = path
+		self.fonds = []
+		self.getFONDs()
+	
+	def getFONDs(self):
+		FONDcount = Res.Count1Resources('FOND')
+		for i in range(FONDcount):
+			fond = FontFamily(Res.Get1IndResource('FOND', i + 1), self.mode)
+			self.fonds.append(fond)
+	
+	def parse(self):
+		self.fondsbyname = {}
+		for fond in self.fonds:
+			fond.parse()
+			if hasattr(fond, "psNames") and fond.psNames:
+				psNames = fond.psNames.values()
+				psNames.sort()
+				self.fondsbyname[psNames[0]] = fond
+	
+	def minimalparse(self):
+		for fond in self.fonds:
+			fond.minimalparse()
+	
+	def close(self):
+		if self.resref <> None:
+			try:
+				Res.CloseResFile(self.resref)
+			except Res.Error:
+				pass
+			self.resref = None
+
+
+class FondSelector:
+	
+	def __init__(self, fondlist):
+		import W
+		if not fondlist:
+			raise ValueError, "expected at least one FOND entry"
+		if len(fondlist) == 1:
+			self.choice = 0
+			return
+		fonds = []
+		for fond in fondlist:
+			fonds.append(fond.name)
+		self.w = W.ModalDialog((200, 200), "aaa")
+		self.w.donebutton = W.Button((-70, -26, 60, 16), "Done", self.close)
+		self.w.l = W.List((10, 10, -10, -36), fonds, self.listhit)
+		self.w.setdefaultbutton(self.w.donebutton)
+		self.w.l.setselection([0])
+		self.w.open()
+	
+	def close(self):
+		self.checksel()
+		sel = self.w.l.getselection()
+		self.choice = sel[0]
+		self.w.close()
+	
+	def listhit(self, isDbl):
+		if isDbl:
+			self.w.donebutton.push()
+		else:
+			self.checksel()
+	
+	def checksel(self):
+		sel = self.w.l.getselection()
+		if not sel:
+			self.w.l.setselection([0])
+		elif len(sel) <> 1:
+			self.w.l.setselection([sel[0]])
+			
diff --git a/Lib/fontTools/misc/__init__.py b/Lib/fontTools/misc/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Lib/fontTools/misc/__init__.py
diff --git a/Lib/fontTools/misc/textTools.py b/Lib/fontTools/misc/textTools.py
new file mode 100644
index 0000000..304f45a
--- /dev/null
+++ b/Lib/fontTools/misc/textTools.py
@@ -0,0 +1,89 @@
+"""fontTools.misc.textTools.py -- miscelaneous routines."""
+
+
+import string
+
+
+def safeEval(data, eval=eval):
+	"""A safe replacement for eval."""
+	return eval(data, {"__builtins__":{}}, {})
+
+
+def readHex(content):
+	"""Convert a list of hex strings to binary data."""
+	hexdata = ""
+	for chunk in content:
+		if type(chunk) == type(""):
+			hexdata = hexdata + chunk
+	return deHexStr(hexdata)
+
+def deHexStr(hexdata):
+	"""Convert a hex string to binary data."""
+	parts = string.split(hexdata)
+	hexdata = string.join(parts, "")
+	if len(hexdata) % 2:
+		hexdata = hexdata + "0"
+	data = ""
+	for i in range(0, len(hexdata), 2):
+		data = data + chr(string.atoi(hexdata[i:i+2], 16))
+	return data
+
+def hexStr(data):
+	"""Convert binary data to a hex string."""
+	h = string.hexdigits
+	r = ''
+	for c in data:
+		i = ord(c)
+		r = r + h[(i >> 4) & 0xF] + h[i & 0xF]
+	return r
+
+
+def num2binary(l, bits=32):
+	all = []
+	bin = ""
+	for i in range(bits):
+		if l & 0x1:
+			bin = "1" + bin
+		else:
+			bin = "0" + bin
+		l = l >> 1
+		if not ((i+1) % 8):
+			all.append(bin)
+			bin = ""
+	all.reverse()
+	assert l in (0, -1), "number doesn't fit in number of bits"
+	return string.join(all, " ")
+
+
+def binary2num(bin):
+	bin = string.join(string.split(bin), "")
+	l = 0
+	for digit in bin:
+		l = l << 1
+		if digit <> "0":
+			l = l | 0x1
+	return l
+
+
+def caselessSort(alist):
+	"""Return a sorted copy of a list. If there are only strings 
+	in the list, it will not consider case.
+	"""
+	
+	try:
+		# turn ['FOO',  'aaBc', 'ABcD'] into 
+		# [('foo', 'FOO'), ('aabc', 'aaBc'), ('abcd', 'ABcD')], 
+		# but only if all elements are strings
+		tupledlist = map(lambda item, lower = string.lower: 
+			(lower(item), item), alist)
+	except TypeError:
+		# at least one element in alist is not a string, proceed the normal way...
+		alist = alist[:]
+		alist.sort()
+		return alist
+	else:
+		tupledlist.sort()
+		# turn [('aabc', 'aaBc'), ('abcd', 'ABcD'), ('foo', 'FOO')] into 
+		# ['aaBc', 'ABcD', 'FOO']
+		return map(lambda x: x[1], tupledlist)
+
diff --git a/Lib/fontTools/nfntLib.py b/Lib/fontTools/nfntLib.py
new file mode 100644
index 0000000..08a54ba
--- /dev/null
+++ b/Lib/fontTools/nfntLib.py
@@ -0,0 +1,144 @@
+import Res
+import macfs
+import struct
+import Qd
+from types import *
+
+
+class NFNT:
+	
+	def __init__(self, nfnt, name = "", _type = 'NFNT'):
+		if type(nfnt) == type(Res.Resource("")):
+			theID, theType, name = nfnt.GetResInfo()
+			if theType <> _type:
+				raise TypeError, 'resource of wrong type; expected ' + _type
+			data = nfnt.data
+		elif type(nfnt) == StringType:
+			fss = macfs.FSSpec(nfnt)
+			data = readnfntresource(nfnt, name, _type)
+		elif type(nfnt) == type(macfs.FSSpec(':')):
+			data = readnfntresource(nfnt, name, _type)
+		else:
+			raise TypeError, 'expected resource, string or fss; found ' + type(nfnt).__name__
+		self.parse_nfnt(data)
+	
+	def parse_nfnt(self, data):
+		# header; FontRec
+		(	self.fontType,
+			self.firstChar,
+			self.lastChar,
+			self.widMax,
+			self.kernMax,
+			self.nDescent,
+			fRectWidth,
+			self.fRectHeight,
+			owTLoc,
+			self.ascent,
+			self.descent,
+			self.leading,
+			self.rowWords	) = struct.unpack("13h", data[:26])
+		if owTLoc < 0:
+			owTLoc = owTLoc + 0x8000	# unsigned short
+		
+		# rest
+		tablesize = 2 * (self.lastChar - self.firstChar + 3)
+		bitmapsize = 2 * self.rowWords * self.fRectHeight
+		
+		self.bits = data[26:26 + bitmapsize]
+		self.bitImage = Qd.BitMap(self.bits, 2 * self.rowWords, (0, 0, self.rowWords * 16, self.fRectHeight))
+		
+		owTable = data[26 + bitmapsize + tablesize:26 + bitmapsize + 2 * tablesize]
+		if len(owTable) <> tablesize:
+			raise ValueError, 'invalid NFNT resource'
+		
+		locTable = data[26 + bitmapsize:26 + bitmapsize + tablesize]
+		if len(locTable) <> tablesize:
+			raise ValueError, 'invalid NFNT resource'
+		
+		# fill tables
+		self.offsettable = []
+		self.widthtable = []
+		self.locationtable = []
+		for i in range(0, tablesize, 2):
+			self.offsettable.append(ord(owTable[i]))
+			self.widthtable.append(ord(owTable[i+1]))
+			loc, = struct.unpack('h', locTable[i:i+2])
+			self.locationtable.append(loc)
+	
+	def drawstring(self, astring, destbits, xoffset = 0, yoffset = 0):
+		drawchar = self.drawchar
+		for ch in astring:
+			xoffset = drawchar(ch, destbits, xoffset, yoffset)
+		return xoffset
+	
+	def drawchar(self, ch, destbits, xoffset, yoffset = 0):
+		width, bounds, destbounds = self.getcharbounds(ch)
+		destbounds = Qd.OffsetRect(destbounds, xoffset, yoffset)
+		Qd.CopyBits(self.bitImage, destbits, bounds, destbounds, 1, None)
+		return xoffset + width
+	
+	def stringwidth(self, astring):
+		charwidth = self.charwidth
+		width = 0
+		for ch in astring:
+			width = width + charwidth(ch)
+		return width
+	
+	def charwidth(self, ch):
+		cindex = ord(ch) - self.firstChar
+		if cindex > self.lastChar or 	\
+				(self.offsettable[cindex] == 255 and self.widthtable[cindex] == 255):
+			cindex = -2		# missing char
+		return self.widthtable[cindex]
+	
+	def getcharbounds(self, ch):
+		cindex = ord(ch) - self.firstChar
+		if cindex > self.lastChar or 	\
+				(self.offsettable[cindex] == 255 and self.widthtable[cindex] == 255):
+			return self.getcharboundsindex(-2)	# missing char
+		return self.getcharboundsindex(cindex)
+	
+	def getcharboundsindex(self, cindex):
+		offset = self.offsettable[cindex]
+		width = self.widthtable[cindex]
+		if offset == 255 and width == 255:
+			raise ValueError, "character not defined"
+		location0 = self.locationtable[cindex]
+		location1 = self.locationtable[cindex + 1]
+		srcbounds = (location0, 0, location1, self.fRectHeight)
+		destbounds = (	offset + self.kernMax, 
+					0, 
+					offset + self.kernMax + location1 - location0, 
+					self.fRectHeight	)
+		return width, srcbounds, destbounds
+
+
+def readnfntresource(fss, name, _type = 'NFNT'):
+	resref = Res.FSpOpenResFile(fss, 1)	# readonly
+	Res.UseResFile(resref)
+	try:
+		if name:
+			res = Res.Get1NamedResource(_type, name)
+		else:
+			# just take the first in the file
+			res = Res.Get1IndResource(_type, 1)
+		theID, theType, name = res.GetResInfo()
+		if theType <> _type:
+			raise TypeError, 'resource of wrong type; expected ' + _type
+		data = res.data
+	finally:
+		Res.CloseResFile(resref)
+	return data
+
+
+if 0:
+	import Win
+	fss, ok = macfs.StandardGetFile('FFIL')
+	if ok:
+		n = NFNT(fss)
+		s = "!!!ABCDEFGHIJKLMN01234 hemeltje lief...x.."
+		x = 10
+		y = 40
+		destbits = Win.FrontWindow().GetWindowPort().portBits
+		n.drawstring(s, destbits, x, y)
+		print n.stringwidth(s)
diff --git a/Lib/fontTools/psCharStrings.py b/Lib/fontTools/psCharStrings.py
new file mode 100644
index 0000000..d618784
--- /dev/null
+++ b/Lib/fontTools/psCharStrings.py
@@ -0,0 +1,974 @@
+"""psCharStrings.py -- module implementing various kinds of CharStrings: 
+CFF dictionary data and Type1/Type2 CharStrings.
+"""
+
+__version__ = "1.0b1"
+__author__ = "jvr"
+
+
+import types
+import struct
+import string
+
+
+t1OperandEncoding = [None] * 256
+t1OperandEncoding[0:32] = (32) * ["do_operator"]
+t1OperandEncoding[32:247] = (247 - 32) * ["read_byte"]
+t1OperandEncoding[247:251] = (251 - 247) * ["read_smallInt1"]
+t1OperandEncoding[251:255] = (255 - 251) * ["read_smallInt2"]
+t1OperandEncoding[255] = "read_longInt"
+assert len(t1OperandEncoding) == 256
+
+t2OperandEncoding = t1OperandEncoding[:]
+t2OperandEncoding[28] = "read_shortInt"
+
+cffDictOperandEncoding = t2OperandEncoding[:]
+cffDictOperandEncoding[29] = "read_longInt"
+cffDictOperandEncoding[30] = "read_realNumber"
+cffDictOperandEncoding[255] = "reserved"
+
+
+realNibbles = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
+		'.', 'E', 'E-', None, '-']
+
+
+class ByteCodeDecompilerBase:
+	
+	def read_byte(self, b0, data, index):
+		return b0 - 139, index
+	
+	def read_smallInt1(self, b0, data, index):
+		b1 = ord(data[index])
+		return (b0-247)*256 + b1 + 108, index+1
+	
+	def read_smallInt2(self, b0, data, index):
+		b1 = ord(data[index])
+		return -(b0-251)*256 - b1 - 108, index+1
+	
+	def read_shortInt(self, b0, data, index):
+		bin = data[index] + data[index+1]
+		value, = struct.unpack(">h", bin)
+		return value, index+2
+	
+	def read_longInt(self, b0, data, index):
+		bin = data[index] + data[index+1] + data[index+2] + data[index+3]
+		value, = struct.unpack(">l", bin)
+		return value, index+4
+	
+	def read_realNumber(self, b0, data, index):
+		number = ''
+		while 1:
+			b = ord(data[index])
+			index = index + 1
+			nibble0 = (b & 0xf0) >> 4
+			nibble1 = b & 0x0f
+			if nibble0 == 0xf:
+				break
+			number = number + realNibbles[nibble0]
+			if nibble1 == 0xf:
+				break
+			number = number + realNibbles[nibble1]
+		return string.atof(number), index
+
+
+def _buildOperatorDict(operatorList):
+	dict = {}
+	for item in operatorList:
+		if len(item) == 2:
+			dict[item[0]] = item[1]
+		else:
+			dict[item[0]] = item[1:]
+	return dict
+
+
+t2Operators = [
+#	opcode     name
+	(1,        'hstem'),
+	(3,        'vstem'),
+	(4,        'vmoveto'),
+	(5,        'rlineto'),
+	(6,        'hlineto'),
+	(7,        'vlineto'),
+	(8,        'rrcurveto'),
+	(10,       'callsubr'),
+	(11,       'return'),
+	(14,       'endchar'),
+	(16,       'blend'),
+	(18,       'hstemhm'),
+	(19,       'hintmask'),
+	(20,       'cntrmask'),
+	(21,       'rmoveto'),
+	(22,       'hmoveto'),
+	(23,       'vstemhm'),
+	(24,       'rcurveline'),
+	(25,       'rlinecurve'),
+	(26,       'vvcurveto'),
+	(27,       'hhcurveto'),
+#	(28,       'shortint'),  # not really an operator
+	(29,       'callgsubr'),
+	(30,       'vhcurveto'),
+	(31,       'hvcurveto'),
+	((12, 3),  'and'),
+	((12, 4),  'or'),
+	((12, 5),  'not'),
+	((12, 8),  'store'),
+	((12, 9),  'abs'),
+	((12, 10), 'add'),
+	((12, 11), 'sub'),
+	((12, 12), 'div'),
+	((12, 13), 'load'),
+	((12, 14), 'neg'),
+	((12, 15), 'eq'),
+	((12, 18), 'drop'),
+	((12, 20), 'put'),
+	((12, 21), 'get'),
+	((12, 22), 'ifelse'),
+	((12, 23), 'random'),
+	((12, 24), 'mul'),
+	((12, 26), 'sqrt'),
+	((12, 27), 'dup'),
+	((12, 28), 'exch'),
+	((12, 29), 'index'),
+	((12, 30), 'roll'),
+	((12, 34), 'hflex'),
+	((12, 35), 'flex'),
+	((12, 36), 'hflex1'),
+	((12, 37), 'flex1'),
+]
+
+class T2CharString(ByteCodeDecompilerBase):
+	
+	operandEncoding = t2OperandEncoding
+	operators = _buildOperatorDict(t2Operators)
+	
+	def __init__(self, bytecode=None, program=None):
+		if program is None:
+			program = []
+		self.bytecode = bytecode
+		self.program = program
+	
+	def __repr__(self):
+		if self.bytecode is None:
+			return "<%s (source) at %x>" % (self.__class__.__name__, id(self))
+		else:
+			return "<%s (bytecode) at %x>" % (self.__class__.__name__, id(self))
+	
+	def needsDecompilation(self):
+		return self.bytecode is not None
+	
+	def setProgram(self, program):
+		self.program = program
+		self.bytecode = None
+	
+	def getToken(self, index, 
+			len=len, ord=ord, getattr=getattr, type=type, StringType=types.StringType):
+		if self.bytecode is not None:
+			if index >= len(self.bytecode):
+				return None, 0, 0
+			b0 = ord(self.bytecode[index])
+			index = index + 1
+			code = self.operandEncoding[b0]
+			handler = getattr(self, code)
+			token, index = handler(b0, self.bytecode, index)
+		else:
+			if index >= len(self.program):
+				return None, 0, 0
+			token = self.program[index]
+			index = index + 1
+		isOperator = type(token) == StringType
+		return token, isOperator, index
+	
+	def getBytes(self, index, nBytes):
+		if self.bytecode is not None:
+			newIndex = index + nBytes
+			bytes = self.bytecode[index:newIndex]
+			index = newIndex
+		else:
+			bytes = self.program[index]
+			index = index + 1
+		assert len(bytes) == nBytes
+		return bytes, index
+	
+	def do_operator(self, b0, data, index):
+		if b0 == 12:
+			op = (b0, ord(data[index]))
+			index = index+1
+		else:
+			op = b0
+		operator = self.operators[op]
+		return operator, index
+	
+	def toXML(self, xmlWriter):
+		from misc.textTools import num2binary
+		if self.bytecode is not None:
+			xmlWriter.dumphex(self.bytecode)
+		else:
+			index = 0
+			args = []
+			while 1:
+				token, isOperator, index = self.getToken(index)
+				if token is None:
+					break
+				if isOperator:
+					args = map(str, args)
+					if token in ('hintmask', 'cntrmask'):
+						hintMask, isOperator, index = self.getToken(index)
+						bits = []
+						for byte in hintMask:
+							bits.append(num2binary(ord(byte), 8))
+						hintMask = repr(string.join(bits, ""))
+						line = string.join(args + [token, hintMask], " ")
+					else:
+						line = string.join(args + [token], " ")
+					xmlWriter.write(line)
+					xmlWriter.newline()
+					args = []
+				else:
+					args.append(token)
+
+
+t1Operators = [
+#	opcode     name
+	(1,        'hstem'),
+	(3,        'vstem'),
+	(4,        'vmoveto'),
+	(5,        'rlineto'),
+	(6,        'hlineto'),
+	(7,        'vlineto'),
+	(8,        'rrcurveto'),
+	(9,        'closepath'),
+	(10,       'callsubr'),
+	(11,       'return'),
+	(13,       'hsbw'),
+	(14,       'endchar'),
+	(21,       'rmoveto'),
+	(22,       'hmoveto'),
+	(30,       'vhcurveto'),
+	(31,       'hvcurveto'),
+	((12, 0),  'dotsection'),
+	((12, 1),  'vstem3'),
+	((12, 2),  'hstem3'),
+	((12, 6),  'seac'),
+	((12, 7),  'sbw'),
+	((12, 12), 'div'),
+	((12, 16), 'callothersubr'),
+	((12, 17), 'pop'),
+	((12, 33), 'setcurrentpoint'),
+]
+
+class T1CharString(T2CharString):
+	
+	operandEncoding = t1OperandEncoding
+	operators = _buildOperatorDict(t1Operators)
+	
+	def decompile(self):
+		if hasattr(self, "program"):
+			return
+		program = []
+		index = 0
+		while 1:
+			token, isOperator, index = self.getToken(index)
+			if token is None:
+				break
+			program.append(token)
+		self.setProgram(program)
+
+
+class SimpleT2Decompiler:
+	
+	def __init__(self, localSubrs, globalSubrs):
+		self.localSubrs = localSubrs
+		self.localBias = calcSubrBias(localSubrs)
+		self.globalSubrs = globalSubrs
+		self.globalBias = calcSubrBias(globalSubrs)
+		self.reset()
+	
+	def reset(self):
+		self.callingStack = []
+		self.operandStack = []
+		self.hintCount = 0
+		self.hintMaskBytes = 0
+	
+	def execute(self, charString):
+		self.callingStack.append(charString)
+		needsDecompilation = charString.needsDecompilation()
+		if needsDecompilation:
+			program = []
+			pushToProgram = program.append
+		else:
+			pushToProgram = lambda x: None
+		pushToStack = self.operandStack.append
+		index = 0
+		while 1:
+			token, isOperator, index = charString.getToken(index)
+			if token is None:
+				break  # we're done!
+			pushToProgram(token)
+			if isOperator:
+				handlerName = "op_" + token
+				if hasattr(self, handlerName):
+					handler = getattr(self, handlerName)
+					rv = handler(index)
+					if rv:
+						hintMaskBytes, index = rv
+						pushToProgram(hintMaskBytes)
+				else:
+					self.popall()
+			else:
+				pushToStack(token)
+		if needsDecompilation:
+			charString.setProgram(program)
+			assert program[-1] in ("endchar", "return", "callsubr", "callgsubr", "seac")
+		del self.callingStack[-1]
+	
+	def pop(self):
+		value = self.operandStack[-1]
+		del self.operandStack[-1]
+		return value
+	
+	def popall(self):
+		stack = self.operandStack[:]
+		self.operandStack[:] = []
+		return stack
+	
+	def push(self, value):
+		self.operandStack.append(value)
+	
+	def op_return(self, index):
+		if self.operandStack:
+			pass
+	
+	def op_endchar(self, index):
+		pass
+	
+	def op_callsubr(self, index):
+		subrIndex = self.pop()
+		subr = self.localSubrs[subrIndex+self.localBias]
+		self.execute(subr)
+	
+	def op_callgsubr(self, index):
+		subrIndex = self.pop()
+		subr = self.globalSubrs[subrIndex+self.globalBias]
+		self.execute(subr)
+	
+	def op_hstemhm(self, index):
+		self.countHints()
+	
+	op_vstemhm = op_hstemhm
+	
+	def op_hintmask(self, index):
+		if not self.hintMaskBytes:
+			self.countHints()
+			self.hintMaskBytes = (self.hintCount + 7) / 8
+		hintMaskBytes, index = self.callingStack[-1].getBytes(index, self.hintMaskBytes)
+		return hintMaskBytes, index
+	
+	op_cntrmask = op_hintmask
+	
+	def countHints(self):
+		assert self.hintMaskBytes == 0
+		args = self.popall()
+		self.hintCount = self.hintCount + len(args) / 2
+
+
+class T2OutlineExtractor(SimpleT2Decompiler):
+	
+	def __init__(self, localSubrs, globalSubrs, nominalWidthX, defaultWidthX):
+		SimpleT2Decompiler.__init__(self, localSubrs, globalSubrs)
+		self.nominalWidthX = nominalWidthX
+		self.defaultWidthX = defaultWidthX
+	
+	def reset(self):
+		import Numeric
+		SimpleT2Decompiler.reset(self)
+		self.hints = []
+		self.gotWidth = 0
+		self.width = 0
+		self.currentPoint = Numeric.array((0, 0), Numeric.Int16)
+		self.contours = []
+	
+	def getContours(self):
+		return self.contours
+	
+	def newPath(self):
+		self.contours.append([[], [], 0])
+	
+	def closePath(self):
+		if self.contours and self.contours[-1][2] == 0:
+			self.contours[-1][2] = 1
+	
+	def appendPoint(self, point, isPrimary):
+		import Numeric
+		point = self.currentPoint + Numeric.array(point, Numeric.Int16)
+		self.currentPoint = point
+		points, flags, isClosed = self.contours[-1]
+		points.append(point)
+		flags.append(isPrimary)
+	
+	def popallWidth(self, evenOdd=0):
+		args = self.popall()
+		if not self.gotWidth:
+			if evenOdd ^ (len(args) % 2):
+				self.width = self.nominalWidthX + args[0]
+				args = args[1:]
+			else:
+				self.width = self.defaultWidthX
+			self.gotWidth = 1
+		return args
+	
+	def countHints(self):
+		assert self.hintMaskBytes == 0
+		args = self.popallWidth()
+		self.hintCount = self.hintCount + len(args) / 2
+	
+	#
+	# hint operators
+	#
+	def op_hstem(self, index):
+		self.popallWidth()  # XXX
+	def op_vstem(self, index):
+		self.popallWidth()  # XXX
+	def op_hstemhm(self, index):
+		self.countHints()
+		#XXX
+	def op_vstemhm(self, index):
+		self.countHints()
+		#XXX
+	#def op_hintmask(self, index):
+	#	self.countHints()
+	#def op_cntrmask(self, index):
+	#	self.countHints()
+	
+	#
+	# path constructors, moveto
+	#
+	def op_rmoveto(self, index):
+		self.closePath()
+		self.newPath()
+		self.appendPoint(self.popallWidth(), 1)
+	def op_hmoveto(self, index):
+		self.closePath()
+		self.newPath()
+		self.appendPoint((self.popallWidth(1)[0], 0), 1)
+	def op_vmoveto(self, index):
+		self.closePath()
+		self.newPath()
+		self.appendPoint((0, self.popallWidth(1)[0]), 1)
+	def op_endchar(self, index):
+		self.closePath()
+	
+	#
+	# path constructors, lines
+	#
+	def op_rlineto(self, index):
+		args = self.popall()
+		for i in range(0, len(args), 2):
+			point = args[i:i+2]
+			self.appendPoint(point, 1)
+	
+	def op_hlineto(self, index):
+		self.alternatingLineto(1)
+	def op_vlineto(self, index):
+		self.alternatingLineto(0)
+	
+	#
+	# path constructors, curves
+	#
+	def op_rrcurveto(self, index):
+		"""{dxa dya dxb dyb dxc dyc}+ rrcurveto"""
+		args = self.popall()
+		for i in range(0, len(args), 6):
+			dxa, dya, dxb, dyb, dxc, dyc, = args[i:i+6]
+			self.rrcurveto((dxa, dya), (dxb, dyb), (dxc, dyc))
+	
+	def op_rcurveline(self, index):
+		"""{dxa dya dxb dyb dxc dyc}+ dxd dyd rcurveline"""
+		args = self.popall()
+		for i in range(0, len(args)-2, 6):
+			dxb, dyb, dxc, dyc, dxd, dyd = args[i:i+6]
+			self.rrcurveto((dxb, dyb), (dxc, dyc), (dxd, dyd))
+		self.appendPoint(args[-2:], 1)
+	
+	def op_rlinecurve(self, index):
+		"""{dxa dya}+ dxb dyb dxc dyc dxd dyd rlinecurve"""
+		args = self.popall()
+		lineArgs = args[:-6]
+		for i in range(0, len(lineArgs), 2):
+			self.appendPoint(lineArgs[i:i+2], 1)
+		dxb, dyb, dxc, dyc, dxd, dyd = args[-6:]
+		self.rrcurveto((dxb, dyb), (dxc, dyc), (dxd, dyd))
+	
+	def op_vvcurveto(self, index):
+		"dx1? {dya dxb dyb dyc}+ vvcurveto"
+		args = self.popall()
+		if len(args) % 2:
+			dx1 = args[0]
+			args = args[1:]
+		else:
+			dx1 = 0
+		for i in range(0, len(args), 4):
+			dya, dxb, dyb, dyc = args[i:i+4]
+			self.rrcurveto((dx1, dya), (dxb, dyb), (0, dyc))
+			dx1 = 0
+	
+	def op_hhcurveto(self, index):
+		"""dy1? {dxa dxb dyb dxc}+ hhcurveto"""
+		args = self.popall()
+		if len(args) % 2:
+			dy1 = args[0]
+			args = args[1:]
+		else:
+			dy1 = 0
+		for i in range(0, len(args), 4):
+			dxa, dxb, dyb, dxc = args[i:i+4]
+			self.rrcurveto((dxa, dy1), (dxb, dyb), (dxc, 0))
+			dy1 = 0
+	
+	def op_vhcurveto(self, index):
+		"""dy1 dx2 dy2 dx3 {dxa dxb dyb dyc dyd dxe dye dxf}* dyf? vhcurveto (30)
+		{dya dxb dyb dxc dxd dxe dye dyf}+ dxf? vhcurveto
+		"""
+		args = self.popall()
+		while args:
+			args = self.vcurveto(args)
+			if args:
+				args = self.hcurveto(args)
+	
+	def op_hvcurveto(self, index):
+		"""dx1 dx2 dy2 dy3 {dya dxb dyb dxc dxd dxe dye dyf}* dxf?
+		{dxa dxb dyb dyc dyd dxe dye dxf}+ dyf?
+		"""
+		args = self.popall()
+		while args:
+			args = self.hcurveto(args)
+			if args:
+				args = self.vcurveto(args)
+	
+	#
+	# path constructors, flex
+	#
+	def op_hflex(self, index):
+		XXX
+	def op_flex(self, index):
+		XXX
+	def op_hflex1(self, index):
+		XXX
+	def op_flex1(self, index):
+		XXX
+	
+	#
+	# MultipleMaster. Well...
+	#
+	def op_blend(self, index):
+		XXX
+	
+	# misc
+	def op_and(self, index):
+		XXX
+	def op_or(self, index):
+		XXX
+	def op_not(self, index):
+		XXX
+	def op_store(self, index):
+		XXX
+	def op_abs(self, index):
+		XXX
+	def op_add(self, index):
+		XXX
+	def op_sub(self, index):
+		XXX
+	def op_div(self, index):
+		num2 = self.pop()
+		num1 = self.pop()
+		d1 = num1/num2
+		d2 = float(num1)/num2
+		if d1 == d2:
+			self.push(d1)
+		else:
+			self.push(d2)
+	def op_load(self, index):
+		XXX
+	def op_neg(self, index):
+		XXX
+	def op_eq(self, index):
+		XXX
+	def op_drop(self, index):
+		XXX
+	def op_put(self, index):
+		XXX
+	def op_get(self, index):
+		XXX
+	def op_ifelse(self, index):
+		XXX
+	def op_random(self, index):
+		XXX
+	def op_mul(self, index):
+		XXX
+	def op_sqrt(self, index):
+		XXX
+	def op_dup(self, index):
+		XXX
+	def op_exch(self, index):
+		XXX
+	def op_index(self, index):
+		XXX
+	def op_roll(self, index):
+		XXX
+	
+	#
+	# miscelaneous helpers
+	#
+	def alternatingLineto(self, isHorizontal):
+		args = self.popall()
+		for arg in args:
+			if isHorizontal:
+				point = (arg, 0)
+			else:
+				point = (0, arg)
+			self.appendPoint(point, 1)
+			isHorizontal = not isHorizontal
+	
+	def rrcurveto(self, p1, p2, p3):
+		self.appendPoint(p1, 0)
+		self.appendPoint(p2, 0)
+		self.appendPoint(p3, 1)
+	
+	def vcurveto(self, args):
+		dya, dxb, dyb, dxc = args[:4]
+		args = args[4:]
+		if len(args) == 1:
+			dyc = args[0]
+			args = []
+		else:
+			dyc = 0
+		self.rrcurveto((0, dya), (dxb, dyb), (dxc, dyc))
+		return args
+	
+	def hcurveto(self, args):
+		dxa, dxb, dyb, dyc = args[:4]
+		args = args[4:]
+		if len(args) == 1:
+			dxc = args[0]
+			args = []
+		else:
+			dxc = 0
+		self.rrcurveto((dxa, 0), (dxb, dyb), (dxc, dyc))
+		return args
+
+
+class T1OutlineExtractor(T2OutlineExtractor):
+	
+	def __init__(self, subrs):
+		self.subrs = subrs
+		self.reset()
+	
+	def reset(self):
+		self.flexing = 0
+		self.width = 0
+		self.sbx = 0
+		T2OutlineExtractor.reset(self)
+	
+	def popallWidth(self, evenOdd=0):
+		return self.popall()
+	
+	def exch(self):
+		stack = self.operandStack
+		stack[-1], stack[-2] = stack[-2], stack[-1]
+	
+	#
+	# path constructors
+	#
+	def op_rmoveto(self, index):
+		if self.flexing:
+			return
+		self.newPath()
+		self.appendPoint(self.popall(), 1)
+	def op_hmoveto(self, index):
+		if self.flexing:
+			# We must add a parameter to the stack if we are flexing
+			self.push(0)
+			return
+		self.newPath()
+		self.appendPoint((self.popall()[0], 0), 1)
+	def op_vmoveto(self, index):
+		if self.flexing:
+			# We must add a parameter to the stack if we are flexing
+			self.push(0)
+			self.exch()
+			return
+		self.newPath()
+		self.appendPoint((0, self.popall()[0]), 1)
+	def op_closepath(self, index):
+		self.closePath()
+	def op_setcurrentpoint(self, index):
+		args = self.popall()
+		x, y = args
+		self.currentPoint[0] = x
+		self.currentPoint[1] = y
+	
+	def op_endchar(self, index):
+		self.closePath()
+	
+	def op_hsbw(self, index):
+		sbx, wx = self.popall()
+		self.width = wx
+		self.sbx = sbx
+		self.currentPoint[0] = sbx
+	def op_sbw(self, index):
+		self.popall()  # XXX
+	
+	#
+	def op_callsubr(self, index):
+		subrIndex = self.pop()
+		subr = self.subrs[subrIndex]
+		self.execute(subr)
+	def op_callothersubr(self, index):
+		subrIndex = self.pop()
+		nArgs = self.pop()
+		#print nArgs, subrIndex, "callothersubr"
+		if subrIndex == 0 and nArgs == 3:
+			self.doFlex()
+			self.flexing = 0
+		elif subrIndex == 1 and nArgs == 0:
+			self.flexing = 1
+		# ignore...
+	def op_pop(self, index):
+		pass  # ignore...
+	
+	def doFlex(self):
+		finaly = self.pop()
+		finalx = self.pop()
+		self.pop()	# flex height is unused
+		
+		p3y = self.pop()
+		p3x = self.pop()
+		bcp4y = self.pop()
+		bcp4x = self.pop()
+		bcp3y = self.pop()
+		bcp3x = self.pop()
+		p2y = self.pop()
+		p2x = self.pop()
+		bcp2y = self.pop()
+		bcp2x = self.pop()
+		bcp1y = self.pop()
+		bcp1x = self.pop()
+		rpy = self.pop()
+		rpx = self.pop()
+		
+		# call rrcurveto
+		self.push(bcp1x+rpx)
+		self.push(bcp1y+rpy)
+		self.push(bcp2x)
+		self.push(bcp2y)
+		self.push(p2x)
+		self.push(p2y)
+		self.op_rrcurveto(None)
+		
+		# call rrcurveto
+		self.push(bcp3x)
+		self.push(bcp3y)
+		self.push(bcp4x)
+		self.push(bcp4y)
+		self.push(p3x)
+		self.push(p3y)
+		self.op_rrcurveto(None)
+		
+		# Push back final coords so subr 0 can find them
+		self.push(finalx)
+		self.push(finaly)
+	
+	def op_dotsection(self, index):
+		self.popall()  # XXX
+	def op_hstem3(self, index):
+		self.popall()  # XXX
+	def op_seac(self, index):
+		"asb adx ady bchar achar seac"
+		asb, adx, ady, bchar, achar = self.popall()  # XXX
+		self.contours.append([(asb, adx, ady, bchar, achar), None, -1])
+	def op_vstem3(self, index):
+		self.popall()  # XXX
+
+
+class DictDecompiler(ByteCodeDecompilerBase):
+	
+	operandEncoding = cffDictOperandEncoding
+	dictDefaults = {}
+	
+	def __init__(self, strings):
+		self.stack = []
+		self.strings = strings
+		self.dict = {}
+	
+	def getDict(self):
+		assert len(self.stack) == 0, "non-empty stack"
+		return self.dict
+	
+	def decompile(self, data):
+		index = 0
+		lenData = len(data)
+		push = self.stack.append
+		while index < lenData:
+			b0 = ord(data[index])
+			index = index + 1
+			code = self.operandEncoding[b0]
+			handler = getattr(self, code)
+			value, index = handler(b0, data, index)
+			if value is not None:
+				push(value)
+	
+	def pop(self):
+		value = self.stack[-1]
+		del self.stack[-1]
+		return value
+	
+	def popall(self):
+		all = self.stack[:]
+		del self.stack[:]
+		return all
+	
+	def do_operator(self, b0, data, index):
+		if b0 == 12:
+			op = (b0, ord(data[index]))
+			index = index+1
+		else:
+			op = b0
+		operator, argType = self.operators[op]
+		self.handle_operator(operator, argType)
+		return None, index
+	
+	def handle_operator(self, operator, argType):
+		if type(argType) == type(()):
+			value = ()
+			for arg in argType:
+				arghandler = getattr(self, "arg_" + arg)
+				value = (arghandler(operator),) + value
+		else:
+			arghandler = getattr(self, "arg_" + argType)
+			value = arghandler(operator)
+		self.dict[operator] = value
+	
+	def arg_number(self, name):
+		return self.pop()
+	def arg_SID(self, name):
+		return self.strings[self.pop()]
+	def arg_array(self, name):
+		return self.popall()
+
+
+topDictOperators = [
+#   opcode     name                  argument type
+	(0,        'version',            'SID'),
+	(1,        'Notice',             'SID'),
+	(2,        'FullName',           'SID'),
+	(3,        'FamilyName',         'SID'),
+	(4,        'Weight',             'SID'),
+	(5,        'FontBBox',           'array'),
+	(13,       'UniqueID',           'number'),
+	(14,       'XUID',               'array'),
+	(15,       'charset',            'number'),
+	(16,       'Encoding',           'number'),
+	(17,       'CharStrings',        'number'),
+	(18,       'Private',            ('number', 'number')),
+	((12, 0),  'Copyright',          'SID'),
+	((12, 1),  'isFixedPitch',       'number'),
+	((12, 2),  'ItalicAngle',        'number'),
+	((12, 3),  'UnderlinePosition',  'number'),
+	((12, 4),  'UnderlineThickness', 'number'),
+	((12, 5),  'PaintType',          'number'),
+	((12, 6),  'CharstringType',     'number'),
+	((12, 7),  'FontMatrix',         'array'),
+	((12, 8),  'StrokeWidth',        'number'),
+	((12, 20), 'SyntheticBase',      'number'),
+	((12, 21), 'PostScript',         'SID'),
+	((12, 22), 'BaseFontName',       'SID'),
+	# CID additions
+	((12, 30), 'ROS',                ('SID', 'SID', 'number')),
+	((12, 31), 'CIDFontVersion',     'number'),
+	((12, 32), 'CIDFontRevision',    'number'),
+	((12, 33), 'CIDFontType',        'number'),
+	((12, 34), 'CIDCount',           'number'),
+	((12, 35), 'UIDBase',            'number'),
+	((12, 36), 'FDArray',            'number'),
+	((12, 37), 'FDSelect',           'number'),
+	((12, 38), 'FontName',           'SID'),
+	# MM, Chameleon. Pft.
+]
+
+topDictDefaults = {
+		'isFixedPitch': 		0,
+		'ItalicAngle': 			0,
+		'UnderlineThickness': 	50,
+		'PaintType': 			0,
+		'CharstringType': 		2,
+		'FontMatrix': 			[0.001, 0, 0, 0.001, 0, 0],
+		'FontBBox': 			[0, 0, 0, 0],
+		'StrokeWidth': 			0,
+		'charset': 				0,
+		'Encoding': 			0,
+		# CID defaults
+		'CIDFontVersion':		0,
+		'CIDFontRevision':		0,
+		'CIDFontType':			0,
+		'CIDCount':				8720,
+}
+
+class TopDictDecompiler(DictDecompiler):
+	
+	operators = _buildOperatorDict(topDictOperators)
+	dictDefaults = topDictDefaults
+	
+
+privateDictOperators = [
+#   opcode     name                  argument type
+	(6,        'BlueValues',         'array'),
+	(7,        'OtherBlues',         'array'),
+	(8,        'FamilyBlues',        'array'),
+	(9,        'FamilyOtherBlues',   'array'),
+	(10,       'StdHW',              'number'),
+	(11,       'StdVW',              'number'),
+	(19,       'Subrs',              'number'),
+	(20,       'defaultWidthX',      'number'),
+	(21,       'nominalWidthX',      'number'),
+	((12, 9),  'BlueScale',          'number'),
+	((12, 10), 'BlueShift',          'number'),
+	((12, 11), 'BlueFuzz',           'number'),
+	((12, 12), 'StemSnapH',          'array'),
+	((12, 13), 'StemSnapV',          'array'),
+	((12, 14), 'ForceBold',          'number'),
+	((12, 15), 'ForceBoldThreshold', 'number'),
+	((12, 16), 'lenIV',              'number'),
+	((12, 17), 'LanguageGroup',      'number'),
+	((12, 18), 'ExpansionFactor',    'number'),
+	((12, 19), 'initialRandomSeed',  'number'),
+]
+
+privateDictDefaults = {
+		'defaultWidthX': 		0,
+		'nominalWidthX': 		0,
+		'BlueScale': 			0.039625,
+		'BlueShift': 			7,
+		'BlueFuzz': 			1,
+		'ForceBold': 			0,
+		'ForceBoldThreshold': 	0,
+		'lenIV': 				-1,
+		'LanguageGroup': 		0,
+		'ExpansionFactor': 		0.06,
+		'initialRandomSeed': 	0,
+}
+
+class PrivateDictDecompiler(DictDecompiler):
+	
+	operators = _buildOperatorDict(privateDictOperators)
+	dictDefaults = privateDictDefaults
+
+
+def calcSubrBias(subrs):
+	nSubrs = len(subrs)
+	if nSubrs < 1240:
+		bias = 107
+	elif nSubrs < 33900:
+		bias = 1131
+	else:
+		bias = 32768
+	return bias
+
diff --git a/Lib/fontTools/psLib.py b/Lib/fontTools/psLib.py
new file mode 100644
index 0000000..8408680
--- /dev/null
+++ b/Lib/fontTools/psLib.py
@@ -0,0 +1,346 @@
+import StringIO
+import regex
+import string
+import eexec
+import types
+from psOperators import *
+
+
+ps_special = '()<>[]{}%'	# / is one too, but we take care of that one differently
+
+whitespace = string.whitespace
+skipwhiteRE = regex.compile("[%s]*" % whitespace)
+
+endofthingPat = "[^][(){}<>/%s%s]*" % ('%', whitespace)
+endofthingRE = regex.compile(endofthingPat)
+
+commentRE = regex.compile("%[^\n\r]*")
+
+# XXX This not entirely correct:
+stringPat = """
+	(
+		\(
+			\(
+				[^()]*   \\\\   [()]
+			\)
+			\|
+			\(
+				[^()]*  (   [^()]*  )
+			\)
+		\)*
+		[^()]*
+	)
+"""
+stringPat = string.join(string.split(stringPat), '')
+stringRE = regex.compile(stringPat)
+
+hexstringRE = regex.compile("<[%s0-9A-Fa-f]*>" % whitespace)
+
+ps_tokenerror = 'ps_tokenerror'
+ps_error = 'ps_error'
+
+class PSTokenizer(StringIO.StringIO):
+	
+	def getnexttoken(self, 
+			# localize some stuff, for performance
+			len = len,
+			ps_special = ps_special,
+			stringmatch = stringRE.match,
+			hexstringmatch = hexstringRE.match,
+			commentmatch = commentRE.match,
+			endmatch = endofthingRE.match, 
+			whitematch = skipwhiteRE.match):
+		
+		self.pos = self.pos + whitematch(self.buf, self.pos)
+		if self.pos >= self.len:
+			return None, None
+		pos = self.pos
+		buf = self.buf
+		char = buf[pos]
+		if char in ps_special:
+			if char in '{}[]':
+				tokentype = 'do_special'
+				token = char
+			elif char == '%':
+				tokentype = 'do_comment'
+				commentlen = commentmatch(buf, pos)
+				token = buf[pos:pos+commentlen]
+			elif char == '(':
+				tokentype = 'do_string'
+				strlen = stringmatch(buf, pos)
+				if strlen < 0:
+					raise ps_tokenerror, 'bad string at character %d' % pos
+				token = buf[pos:pos+strlen]
+			elif char == '<':
+				tokentype = 'do_hexstring'
+				strlen = hexstringmatch(buf, pos)
+				if strlen < 0:
+					raise ps_tokenerror, 'bad hexstring at character %d' % pos
+				token = buf[pos:pos+strlen]
+			else:
+				raise ps_tokenerror, 'bad token at character %d' % pos
+		else:
+			if char == '/':
+				tokentype = 'do_literal'
+				endofthing = endmatch(buf, pos + 1) + 1
+			else:
+				tokentype = ''
+				endofthing = endmatch(buf, pos)
+			if endofthing <= 0:
+				raise ps_tokenerror, 'bad token at character %d' % pos
+			token = buf[pos:pos + endofthing]
+		self.pos = pos + len(token)
+		return tokentype, token
+	
+	def skipwhite(self, whitematch = skipwhiteRE.match):
+		self.pos = self.pos + whitematch(self.buf, self.pos)
+	
+	def starteexec(self):
+		self.pos = self.pos + 1
+		#self.skipwhite()
+		self.dirtybuf = self.buf[self.pos:]
+		self.buf, R = eexec.Decrypt(self.dirtybuf, 55665)
+		self.len = len(self.buf)
+		self.pos = 4
+	
+	def stopeexec(self):
+		if not hasattr(self, 'dirtybuf'):
+			return
+		self.buf = self.dirtybuf
+		del self.dirtybuf
+	
+	def flush(self):
+		if self.buflist:
+			self.buf = self.buf + string.join(self.buflist, '')
+			self.buflist = []
+
+
+class PSInterpreter(PSOperators):
+	
+	def __init__(self):
+		systemdict = {}
+		userdict = {}
+		self.dictstack = [systemdict, userdict]
+		self.stack = []
+		self.proclevel = 0
+		self.procmark = ps_procmark()
+		self.fillsystemdict()
+	
+	def fillsystemdict(self):
+		systemdict = self.dictstack[0]
+		systemdict['['] = systemdict['mark'] = self.mark = ps_mark()
+		systemdict[']'] = ps_operator(']', self.do_makearray)
+		systemdict['true'] = ps_boolean(1)
+		systemdict['false'] = ps_boolean(0)
+		systemdict['StandardEncoding'] = ps_array(ps_StandardEncoding)
+		systemdict['FontDirectory'] = ps_dict({})
+		self.suckoperators(systemdict, self.__class__)
+	
+	def suckoperators(self, systemdict, klass):
+		for name in dir(klass):
+			attr = getattr(self, name)
+			if callable(attr) and name[:3] == 'ps_':
+				name = name[3:]
+				systemdict[name] = ps_operator(name, attr)
+		for baseclass in klass.__bases__:
+			self.suckoperators(systemdict, baseclass)
+	
+	def interpret(self, data, getattr = getattr):
+		tokenizer = self.tokenizer = PSTokenizer(data)
+		getnexttoken = tokenizer.getnexttoken
+		do_token = self.do_token
+		handle_object = self.handle_object
+		try:
+			while 1:
+				tokentype, token = getnexttoken()
+				#print token
+				if not token:
+					break
+				if tokentype:
+					handler = getattr(self, tokentype)
+					object = handler(token)
+				else:
+					object = do_token(token)
+				if object is not None:
+					handle_object(object)
+			tokenizer.close()
+			self.tokenizer = None
+		finally:
+			if self.tokenizer is not None:
+				print 'ps error:\n- - - - - - -'
+				print self.tokenizer.buf[self.tokenizer.pos-50:self.tokenizer.pos]
+				print '>>>'
+				print self.tokenizer.buf[self.tokenizer.pos:self.tokenizer.pos+50]
+				print '- - - - - - -'
+	
+	def handle_object(self, object):
+		if not (self.proclevel or object.literal or object.type == 'proceduretype'):
+			if object.type <> 'operatortype':
+				object = self.resolve_name(object.value)
+			if object.literal:
+				self.push(object)
+			else:
+				if object.type == 'proceduretype':
+					self.call_procedure(object)
+				else:
+					object.function()
+		else:
+			self.push(object)
+	
+	def call_procedure(self, proc):
+		handle_object = self.handle_object
+		for item in proc.value:
+			handle_object(item)
+	
+	def resolve_name(self, name):
+		dictstack = self.dictstack
+		for i in range(len(dictstack)-1, -1, -1):
+			if dictstack[i].has_key(name):
+				return dictstack[i][name]
+		raise ps_error, 'name error: ' + str(name)
+	
+	def do_token(self, token,
+				atoi = string.atoi, 
+				atof = string.atof,
+				ps_name = ps_name,
+				ps_integer = ps_integer,
+				ps_real = ps_real):
+		try:
+			num = atoi(token)
+		except (ValueError, OverflowError):
+			try:
+				num = atof(token)
+			except (ValueError, OverflowError):
+				if '#' in token:
+					hashpos = string.find(token, '#')
+					try:
+						base = string.atoi(token[:hashpos])
+						num = string.atoi(token[hashpos+1:], base)
+					except (ValueError, OverflowError):
+						return ps_name(token)
+					else:
+						return ps_integer(num)
+				else:
+					return ps_name(token)
+			else:
+				return ps_real(num)
+		else:
+			return ps_integer(num)
+	
+	def do_comment(self, token):
+		pass
+	
+	def do_literal(self, token):
+		return ps_literal(token[1:])
+	
+	def do_string(self, token):
+		return ps_string(token[1:-1])
+	
+	def do_hexstring(self, token):
+		hexStr = string.join(string.split(token[1:-1]), '')
+		if len(hexStr) % 2:
+			hexStr = hexStr + '0'
+		cleanstr = []
+		for i in range(0, len(hexStr), 2):
+			cleanstr.append(chr(string.atoi(hexStr[i:i+2], 16)))
+		cleanstr = string.join(cleanstr, '')
+		return ps_string(cleanstr)
+	
+	def do_special(self, token):
+		if token == '{':
+			self.proclevel = self.proclevel + 1
+			return self.procmark
+		elif token == '}':
+			proc = []
+			while 1:
+				topobject = self.pop()
+				if topobject == self.procmark:
+					break
+				proc.append(topobject)
+			self.proclevel = self.proclevel - 1
+			proc.reverse()
+			return ps_procedure(proc)
+		elif token == '[':
+			return self.mark
+		elif token == ']':
+			return ps_name(']')
+		else:
+			raise ps_tokenerror, 'huh?'
+	
+	def push(self, object):
+		self.stack.append(object)
+	
+	def pop(self, *types):
+		stack = self.stack
+		if not stack:
+			raise ps_error, 'stack underflow'
+		object = stack[-1]
+		if types:
+			if object.type not in types:
+				raise ps_error, 'typecheck, expected %s, found %s' % (`types`, object.type)
+		del stack[-1]
+		return object
+	
+	def do_makearray(self):
+		array = []
+		while 1:
+			topobject = self.pop()
+			if topobject == self.mark:
+				break
+			array.append(topobject)
+		array.reverse()
+		self.push(ps_array(array))
+	
+	def close(self):
+		"""Remove circular references."""
+		del self.stack
+		del self.dictstack
+
+
+def unpack_item(item):
+	tp = type(item.value)
+	if tp == types.DictionaryType:
+		newitem = {}
+		for key, value in item.value.items():
+			newitem[key] = unpack_item(value)
+	elif tp == types.ListType:
+		newitem = [None] * len(item.value)
+		for i in range(len(item.value)):
+			newitem[i] = unpack_item(item.value[i])
+		if item.type == 'proceduretype':
+			newitem = tuple(newitem)
+	else:
+		newitem = item.value
+	return newitem
+
+def suckfont(data):
+	import re
+	m = re.search(r"/FontName\s+/([^ \t\n\r]+)\s+def", data)
+	if m:
+		fontName = m.group(1)
+	else:
+		fontName = None
+	interpreter = PSInterpreter()
+	interpreter.interpret("/Helvetica 4 dict dup /Encoding StandardEncoding put definefont pop")
+	interpreter.interpret(data)
+	fontdir = interpreter.dictstack[0]['FontDirectory'].value
+	if fontdir.has_key(fontName):
+		rawfont = fontdir[fontName]
+	else:
+		# fall back, in case fontName wasn't found
+		fontNames = fontdir.keys()
+		if len(fontNames) > 1:
+			fontNames.remove("Helvetica")
+		fontNames.sort()
+		rawfont = fontdir[fontNames[0]]
+	interpreter.close()
+	return unpack_item(rawfont)
+
+
+if __name__ == "__main__":
+	import macfs
+	fss, ok = macfs.StandardGetFile("LWFN")
+	if ok:
+		import t1Lib
+		data, kind = t1Lib.read(fss.as_pathname())
+		font = suckfont(data)
diff --git a/Lib/fontTools/psOperators.py b/Lib/fontTools/psOperators.py
new file mode 100644
index 0000000..533f484
--- /dev/null
+++ b/Lib/fontTools/psOperators.py
@@ -0,0 +1,580 @@
+import string
+
+
+_accessstrings = {0: "", 1: "readonly", 2: "executeonly", 3: "noaccess"}
+
+class ps_object:
+	
+	literal = 1
+	access = 0
+	value = None
+	
+	def __init__(self, value):
+		self.value = value
+		self.type = self.__class__.__name__[3:] + "type"
+	
+	def __repr__(self):
+		return "<%s %s>" % (self.__class__.__name__[3:], repr(self.value))
+
+
+class ps_operator(ps_object):
+	
+	literal = 0
+	
+	def __init__(self, name, function):
+		self.name = name
+		self.function = function
+		self.type = self.__class__.__name__[3:] + "type"
+	def __repr__(self):
+		return "<operator %s>" % self.name
+
+class ps_procedure(ps_object):
+	literal = 0
+	def __repr__(self):
+		return "<procedure>"
+	def __str__(self):
+		psstring = '{'
+		for i in range(len(self.value)):
+			if i:
+				psstring = psstring + ' ' + str(self.value[i])
+			else:
+				psstring = psstring + str(self.value[i])
+		return psstring + '}'
+
+class ps_name(ps_object):
+	literal = 0
+	def __str__(self):
+		if self.literal:
+			return '/' + self.value
+		else:
+			return self.value
+
+class ps_literal(ps_object):
+	def __str__(self):
+		return '/' + self.value
+
+class ps_array(ps_object):
+	def __str__(self):
+		psstring = '['
+		for i in range(len(self.value)):
+			item = self.value[i]
+			access = _accessstrings[item.access]
+			if access:
+				access = ' ' + access
+			if i:
+				psstring = psstring + ' ' + str(item) + access
+			else:
+				psstring = psstring + str(item) + access
+		return psstring + ']'
+	def __repr__(self):
+		return "<array>"
+
+_type1_pre_eexec_order = [
+		"FontInfo",
+		"FontName",
+		"Encoding",
+		"PaintType",
+		"FontType",
+		"FontMatrix",
+		"FontBBox",
+		"UniqueID",
+		"Metrics",
+		"StrokeWidth"
+	]
+
+_type1_fontinfo_order = [
+		"version",
+		"Notice",
+		"FullName",
+		"FamilyName",
+		"Weight",
+		"ItalicAngle",
+		"isFixedPitch",
+		"UnderlinePosition",
+		"UnderlineThickness"
+	]
+
+_type1_post_eexec_order = [
+		"Private",
+		"CharStrings",
+		"FID"
+	]
+
+def _type1_item_repr(key, value):
+	psstring = ""
+	access = _accessstrings[value.access]
+	if access:
+		access = access + ' '
+	if key == 'CharStrings':
+		psstring = psstring + "/%s %s def\n" % (key, _type1_CharString_repr(value.value))
+	elif key == 'Encoding':
+		psstring = psstring + _type1_Encoding_repr(value, access)
+	else:
+		psstring = psstring + "/%s %s %sdef\n" % (str(key), str(value), access)
+	return psstring
+
+def _type1_Encoding_repr(encoding, access):
+	encoding = encoding.value
+	psstring = "/Encoding 256 array\n0 1 255 {1 index exch /.notdef put} for\n"
+	for i in range(256):
+		name = encoding[i].value
+		if name <> '.notdef':
+			psstring = psstring + "dup %d /%s put\n" % (i, name)
+	return psstring + access + "def\n"
+
+def _type1_CharString_repr(charstrings):
+	items = charstrings.items()
+	items.sort()
+	return 'xxx'
+
+class ps_font(ps_object):
+	def __str__(self):
+		psstring = "%d dict dup begin\n" % len(self.value)
+		for key in _type1_pre_eexec_order:
+			try:
+				value = self.value[key]
+			except KeyError:
+				pass
+			else:
+				psstring = psstring + _type1_item_repr(key, value)
+		items = self.value.items()
+		items.sort()
+		for key, value in items:
+			if key not in _type1_pre_eexec_order + _type1_post_eexec_order:
+				psstring = psstring + _type1_item_repr(key, value)
+		psstring = psstring + "currentdict end\ncurrentfile eexec\ndup "
+		for key in _type1_post_eexec_order:
+			try:
+				value = self.value[key]
+			except KeyError:
+				pass
+			else:
+				psstring = psstring + _type1_item_repr(key, value)
+		return psstring + 'dup/FontName get exch definefont pop\nmark currentfile closefile\n' + \
+				8 * (64 * '0' + '\n') + 'cleartomark' + '\n'
+	def __repr__(self):
+		return '<font>'
+
+class ps_file(ps_object):
+	pass
+
+class ps_dict(ps_object):
+	def __str__(self):
+		psstring = "%d dict dup begin\n" % len(self.value)
+		items = self.value.items()
+		items.sort()
+		dictrepr = "%d dict dup begin\n" % len(items)
+		for key, value in items:
+			access = _accessstrings[value.access]
+			if access:
+				access = access + ' '
+			psstring = psstring + "/%s %s %sdef\n" % (str(key), str(value), access)
+		return psstring + 'end '
+	def __repr__(self):
+		return "<dict>"
+
+class ps_mark(ps_object):
+	def __init__(self): 
+		self.value = 'mark'
+		self.type = self.__class__.__name__[3:] + "type"
+
+class ps_procmark(ps_object):
+	def __init__(self):
+		self.value = 'procmark'
+		self.type = self.__class__.__name__[3:] + "type"
+
+class ps_null(ps_object):
+	def __init__(self):
+		self.type = self.__class__.__name__[3:] + "type"
+
+class ps_boolean(ps_object):
+	def __str__(self):
+		if self.value:
+			return 'true'
+		else:
+			return 'false'
+
+class ps_string(ps_object):
+	def __str__(self):
+		return "(%s)" % `self.value`[1:-1]
+
+class ps_integer(ps_object):
+	def __str__(self):
+		return `self.value`
+
+class ps_real(ps_object):
+	def __str__(self):
+		return `self.value`
+
+
+class PSOperators:
+	
+	def ps_def(self):
+		object = self.pop()
+		name = self.pop()
+		self.dictstack[-1][name.value] = object
+	
+	def ps_bind(self):
+		proc = self.pop('proceduretype')
+		self.proc_bind(proc)
+		self.push(proc)
+	
+	def proc_bind(self, proc):
+		for i in range(len(proc.value)):
+			item = proc.value[i]
+			if item.type == 'proceduretype':
+				self.proc_bind(item)
+			else:
+				if not item.literal:
+					try:
+						object = self.resolve_name(item.value)
+					except:
+						pass
+					else:
+						if object.type == 'operatortype':
+							proc.value[i] = object
+	
+	def ps_exch(self):
+		if len(self.stack) < 2:
+			raise RuntimeError, 'stack underflow'
+		obj1 = self.pop()
+		obj2 = self.pop()
+		self.push(obj1)
+		self.push(obj2)
+	
+	def ps_dup(self):
+		if not self.stack:
+			raise RuntimeError, 'stack underflow'
+		self.push(self.stack[-1])
+	
+	def ps_exec(self):
+		object = self.pop()
+		if object.type == 'proceduretype':
+			self.call_procedure(object)
+		else:
+			self.handle_object(object)
+	
+	def ps_count(self):
+		self.push(ps_integer(len(self.stack)))
+	
+	def ps_eq(self):
+		any1 = self.pop()
+		any2 = self.pop()
+		self.push(ps_boolean(any1.value == any2.value))
+	
+	def ps_ne(self):
+		any1 = self.pop()
+		any2 = self.pop()
+		self.push(ps_boolean(any1.value <> any2.value))
+	
+	def ps_cvx(self):
+		obj = self.pop()
+		obj.literal = 0
+		self.push(obj)
+	
+	def ps_matrix(self):
+		matrix = [ps_real(1.0), ps_integer(0), ps_integer(0), ps_real(1.0), ps_integer(0), ps_integer(0)]
+		self.push(ps_array(matrix))
+	
+	def ps_string(self):
+		num = self.pop('integertype').value
+		self.push(ps_string('\0' * num))
+	
+	def ps_type(self):
+		obj = self.pop()
+		self.push(ps_string(obj.type))
+	
+	def ps_store(self):
+		value = self.pop()
+		key = self.pop()
+		name = key.value
+		for i in range(len(self.dictstack)-1, -1, -1):
+			if self.dictstack[i].has_key(name):
+				self.dictstack[i][name] = value
+				break
+		self.dictstack[-1][name] = value
+	
+	def ps_where(self):
+		name = self.pop()
+		# XXX
+		self.push(ps_boolean(0))
+	
+	def ps_systemdict(self):
+		self.push(ps_dict(self.dictstack[0]))
+	
+	def ps_userdict(self):
+		self.push(ps_dict(self.dictstack[1]))
+	
+	def ps_currentdict(self):
+		self.push(ps_dict(self.dictstack[-1]))
+	
+	def ps_currentfile(self):
+		self.push(ps_file(self.tokenizer))
+	
+	def ps_eexec(self):
+		file = self.pop('filetype').value
+		file.starteexec()
+	
+	def ps_closefile(self):
+		file = self.pop('filetype').value
+		file.skipwhite()
+		file.stopeexec()
+	
+	def ps_cleartomark(self):
+		obj = self.pop()
+		while obj <> self.mark:
+			obj = self.pop()
+	
+	def ps_readstring(self,
+				ps_boolean = ps_boolean,
+				len = len):
+		string = self.pop('stringtype')
+		oldstr = string.value
+		file = self.pop('filetype')
+		#pad = file.value.read(1)
+		# for StringIO, this is faster
+		file.value.pos = file.value.pos + 1
+		newstr = file.value.read(len(oldstr))
+		string.value = newstr
+		self.push(string)
+		self.push(ps_boolean(len(oldstr) == len(newstr)))
+	
+	def ps_known(self):
+		key = self.pop()
+		dict = self.pop('dicttype', 'fonttype')
+		self.push(ps_boolean(dict.value.has_key(key.value)))
+	
+	def ps_if(self):
+		proc = self.pop('proceduretype')
+		bool = self.pop('booleantype')
+		if bool.value:
+			self.call_procedure(proc)
+	
+	def ps_ifelse(self):
+		proc2 = self.pop('proceduretype')
+		proc1 = self.pop('proceduretype')
+		bool = self.pop('booleantype')
+		if bool.value:
+			self.call_procedure(proc1)
+		else:
+			self.call_procedure(proc2)
+	
+	def ps_readonly(self):
+		obj = self.pop()
+		if obj.access < 1:
+			obj.access = 1
+		self.push(obj)
+	
+	def ps_executeonly(self):
+		obj = self.pop()
+		if obj.access < 2:
+			obj.access = 2
+		self.push(obj)
+	
+	def ps_noaccess(self):
+		obj = self.pop()
+		if obj.access < 3:
+			obj.access = 3
+		self.push(obj)
+	
+	def ps_not(self):
+		obj = self.pop('booleantype', 'integertype')
+		if obj.type == 'booleantype':
+			self.push(ps_boolean(not obj.value))
+		else:
+			self.push(ps_integer(~obj.value))
+	
+	def ps_print(self):
+		str = self.pop('stringtype')
+		print 'PS output --->', str.value
+	
+	def ps_anchorsearch(self):
+		seek = self.pop('stringtype')
+		string = self.pop('stringtype')
+		seeklen = len(seek.value)
+		if string.value[:seeklen] == seek.value:
+			self.push(ps_string(string.value[seeklen:]))
+			self.push(seek)
+			self.push(ps_boolean(1))
+		else:
+			self.push(string)
+			self.push(ps_boolean(0))
+	
+	def ps_array(self):
+		num = self.pop('integertype')
+		array = ps_array([None] * num.value)
+		self.push(array)
+	
+	def ps_astore(self):
+		array = self.pop('arraytype')
+		for i in range(len(array.value)-1, -1, -1):
+			array.value[i] = self.pop()
+		self.push(array)
+	
+	def ps_load(self):
+		name = self.pop()
+		object = self.resolve_name(name.value)
+		self.push(object)
+	
+	def ps_put(self):
+		obj1 = self.pop()
+		obj2 = self.pop()
+		obj3 = self.pop('arraytype', 'dicttype', 'stringtype', 'proceduretype')
+		tp = obj3.type
+		if tp == 'arraytype' or tp == 'proceduretype':
+			obj3.value[obj2.value] = obj1
+		elif tp == 'dicttype':
+			obj3.value[obj2.value] = obj1
+		elif tp == 'stringtype':
+			index = obj2.value
+			obj3.value = obj3.value[:index] + chr(obj1.value) + obj3.value[index+1:]
+	
+	def ps_get(self):
+		obj1 = self.pop()
+		if obj1.value == "Encoding":
+			pass
+		obj2 = self.pop('arraytype', 'dicttype', 'stringtype', 'proceduretype', 'fonttype')
+		tp = obj2.type
+		if tp in ('arraytype', 'proceduretype'):
+			self.push(obj2.value[obj1.value])
+		elif tp in ('dicttype', 'fonttype'):
+			self.push(obj2.value[obj1.value])
+		elif tp == 'stringtype':
+			self.push(ps_integer(ord(obj2.value[obj1.value])))
+		else:
+			assert 0, "shouldn't get here"
+	
+	def ps_getinterval(self):
+		obj1 = self.pop('integertype')
+		obj2 = self.pop('integertype')
+		obj3 = self.pop('arraytype', 'stringtype')
+		tp = obj3.type
+		if tp == 'arraytype':
+			self.push(ps_array(obj3.value[obj2.value:obj2.value + obj1.value]))
+		elif tp == 'stringtype':
+			self.push(ps_string(obj3.value[obj2.value:obj2.value + obj1.value]))
+	
+	def ps_putinterval(self):
+		obj1 = self.pop('arraytype', 'stringtype')
+		obj2 = self.pop('integertype')
+		obj3 = self.pop('arraytype', 'stringtype')
+		tp = obj3.type
+		if tp == 'arraytype':
+			obj3.value[obj2.value:obj2.value + len(obj1.value)] = obj1.value
+		elif tp == 'stringtype':
+			newstr = obj3.value[:obj2.value]
+			newstr = newstr + obj1.value
+			newstr = newstr + obj3.value[obj2.value + len(obj1.value):]
+			obj3.value = newstr
+	
+	def ps_cvn(self):
+		str = self.pop('stringtype')
+		self.push(ps_name(str.value))
+	
+	def ps_index(self):
+		n = self.pop('integertype').value
+		if n < 0:
+			raise RuntimeError, 'index may not be negative'
+		self.push(self.stack[-1-n])
+	
+	def ps_for(self):
+		proc = self.pop('proceduretype')
+		limit = self.pop('integertype', 'realtype').value
+		increment = self.pop('integertype', 'realtype').value
+		i = self.pop('integertype', 'realtype').value
+		while 1:
+			if increment > 0:
+				if i > limit:
+					break
+			else:
+				if i < limit:
+					break
+			if type(i) == type(0.0):
+				self.push(ps_real(i))
+			else:
+				self.push(ps_integer(i))
+			self.call_procedure(proc)
+			i = i + increment
+	
+	def ps_forall(self):
+		proc = self.pop('proceduretype')
+		obj = self.pop('arraytype', 'stringtype', 'dicttype')
+		tp = obj.type
+		if tp == 'arraytype':
+			for item in obj.value:
+				self.push(item)
+				self.call_procedure(proc)
+		elif tp == 'stringtype':
+			for item in obj.value:
+				self.push(ps_integer(ord(item)))
+				self.call_procedure(proc)
+		elif tp == 'dicttype':
+			for key, value in obj.value.items():
+				self.push(ps_name(key))
+				self.push(value)
+				self.call_procedure(proc)		
+	
+	def ps_definefont(self):
+		font = self.pop('dicttype')
+		name = self.pop()
+		font = ps_font(font.value)
+		self.dictstack[0]['FontDirectory'].value[name.value] = font
+		self.push(font)
+	
+	def ps_findfont(self):
+		name = self.pop()
+		font = self.dictstack[0]['FontDirectory'].value[name.value]
+		self.push(font)
+	
+	def ps_pop(self):
+		self.pop()
+	
+	def ps_dict(self):
+		num = self.pop('integertype')
+		dict = ps_dict({})
+		self.push(dict)
+	
+	def ps_begin(self):
+		dict = self.pop('dicttype')
+		self.dictstack.append(dict.value)
+	
+	def ps_end(self):
+		if len(self.dictstack) > 2:
+			del self.dictstack[-1]
+		else:
+			raise RuntimeError, 'dictstack underflow'
+	
+notdef = '.notdef'
+StandardEncoding = [ notdef, notdef, notdef, notdef, notdef, notdef,
+	notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+	notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+	notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+	notdef, notdef, 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
+	'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma',
+	'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', 'five', 'six',
+	'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question',
+	'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
+	'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
+	'asciicircum', 'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
+	'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+	'braceleft', 'bar', 'braceright', 'asciitilde', notdef, notdef, notdef,
+	notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+	notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+	notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+	notdef, notdef, notdef, notdef, notdef, notdef, notdef, 'exclamdown',
+	'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', 'quotesingle',
+	'quotedblleft', 'guillemotleft', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', notdef,
+	'endash', 'dagger', 'daggerdbl', 'periodcentered', notdef, 'paragraph', 'bullet',
+	'quotesinglbase', 'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis',
+	'perthousand', notdef, 'questiondown', notdef, 'grave', 'acute', 'circumflex',
+	'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', notdef, 'ring', 'cedilla',
+	notdef, 'hungarumlaut', 'ogonek', 'caron', 'emdash', notdef, notdef, notdef,
+	notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+	notdef, notdef, notdef, notdef, notdef, 'AE', notdef, 'ordfeminine',
+	notdef, notdef, notdef, notdef, 'Lslash', 'Oslash', 'OE', 'ordmasculine',
+	notdef, notdef, notdef, notdef, notdef, 'ae', notdef, notdef,
+	notdef, 'dotlessi', notdef, notdef, 'lslash', 'oslash', 'oe', 'germandbls',
+	notdef, notdef, notdef, notdef ]
+
+ps_StandardEncoding = map(ps_name, StandardEncoding)
+
diff --git a/Lib/fontTools/t1Lib.py b/Lib/fontTools/t1Lib.py
new file mode 100644
index 0000000..a2c63fb
--- /dev/null
+++ b/Lib/fontTools/t1Lib.py
@@ -0,0 +1,347 @@
+"""fontTools.t1Lib.py -- Tools for PostScript Type 1 fonts
+
+Functions for reading and writing raw Type 1 data:
+
+read(path)
+	reads any Type 1 font file, returns the raw data and a type indicator: 
+	'LWFN', 'PFB' or 'OTHER', depending on the format of the file pointed 
+	to by 'path'. 
+	Raises an error when the file does not contain valid Type 1 data.
+
+write(path, data, kind = 'OTHER', dohex = 0)
+	writes raw Type 1 data to the file pointed to by 'path'. 
+	'kind' can be one of 'LWFN', 'PFB' or 'OTHER'; it defaults to 'OTHER'.
+	'dohex' is a flag which determines whether the eexec encrypted
+	part should be written as hexadecimal or binary, but only if kind
+	is 'LWFN' or 'PFB'.
+"""
+
+__author__ = "jvr"
+__version__ = "1.0b2"
+DEBUG = 0
+
+import eexec
+import string
+import re
+import os
+
+if os.name == 'mac':
+	import Res
+	import macfs
+
+error = 't1Lib.error'
+
+# work in progress
+
+
+class T1Font:
+	
+	"""Type 1 font class. 
+	XXX This is work in progress! For now just use the read()
+	and write() functions as described above, they are stable.
+	"""
+	
+	def __init__(self, path=None):
+		if path is not None:
+			self.data, type = read(path)
+		else:
+			pass # XXX
+	
+	def saveAs(self, path, type):
+		self.write(path, self.getData(), type)
+	
+	def getData(self):
+		return self.data
+	
+	def __getitem__(self, key):
+		if not hasattr(self, "font"):
+			self.parse()
+			return self.font[key]
+		else:
+			return self.font[key]
+	
+	def parse(self):
+		import psLib
+		import psCharStrings
+		self.font = psLib.suckfont(self.data)
+		charStrings = self.font["CharStrings"]
+		lenIV = self.font["Private"].get("lenIV", 4)
+		assert lenIV >= 0
+		for glyphName, charString in charStrings.items():
+			charString, R = eexec.Decrypt(charString, 4330)
+			charStrings[glyphName] = psCharStrings.T1CharString(charString[lenIV:])
+		subrs = self.font["Private"]["Subrs"]
+		for i in range(len(subrs)):
+			charString, R = eexec.Decrypt(subrs[i], 4330)
+			subrs[i] = psCharStrings.T1CharString(charString[lenIV:])
+		del self.data
+	
+
+
+# public functions
+
+def read(path):
+	"""reads any Type 1 font file, returns raw data"""
+	normpath = string.lower(path)
+	if os.name == 'mac':
+		fss = macfs.FSSpec(path)
+		creator, type = fss.GetCreatorType()
+		if type == 'LWFN':
+			return readlwfn(path), 'LWFN'
+	if normpath[-4:] == '.pfb':
+		return readpfb(path), 'PFB'
+	else:
+		return readother(path), 'OTHER'
+
+def write(path, data, kind='OTHER', dohex=0):
+	asserttype1(data)
+	kind = string.upper(kind)
+	try:
+		os.remove(path)
+	except os.error:
+		pass
+	err = 1
+	try:
+		if kind == 'LWFN':
+			writelwfn(path, data)
+		elif kind == 'PFB':
+			writepfb(path, data)
+		else:
+			writeother(path, data, dohex)
+		err = 0
+	finally:
+		if err and not DEBUG:
+			try:
+				os.remove(path)
+			except os.error:
+				pass
+
+
+# -- internal -- 
+
+LWFNCHUNKSIZE = 2000
+HEXLINELENGTH = 80
+
+
+def readlwfn(path):
+	"""reads an LWFN font file, returns raw data"""
+	resref = Res.OpenResFile(path)
+	try:
+		Res.UseResFile(resref)
+		n = Res.Count1Resources('POST')
+		data = []
+		for i in range(501, 501 + n):
+			res = Res.Get1Resource('POST', i)
+			code = ord(res.data[0])
+			if ord(res.data[1]) <> 0:
+				raise error, 'corrupt LWFN file'
+			if code in [1, 2]:
+				data.append(res.data[2:])
+			elif code in [3, 5]:
+				break
+			elif code == 4:
+				f = open(path, "rb")
+				data.append(f.read())
+				f.close()
+			elif code == 0:
+				pass # comment, ignore
+			else:
+				raise error, 'bad chunk code: ' + `code`
+	finally:
+		Res.CloseResFile(resref)
+	data = string.join(data, '')
+	asserttype1(data)
+	return data
+
+def readpfb(path):
+	"""reads a PFB font file, returns raw data"""
+	f = open(path, "rb")
+	data = []
+	while 1:
+		if f.read(1) <> chr(128):
+			raise error, 'corrupt PFB file'
+		code = ord(f.read(1))
+		if code in [1, 2]:
+			chunklen = string2long(f.read(4))
+			data.append(f.read(chunklen))
+		elif code == 3:
+			break
+		else:
+			raise error, 'bad chunk code: ' + `code`
+	f.close()
+	data = string.join(data, '')
+	asserttype1(data)
+	return data
+
+def readother(path):
+	"""reads any (font) file, returns raw data"""
+	f = open(path, "rb")
+	data = f.read()
+	f.close()
+	asserttype1(data)
+	
+	chunks = findencryptedchunks(data)
+	data = []
+	for isencrypted, chunk in chunks:
+		if isencrypted and ishex(chunk[:4]):
+			data.append(dehexstring(chunk))
+		else:
+			data.append(chunk)
+	return string.join(data, '')
+
+# file writing tools
+
+def writelwfn(path, data):
+	Res.CreateResFile(path)
+	fss = macfs.FSSpec(path)
+	fss.SetCreatorType('just', 'LWFN')
+	resref = Res.OpenResFile(path)
+	try:
+		Res.UseResFile(resref)
+		resID = 501
+		chunks = findencryptedchunks(data)
+		for isencrypted, chunk in chunks:
+			if isencrypted:
+				code = 2
+			else:
+				code = 1
+			while chunk:
+				res = Res.Resource(chr(code) + '\0' + chunk[:LWFNCHUNKSIZE - 2])
+				res.AddResource('POST', resID, '')
+				chunk = chunk[LWFNCHUNKSIZE - 2:]
+				resID = resID + 1
+		res = Res.Resource(chr(5) + '\0')
+		res.AddResource('POST', resID, '')
+	finally:
+		Res.CloseResFile(resref)
+
+def writepfb(path, data):
+	chunks = findencryptedchunks(data)
+	f = open(dstpath, "wb")
+	try:
+		for isencrypted, chunk in chunks:
+			if isencrypted:
+				code = 2
+			else:
+				code = 1
+			f.write(chr(128) + chr(code))
+			f.write(long2string(len(chunk)))
+			f.write(chunk)
+		f.write(chr(128) + chr(3))
+	finally:
+		f.close()
+	if os.name == 'mac':
+		fss = macfs.FSSpec(dstpath)
+		fss.SetCreatorType('mdos', 'BINA')
+
+def writeother(path, data, dohex = 0):
+	chunks = findencryptedchunks(data)
+	f = open(path, "wb")
+	try:
+		hexlinelen = HEXLINELENGTH / 2
+		for isencrypted, chunk in chunks:
+			if isencrypted:
+				code = 2
+			else:
+				code = 1
+			if code == 2 and dohex:
+				while chunk:
+					f.write(eexec.hexstring(chunk[:hexlinelen]))
+					f.write('\r')
+					chunk = chunk[hexlinelen:]
+			else:
+				f.write(chunk)
+	finally:
+		f.close()
+	if os.name == 'mac':
+		fss = macfs.FSSpec(path)
+		fss.SetCreatorType('R*ch', 'TEXT') # BBEdit text file
+
+
+# decryption tools
+
+EEXECBEGIN = "currentfile eexec"
+EEXECEND = '0' * 64
+EEXECINTERNALEND = "currentfile closefile"
+EEXECBEGINMARKER = "%-- eexec start\r"
+EEXECENDMARKER = "%-- eexec end\r"
+
+_ishexRE = re.compile('[0-9A-Fa-f]*$')
+
+def ishex(text):
+	return _ishexRE.match(text) is not None
+
+
+def decrypttype1(data):
+	chunks = findencryptedchunks(data)
+	data = []
+	for isencrypted, chunk in chunks:
+		if isencrypted:
+			if ishex(chunk[:4]):
+				chunk = dehexstring(chunk)
+			decrypted, R = eexec.Decrypt(chunk, 55665)
+			decrypted = decrypted[4:]
+			if decrypted[-len(EEXECINTERNALEND)-1:-1] <> EEXECINTERNALEND \
+					and decrypted[-len(EEXECINTERNALEND)-2:-2] <> EEXECINTERNALEND:
+				raise error, "invalid end of eexec part"
+			decrypted = decrypted[:-len(EEXECINTERNALEND)-2] + '\r'
+			data.append(EEXECBEGINMARKER + decrypted + EEXECENDMARKER)
+		else:
+			if chunk[-len(EEXECBEGIN)-1:-1] == EEXECBEGIN:
+				data.append(chunk[:-len(EEXECBEGIN)-1])
+			else:
+				data.append(chunk)
+	return string.join(data, '')
+
+def findencryptedchunks(data):
+	chunks = []
+	while 1:
+		ebegin = string.find(data, EEXECBEGIN)
+		if ebegin < 0:
+			break
+		eend = string.find(data, EEXECEND, ebegin)
+		if eend < 0:
+			raise error, "can't find end of eexec part"
+		chunks.append((0, data[:ebegin + len(EEXECBEGIN) + 1]))
+		chunks.append((1, data[ebegin + len(EEXECBEGIN) + 1:eend]))
+		data = data[eend:]
+	chunks.append((0, data))
+	return chunks
+
+def dehexstring(hexstring):
+	return eexec.dehexstring(string.join(string.split(hexstring), ""))
+
+
+# Type 1 assertion
+
+_fontType1RE = re.compile(r"/FontType\s+1\s+def")
+
+def asserttype1(data):
+	for head in ['%!PS-AdobeFont', '%!FontType1-1.0']:
+		if data[:len(head)] == head:
+			break
+	else:
+		raise error, "not a PostScript font"
+	if not _fontType1RE.search(data):
+		raise error, "not a Type 1 font"
+	if string.find(data, "currentfile eexec") < 0:
+		raise error, "not an encrypted Type 1 font"
+	# XXX what else?
+	return data
+
+
+# pfb helpers
+
+def long2string(long):
+	str = ""
+	for i in range(4):
+		str = str + chr((long & (0xff << (i * 8))) >> i * 8)
+	return str
+
+def string2long(str):
+	if len(str) <> 4:
+		raise ValueError, 'string must be 4 bytes long'
+	long = 0
+	for i in range(4):
+		long = long + (ord(str[i]) << (i * 8))
+	return long
diff --git a/Lib/fontTools/ttLib/__init__.py b/Lib/fontTools/ttLib/__init__.py
new file mode 100644
index 0000000..e087465
--- /dev/null
+++ b/Lib/fontTools/ttLib/__init__.py
@@ -0,0 +1,555 @@
+"""ttLib -- a package for dealing with TrueType fonts.
+
+This package offers translators to convert TrueType fonts to Python 
+objects and vice versa, and additionally from Python to XML and vice versa.
+
+Example interactive session:
+
+Python 1.5.2c1 (#43, Mar  9 1999, 13:06:43)  [CW PPC w/GUSI w/MSL]
+Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
+>>> from fontTools import ttLib
+>>> tt = ttLib.TTFont("afont.ttf")
+>>> tt['maxp'].numGlyphs
+242
+>>> tt['OS/2'].achVendID
+'B&H\000'
+>>> tt['head'].unitsPerEm
+2048
+>>> tt.saveXML("afont.xml")
+Dumping 'LTSH' table...
+Dumping 'OS/2' table...
+Dumping 'VDMX' table...
+Dumping 'cmap' table...
+Dumping 'cvt ' table...
+Dumping 'fpgm' table...
+Dumping 'glyf' table...
+Dumping 'hdmx' table...
+Dumping 'head' table...
+Dumping 'hhea' table...
+Dumping 'hmtx' table...
+Dumping 'loca' table...
+Dumping 'maxp' table...
+Dumping 'name' table...
+Dumping 'post' table...
+Dumping 'prep' table...
+>>> tt2 = ttLib.TTFont()
+>>> tt2.importXML("afont.xml")
+>>> tt2['maxp'].numGlyphs
+242
+>>> 
+
+"""
+
+__author__ = "Just van Rossum, just@letterror.com"
+__version__ = "1.0a5"
+
+
+import os
+import stat
+import types
+
+class TTLibError(Exception): pass
+
+
+class TTFont:
+	
+	"""The main font object. It manages file input and output, and offers
+	a convenient way of accessing tables. 
+	Tables will be only decompiled when neccesary, ie. when they're actually
+	accessed. This means that simple operations can be extremely fast.
+	"""
+	
+	def __init__(self, file=None, res_name_or_index=None, 
+			sfntVersion="\000\001\000\000", checkchecksums=0, verbose=0):
+		
+		"""The constructor can be called with a few different arguments.
+		When reading a font from disk, 'file' should be either a pathname
+		pointing to a file, or a readable file object. 
+		
+		It we're running on a Macintosh, 'res_name_or_index' maybe an sfnt 
+		resource name or an sfnt resource index number or zero. The latter 
+		case will cause TTLib to autodetect whether the file is a flat file 
+		or a suitcase. (If it's a suitcase, only the first 'sfnt' resource
+		will be read!)
+		
+		The 'checkchecksums' argument is used to specify how sfnt
+		checksums are treated upon reading a file from disk:
+			0: don't check (default)
+			1: check, print warnings if a wrong checksum is found (default)
+			2: check, raise an exception if a wrong checksum is found.
+		
+		The TTFont constructor can also be called without a 'file' 
+		argument: this is the way to create a new empty font. 
+		In this case you can optionally supply the 'sfntVersion' argument.
+		"""
+		
+		import sfnt
+		self.verbose = verbose
+		self.tables = {}
+		self.reader = None
+		if not file:
+			self.sfntVersion = sfntVersion
+			return
+		if type(file) == types.StringType:
+			if os.name == "mac" and res_name_or_index is not None:
+				# on the mac, we deal with sfnt resources as well as flat files
+				import macUtils
+				if res_name_or_index == 0:
+					if macUtils.getSFNTResIndices(file):
+						# get the first available sfnt font.
+						file = macUtils.SFNTResourceReader(file, 1)
+					else:
+						file = open(file, "rb")
+				else:
+					file = macUtils.SFNTResourceReader(file, res_name_or_index)
+			else:
+				file = open(file, "rb")
+		else:
+			pass # assume "file" is a readable file object
+		self.reader = sfnt.SFNTReader(file, checkchecksums)
+		self.sfntVersion = self.reader.sfntVersion
+	
+	def close(self):
+		"""If we still have a reader object, close it."""
+		if self.reader is not None:
+			self.reader.close()
+	
+	def save(self, file, make_suitcase=0):
+		"""Save the font to disk. Similarly to the constructor, 
+		the 'file' argument can be either a pathname or a writable
+		file object.
+		
+		On the Mac, if make_suitcase is non-zero, a suitcase file will
+		we made instead of a flat .ttf file. 
+		"""
+		import sfnt
+		if type(file) == types.StringType:
+			if os.name == "mac" and make_suitcase:
+				import macUtils
+				file = macUtils.SFNTResourceWriter(file, self)
+			else:
+				file = open(file, "wb")
+				if os.name == "mac":
+					import macfs
+					fss = macfs.FSSpec(file.name)
+					fss.SetCreatorType('mdos', 'BINA')
+		else:
+			pass # assume "file" is a writable file object
+		
+		tags = self.keys()
+		numTables = len(tags)
+		writer = sfnt.SFNTWriter(file, numTables, self.sfntVersion)
+		
+		done = []
+		for tag in tags:
+			self._writeTable(tag, writer, done)
+		
+		writer.close()
+	
+	def saveXML(self, file, progress=None, tables=None):
+		"""Export the font as an XML-based text file.
+		"""
+		import xmlWriter
+		writer = xmlWriter.XMLWriter(file)
+		writer.begintag("ttFont", sfntVersion=`self.sfntVersion`[1:-1], 
+				ttlibVersion=__version__)
+		writer.newline()
+		writer.newline()
+		if not tables:
+			tables = self.keys()
+		numTables = len(tables)
+		numGlyphs = self['maxp'].numGlyphs
+		if progress:
+			progress.set(0, numTables * numGlyphs)
+		for i in range(numTables):
+			tag = tables[i]
+			table = self[tag]
+			report = "Dumping '%s' table..." % tag
+			if progress:
+				progress.setlabel(report)
+			elif self.verbose:
+				debugmsg(report)
+			else:
+				print report
+			xmltag = tag2xmltag(tag)
+			writer.begintag(xmltag)
+			writer.newline()
+			if tag == "glyf":
+				table.toXML(writer, self, progress)
+			elif tag == "CFF ":
+				table.toXML(writer, self, progress)
+			else:
+				table.toXML(writer, self)
+			writer.endtag(xmltag)
+			writer.newline()
+			writer.newline()
+			if progress:
+				progress.set(i * numGlyphs, numTables * numGlyphs)
+		writer.endtag("ttFont")
+		writer.newline()
+		writer.close()
+		if self.verbose:
+			debugmsg("Done dumping XML")
+	
+	def importXML(self, file, progress=None):
+		"""Import an XML-based text file, so as to recreate
+		a font object.
+		"""
+		if self.tables:
+			raise error, "Can't import XML into existing font."
+		import xmlImport
+		from xml.parsers.xmlproc import xmlproc
+		builder = xmlImport.XMLApplication(self, progress)
+		if progress:
+			progress.set(0, os.stat(file)[stat.ST_SIZE] / 100 or 1)
+		proc = xmlImport.UnicodeProcessor()
+		proc.set_application(builder)
+		proc.set_error_handler(xmlImport.XMLErrorHandler(proc))
+		dir, filename = os.path.split(file)
+		if dir:
+			olddir = os.getcwd()
+			os.chdir(dir)
+		try:
+			proc.parse_resource(filename)
+			root = builder.root
+		finally:
+			if dir:
+				os.chdir(olddir)
+			# remove circular references
+			proc.deref()
+			del builder.progress
+	
+	def isLoaded(self, tag):
+		"""Return true if the table identified by 'tag' has been 
+		decompiled and loaded into memory."""
+		return self.tables.has_key(tag)
+	
+	def has_key(self, tag):
+		"""Pretend we're a dictionary."""
+		if self.isLoaded(tag):
+			return 1
+		elif self.reader and self.reader.has_key(tag):
+			return 1
+		else:
+			return 0
+	
+	def keys(self):
+		"""Pretend we're a dictionary."""
+		keys = self.tables.keys()
+		if self.reader:
+			for key in self.reader.keys():
+				if key not in keys:
+					keys.append(key)
+		keys.sort()
+		return keys
+	
+	def __len__(self):
+		"""Pretend we're a dictionary."""
+		return len(self.keys())
+	
+	def __getitem__(self, tag):
+		"""Pretend we're a dictionary."""
+		try:
+			return self.tables[tag]
+		except KeyError:
+			if self.reader is not None:
+				if self.verbose:
+					debugmsg("reading '%s' table from disk" % tag)
+				data = self.reader[tag]
+				tableclass = getTableClass(tag)
+				table = tableclass(tag)
+				self.tables[tag] = table
+				if self.verbose:
+					debugmsg("decompiling '%s' table" % tag)
+				table.decompile(data, self)
+				return table
+			else:
+				raise KeyError, "'%s' table not found" % tag
+	
+	def __setitem__(self, tag, table):
+		"""Pretend we're a dictionary."""
+		self.tables[tag] = table
+	
+	def __delitem__(self, tag):
+		"""Pretend we're a dictionary."""
+		del self.tables[tag]
+	
+	def setGlyphOrder(self, glyphOrder):
+		self.glyphOrder = glyphOrder
+		if self.has_key('CFF '):
+			self['CFF '].setGlyphOrder(glyphOrder)
+		if self.has_key('glyf'):
+			self['glyf'].setGlyphOrder(glyphOrder)
+	
+	def getGlyphOrder(self):
+		if not hasattr(self, "glyphOrder"):
+			if self.has_key('CFF '):
+				# CFF OpenType font
+				self.glyphOrder = self['CFF '].getGlyphOrder()
+			else:
+				# TrueType font
+				glyphOrder = self['post'].getGlyphOrder()
+				if glyphOrder is None:
+					#
+					# No names found in the 'post' table.
+					# Try to create glyph names from the unicode cmap (if available) 
+					# in combination with the Adobe Glyph List (AGL).
+					#
+					self._getGlyphNamesFromCmap()
+				else:
+					self.glyphOrder = glyphOrder
+			# XXX what if a font contains 'glyf'/'post' table *and* CFF?
+		return self.glyphOrder
+	
+	def _getGlyphNamesFromCmap(self):
+		# Make up glyph names based on glyphID, which will be used 
+		# in case we don't find a unicode cmap.
+		numGlyphs = int(self['maxp'].numGlyphs)
+		glyphOrder = [None] * numGlyphs
+		glyphOrder[0] = ".notdef"
+		for i in range(1, numGlyphs):
+			glyphOrder[i] = "glyph%.5d" % i
+		# Set the glyph order, so the cmap parser has something
+		# to work with
+		self.glyphOrder = glyphOrder
+		# Get the temporary cmap (based on the just invented names)
+		tempcmap = self['cmap'].getcmap(3, 1)
+		if tempcmap is not None:
+			# we have a unicode cmap
+			import agl, string
+			cmap = tempcmap.cmap
+			# create a reverse cmap dict
+			reversecmap = {}
+			for unicode, name in cmap.items():
+				reversecmap[name] = unicode
+			assert len(reversecmap) == len(cmap)
+			for i in range(numGlyphs):
+				tempName = glyphOrder[i]
+				if reversecmap.has_key(tempName):
+					unicode = reversecmap[tempName]
+					if agl.UV2AGL.has_key(unicode):
+						# get name from the Adobe Glyph List
+						glyphOrder[i] = agl.UV2AGL[unicode]
+					else:
+						# create uni<CODE> name
+						glyphOrder[i] = "uni" + string.upper(string.zfill(hex(unicode)[2:], 4))
+			# Delete the cmap table from the cache, so it can be 
+			# parsed again with the right names.
+			del self.tables['cmap']
+		else:
+			pass # no unicode cmap available, stick with the invented names
+		self.glyphOrder = glyphOrder
+	
+	def getGlyphNames(self):
+		"""Get a list of glyph names, sorted alphabetically."""
+		glyphNames = self.getGlyphOrder()[:]
+		glyphNames.sort()
+		return glyphNames
+	
+	def getGlyphNames2(self):
+		"""Get a list of glyph names, sorted alphabetically, but not case sensitive."""
+		from fontTools.misc import textTools
+		return textTools.caselessSort(self.getGlyphOrder())
+	
+	def getGlyphName(self, glyphID):
+		return self.getGlyphOrder()[glyphID]
+	
+	def getGlyphID(self, glyphName):
+		if not hasattr(self, "_reverseGlyphOrderDict"):
+			self._buildReverseGlyphOrderDict()
+		glyphOrder = self.getGlyphOrder()
+		d = self._reverseGlyphOrderDict
+		if not d.has_key(glyphName):
+			if glyphName in glyphOrder:
+				self._buildReverseGlyphOrderDict()
+				return self.getGlyphID(glyphName)
+			else:
+				raise KeyError, glyphName
+		glyphID = d[glyphName]
+		if glyphName <> glyphOrder[glyphID]:
+			self._buildReverseGlyphOrderDict()
+			return self.getGlyphID(glyphName)
+		return glyphID
+	
+	def _buildReverseGlyphOrderDict(self):
+		self._reverseGlyphOrderDict = d = {}
+		glyphOrder = self.getGlyphOrder()
+		for glyphID in range(len(glyphOrder)):
+			d[glyphOrder[glyphID]] = glyphID
+	
+	def _writeTable(self, tag, writer, done):
+		"""Internal helper function for self.save(). Keeps track of 
+		inter-table dependencies.
+		"""
+		if tag in done:
+			return
+		tableclass = getTableClass(tag)
+		for masterTable in tableclass.dependencies:
+			if masterTable not in done:
+				if self.has_key(masterTable):
+					self._writeTable(masterTable, writer, done)
+				else:
+					done.append(masterTable)
+		tabledata = self._getTableData(tag)
+		if self.verbose:
+			debugmsg("writing '%s' table to disk" % tag)
+		writer[tag] = tabledata
+		done.append(tag)
+	
+	def _getTableData(self, tag):
+		"""Internal helper function. Returns raw table data,
+		whether compiled or directly read from disk.
+		"""
+		if self.isLoaded(tag):
+			if self.verbose:
+				debugmsg("compiling '%s' table" % tag)
+			return self.tables[tag].compile(self)
+		elif self.reader and self.reader.has_key(tag):
+			if self.verbose:
+				debugmsg("reading '%s' table from disk" % tag)
+			return self.reader[tag]
+		else:
+			raise KeyError, tag
+
+
+def _test_endianness():
+	"""Test the endianness of the machine. This is crucial to know
+	since TrueType data is always big endian, even on little endian
+	machines. There are quite a few situations where we explicitly
+	need to swap some bytes.
+	"""
+	import struct
+	data = struct.pack("h", 0x01)
+	if data == "\000\001":
+		return "big"
+	elif data == "\001\000":
+		return "little"
+	else:
+		assert 0, "endian confusion!"
+
+endian = _test_endianness()
+
+
+def getTableModule(tag):
+	"""Fetch the packer/unpacker module for a table. 
+	Return None when no module is found.
+	"""
+	import imp
+	import tables
+	py_tag = tag2identifier(tag)
+	try:
+		f, path, kind = imp.find_module(py_tag, tables.__path__)
+		if f:
+			f.close()
+	except ImportError:
+		return None
+	else:
+		module = __import__("fontTools.ttLib.tables." + py_tag)
+		return getattr(tables, py_tag)
+
+
+def getTableClass(tag):
+	"""Fetch the packer/unpacker class for a table. 
+	Return None when no class is found.
+	"""
+	module = getTableModule(tag)
+	if module is None:
+		from tables.DefaultTable import DefaultTable
+		return DefaultTable
+	py_tag = tag2identifier(tag)
+	tableclass = getattr(module, "table_" + py_tag)
+	return tableclass
+
+
+def newtable(tag):
+	"""Return a new instance of a table."""
+	tableclass = getTableClass(tag)
+	return tableclass(tag)
+
+
+def _escapechar(c):
+	"""Helper function for tag2identifier()"""
+	import re
+	if re.match("[a-z0-9]", c):
+		return "_" + c
+	elif re.match("[A-Z]", c):
+		return c + "_"
+	else:
+		return hex(ord(c))[2:]
+
+
+def tag2identifier(tag):
+	"""Convert a table tag to a valid (but UGLY) python identifier, 
+	as well as a filename that's guaranteed to be unique even on a 
+	caseless file system. Each character is mapped to two characters.
+	Lowercase letters get an underscore before the letter, uppercase
+	letters get an underscore after the letter. Trailing spaces are
+	trimmed. Illegal characters are escaped as two hex bytes. If the
+	result starts with a number (as the result of a hex escape), an
+	extra underscore is prepended. Examples: 
+		'glyf' -> '_g_l_y_f'
+		'cvt ' -> '_c_v_t'
+		'OS/2' -> 'O_S_2f_2'
+	"""
+	import re
+	assert len(tag) == 4, "tag should be 4 characters long"
+	while len(tag) > 1 and tag[-1] == ' ':
+		tag = tag[:-1]
+	ident = ""
+	for c in tag:
+		ident = ident + _escapechar(c)
+	if re.match("[0-9]", ident):
+		ident = "_" + ident
+	return ident
+
+
+def identifier2tag(ident):
+	"""the opposite of tag2identifier()"""
+	import string
+	if len(ident) % 2 and ident[0] == "_":
+		ident = ident[1:]
+	assert not (len(ident) % 2)
+	tag = ""
+	for i in range(0, len(ident), 2):
+		if ident[i] == "_":
+			tag = tag + ident[i+1]
+		elif ident[i+1] == "_":
+			tag = tag + ident[i]
+		else:
+			# assume hex
+			tag = tag + chr(string.atoi(ident[i:i+2], 16))
+	# append trailing spaces
+	tag = tag + (4 - len(tag)) * ' '
+	return tag
+
+
+def tag2xmltag(tag):
+	"""Similarly to tag2identifier(), this converts a TT tag
+	to a valid XML element name. Since XML element names are
+	case sensitive, this is a fairly simple/readable translation.
+	"""
+	import string, re
+	if tag == "OS/2":
+		return "OS_2"
+	if re.match("[A-Za-z_][A-Za-z_0-9]* *$", tag):
+		return string.strip(tag)
+	else:
+		return tag2identifier(tag)
+
+
+def xmltag2tag(tag):
+	"""The opposite of tag2xmltag()"""
+	if tag == "OS_2":
+		return "OS/2"
+	if len(tag) == 8:
+		return identifier2tag(tag)
+	else:
+		return tag + " " * (4 - len(tag))
+	return tag
+
+
+def debugmsg(msg):
+	import time
+	print msg + time.strftime("  (%H:%M:%S)", time.localtime(time.time()))
+
+
diff --git a/Lib/fontTools/ttLib/macUtils.py b/Lib/fontTools/ttLib/macUtils.py
new file mode 100644
index 0000000..bace3b4
--- /dev/null
+++ b/Lib/fontTools/ttLib/macUtils.py
@@ -0,0 +1,212 @@
+"""ttLib.macUtils.py -- Various Mac-specific stuff."""
+
+
+import os
+if os.name <> "mac":
+	raise ImportError, "This module is Mac-only!"
+
+import Res, macfs
+import cStringIO
+
+
+def getSFNTResIndices(path):
+	"""Determine whether a file has a resource fork or not."""
+	fss = macfs.FSSpec(path)
+	try:
+		resref = Res.FSpOpenResFile(fss, 1)  # read only
+	except Res.Error:
+		return []
+	Res.UseResFile(resref)
+	numSFNTs = Res.Count1Resources('sfnt')
+	Res.CloseResFile(resref)
+	return range(1, numSFNTs + 1)
+
+
+def openTTFonts(path):
+	"""Given a pathname, return a list of TTFont objects. In the case 
+	of a flat TTF/OTF file, the list will contain just one font object;
+	but in the case of a Mac font suitcase it will contain as many
+	font objects as there are sfnt resources in the file.
+	"""
+	from fontTools import ttLib
+	fonts = []
+	sfnts = getSFNTResIndices(path)
+	if not sfnts:
+		fonts.append(ttLib.TTFont(path))
+	else:
+		for index in sfnts:
+			fonts.append(ttLib.TTFont(path, index))
+		if not fonts:
+			raise ttLib.TTLibError, "no fonts found in file '%s'" % path
+	return fonts
+
+
+class ProgressBar:
+	
+	def __init__(self, title, maxval=100):
+		import EasyDialogs
+		self.bar = EasyDialogs.ProgressBar(title, maxval=maxval)
+	
+	def set(self, val, maxval=None):
+		if maxval <> None:
+			self.bar.maxval = maxval
+		self.bar.set(val)
+	
+	def increment(self, val=1):
+		self.bar.inc(val)
+	
+	def setlabel(self, text):
+		self.bar.label(text)
+	
+	def close(self):
+		self.bar.d.HideWindow()
+		del self.bar
+
+
+class SFNTResourceReader:
+	
+	"""Simple (Mac-only) read-only file wrapper for 'sfnt' resources."""
+	
+	def __init__(self, path, res_name_or_index):
+		fss = macfs.FSSpec(path)
+		resref = Res.FSpOpenResFile(fss, 1)  # read-only
+		Res.UseResFile(resref)
+		if type(res_name_or_index) == type(""):
+			res = Res.Get1NamedResource('sfnt', res_name_or_index)
+		else:
+			res = Res.Get1IndResource('sfnt', res_name_or_index)
+		self.file = cStringIO.StringIO(res.data)
+		Res.CloseResFile(resref)
+		self.name = path
+	
+	def __getattr__(self, attr):
+		# cheap inheritance
+		return getattr(self.file, attr)
+
+
+class SFNTResourceWriter:
+	
+	"""Simple (Mac-only) file wrapper for 'sfnt' resources."""
+	
+	def __init__(self, path, ttFont, res_id=None):
+		self.file = cStringIO.StringIO()
+		self.name = path
+		self.closed = 0
+		fullname = ttFont['name'].getname(4, 1, 0) # Full name, mac, default encoding
+		familyname = ttFont['name'].getname(1, 1, 0) # Fam. name, mac, default encoding
+		psname = ttFont['name'].getname(6, 1, 0) # PostScript name, etc.
+		if fullname is None or fullname is None or psname is None:
+			from fontTools import ttLib
+			raise ttLib.TTLibError, "can't make 'sfnt' resource, no Macintosh 'name' table found"
+		self.fullname = fullname.string
+		self.familyname = familyname.string
+		self.psname = psname.string
+		if self.familyname <> self.psname[:len(self.familyname)]:
+			# ugh. force fam name to be the same as first part of ps name,
+			# fondLib otherwise barfs.
+			for i in range(min(len(self.psname), len(self.familyname))):
+				if self.familyname[i] <> self.psname[i]:
+					break
+			self.familyname = self.psname[:i]
+		
+		self.ttFont = ttFont
+		self.res_id = res_id
+		fss = macfs.FSSpec(self.name)
+		if os.path.exists(self.name):
+			os.remove(self.name)
+		Res.FSpCreateResFile(fss, 'DMOV', 'FFIL', 0)
+		self.resref = Res.FSpOpenResFile(fss, 3)  # exclusive read/write permission
+	
+	def close(self):
+		if self.closed:
+			return
+		Res.UseResFile(self.resref)
+		try:
+			res = Res.Get1NamedResource('sfnt', self.fullname)
+		except Res.Error:
+			pass
+		else:
+			res.RemoveResource()
+		res = Res.Resource(self.file.getvalue())
+		if self.res_id is None:
+			self.res_id = Res.Unique1ID('sfnt')
+		res.AddResource('sfnt', self.res_id, self.fullname)
+		res.ChangedResource()
+		
+		self.createFond()
+		del self.ttFont
+		Res.CloseResFile(self.resref)
+		self.file.close()
+		self.closed = 1
+	
+	def createFond(self):
+		fond_res = Res.Resource("")
+		fond_res.AddResource('FOND', self.res_id, self.fullname)
+		
+		from fontTools import fondLib
+		fond = fondLib.FontFamily(fond_res, "w")
+		
+		fond.ffFirstChar = 0
+		fond.ffLastChar = 255
+		fond.fondClass = 0
+		fond.fontAssoc = [(0, 0, self.res_id)]
+		fond.ffFlags = 20480	# XXX ???
+		fond.ffIntl = (0, 0)
+		fond.ffLeading = 0
+		fond.ffProperty = (0, 0, 0, 0, 0, 0, 0, 0, 0)
+		fond.ffVersion = 0
+		fond.glyphEncoding = {}
+		if self.familyname == self.psname:
+			fond.styleIndices = (1,) * 48  # uh-oh, fondLib is too dumb.
+		else:
+			fond.styleIndices = (2,) * 48
+		fond.styleStrings = []
+		fond.boundingBoxes = None
+		fond.ffFamID = self.res_id
+		fond.changed = 1
+		fond.glyphTableOffset = 0
+		fond.styleMappingReserved = 0
+		
+		# calc:
+		scale = 4096.0 / self.ttFont['head'].unitsPerEm
+		fond.ffAscent = scale * self.ttFont['hhea'].ascent
+		fond.ffDescent = scale * self.ttFont['hhea'].descent
+		fond.ffWidMax = scale * self.ttFont['hhea'].advanceWidthMax
+		
+		fond.ffFamilyName = self.familyname
+		fond.psNames = {0: self.psname}
+		
+		fond.widthTables = {}
+		fond.kernTables = {}
+		cmap = self.ttFont['cmap'].getcmap(1, 0)
+		if cmap:
+			names = {}
+			for code, name in cmap.cmap.items():
+				names[name] = code
+			if self.ttFont.has_key('kern'):
+				kern = self.ttFont['kern'].getkern(0)
+				if kern:
+					fondkerning = []
+					for (left, right), value in kern.kernTable.items():
+						if names.has_key(left) and names.has_key(right):
+							fondkerning.append((names[left], names[right], scale * value))
+					fondkerning.sort()
+					fond.kernTables = {0: fondkerning}
+			if self.ttFont.has_key('hmtx'):
+				hmtx = self.ttFont['hmtx']
+				fondwidths = [2048] * 256 + [0, 0]  # default width, + plus two zeros.
+				for name, (width, lsb) in hmtx.metrics.items():
+					if names.has_key(name):
+						fondwidths[names[name]] = scale * width
+				fond.widthTables = {0: fondwidths}
+		fond.save()
+	
+	def __del__(self):
+		if not self.closed:
+			self.close()
+	
+	def __getattr__(self, attr):
+		# cheap inheritance
+		return getattr(self.file, attr)
+	
+
diff --git a/Lib/fontTools/ttLib/sfnt.py b/Lib/fontTools/ttLib/sfnt.py
new file mode 100644
index 0000000..2fdeb99
--- /dev/null
+++ b/Lib/fontTools/ttLib/sfnt.py
@@ -0,0 +1,230 @@
+"""ttLib/sfnt.py -- low-level module to deal with the sfnt file format.
+
+Defines two public classes:
+	SFNTReader
+	SFNTWriter
+
+(Normally you don't have to use these classes explicitly; they are 
+used automatically by ttLib.TTFont.)
+
+The reading and writing of sfnt files is separated in two distinct 
+classes, since whenever to number of tables changes or whenever
+a table's length chages you need to rewrite the whole file anyway.
+"""
+
+import struct, sstruct
+import Numeric
+import os
+
+class SFNTReader:
+	
+	def __init__(self, file, checkchecksums=1):
+		self.file = file
+		self.checkchecksums = checkchecksums
+		data = self.file.read(sfntDirectorySize)
+		if len(data) <> sfntDirectorySize:
+			from fontTools import ttLib
+			raise ttLib.TTLibError, "Not a TrueType or OpenType font (not enough data)"
+		sstruct.unpack(sfntDirectoryFormat, data, self)
+		if self.sfntVersion not in ("\000\001\000\000", "OTTO", "true"):
+			from fontTools import ttLib
+			raise ttLib.TTLibError, "Not a TrueType or OpenType font (bad sfntVersion)"
+		self.tables = {}
+		for i in range(self.numTables):
+			entry = SFNTDirectoryEntry()
+			entry.fromfile(self.file)
+			self.tables[entry.tag] = entry
+	
+	def has_key(self, tag):
+		return self.tables.has_key(tag)
+	
+	def keys(self):
+		return self.tables.keys()
+	
+	def __getitem__(self, tag):
+		"""Fetch the raw table data."""
+		entry = self.tables[tag]
+		self.file.seek(entry.offset)
+		data = self.file.read(entry.length)
+		if self.checkchecksums:
+			if tag == 'head':
+				# Beh: we have to special-case the 'head' table.
+				checksum = calcchecksum(data[:8] + '\0\0\0\0' + data[12:])
+			else:
+				checksum = calcchecksum(data)
+			if self.checkchecksums > 1:
+				# Be obnoxious, and barf when it's wrong
+				assert checksum == entry.checksum, "bad checksum for '%s' table" % tag
+			elif checksum <> entry.checkSum:
+				# Be friendly, and just print a warning.
+				print "bad checksum for '%s' table" % tag
+		return data
+	
+	def close(self):
+		self.file.close()
+
+
+class SFNTWriter:
+	
+	def __init__(self, file, numTables, sfntVersion="\000\001\000\000"):
+		self.file = file
+		self.numTables = numTables
+		self.sfntVersion = sfntVersion
+		self.searchRange, self.entrySelector, self.rangeShift = getsearchrange(numTables)
+		self.nextTableOffset = sfntDirectorySize + numTables * sfntDirectoryEntrySize
+		# clear out directory area
+		self.file.seek(self.nextTableOffset)
+		# make sure we're actually where we want to be. (XXX old cStringIO bug)
+		self.file.write('\0' * (self.nextTableOffset - self.file.tell()))
+		self.tables = {}
+	
+	def __setitem__(self, tag, data):
+		"""Write raw table data to disk."""
+		if self.tables.has_key(tag):
+			# We've written this table to file before. If the length
+			# of the data is still the same, we allow overwritng it.
+			entry = self.tables[tag]
+			if len(data) <> entry.length:
+				from fontTools import ttLib
+				raise ttLib.TTLibError, "cannot rewrite '%s' table: length does not match directory entry" % tag
+		else:
+			entry = SFNTDirectoryEntry()
+			entry.tag = tag
+			entry.offset = self.nextTableOffset
+			entry.length = len(data)
+			self.nextTableOffset = self.nextTableOffset + ((len(data) + 3) & ~3)
+		self.file.seek(entry.offset)
+		self.file.write(data)
+		self.file.seek(self.nextTableOffset)
+		# make sure we're actually where we want to be. (XXX old cStringIO bug)
+		self.file.write('\0' * (self.nextTableOffset - self.file.tell()))
+		
+		if tag == 'head':
+			entry.checkSum = calcchecksum(data[:8] + '\0\0\0\0' + data[12:])
+		else:
+			entry.checkSum = calcchecksum(data)
+		self.tables[tag] = entry
+	
+	def close(self):
+		"""All tables must have been written to disk. Now write the
+		directory.
+		"""
+		tables = self.tables.items()
+		tables.sort()
+		if len(tables) <> self.numTables:
+			from fontTools import ttLib
+			raise ttLib.TTLibError, "wrong number of tables; expected %d, found %d" % (self.numTables, len(tables))
+		
+		directory = sstruct.pack(sfntDirectoryFormat, self)
+		
+		self.file.seek(sfntDirectorySize)
+		for tag, entry in tables:
+			directory = directory + entry.tostring()
+		self.calcmasterchecksum(directory)
+		self.file.seek(0)
+		self.file.write(directory)
+		self.file.close()
+	
+	def calcmasterchecksum(self, directory):
+		# calculate checkSumAdjustment
+		tags = self.tables.keys()
+		checksums = Numeric.zeros(len(tags)+1)
+		for i in range(len(tags)):
+			checksums[i] = self.tables[tags[i]].checkSum
+		
+		directory_end = sfntDirectorySize + len(self.tables) * sfntDirectoryEntrySize
+		assert directory_end == len(directory)
+		
+		checksums[-1] = calcchecksum(directory)
+		checksum = Numeric.add.reduce(checksums)
+		# BiboAfba!
+		checksumadjustment = Numeric.array(0xb1b0afba) - checksum
+		# write the checksum to the file
+		self.file.seek(self.tables['head'].offset + 8)
+		self.file.write(struct.pack("l", checksumadjustment))
+		
+
+# -- sfnt directory helpers and cruft
+
+sfntDirectoryFormat = """
+		> # big endian
+		sfntVersion: 	4s
+		numTables:		H		# number of tables
+		searchRange:	H		# (max2 <= numTables)*16
+		entrySelector:	H		# log2(max2 <= numTables)
+		rangeShift:		H		# numTables*16-searchRange
+"""
+
+sfntDirectorySize = sstruct.calcsize(sfntDirectoryFormat)
+
+sfntDirectoryEntryFormat = """
+		> # big endian
+		tag:		4s
+		checkSum:	l
+		offset:		l
+		length:		l
+"""
+
+sfntDirectoryEntrySize = sstruct.calcsize(sfntDirectoryEntryFormat)
+
+class SFNTDirectoryEntry:
+	
+	def fromfile(self, file):
+		sstruct.unpack(sfntDirectoryEntryFormat, 
+				file.read(sfntDirectoryEntrySize), self)
+	
+	def fromstring(self, str):
+		sstruct.unpack(sfntDirectoryEntryFormat, str, self)
+	
+	def tostring(self):
+		return sstruct.pack(sfntDirectoryEntryFormat, self)
+	
+	def __repr__(self):
+		if hasattr(self, "tag"):
+			return "<SFNTDirectoryEntry '%s' at %x>" % (self.tag, id(self))
+		else:
+			return "<SFNTDirectoryEntry at %x>" % id(self)
+
+
+def calcchecksum(data, start=0):
+	"""Calculate the checksum for an arbitrary block of data.
+	Optionally takes a 'start' argument, which allows you to
+	calculate a checksum in chunks by feeding it a previous
+	result.
+	
+	If the data length is not a multiple of four, it assumes
+	it is to be padded with null byte. 
+	"""
+	from fontTools import ttLib
+	remainder = len(data) % 4
+	if remainder:
+		data = data + '\0' * (4-remainder)
+	a = Numeric.fromstring(struct.pack(">l", start) + data, Numeric.Int32)
+	if ttLib.endian <> "big":
+		a = a.byteswapped()
+	return Numeric.add.reduce(a)
+
+
+def maxpoweroftwo(x):
+	"""Return the highest exponent of two, so that
+	(2 ** exponent) <= x
+	"""
+	exponent = 0
+	while x:
+		x = x >> 1
+		exponent = exponent + 1
+	return exponent - 1
+
+
+def getsearchrange(n):
+	"""Calculate searchRange, entrySelector, rangeShift for the
+	sfnt directory. 'n' is the number of tables.
+	"""
+	# This stuff needs to be stored in the file, because?
+	import math
+	exponent = maxpoweroftwo(n)
+	searchRange = (2 ** exponent) * 16
+	entrySelector = exponent
+	rangeShift = n * 16 - searchRange
+	return searchRange, entrySelector, rangeShift
+
diff --git a/Lib/fontTools/ttLib/standardGlyphOrder.py b/Lib/fontTools/ttLib/standardGlyphOrder.py
new file mode 100644
index 0000000..4ef2eb4
--- /dev/null
+++ b/Lib/fontTools/ttLib/standardGlyphOrder.py
@@ -0,0 +1,263 @@
+# XXX is this *really* correct?
+
+standardGlyphOrder = [
+	".notdef",				# 0 
+	".null",				# 1 
+	"nonmarkingreturn",		# 2 
+	"space",				# 3 
+	"exclam",				# 4 
+	"quotedbl",				# 5 
+	"numbersign",			# 6 
+	"dollar",				# 7 
+	"percent",				# 8 
+	"ampersand",			# 9 
+	"quotesingle",			# 10 
+	"parenleft",			# 11 
+	"parenright",			# 12 
+	"asterisk",				# 13 
+	"plus",					# 14 
+	"comma",				# 15 
+	"hyphen",				# 16 
+	"period",				# 17 
+	"slash",				# 18 
+	"zero",					# 19 
+	"one",					# 20 
+	"two",					# 21 
+	"three",				# 22 
+	"four",					# 23 
+	"five",					# 24 
+	"six",					# 25 
+	"seven",				# 26 
+	"eight",				# 27 
+	"nine",					# 28 
+	"colon",				# 29 
+	"semicolon",			# 30 
+	"less",					# 31 
+	"equal",				# 32 
+	"greater",				# 33 
+	"question",				# 34 
+	"at",					# 35 
+	"A",					# 36 
+	"B",					# 37 
+	"C",					# 38 
+	"D",					# 39 
+	"E",					# 40 
+	"F",					# 41 
+	"G",					# 42 
+	"H",					# 43 
+	"I",					# 44 
+	"J",					# 45 
+	"K",					# 46 
+	"L",					# 47 
+	"M",					# 48 
+	"N",					# 49 
+	"O",					# 50 
+	"P",					# 51 
+	"Q",					# 52 
+	"R",					# 53 
+	"S",					# 54 
+	"T",					# 55 
+	"U",					# 56 
+	"V",					# 57 
+	"W",					# 58 
+	"X",					# 59 
+	"Y",					# 60 
+	"Z",					# 61 
+	"bracketleft",			# 62 
+	"backslash",			# 63 
+	"bracketright",			# 64 
+	"asciicircum",			# 65 
+	"underscore",			# 66 
+	"grave",				# 67 
+	"a",					# 68 
+	"b",					# 69 
+	"c",					# 70 
+	"d",					# 71 
+	"e",					# 72 
+	"f",					# 73 
+	"g",					# 74 
+	"h",					# 75 
+	"i",					# 76 
+	"j",					# 77 
+	"k",					# 78 
+	"l",					# 79 
+	"m",					# 80 
+	"n",					# 81 
+	"o",					# 82 
+	"p",					# 83 
+	"q",					# 84 
+	"r",					# 85 
+	"s",					# 86 
+	"t",					# 87 
+	"u",					# 88 
+	"v",					# 89 
+	"w",					# 90 
+	"x",					# 91 
+	"y",					# 92 
+	"z",					# 93 
+	"braceleft",			# 94 
+	"bar",					# 95 
+	"braceright",			# 96 
+	"asciitilde",			# 97 
+	"Adieresis",			# 98 
+	"Aring",				# 99 
+	"Ccedilla",				# 100 
+	"Eacute",				# 101 
+	"Ntilde",				# 102 
+	"Odieresis",			# 103 
+	"Udieresis",			# 104 
+	"aacute",				# 105 
+	"agrave",				# 106 
+	"acircumflex",			# 107 
+	"adieresis",			# 108 
+	"atilde",				# 109 
+	"aring",				# 110 
+	"ccedilla",				# 111 
+	"eacute",				# 112 
+	"egrave",				# 113 
+	"ecircumflex",			# 114 
+	"edieresis",			# 115 
+	"iacute",				# 116 
+	"igrave",				# 117 
+	"icircumflex",			# 118 
+	"idieresis",			# 119 
+	"ntilde",				# 120 
+	"oacute",				# 121 
+	"ograve",				# 122 
+	"ocircumflex",			# 123 
+	"odieresis",			# 124 
+	"otilde",				# 125 
+	"uacute",				# 126 
+	"ugrave",				# 127 
+	"ucircumflex",			# 128 
+	"udieresis",			# 129 
+	"dagger",				# 130 
+	"degree",				# 131 
+	"cent",					# 132 
+	"sterling",				# 133 
+	"section",				# 134 
+	"bullet",				# 135 
+	"paragraph",			# 136 
+	"germandbls",			# 137 
+	"registered",			# 138 
+	"copyright",			# 139 
+	"trademark",			# 140 
+	"acute",				# 141 
+	"dieresis",				# 142 
+	"notequal",				# 143 
+	"AE",					# 144 
+	"Oslash",				# 145 
+	"infinity",				# 146 
+	"plusminus",			# 147 
+	"lessequal",			# 148 
+	"greaterequal",			# 149 
+	"yen",					# 150 
+	"mu",					# 151 
+	"partialdiff",			# 152 
+	"summation",			# 153 
+	"product",				# 154 
+	"pi",					# 155 
+	"integral",				# 156 
+	"ordfeminine",			# 157 
+	"ordmasculine",			# 158 
+	"Omega",				# 159 
+	"ae",					# 160 
+	"oslash",				# 161 
+	"questiondown",			# 162 
+	"exclamdown",			# 163 
+	"logicalnot",			# 164 
+	"radical",				# 165 
+	"florin",				# 166 
+	"approxequal",			# 167 
+	"Delta",				# 168 
+	"guillemotleft",		# 169 
+	"guillemotright",		# 170 
+	"ellipsis",				# 171 
+	"nonbreakingspace",		# 172 
+	"Agrave",				# 173 
+	"Atilde",				# 174 
+	"Otilde",				# 175 
+	"OE",					# 176 
+	"oe",					# 177 
+	"endash",				# 178 
+	"emdash",				# 179 
+	"quotedblleft",			# 180 
+	"quotedblright",		# 181 
+	"quoteleft",			# 182 
+	"quoteright",			# 183 
+	"divide",				# 184 
+	"lozenge",				# 185 
+	"ydieresis",			# 186 
+	"Ydieresis",			# 187 
+	"fraction",				# 188
+	"currency",				# 189
+	"guilsinglleft",		# 190 
+	"guilsinglright",		# 191 
+	"fi",					# 192 
+	"fl",					# 193 
+	"daggerdbl",			# 194 
+	"periodcentered",		# 195 
+	"quotesinglbase",		# 196 
+	"quotedblbase",			# 197 
+	"perthousand",			# 198 
+	"Acircumflex",			# 199 
+	"Ecircumflex",			# 200 
+	"Aacute",				# 201 
+	"Edieresis",			# 202 
+	"Egrave",				# 203 
+	"Iacute",				# 204 
+	"Icircumflex",			# 205 
+	"Idieresis",			# 206 
+	"Igrave",				# 207 
+	"Oacute",				# 208 
+	"Ocircumflex",			# 209 
+	"apple",				# 210 
+	"Ograve",				# 211 
+	"Uacute",				# 212 
+	"Ucircumflex",			# 213 
+	"Ugrave",				# 214 
+	"dotlessi",				# 215 
+	"circumflex",			# 216 
+	"tilde",				# 217 
+	"macron",				# 218 
+	"breve",				# 219 
+	"dotaccent",			# 220 
+	"ring",					# 221 
+	"cedilla",				# 222 
+	"hungarumlaut",			# 223 
+	"ogonek",				# 224 
+	"caron",				# 225 
+	"Lslash",				# 226 
+	"lslash",				# 227 
+	"Scaron",				# 228 
+	"scaron",				# 229 
+	"Zcaron",				# 230 
+	"zcaron",				# 231 
+	"brokenbar",			# 232 
+	"Eth",					# 233 
+	"eth",					# 234 
+	"Yacute",				# 235 
+	"yacute",				# 236 
+	"Thorn",				# 237 
+	"thorn",				# 238 
+	"minus",				# 239 
+	"multiply",				# 240 
+	"onesuperior",			# 241 
+	"twosuperior",			# 242 
+	"threesuperior",		# 243 
+	"onehalf",				# 244 
+	"onequarter",			# 245 
+	"threequarters",		# 246 
+	"franc",				# 247 
+	"Gbreve",				# 248 
+	"gbreve",				# 249 
+	"Idotaccent",			# 250 
+	"Scedilla",				# 251 
+	"scedilla",				# 252 
+	"Cacute",				# 253 
+	"cacute",				# 254 
+	"Ccaron",				# 255 
+	"ccaron",				# 256 
+	"dcroat"				# 257 
+]
+
diff --git a/Lib/fontTools/ttLib/tables/C_F_F_.py b/Lib/fontTools/ttLib/tables/C_F_F_.py
new file mode 100644
index 0000000..8148f06
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/C_F_F_.py
@@ -0,0 +1,35 @@
+import DefaultTable
+from fontTools import cffLib
+
+
+class table_C_F_F_(DefaultTable.DefaultTable, cffLib.CFFFontSet):
+	
+	def __init__(self, tag):
+		DefaultTable.DefaultTable.__init__(self, tag)
+		cffLib.CFFFontSet.__init__(self)
+		self._gaveGlyphOrder = 0
+	
+	def decompile(self, data, otFont):
+		self.data = data  # XXX while work is in progress...
+		cffLib.CFFFontSet.decompile(self, data)
+		assert len(self.fonts) == 1, "can't deal with multi-font CFF tables."
+	
+	#def compile(self, otFont):
+	#	xxx
+	
+	def getGlyphOrder(self):
+		if self._gaveGlyphOrder:
+			from fontTools import ttLib
+			raise ttLib.TTLibError, "illegal use of getGlyphOrder()"
+		self._gaveGlyphOrder = 1
+		return self.fonts[self.fontNames[0]].getGlyphOrder()
+	
+	def setGlyphOrder(self, glyphOrder):
+		self.fonts[self.fontNames[0]].setGlyphOrder(glyphOrder)
+	
+	def toXML(self, writer, otFont, progress=None):
+		cffLib.CFFFontSet.toXML(self, writer, progress)
+	
+	#def fromXML(self, (name, attrs, content), otFont):
+	#	xxx
+
diff --git a/Lib/fontTools/ttLib/tables/D_S_I_G_.py b/Lib/fontTools/ttLib/tables/D_S_I_G_.py
new file mode 100644
index 0000000..bea5654
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/D_S_I_G_.py
@@ -0,0 +1,12 @@
+import DefaultTable
+
+class table_D_S_I_G_(DefaultTable.DefaultTable):
+	
+	def toXML(self, xmlWriter, ttFont):
+		xmlWriter.comment("note that the Digital Signature will be invalid after recompilation!")
+		xmlWriter.newline()
+		xmlWriter.begintag("hexdata")
+		xmlWriter.newline()
+		xmlWriter.dumphex(self.compile(ttFont))
+		xmlWriter.endtag("hexdata")
+		xmlWriter.newline()
diff --git a/Lib/fontTools/ttLib/tables/DefaultTable.py b/Lib/fontTools/ttLib/tables/DefaultTable.py
new file mode 100644
index 0000000..745f237
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/DefaultTable.py
@@ -0,0 +1,36 @@
+import string
+import sys
+
+class DefaultTable:
+	
+	dependencies = []
+	
+	def __init__(self, tag):
+		self.tableTag = tag
+	
+	def decompile(self, data, ttFont):
+		self.data = data
+	
+	def compile(self, ttFont):
+		return self.data
+	
+	def toXML(self, writer, ttFont):
+		writer.begintag("hexdata")
+		writer.newline()
+		writer.dumphex(self.compile(ttFont))
+		writer.endtag("hexdata")
+		writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		from fontTools.misc.textTools import readHex
+		from fontTools import ttLib
+		if name <> "hexdata":
+			raise ttLib.TTLibError, "can't handle '%s' element" % name
+		self.decompile(readHex(content), ttFont)
+	
+	def __repr__(self):
+		return "<'%s' table at %x>" % (self.tableTag, id(self))
+	
+	def __cmp__(self, other):
+		return cmp(self.__dict__, other.__dict__)
+
diff --git a/Lib/fontTools/ttLib/tables/G_P_O_S_.py b/Lib/fontTools/ttLib/tables/G_P_O_S_.py
new file mode 100644
index 0000000..7bec887
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/G_P_O_S_.py
@@ -0,0 +1,294 @@
+import otCommon
+
+
+class table_G_P_O_S_(otCommon.base_GPOS_GSUB):
+	
+	def getLookupTypeClass(self, lookupType):
+		return lookupTypeClasses[lookupType]
+
+
+class SinglePos:
+	
+	def decompile(self, reader, otFont):
+		pass
+	
+	def compile(self, otFont):
+		xxx
+	
+	def toXML(self, xmlWriter, otFont):
+		xmlWriter.comment("XXX")
+		xmlWriter.newline()
+			
+	def fromXML(self, (name, attrs, content), otFont):
+		xxx
+
+
+class PairPos:
+	
+	def decompile(self, reader, otFont):
+		self.format = reader.readUShort()
+		if self.format == 1:
+			self.decompileFormat1(reader, otFont)
+		elif self.format == 2:
+			self.decompileFormat2(reader, otFont)
+		else:
+			from fontTools import ttLib
+			raise ttLib.TTLibError, "unknown PairPos format: %d" % self.format
+	
+	def decompileFormat1(self, reader, otFont):
+		coverage = reader.readTable(otCommon.CoverageTable, otFont)
+		glyphNames = coverage.glyphNames
+		valueFactory1 = ValueRecordFactory(reader.readUShort())
+		valueFactory2 = ValueRecordFactory(reader.readUShort())
+		self.pairs = pairs = {}
+		for i in range(reader.readUShort()):
+			firstGlyphName = glyphNames[i]
+			offset = reader.readOffset()
+			setData = reader.getSubString(offset)
+			set = PairSet()
+			set.decompile(setData, otFont, valueFactory1, valueFactory2)
+			pairs[firstGlyphName] = set.values
+	
+	def decompileFormat2(self, reader, otFont):
+		coverage = reader.readTable(otCommon.CoverageTable, otFont)
+		glyphNames = coverage.glyphNames
+		valueFactory1 = ValueRecordFactory(reader.readUShort())
+		valueFactory2 = ValueRecordFactory(reader.readUShort())
+		self.classDef1 = reader.readTable(otCommon.ClassDefinitionTable, otFont)
+		self.classDef2 = reader.readTable(otCommon.ClassDefinitionTable, otFont)
+		class1Count = reader.readUShort()
+		class2Count = reader.readUShort()
+		self.pairs = pairs = {}  # sparse matrix
+		for i in range(class1Count):
+			row = {}
+			for j in range(class2Count):
+				value1 = valueFactory1.getValueRecord(reader)
+				value2 = valueFactory2.getValueRecord(reader)
+				if value1 or value2:
+					row[j] = (value1, value2)
+			if row:
+				pairs[i] = row
+	
+	def compile(self, otFont):
+		xxx
+	
+	def toXML(self, xmlWriter, otFont):
+		if self.format == 1:
+			self.toXMLFormat1(xmlWriter, otFont)
+		elif self.format == 2:
+			self.toXMLFormat2(xmlWriter, otFont)
+		else:
+			from fontTools import ttLib
+			raise ttLib.TTLibError, "unknown PairPos format: %d" % self.format
+	
+	def toXMLFormat1(self, xmlWriter, otFont):
+		pairs = self.pairs.items()
+		pairs.sort()
+		for firstGlyph, secondGlyphs in pairs:
+			for secondGlyph, value1, value2 in secondGlyphs:
+				#XXXXXXXXX
+				xmlWriter.begintag("Pair", first=firstGlyph, second=secondGlyph)
+				xmlWriter.newline()
+				if value1:
+					value1.toXML(xmlWriter, otFont)
+				if value2:
+					value2.toXML(xmlWriter, otFont)
+				xmlWriter.endtag("Pair")
+				xmlWriter.newline()
+	
+	def toXMLFormat2(self, xmlWriter, otFont):
+		xmlWriter.comment("XXX")
+		xmlWriter.newline()
+	
+	def fromXML(self, (name, attrs, content), otFont):
+		xxx
+
+
+class PairSet:
+	
+	def decompile(self, reader, otFont, valueFactory1, valueFactory2):
+		pairValueCount = reader.readUShort()
+		self.values = values = []
+		for j in range(pairValueCount):
+			secondGlyphID = reader.readUShort()
+			secondGlyphName = otFont.getGlyphName(secondGlyphID)
+			value1 = valueFactory1.getValueRecord(reader)
+			value2 = valueFactory2.getValueRecord(reader)
+			values.append((secondGlyphName, value1, value2))
+	
+	def compile(self, otFont):
+		xxx
+
+#
+# ------------------
+#
+
+class CursivePos:
+	
+	def decompile(self, reader, otFont):
+		pass
+	
+	def compile(self, otFont):
+		xxx
+	
+	def toXML(self, xmlWriter, otFont):
+		xmlWriter.comment("XXX")
+		xmlWriter.newline()
+
+
+class MarkBasePos:
+	
+	def decompile(self, reader, otFont):
+		pass
+	
+	def compile(self, otFont):
+		xxx
+	
+	def toXML(self, xmlWriter, otFont):
+		xmlWriter.comment("XXX")
+		xmlWriter.newline()
+
+
+class MarkLigPos:
+	
+	def decompile(self, reader, otFont):
+		pass
+	
+	def compile(self, otFont):
+		xxx
+	
+	def toXML(self, xmlWriter, otFont):
+		xmlWriter.comment("XXX")
+		xmlWriter.newline()
+
+
+class MarkMarkPos:
+	
+	def decompile(self, reader, otFont):
+		pass
+	
+	def compile(self, otFont):
+		xxx
+	
+	def toXML(self, xmlWriter, otFont):
+		xmlWriter.comment("XXX")
+		xmlWriter.newline()
+
+
+class ContextPos:
+	
+	def decompile(self, reader, otFont):
+		pass
+	
+	def compile(self, otFont):
+		xxx
+	
+	def toXML(self, xmlWriter, otFont):
+		xmlWriter.comment("XXX")
+		xmlWriter.newline()
+
+
+class ChainContextPos:
+	
+	def decompile(self, reader, otFont):
+		pass
+	
+	def compile(self, otFont):
+		xxx
+	
+	def toXML(self, xmlWriter, otFont):
+		xmlWriter.comment("XXX")
+		xmlWriter.newline()
+
+
+lookupTypeClasses = {
+	1: SinglePos,
+	2: PairPos,
+	3: CursivePos,
+	4: MarkBasePos,
+	5: MarkLigPos,
+	6: MarkMarkPos,
+	7: ContextPos,
+	8: ChainContextPos,
+}
+
+
+valueRecordFormat = [
+#	Mask	 Name		     struct format char
+	(0x0001, "XPlacement",   "h"),
+	(0x0002, "YPlacement",   "h"),
+	(0x0004, "XAdvance",     "h"),
+	(0x0008, "YAdvance",     "h"),
+	(0x0010, "XPlaDevice",   "H"),
+	(0x0020, "YPlaDevice",   "H"),
+	(0x0040, "XAdvDevice",   "H"),
+	(0x0080, "YAdvDevice",   "H"),
+# 	reserved:
+	(0x0100, "Reserved1",    "H"),
+	(0x0200, "Reserved2",    "H"),
+	(0x0400, "Reserved3",    "H"),
+	(0x0800, "Reserved4",    "H"),
+	(0x1000, "Reserved5",    "H"),
+	(0x2000, "Reserved6",    "H"),
+	(0x4000, "Reserved7",    "H"),
+	(0x8000, "Reserved8",    "H"),
+]
+
+
+class ValueRecordFactory:
+	
+	def __init__(self, valueFormat):
+		format = ">"
+		names = []
+		for mask, name, formatChar in valueRecordFormat:
+			if valueFormat & mask:
+				names.append(name)
+				format = format + formatChar
+		self.names, self.format = names, format
+		self.size = 2 * len(names)
+	
+	def getValueRecord(self, reader):
+		names = self.names
+		if not names:
+			return None
+		values = reader.readStruct(self.format, self.size)
+		values = map(int, values)
+		valueRecord = ValueRecord()
+		items = map(None, names, values)
+		for name, value in items:
+			setattr(valueRecord, name, value)
+		return valueRecord
+
+
+class ValueRecord:
+	# see ValueRecordFactory
+	
+	def __nonzero__(self):
+		for value in self.__dict__.values():
+			if value:
+				return 1
+		return 0
+			
+	def toXML(self, xmlWriter, otFont):
+		simpleItems = []
+		for mask, name, format in valueRecordFormat[:4]:  # "simple" values
+			if hasattr(self, name):
+				simpleItems.append((name, getattr(self, name)))
+		deviceItems = []
+		for mask, name, format in valueRecordFormat[4:8]:  # device records
+			if hasattr(self, name):
+				deviceItems.append((name, getattr(self, name)))
+		if deviceItems:
+			xmlWriter.begintag("ValueRecord", simpleItems)
+			xmlWriter.newline()
+			for name, deviceRecord in deviceItems:
+				xxx
+			xmlWriter.endtag("ValueRecord")
+			xmlWriter.newline()
+		else:
+			xmlWriter.simpletag("ValueRecord", simpleItems)
+			xmlWriter.newline()
+	
+	def __repr__(self):
+		return "<ValueRecord>"
+
diff --git a/Lib/fontTools/ttLib/tables/G_S_U_B_.py b/Lib/fontTools/ttLib/tables/G_S_U_B_.py
new file mode 100644
index 0000000..d0c4dce
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/G_S_U_B_.py
@@ -0,0 +1,283 @@
+import otCommon
+
+
+class table_G_S_U_B_(otCommon.base_GPOS_GSUB):
+	
+	def getLookupTypeClass(self, lookupType):
+		return lookupTypeClasses[lookupType]
+
+
+class SingleSubst:
+	
+	def decompile(self, reader, otFont):
+		self.format = reader.readUShort()
+		if self.format == 1:
+			self.decompileFormat1(reader, otFont)
+		elif self.format == 2:
+			self.decompileFormat2(reader, otFont)
+		else:
+			from fontTools import ttLib
+			raise ttLib.TTLibError, "unknown SingleSub format: %d" % self.format
+	
+	def decompileFormat1(self, reader, otFont):
+		coverage = reader.readTable(otCommon.CoverageTable, otFont)
+		glyphIDs = coverage.getGlyphIDs()
+		glyphNames = coverage.getGlyphNames()
+		self.substitutions = substitutions = {}
+		deltaGlyphID = reader.readShort()
+		for i in range(len(glyphIDs)):
+			input = glyphNames[i]
+			output = otFont.getGlyphName(glyphIDs[i] + deltaGlyphID)
+			substitutions[input] = output
+	
+	def decompileFormat2(self, reader, otFont):
+		coverage = reader.readTable(otCommon.CoverageTable, otFont)
+		glyphNames = coverage.getGlyphNames()
+		glyphCount = reader.readUShort()
+		self.substitutions = substitutions = {}
+		for i in range(glyphCount):
+			glyphID = reader.readUShort()
+			output = otFont.getGlyphName(glyphID)
+			input = glyphNames[i]
+			substitutions[input] = output
+	
+	def compile(self, otFont):
+		xxx
+	
+	def toXML(self, xmlWriter, otFont):
+		substitutions = self.substitutions.items()
+		substitutions.sort()
+		for input, output in substitutions:
+			xmlWriter.simpletag("Subst", [("in", input), ("out", output)])
+			xmlWriter.newline()
+	
+	def fromXML(self, (name, attrs, content), otFont):
+		xxx
+
+
+class MultipleSubst:
+	
+	def decompile(self, reader, otFont):
+		format = reader.readUShort()
+		if format <> 1:
+			from fontTools import ttLib
+			raise ttLib.TTLibError, "unknown MultipleSubst format: %d" % format
+		glyphNames = reader.readTable(otCommon.CoverageTable, otFont).getGlyphNames()
+		sequenceCount = reader.readUShort()
+		self.substitutions = substitutions = {}
+		for i in range(sequenceCount):
+			sequence = reader.readTable(Sequence, otFont)
+			substitutions[glyphNames[i]] = sequence.glyphs
+	
+	def compile(self, otFont):
+		xxx
+	
+	def toXML(self, xmlWriter, otFont):
+		import string
+		items = self.substitutions.items()
+		items.sort()
+		for input, output in items:
+			xmlWriter.simpletag("Subst", [("in", input), ("out", string.join(output, ","))])
+			xmlWriter.newline()
+
+
+class Sequence:
+	
+	def decompile(self, reader, otFont):
+		self.glyphs = []
+		for i in range(reader.readUShort()):
+			self.glyphs.append(otFont.getGlyphName(reader.readUShort()))
+	
+	def compile(self, otFont):
+		xxx
+
+
+class AlternateSubst:
+	
+	def decompile(self, reader, otFont):
+		format = reader.readUShort()
+		if format <> 1:
+			from fontTools import ttLib
+			raise ttLib.TTLibError, "unknown AlternateSubst format: %d" % format
+		coverage = reader.readTable(otCommon.CoverageTable, otFont)
+		glyphNames = coverage.getGlyphNames()
+		alternateSetCount = reader.readUShort()
+		self.alternateSet = alternateSet = {}
+		for i in range(alternateSetCount):
+			set = reader.readTable(AlternateSet, otFont)
+			alternateSet[glyphNames[i]] = set.glyphs
+	
+	def compile(self, otFont):
+		xxx
+	
+	def toXML(self, xmlWriter, otFont):
+		alternates = self.alternateSet.items()
+		alternates.sort()
+		for input, substList in alternates:
+			xmlWriter.begintag("AlternateSet", [("in", input)])
+			xmlWriter.newline()
+			for output in substList:
+				xmlWriter.simpletag("Subst", out=output)
+				xmlWriter.newline()
+			xmlWriter.endtag("AlternateSet")
+			xmlWriter.newline()
+
+
+class AlternateSet:
+	
+	def decompile(self, reader, otFont):
+		glyphCount = reader.readUShort()
+		glyphIDs = reader.readUShortArray(glyphCount)
+		self.glyphs = map(otFont.getGlyphName, glyphIDs)
+	
+	def compile(self, otFont):
+		xxx
+
+
+class LigatureSubst:
+	
+	def decompile(self, reader, otFont):
+		format = reader.readUShort()
+		if format <> 1:
+			from fontTools import ttLib
+			raise ttLib.TTLibError, "unknown LigatureSubst format: %d" % format
+		coverage = reader.readTable(otCommon.CoverageTable, otFont)
+		glyphNames = coverage.getGlyphNames()
+		ligSetCount = reader.readUShort()
+		self.ligatures = ligatures = []
+		for i in range(ligSetCount):
+			firstGlyph = glyphNames[i]
+			ligSet = reader.readTable(LigatureSet, otFont)
+			for ligatureGlyph, components in ligSet.ligatures:
+				ligatures.append(((firstGlyph,) + tuple(components)), ligatureGlyph)
+	
+	def compile(self, otFont):
+		xxx
+	
+	def toXML(self, xmlWriter, otFont):
+		import string
+		for input, output in self.ligatures:
+			xmlWriter.simpletag("Subst", [("in", string.join(input, ",")), ("out", output)])
+			xmlWriter.newline()
+
+
+class LigatureSet:
+	
+	def decompile(self, reader, otFont):
+		ligatureCount = reader.readUShort()
+		self.ligatures = ligatures = []
+		for i in range(ligatureCount):
+			lig = reader.readTable(Ligature, otFont)
+			ligatures.append((lig.ligatureGlyph, lig.components))
+	
+	def compile(self, otFont):
+		xxx
+
+
+class Ligature:
+	
+	def decompile(self, reader, otFont):
+		self.ligatureGlyph = otFont.getGlyphName(reader.readUShort())
+		compCount = reader.readUShort()
+		self.components = components = []
+		for i in range(compCount-1):
+			components.append(otFont.getGlyphName(reader.readUShort()))
+	
+	def compile(self, otFont):
+		xxx
+
+
+class ContextSubst:
+	
+	def decompile(self, reader, otFont):
+		format = reader.readUShort()
+		if format == 1:
+			self.decompileFormat1(reader, otFont)
+		elif format == 2:
+			self.decompileFormat2(reader, otFont)
+		elif format == 3:
+			self.decompileFormat3(reader, otFont)
+		else:
+			from fontTools import ttLib
+			raise ttLib.TTLibError, "unknown ContextSubst format: %d" % format
+	
+	def decompileFormat1(self, reader, otFont):
+		xxx
+	
+	def decompileFormat2(self, reader, otFont):
+		xxx
+	
+	def decompileFormat3(self, reader, otFont):
+		glyphCount = reader.readUShort()
+		substCount = reader.readUShort()
+		coverage = []
+		for i in range(glyphCount):
+			coverage.append(reader.readTable(otCommon.CoverageTable, otFont))
+		self.substitutions = substitutions = []
+		for i in range(substCount):
+			lookupRecord = SubstLookupRecord()
+			lookupRecord.decompile(reader, otFont)
+			substitutions.append((coverage[i].getGlyphNames(), lookupRecord))
+	
+	def compile(self, otFont):
+		xxx
+	
+	def toXML(self, xmlWriter, otFont):
+		xmlWriter.comment("XXX")
+		xmlWriter.newline()
+
+
+class ChainContextSubst:
+	
+	def decompile(self, reader, otFont):
+		self.format = reader.readUShort()
+		if self.format == 1:
+			self.decompileFormat1(reader, otFont)
+		elif self.format == 2:
+			self.decompileFormat2(reader, otFont)
+		elif self.format == 3:
+			self.decompileFormat3(reader, otFont)
+		else:
+			from fontTools import ttLib
+			raise ttLib.TTLibError, "unknown ChainContextSubst format: %d" % self.format
+	
+	def decompileFormat1(self, reader, otFont):
+		pass
+	
+	def decompileFormat2(self, reader, otFont):
+		pass
+	
+	def decompileFormat3(self, reader, otFont):
+		pass
+		
+	def compile(self, otFont):
+		xxx
+	
+	def toXML(self, xmlWriter, otFont):
+		xmlWriter.comment("XXX")
+		xmlWriter.newline()
+
+
+lookupTypeClasses = {
+	1: SingleSubst,
+	2: MultipleSubst,
+	3: AlternateSubst,
+	4: LigatureSubst,
+	5: ContextSubst,
+	6: ChainContextSubst,
+}
+
+
+#
+# Shared classes
+#
+
+class SubstLookupRecord:
+	
+	def decompile(self, reader, otFont):
+		self.sequenceIndex = reader.readUShort()
+		self.lookupListIndex = reader.readUShort()
+	
+	def compile(self, otFont):
+		xxx
+
diff --git a/Lib/fontTools/ttLib/tables/L_T_S_H_.py b/Lib/fontTools/ttLib/tables/L_T_S_H_.py
new file mode 100644
index 0000000..20701d6
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/L_T_S_H_.py
@@ -0,0 +1,50 @@
+import DefaultTable
+import array
+import struct
+from fontTools.misc.textTools import safeEval
+
+# XXX I've lowered the strictness, to make sure Apple's own Chicago
+# XXX gets through. They're looking into it, I hope to raise the standards
+# XXX back to normal eventually.
+
+class table_L_T_S_H_(DefaultTable.DefaultTable):
+	
+	def decompile(self, data, ttFont):
+		version, numGlyphs = struct.unpack(">HH", data[:4])
+		data = data[4:]
+		assert version == 0
+		assert len(data) == numGlyphs
+		# ouch: the assertion is not true in Chicago!
+		#assert numGlyphs == ttFont['maxp'].numGlyphs
+		yPels = array.array("B")
+		yPels.fromstring(data)
+		self.yPels = {}
+		for i in range(numGlyphs):
+			self.yPels[ttFont.getGlyphName(i)] = yPels[i]
+	
+	def compile(self, ttFont):
+		version = 0
+		names = self.yPels.keys()
+		numGlyphs = len(names)
+		yPels = [0] * numGlyphs
+		# ouch: the assertion is not true in Chicago!
+		#assert len(self.yPels) == ttFont['maxp'].numGlyphs == numGlyphs
+		for name in names:
+			yPels[ttFont.getGlyphID(name)] = self.yPels[name]
+		yPels = array.array("B", yPels)
+		return struct.pack(">HH", version, numGlyphs) + yPels.tostring()
+	
+	def toXML(self, writer, ttFont):
+		names = self.yPels.keys()
+		names.sort()
+		for name in names:
+			writer.simpletag("yPel", name=name, value=self.yPels[name])
+			writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		if not hasattr(self, "yPels"):
+			self.yPels = {}
+		if name <> "yPel":
+			return # ignore unknown tags
+		self.yPels[attrs["name"]] = safeEval(attrs["value"])
+
diff --git a/Lib/fontTools/ttLib/tables/O_S_2f_2.py b/Lib/fontTools/ttLib/tables/O_S_2f_2.py
new file mode 100644
index 0000000..498275f
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/O_S_2f_2.py
@@ -0,0 +1,164 @@
+import DefaultTable
+import sstruct
+from fontTools.misc.textTools import safeEval, num2binary, binary2num
+
+# panose classification
+
+panoseFormat = """
+	bFamilyType:		B
+	bSerifStyle:		B
+	bWeight:			B
+	bProportion:		B
+	bContrast:			B
+	bStrokeVariation:	B
+	bArmStyle:			B
+	bLetterForm:		B
+	bMidline:			B
+	bXHeight:			B
+"""
+
+class Panose:
+	
+	def toXML(self, writer, ttFont):
+		formatstring, names, fixes = sstruct.getformat(panoseFormat)
+		for name in names:
+			writer.simpletag(name, value=getattr(self, name))
+			writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		setattr(self, name, safeEval(attrs["value"]))
+
+
+# 'sfnt' OS/2 and Windows Metrics table - 'OS/2'
+
+OS2_format_0 = """
+	>	# big endian
+	version:				H		# version
+	xAvgCharWidth:			h		# average character width
+	usWeightClass:			H		# degree of thickness of strokes
+	usWidthClass:			H		# aspect ratio
+	fsType:					h		# type flags
+	ySubscriptXSize:		h		# subscript horizontal font size
+	ySubscriptYSize:		h		# subscript vertical font size
+	ySubscriptXOffset:		h		# subscript x offset
+	ySubscriptYOffset:		h		# subscript y offset
+	ySuperscriptXSize:		h		# superscript horizontal font size
+	ySuperscriptYSize:		h		# superscript vertical font size
+	ySuperscriptXOffset:	h		# superscript x offset
+	ySuperscriptYOffset:	h		# superscript y offset
+	yStrikeoutSize:			h		# strikeout size
+	yStrikeoutPosition:		h		# strikeout position
+	sFamilyClass:			h		# font family class and subclass
+	panose: 				10s		# panose classification number
+	ulUnicodeRange1:		l		# character range
+	ulUnicodeRange2:		l		# character range
+	ulUnicodeRange3:		l		# character range
+	ulUnicodeRange4:		l		# character range
+	achVendID:				4s		# font vendor identification
+	fsSelection:			H		# font selection flags
+	fsFirstCharIndex:		H		# first unicode character index
+	fsLastCharIndex:		H		# last unicode character index
+	usTypoAscender:			H		# typographic ascender
+	usTypoDescender:		H		# typographic descender
+	usTypoLineGap:			H		# typographic line gap
+	usWinAscent:			H		# Windows ascender
+	usWinDescent:			H		# Windows descender
+"""
+
+OS2_format_1_addition =  """
+	ulCodePageRange1:	l
+	ulCodePageRange2:	l	
+"""
+
+OS2_format_2_addition =  OS2_format_1_addition + """
+	sxHeight:			h
+	sCapHeight:			h
+	usDefaultChar:		H
+	usBreakChar:		H
+	usMaxContex:		H
+"""
+
+bigendian = "	>	# big endian\n"
+
+OS2_format_1 = OS2_format_0 + OS2_format_1_addition
+OS2_format_2 = OS2_format_0 + OS2_format_2_addition
+OS2_format_1_addition = bigendian + OS2_format_1_addition
+OS2_format_2_addition = bigendian + OS2_format_2_addition
+
+
+class table_O_S_2f_2(DefaultTable.DefaultTable):
+	
+	"""the OS/2 table"""
+	
+	def decompile(self, data, ttFont):
+		dummy, data = sstruct.unpack2(OS2_format_0, data, self)
+		if self.version == 1:
+			sstruct.unpack(OS2_format_1_addition, data, self)
+		elif self.version == 2:
+			sstruct.unpack(OS2_format_2_addition, data, self)
+		elif self.version <> 0:
+			from fontTools import ttLib
+			raise ttLib.TTLibError, "unknown format for OS/2 table: version %s" % self.version
+		self.panose = sstruct.unpack(panoseFormat, self.panose, Panose())
+	
+	def compile(self, ttFont):
+		panose = self.panose
+		self.panose = sstruct.pack(panoseFormat, self.panose)
+		if self.version == 0:
+			data = sstruct.pack(OS2_format_0, self)
+		elif self.version == 1:
+			data = sstruct.pack(OS2_format_1, self)
+		elif self.version == 2:
+			data = sstruct.pack(OS2_format_2, self)
+		else:
+			from fontTools import ttLib
+			raise ttLib.TTLibError, "unknown format for OS/2 table: version %s" % self.version
+		self.panose = panose
+		return data
+	
+	def toXML(self, writer, ttFont):
+		if self.version == 1:
+			format = OS2_format_1
+		elif self.version == 2:
+			format = OS2_format_2
+		else:
+			format = OS2_format_0
+		formatstring, names, fixes = sstruct.getformat(format)
+		for name in names:
+			value = getattr(self, name)
+			if type(value) == type(0L):
+				value = int(value)
+			if name=="panose":
+				writer.begintag("panose")
+				writer.newline()
+				value.toXML(writer, ttFont)
+				writer.endtag("panose")
+			elif name in ("ulUnicodeRange1", "ulUnicodeRange2", 
+					"ulUnicodeRange3", "ulUnicodeRange4",
+					"ulCodePageRange1", "ulCodePageRange2"):
+				writer.simpletag(name, value=num2binary(value))
+			elif name in ("fsType", "fsSelection"):
+				writer.simpletag(name, value=num2binary(value, 16))
+			elif name == "achVendID":
+				writer.simpletag(name, value=repr(value)[1:-1])
+			else:
+				writer.simpletag(name, value=value)
+			writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		if name == "panose":
+			self.panose = panose = Panose()
+			for element in content:
+				if type(element) == type(()):
+					panose.fromXML(element, ttFont)
+		elif name in ("ulUnicodeRange1", "ulUnicodeRange2", 
+				"ulUnicodeRange3", "ulUnicodeRange4",
+				"ulCodePageRange1", "ulCodePageRange2",
+				"fsType", "fsSelection"):
+			setattr(self, name, binary2num(attrs["value"]))
+		elif name == "achVendID":
+			setattr(self, name, safeEval("'''" + attrs["value"] + "'''"))
+		else:
+			setattr(self, name, safeEval(attrs["value"]))
+
+
diff --git a/Lib/fontTools/ttLib/tables/T_S_I__0.py b/Lib/fontTools/ttLib/tables/T_S_I__0.py
new file mode 100644
index 0000000..988d29a
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/T_S_I__0.py
@@ -0,0 +1,45 @@
+import DefaultTable
+import struct
+
+tsi0Format = '>HHl'
+
+def fixlongs((glyphID, textLength, textOffset)):
+	return int(glyphID), int(textLength), textOffset	
+
+
+class table_T_S_I__0(DefaultTable.DefaultTable):
+	
+	dependencies = ["TSI1"]
+	
+	def decompile(self, data, ttFont):
+		numGlyphs = ttFont['maxp'].numGlyphs
+		indices = []
+		size = struct.calcsize(tsi0Format)
+		for i in range(numGlyphs + 5):
+			glyphID, textLength, textOffset = fixlongs(struct.unpack(tsi0Format, data[:size]))
+			indices.append((glyphID, textLength, textOffset))
+			data = data[size:]
+		assert len(data) == 0
+		assert indices[-5] == (0XFFFE, 0, 0xABFC1F34), "bad magic number"
+		self.indices = indices[:-5]
+		self.extra_indices = indices[-4:]
+	
+	def compile(self, ttFont):
+		data = ""
+		size = struct.calcsize(tsi0Format)
+		for index, textLength, textOffset in self.indices:
+			data = data + struct.pack(tsi0Format, index, textLength, textOffset)
+		data = data + struct.pack(tsi0Format, 0XFFFE, 0, 0xABFC1F34)
+		for index, textLength, textOffset in self.extra_indices:
+			data = data + struct.pack(tsi0Format, index, textLength, textOffset)
+		return data
+	
+	def set(self, indices, extra_indices):
+		# gets called by 'TSI1' or 'TSI3'
+		self.indices = indices
+		self.extra_indices = extra_indices
+	
+	def toXML(self, writer, ttFont):
+		writer.comment("This table will be calculated by the compiler")
+		writer.newline()
+
diff --git a/Lib/fontTools/ttLib/tables/T_S_I__1.py b/Lib/fontTools/ttLib/tables/T_S_I__1.py
new file mode 100644
index 0000000..8ee4e16
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/T_S_I__1.py
@@ -0,0 +1,116 @@
+import DefaultTable
+import string
+
+class table_T_S_I__1(DefaultTable.DefaultTable):
+	
+	extras = {0xfffa: "ppgm", 0xfffb: "cvt", 0xfffc: "reserved", 0xfffd: "fpgm"}
+	
+	indextable = "TSI0"
+	
+	def decompile(self, data, ttFont):
+		indextable = ttFont[self.indextable]
+		self.glyphPrograms = {}
+		for i in range(len(indextable.indices)):
+			glyphID, textLength, textOffset = indextable.indices[i]
+			if textLength == 0x8000:
+				# Ugh. Hi Beat!
+				textLength = indextable.indices[i+1][1]
+			if textLength > 0x8000:
+				pass  # XXX Hmmm.
+			text = data[textOffset:textOffset+textLength]
+			assert len(text) == textLength
+			if text:
+				self.glyphPrograms[ttFont.getGlyphName(glyphID)] = text
+		
+		self.extraPrograms = {}
+		for i in range(len(indextable.extra_indices)):
+			extraCode, textLength, textOffset = indextable.extra_indices[i]
+			if textLength == 0x8000:
+				if extraName == "fpgm":	# this is the last one
+					textLength = len(data) - textOffset
+				else:
+					textLength = indextable.extra_indices[i+1][1]
+			text = data[textOffset:textOffset+textLength]
+			assert len(text) == textLength
+			if text:
+				self.extraPrograms[self.extras[extraCode]] = text
+	
+	def compile(self, ttFont):
+		data = ''
+		indextable = ttFont[self.indextable]
+		glyphNames = ttFont.getGlyphOrder()
+		
+		indices = []
+		for i in range(len(glyphNames)):
+			if len(data) % 2:
+				data = data + "\015"  # align on 2-byte boundaries, fill with return chars. Yum.
+			name = glyphNames[i]
+			if self.glyphPrograms.has_key(name):
+				text = self.glyphPrograms[name]
+			else:
+				text = ""
+			textLength = len(text)
+			if textLength >= 0x8000:
+				textLength = 0x8000  # XXX ???
+			indices.append((i, textLength, len(data)))
+			data = data + text
+		
+		extra_indices = []
+		codes = self.extras.items()
+		codes.sort()
+		for i in range(len(codes)):
+			if len(data) % 2:
+				data = data + "\015"  # align on 2-byte boundaries, fill with return chars.
+			code, name = codes[i]
+			if self.extraPrograms.has_key(name):
+				text = self.extraPrograms[name]
+			else:
+				text = ""
+			textLength = len(text)
+			if textLength >= 0x8000:
+				textLength = 0x8000  # XXX ???
+			extra_indices.append((code, textLength, len(data)))
+			data = data + text
+		indextable.set(indices, extra_indices)
+		return data
+	
+	def toXML(self, writer, ttFont):
+		names = self.glyphPrograms.keys()
+		names.sort()
+		writer.newline()
+		for name in names:
+			text = self.glyphPrograms[name]
+			if not text:
+				continue
+			writer.begintag("glyphProgram", name=name)
+			writer.newline()
+			writer.write_noindent(string.replace(text, "\r", "\n"))
+			writer.newline()
+			writer.endtag("glyphProgram")
+			writer.newline()
+			writer.newline()
+		extra_names = self.extraPrograms.keys()
+		extra_names.sort()
+		for name in extra_names:
+			text = self.extraPrograms[name]
+			if not text:
+				continue
+			writer.begintag("extraProgram", name=name)
+			writer.newline()
+			writer.write_noindent(string.replace(text, "\r", "\n"))
+			writer.newline()
+			writer.endtag("extraProgram")
+			writer.newline()
+			writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		if not hasattr(self, "glyphPrograms"):
+			self.glyphPrograms = {}
+			self.extraPrograms = {}
+		lines = string.split(string.replace(string.join(content, ""), "\r", "\n"), "\n")
+		text = string.join(lines[1:-1], "\r")
+		if name == "glyphProgram":
+			self.glyphPrograms[attrs["name"]] = text
+		elif name == "extraProgram":
+			self.extraPrograms[attrs["name"]] = text
+
diff --git a/Lib/fontTools/ttLib/tables/T_S_I__2.py b/Lib/fontTools/ttLib/tables/T_S_I__2.py
new file mode 100644
index 0000000..15c02ab
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/T_S_I__2.py
@@ -0,0 +1,8 @@
+from fontTools import ttLib
+
+superclass = ttLib.getTableClass("TSI0")
+
+class table_T_S_I__2(superclass):
+	
+	dependencies = ["TSI3"]
+
diff --git a/Lib/fontTools/ttLib/tables/T_S_I__3.py b/Lib/fontTools/ttLib/tables/T_S_I__3.py
new file mode 100644
index 0000000..eb4087c
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/T_S_I__3.py
@@ -0,0 +1,11 @@
+from fontTools import ttLib
+
+superclass = ttLib.getTableClass("TSI1")
+
+class table_T_S_I__3(superclass):
+	
+	extras = {0xfffa: "reserved0", 0xfffb: "reserved1", 0xfffc: "reserved2", 0xfffd: "reserved3"}
+	
+	indextable = "TSI2"
+
+
diff --git a/Lib/fontTools/ttLib/tables/T_S_I__5.py b/Lib/fontTools/ttLib/tables/T_S_I__5.py
new file mode 100644
index 0000000..35b9ee1
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/T_S_I__5.py
@@ -0,0 +1,42 @@
+import DefaultTable
+import array
+from fontTools import ttLib
+from fontTools.misc.textTools import safeEval
+
+
+class table_T_S_I__5(DefaultTable.DefaultTable):
+	
+	def decompile(self, data, ttFont):
+		numGlyphs = ttFont['maxp'].numGlyphs
+		assert len(data) == 2 * numGlyphs
+		a = array.array("H")
+		a.fromstring(data)
+		if ttLib.endian <> "big":
+			a.byteswap()
+		self.glyphGrouping = {}
+		for i in range(numGlyphs):
+			self.glyphGrouping[ttFont.getGlyphName(i)] = a[i]
+	
+	def compile(self, ttFont):
+		glyphNames = ttFont.getGlyphOrder()
+		a = array.array("H")
+		for i in range(len(glyphNames)):
+			a.append(self.glyphGrouping[glyphNames[i]])
+		if ttLib.endian <> "big":
+			a.byteswap()
+		return a.tostring()
+	
+	def toXML(self, writer, ttFont):
+		names = self.glyphGrouping.keys()
+		names.sort()
+		for glyphName in names:
+			writer.simpletag("glyphgroup", name=glyphName, value=self.glyphGrouping[glyphName])
+			writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		if not hasattr(self, "glyphGrouping"):
+			self.glyphGrouping = {}
+		if name <> "glyphgroup":
+			return
+		self.glyphGrouping[attrs["name"]] = safeEval(attrs["value"])
+
diff --git a/Lib/fontTools/ttLib/tables/__init__.py b/Lib/fontTools/ttLib/tables/__init__.py
new file mode 100644
index 0000000..2f17637
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/__init__.py
@@ -0,0 +1 @@
+# dummy file, so Python knows ttLib.tables is a subpackage
diff --git a/Lib/fontTools/ttLib/tables/_c_m_a_p.py b/Lib/fontTools/ttLib/tables/_c_m_a_p.py
new file mode 100644
index 0000000..b067ac6
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/_c_m_a_p.py
@@ -0,0 +1,397 @@
+import DefaultTable
+import struct
+import string
+import array
+from fontTools import ttLib
+from fontTools.misc.textTools import safeEval, readHex
+
+
+class table__c_m_a_p(DefaultTable.DefaultTable):
+	
+	def getcmap(self, platformID, platEncID):
+		for subtable in self.tables:
+			if (subtable.platformID == platformID and 
+					subtable.platEncID == platEncID):
+				return subtable
+		return None # not found
+	
+	def decompile(self, data, ttFont):
+		tableVersion, numSubTables = struct.unpack(">HH", data[:4])
+		self.tableVersion = int(tableVersion)
+		self.tables = tables = []
+		for i in range(numSubTables):
+			platformID, platEncID, offset = struct.unpack(
+					">HHl", data[4+i*8:4+(i+1)*8])
+			platformID, platEncID = int(platformID), int(platEncID)
+			format, length = struct.unpack(">HH", data[offset:offset+4])
+			if not cmap_classes.has_key(format):
+				table = cmap_format_unknown(format)
+			else:
+				table = cmap_classes[format](format)
+			table.platformID = platformID
+			table.platEncID = platEncID
+			table.decompile(data[offset:offset+int(length)], ttFont)
+			tables.append(table)
+	
+	def compile(self, ttFont):
+		self.tables.sort()    # sort according to the spec; see CmapSubtable.__cmp__()
+		numSubTables = len(self.tables)
+		totalOffset = 4 + 8 * numSubTables
+		data = struct.pack(">HH", self.tableVersion, numSubTables)
+		tableData = ""
+		done = {}  # remember the data so we can reuse the "pointers"
+		for table in self.tables:
+			chunk = table.compile(ttFont)
+			if done.has_key(chunk):
+				offset = done[chunk]
+			else:
+				offset = done[chunk] = totalOffset + len(tableData)
+			tableData = tableData + chunk
+			data = data + struct.pack(">HHl", table.platformID, table.platEncID, offset)
+		return data + tableData
+	
+	def toXML(self, writer, ttFont):
+		writer.simpletag("tableVersion", version=self.tableVersion)
+		writer.newline()
+		for table in self.tables:
+			table.toXML(writer, ttFont)
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		if name == "tableVersion":
+			self.tableVersion = safeEval(attrs["version"])
+			return
+		if name[:12] <> "cmap_format_":
+			return
+		if not hasattr(self, "tables"):
+			self.tables = []
+		format = safeEval(name[12])
+		if not cmap_classes.has_key(format):
+			table = cmap_format_unknown(format)
+		else:
+			table = cmap_classes[format](format)
+		table.platformID = safeEval(attrs["platformID"])
+		table.platEncID = safeEval(attrs["platEncID"])
+		table.fromXML((name, attrs, content), ttFont)
+		self.tables.append(table)
+
+
+class CmapSubtable:
+	
+	def __init__(self, format):
+		self.format = format
+	
+	def toXML(self, writer, ttFont):
+		writer.begintag(self.__class__.__name__, [
+				("platformID", self.platformID),
+				("platEncID", self.platEncID),
+				])
+		writer.newline()
+		writer.dumphex(self.compile(ttFont))
+		writer.endtag(self.__class__.__name__)
+		writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		self.decompile(readHex(content), ttFont)
+	
+	def __cmp__(self, other):
+		# implemented so that list.sort() sorts according to the cmap spec.
+		selfTuple = (
+					self.platformID,
+					self.platEncID,
+					self.version,
+					self.__dict__)
+		otherTuple = (
+					other.platformID,
+					other.platEncID,
+					other.version,
+					other.__dict__)
+		return cmp(selfTuple, otherTuple)
+
+
+class cmap_format_0(CmapSubtable):
+	
+	def decompile(self, data, ttFont):
+		format, length, version = struct.unpack(">HHH", data[:6])
+		self.version = int(version)
+		assert len(data) == 262 == length
+		glyphIdArray = array.array("B")
+		glyphIdArray.fromstring(data[6:])
+		self.cmap = cmap = {}
+		for charCode in range(len(glyphIdArray)):
+			cmap[charCode] = ttFont.getGlyphName(glyphIdArray[charCode])
+	
+	def compile(self, ttFont):
+		charCodes = self.cmap.keys()
+		charCodes.sort()
+		assert charCodes == range(256)  # charCodes[charCode] == charCode
+		for charCode in charCodes:
+			# reusing the charCodes list!
+			charCodes[charCode] = ttFont.getGlyphID(self.cmap[charCode])
+		glyphIdArray = array.array("B", charCodes)
+		data = struct.pack(">HHH", 0, 262, self.version) + glyphIdArray.tostring()
+		assert len(data) == 262
+		return data
+	
+	def toXML(self, writer, ttFont):
+		writer.begintag(self.__class__.__name__, [
+				("platformID", self.platformID),
+				("platEncID", self.platEncID),
+				("version", self.version),
+				])
+		writer.newline()
+		items = self.cmap.items()
+		items.sort()
+		for code, name in items:
+			writer.simpletag("map", code=hex(code), name=name)
+			writer.newline()
+		writer.endtag(self.__class__.__name__)
+		writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		self.version = safeEval(attrs["version"])
+		self.cmap = {}
+		for element in content:
+			if type(element) <> type(()):
+				continue
+			name, attrs, content = element
+			if name <> "map":
+				continue
+			self.cmap[safeEval(attrs["code"])] = attrs["name"]
+			
+
+
+class cmap_format_2(CmapSubtable):
+	
+	def decompile(self, data, ttFont):
+		format, length, version = struct.unpack(">HHH", data[:6])
+		self.version = int(version)
+		self.data = data
+	
+	def compile(self, ttFont):
+		return self.data
+
+
+cmap_format_4_format = ">7H"
+
+#uint16	endCode[segCount]			# Ending character code for each segment, last = 0xFFFF.
+#uint16	reservedPad					# This value should be zero
+#uint16	startCode[segCount]			# Starting character code for each segment
+#uint16	idDelta[segCount]			# Delta for all character codes in segment
+#uint16	idRangeOffset[segCount]		# Offset in bytes to glyph indexArray, or 0
+#uint16	glyphIndexArray[variable]	# Glyph index array
+
+class cmap_format_4(CmapSubtable):
+	
+	def decompile(self, data, ttFont):
+		(format, length, self.version, segCountX2, 
+				searchRange, entrySelector, rangeShift) = \
+					struct.unpack(cmap_format_4_format, data[:14])
+		assert len(data) == length, "corrupt cmap table (%d, %d)" % (len(data), length)
+		data = data[14:]
+		segCountX2 = int(segCountX2)
+		segCount = segCountX2 / 2
+		
+		allcodes = array.array("H")
+		allcodes.fromstring(data)
+		if ttLib.endian <> "big":
+			allcodes.byteswap()
+		
+		# divide the data
+		endCode = allcodes[:segCount]
+		allcodes = allcodes[segCount+1:]
+		startCode = allcodes[:segCount]
+		allcodes = allcodes[segCount:]
+		idDelta = allcodes[:segCount]
+		allcodes = allcodes[segCount:]
+		idRangeOffset = allcodes[:segCount]
+		glyphIndexArray = allcodes[segCount:]
+		
+		# build 2-byte character mapping
+		cmap = {}
+		for i in range(len(startCode) - 1):	# don't do 0xffff!
+			for charCode in range(startCode[i], endCode[i] + 1):
+				rangeOffset = idRangeOffset[i]
+				if rangeOffset == 0:
+					glyphID = charCode + idDelta[i]
+				else:
+					# *someone* needs to get killed.
+					index = idRangeOffset[i] / 2 + (charCode - startCode[i]) + i - len(idRangeOffset)
+					if glyphIndexArray[index] <> 0:  # if not missing glyph
+						glyphID = glyphIndexArray[index] + idDelta[i]
+					else:
+						glyphID = 0  # missing glyph
+				cmap[charCode] = ttFont.getGlyphName(glyphID % 0x10000)
+		self.cmap = cmap
+	
+	def compile(self, ttFont):
+		from fontTools.ttLib.sfnt import maxpoweroftwo
+		
+		codes = self.cmap.items()
+		codes.sort()
+		
+		# build startCode and endCode lists
+		last = codes[0][0]
+		endCode = []
+		startCode = [last]
+		for charCode, glyphName in codes[1:]:  # skip the first code, it's the first start code
+			if charCode == last + 1:
+				last = charCode
+				continue
+			endCode.append(last)
+			startCode.append(charCode)
+			last = charCode
+		endCode.append(last)
+		startCode.append(0xffff)
+		endCode.append(0xffff)
+		
+		# build up rest of cruft.
+		idDelta = []
+		idRangeOffset = []
+		glyphIndexArray = []
+		
+		for i in range(len(endCode)-1):  # skip the closing codes (0xffff)
+			indices = []
+			for charCode in range(startCode[i], endCode[i]+1):
+				indices.append(ttFont.getGlyphID(self.cmap[charCode]))
+			if indices == range(indices[0], indices[0] + len(indices)):
+				idDelta.append((indices[0] - startCode[i]) % 0x10000)
+				idRangeOffset.append(0)
+			else:
+				# someone *definitely* needs to get killed.
+				idDelta.append(0)
+				idRangeOffset.append(2 * (len(endCode) + len(glyphIndexArray) - i))
+				glyphIndexArray = glyphIndexArray + indices
+		idDelta.append(1)  # 0xffff + 1 == (tadaa!) 0. So this end code maps to .notdef
+		idRangeOffset.append(0)
+		
+		# Insane. 
+		segCount = len(endCode)
+		segCountX2 = segCount * 2
+		maxexponent = maxpoweroftwo(segCount)
+		searchRange = 2 * (2 ** maxexponent)
+		entrySelector = maxexponent
+		rangeShift = 2 * segCount - searchRange
+		
+		allcodes = array.array("H", 
+				endCode + [0] + startCode + idDelta + idRangeOffset + glyphIndexArray)
+		if ttLib.endian <> "big":
+			allcodes.byteswap()
+		data = allcodes.tostring()
+		length = struct.calcsize(cmap_format_4_format) + len(data)
+		header = struct.pack(cmap_format_4_format, self.format, length, self.version, 
+				segCountX2, searchRange, entrySelector, rangeShift)
+		return header + data
+	
+	def toXML(self, writer, ttFont):
+		from fontTools.unicode import Unicode
+		codes = self.cmap.items()
+		codes.sort()
+		writer.begintag(self.__class__.__name__, [
+				("platformID", self.platformID),
+				("platEncID", self.platEncID),
+				("version", self.version),
+				])
+		writer.newline()
+		
+		for code, name in codes:
+			writer.simpletag("map", code=hex(code), name=name)
+			writer.comment(Unicode[code])
+			writer.newline()
+		
+		writer.endtag(self.__class__.__name__)
+		writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		self.version = safeEval(attrs["version"])
+		self.cmap = {}
+		for element in content:
+			if type(element) <> type(()):
+				continue
+			name, attrs, content = element
+			if name <> "map":
+				continue
+			self.cmap[safeEval(attrs["code"])] = attrs["name"]
+
+
+class cmap_format_6(CmapSubtable):
+	
+	def decompile(self, data, ttFont):
+		format, length, version, firstCode, entryCount = struct.unpack(
+				">HHHHH", data[:10])
+		self.version = int(version)
+		firstCode = int(firstCode)
+		self.version = int(version)
+		data = data[10:]
+		assert len(data) == 2 * entryCount
+		glyphIndexArray = array.array("H")
+		glyphIndexArray.fromstring(data)
+		if ttLib.endian <> "big":
+			glyphIndexArray.byteswap()
+		self.cmap = cmap = {}
+		for i in range(len(glyphIndexArray)):
+			glyphID = glyphIndexArray[i]
+			glyphName = ttFont.getGlyphName(glyphID)
+			cmap[i+firstCode] = glyphName
+	
+	def compile(self, ttFont):
+		codes = self.cmap.keys()
+		codes.sort()
+		assert codes == range(codes[0], codes[0] + len(codes))
+		glyphIndexArray = array.array("H", [0] * len(codes))
+		firstCode = codes[0]
+		for i in range(len(codes)):
+			code = codes[i]
+			glyphIndexArray[code-firstCode] = ttFont.getGlyphID(self.cmap[code])
+		if ttLib.endian <> "big":
+			glyphIndexArray.byteswap()
+		data = glyphIndexArray.tostring()
+		header = struct.pack(">HHHHH", 
+				6, len(data) + 10, self.version, firstCode, len(self.cmap))
+		return header + data
+	
+	def toXML(self, writer, ttFont):
+		codes = self.cmap.items()
+		codes.sort()
+		writer.begintag(self.__class__.__name__, [
+				("platformID", self.platformID),
+				("platEncID", self.platEncID),
+				("version", self.version),
+				])
+		writer.newline()
+		
+		for code, name in codes:
+			writer.simpletag("map", code=hex(code), name=name)
+			writer.newline()
+		
+		writer.endtag(self.__class__.__name__)
+		writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		self.version = safeEval(attrs["version"])
+		self.cmap = {}
+		for element in content:
+			if type(element) <> type(()):
+				continue
+			name, attrs, content = element
+			if name <> "map":
+				continue
+			self.cmap[safeEval(attrs["code"])] = attrs["name"]
+
+
+class cmap_format_unknown(CmapSubtable):
+	
+	def decompile(self, data, ttFont):
+		self.data = data
+	
+	def compile(self, ttFont):
+		return self.data
+
+
+cmap_classes = {
+		0: cmap_format_0,
+		2: cmap_format_2,
+		4: cmap_format_4,
+		6: cmap_format_6,
+		}
+
+
diff --git a/Lib/fontTools/ttLib/tables/_c_v_t.py b/Lib/fontTools/ttLib/tables/_c_v_t.py
new file mode 100644
index 0000000..ced5523
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/_c_v_t.py
@@ -0,0 +1,48 @@
+import DefaultTable
+import array
+from fontTools import ttLib
+from fontTools.misc.textTools import safeEval
+
+class table__c_v_t(DefaultTable.DefaultTable):
+	
+	def decompile(self, data, ttFont):
+		values = array.array("h")
+		values.fromstring(data)
+		if ttLib.endian <> "big":
+			values.byteswap()
+		self.values = values
+	
+	def compile(self, ttFont):
+		values = self.values[:]
+		if ttLib.endian <> "big":
+			values.byteswap()
+		return values.tostring()
+	
+	def toXML(self, writer, ttFont):
+		for i in range(len(self.values)):
+			value = self.values[i]
+			writer.simpletag("cv", value=value, index=i)
+			writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		if not hasattr(self, "values"):
+			self.values = array.array("h")
+		if name == "cv":
+			index = safeEval(attrs["index"])
+			value = safeEval(attrs["value"])
+			for i in range(1 + index - len(self.values)):
+				self.values.append(0)
+			self.values[index] = value
+	
+	def __len__(self):
+		return len(self.values)
+	
+	def __getitem__(self, index):
+		return self.values[index]
+	
+	def __setitem__(self, index, value):
+		self.values[index] = value
+	
+	def __delitem__(self, index):
+		del self.values[index]
+
diff --git a/Lib/fontTools/ttLib/tables/_f_p_g_m.py b/Lib/fontTools/ttLib/tables/_f_p_g_m.py
new file mode 100644
index 0000000..f7cc8a3
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/_f_p_g_m.py
@@ -0,0 +1,14 @@
+import DefaultTable
+import array
+
+class table__f_p_g_m(DefaultTable.DefaultTable):
+	
+	def decompile(self, data, ttFont):
+		self.fpgm = data
+	
+	def compile(self, ttFont):
+		return self.fpgm
+	
+	def __len__(self):
+		return len(self.fpgm)
+	
diff --git a/Lib/fontTools/ttLib/tables/_g_a_s_p.py b/Lib/fontTools/ttLib/tables/_g_a_s_p.py
new file mode 100644
index 0000000..e49cceb
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/_g_a_s_p.py
@@ -0,0 +1,46 @@
+import DefaultTable
+import struct
+from fontTools.misc.textTools import safeEval
+
+
+GASP_DOGRAY = 0x0002
+GASP_GRIDFIT = 0x0001
+
+class table__g_a_s_p(DefaultTable.DefaultTable):
+	
+	def decompile(self, data, ttFont):
+		self.version, numRanges = struct.unpack(">HH", data[:4])
+		assert self.version == 0, "unknown 'gasp' format: %s" % self.version
+		data = data[4:]
+		self.gaspRange = {}
+		for i in range(numRanges):
+			rangeMaxPPEM, rangeGaspBehavior = struct.unpack(">HH", data[:4])
+			self.gaspRange[int(rangeMaxPPEM)] = int(rangeGaspBehavior)
+			data = data[4:]
+		assert not data, "too much data"
+	
+	def compile(self, ttFont):
+		numRanges = len(self.gaspRange)
+		data = struct.pack(">HH", 0, numRanges)
+		items = self.gaspRange.items()
+		items.sort()
+		for rangeMaxPPEM, rangeGaspBehavior in items:
+			data = data + struct.pack(">HH", rangeMaxPPEM, rangeGaspBehavior)
+		return data
+	
+	def toXML(self, writer, ttFont):
+		items = self.gaspRange.items()
+		items.sort()
+		for rangeMaxPPEM, rangeGaspBehavior in items:
+			writer.simpletag("gaspRange", [
+					("rangeMaxPPEM", rangeMaxPPEM),
+					("rangeGaspBehavior", rangeGaspBehavior)])
+			writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		if name <> "gaspRange":
+			return
+		if not hasattr(self, "gaspRange"):
+			self.gaspRange = {}
+		self.gaspRange[safeEval(attrs["rangeMaxPPEM"])] = safeEval(attrs["rangeGaspBehavior"])
+
diff --git a/Lib/fontTools/ttLib/tables/_g_l_y_f.py b/Lib/fontTools/ttLib/tables/_g_l_y_f.py
new file mode 100644
index 0000000..29f9be5
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/_g_l_y_f.py
@@ -0,0 +1,778 @@
+"""_g_l_y_f.py -- Converter classes for the 'glyf' table."""
+
+
+#
+# The Apple and MS rasterizers behave differently for 
+# scaled composite components: one does scale first and then translate
+# and the other does it vice versa. MS defined some flags to indicate
+# the difference, but it seems nobody actually _sets_ those flags.
+#
+# Funny thing: Apple seems to _only_ do their thing in the
+# WE_HAVE_A_SCALE (eg. Chicago) case, and not when it's WE_HAVE_AN_X_AND_Y_SCALE 
+# (eg. Charcoal)...
+#
+SCALE_COMPONENT_OFFSET_DEFAULT = 0   # 0 == MS, 1 == Apple
+
+
+import struct, sstruct
+import DefaultTable
+from fontTools import ttLib
+from fontTools.misc.textTools import safeEval, readHex
+import array
+import Numeric
+import types
+
+class table__g_l_y_f(DefaultTable.DefaultTable):
+	
+	def decompile(self, data, ttFont):
+		loca = ttFont['loca']
+		last = loca[0]
+		self.glyphs = {}
+		self.glyphOrder = []
+		self.glyphOrder = glyphOrder = ttFont.getGlyphOrder()
+		for i in range(0, len(loca)-1):
+			glyphName = glyphOrder[i]
+			next = loca[i+1]
+			glyphdata = data[last:next]
+			if len(glyphdata) <> (next - last):
+				raise ttLib.TTLibError, "not enough 'glyf' table data"
+			glyph = Glyph(glyphdata)
+			self.glyphs[glyphName] = glyph
+			last = next
+		if len(data) > next:
+			raise ttLib.TTLibError, "too much 'glyf' table data"
+	
+	def compile(self, ttFont):
+		import string
+		locations = []
+		currentLocation = 0
+		dataList = []
+		for glyphName in ttFont.getGlyphOrder():
+			glyph = self[glyphName]
+			glyphData = glyph.compile(self)
+			locations.append(currentLocation)
+			currentLocation = currentLocation + len(glyphData)
+			dataList.append(glyphData)
+		locations.append(currentLocation)
+		data = string.join(dataList, "")
+		ttFont['loca'].set(locations)
+		ttFont['maxp'].numGlyphs = len(self.glyphs)
+		return data
+	
+	def toXML(self, writer, ttFont, progress=None, compactGlyphs=0):
+		writer.newline()
+		glyphOrder = ttFont.getGlyphOrder()
+		writer.begintag("GlyphOrder")
+		writer.newline()
+		for i in range(len(glyphOrder)):
+			glyphName = glyphOrder[i]
+			writer.simpletag("GlyphID", id=i, name=glyphName)
+			writer.newline()
+		writer.endtag("GlyphOrder")
+		writer.newline()
+		writer.newline()
+		glyphNames = ttFont.getGlyphNames()
+		writer.comment("The xMin, yMin, xMax and yMax values\nwill be recalculated by the compiler.")
+		writer.newline()
+		writer.newline()
+		for glyphName in glyphNames:
+			if progress:
+				progress.setlabel("Dumping 'glyf' table... (%s)" % glyphName)
+				progress.increment()
+			glyph = self[glyphName]
+			if glyph.numberOfContours:
+				writer.begintag('TTGlyph', [
+						("name", glyphName),
+						("xMin", glyph.xMin),
+						("yMin", glyph.yMin),
+						("xMax", glyph.xMax),
+						("yMax", glyph.yMax),
+						])
+				writer.newline()
+				glyph.toXML(writer, ttFont)
+				if compactGlyphs:
+					glyph.compact(self)
+				writer.endtag('TTGlyph')
+				writer.newline()
+			else:
+				writer.simpletag('TTGlyph', name=glyphName)
+				writer.comment("contains no outline data")
+				writer.newline()
+			writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		if name == "GlyphOrder":
+			glyphOrder = []
+			for element in content:
+				if type(element) == types.StringType:
+					continue
+				name, attrs, content = element
+				if name == "GlyphID":
+					index = safeEval(attrs["id"])
+					glyphName = attrs["name"]
+					glyphOrder = glyphOrder + (1 + index - len(glyphOrder)) * [".notdef"]
+					glyphOrder[index] = glyphName
+			ttFont.setGlyphOrder(glyphOrder)
+		elif name == "TTGlyph":
+			if not hasattr(self, "glyphs"):
+				self.glyphs = {}
+			glyphName = attrs["name"]
+			if ttFont.verbose:
+				ttLib.debugmsg("unpacking glyph '%s'" % glyphName)
+			glyph = Glyph()
+			for attr in ['xMin', 'yMin', 'xMax', 'yMax']:
+				setattr(glyph, attr, safeEval(attrs.get(attr, '0')))
+			self.glyphs[glyphName] = glyph
+			for element in content:
+				if type(element) == types.StringType:
+					continue
+				glyph.fromXML(element, ttFont)
+	
+	def setGlyphOrder(self, glyphOrder):
+		self.glyphOrder = glyphOrder
+	
+	def getGlyphName(self, glyphID):
+		return self.glyphOrder[glyphID]
+	
+	def getGlyphID(self, glyphName):
+		# XXX optimize with reverse dict!!!
+		return self.glyphOrder.index(glyphName)
+	
+	#def keys(self):
+	#	return self.glyphOrder[:]
+	#
+	#def has_key(self, glyphName):
+	#	return self.glyphs.has_key(glyphName)
+	#
+	def __getitem__(self, glyphName):
+		glyph = self.glyphs[glyphName]
+		glyph.expand(self)
+		return glyph
+	
+	def __setitem__(self, glyphName, glyph):
+		self.glyphs[glyphName] = glyph
+		if glyphName not in self.glyphOrder:
+			self.glyphOrder.append(glyphName)
+	
+	def __delitem__(self, glyphName):
+		del self.glyphs[glyphName]
+		self.glyphOrder.remove(glyphName)
+	
+	def __len__(self):
+		assert len(self.glyphOrder) == len(self.glyphs)
+		return len(self.glyphs)
+
+
+glyphHeaderFormat = """
+		>	# big endian
+		numberOfContours:	h
+		xMin:				h
+		yMin:				h
+		xMax:				h
+		yMax:				h
+"""
+
+# flags
+flagOnCurve = 0x01
+flagXShort = 0x02
+flagYShort = 0x04
+flagRepeat = 0x08
+flagXsame =  0x10
+flagYsame = 0x20
+flagReserved1 = 0x40
+flagReserved2 = 0x80
+
+
+ARG_1_AND_2_ARE_WORDS      = 0x0001  # if set args are words otherwise they are bytes 
+ARGS_ARE_XY_VALUES         = 0x0002  # if set args are xy values, otherwise they are points 
+ROUND_XY_TO_GRID           = 0x0004  # for the xy values if above is true 
+WE_HAVE_A_SCALE            = 0x0008  # Sx = Sy, otherwise scale == 1.0 
+NON_OVERLAPPING            = 0x0010  # set to same value for all components (obsolete!)
+MORE_COMPONENTS            = 0x0020  # indicates at least one more glyph after this one 
+WE_HAVE_AN_X_AND_Y_SCALE   = 0x0040  # Sx, Sy 
+WE_HAVE_A_TWO_BY_TWO       = 0x0080  # t00, t01, t10, t11 
+WE_HAVE_INSTRUCTIONS       = 0x0100  # instructions follow 
+USE_MY_METRICS             = 0x0200  # apply these metrics to parent glyph 
+OVERLAP_COMPOUND           = 0x0400  # used by Apple in GX fonts 
+SCALED_COMPONENT_OFFSET    = 0x0800  # composite designed to have the component offset scaled (designed for Apple) 
+UNSCALED_COMPONENT_OFFSET  = 0x1000  # composite designed not to have the component offset scaled (designed for MS) 
+
+
+class Glyph:
+	
+	def __init__(self, data=""):
+		if not data:
+			# empty char
+			self.numberOfContours = 0
+			return
+		self.data = data
+	
+	def compact(self, glyfTable):
+		data = self.compile(glyfTable)
+		self.__dict__.clear()
+		self.data = data
+	
+	def expand(self, glyfTable):
+		if not hasattr(self, "data"):
+			# already unpacked
+			return
+		dummy, data = sstruct.unpack2(glyphHeaderFormat, self.data, self)
+		del self.data
+		if self.numberOfContours == -1:
+			self.decompileComponents(data, glyfTable)
+		else:
+			self.decompileCoordinates(data)
+	
+	def compile(self, glyfTable):
+		if hasattr(self, "data"):
+			return self.data
+		if self.numberOfContours == 0:
+			return ""
+		self.recalcBounds(glyfTable)
+		data = sstruct.pack(glyphHeaderFormat, self)
+		if self.numberOfContours == -1:
+			data = data + self.compileComponents(glyfTable)
+		else:
+			data = data + self.compileCoordinates()
+		# from the spec: "Note that the local offsets should be word-aligned"
+		if len(data) % 2:
+			# ...so if the length of the data is odd, append a null byte
+			data = data + "\0"
+		return data
+	
+	def toXML(self, writer, ttFont):
+		if self.numberOfContours == -1:
+			for compo in self.components:
+				compo.toXML(writer, ttFont)
+			if hasattr(self, "instructions"):
+				writer.begintag("instructions")
+				writer.newline()
+				writer.dumphex(self.instructions)
+				writer.endtag("instructions")
+				writer.newline()
+		else:
+			last = 0
+			for i in range(self.numberOfContours):
+				writer.begintag("contour")
+				writer.newline()
+				for j in range(last, self.endPtsOfContours[i] + 1):
+					writer.simpletag("pt", [
+							("x", self.coordinates[j][0]), 
+							("y", self.coordinates[j][1]),
+							("on", self.flags[j] & flagOnCurve)])
+					writer.newline()
+				last = self.endPtsOfContours[i] + 1
+				writer.endtag("contour")
+				writer.newline()
+			if self.numberOfContours:
+				writer.begintag("instructions")
+				writer.newline()
+				writer.dumphex(self.instructions)
+				writer.endtag("instructions")
+				writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		if name == "contour":
+			self.numberOfContours = self.numberOfContours + 1
+			if self.numberOfContours < 0:
+				raise ttLib.TTLibError, "can't mix composites and contours in glyph"
+			coordinates = []
+			flags = []
+			for element in content:
+				if type(element) == types.StringType:
+					continue
+				name, attrs, content = element
+				if name <> "pt":
+					continue  # ignore anything but "pt"
+				coordinates.append([safeEval(attrs["x"]), safeEval(attrs["y"])])
+				flags.append(not not safeEval(attrs["on"]))
+			coordinates = Numeric.array(coordinates, Numeric.Int16)
+			flags = Numeric.array(flags, Numeric.Int8)
+			if not hasattr(self, "coordinates"):
+				self.coordinates = coordinates
+				self.flags = flags
+				self.endPtsOfContours = [len(coordinates)-1]
+			else:
+				self.coordinates = Numeric.concatenate((self.coordinates, coordinates))
+				self.flags = Numeric.concatenate((self.flags, flags))
+				self.endPtsOfContours.append(len(self.coordinates)-1)
+		elif name == "component":
+			if self.numberOfContours > 0:
+				raise ttLib.TTLibError, "can't mix composites and contours in glyph"
+			self.numberOfContours = -1
+			if not hasattr(self, "components"):
+				self.components = []
+			component = GlyphComponent()
+			self.components.append(component)
+			component.fromXML((name, attrs, content), ttFont)
+		elif name == "instructions":
+			self.instructions = readHex(content)
+	
+	def getCompositeMaxpValues(self, glyfTable, maxComponentDepth=1):
+		assert self.numberOfContours == -1
+		nContours = 0
+		nPoints = 0
+		for compo in self.components:
+			baseGlyph = glyfTable[compo.glyphName]
+			if baseGlyph.numberOfContours == 0:
+				continue
+			elif baseGlyph.numberOfContours > 0:
+				nP, nC = baseGlyph.getMaxpValues()
+			else:
+				nP, nC, maxComponentDepth = baseGlyph.getCompositeMaxpValues(
+						glyfTable, maxComponentDepth + 1)
+			nPoints = nPoints + nP
+			nContours = nContours + nC
+		return nPoints, nContours, maxComponentDepth
+	
+	def getMaxpValues(self):
+		assert self.numberOfContours > 0
+		return len(self.coordinates), len(self.endPtsOfContours)
+	
+	def decompileComponents(self, data, glyfTable):
+		self.components = []
+		more = 1
+		haveInstructions = 0
+		while more:
+			component = GlyphComponent()
+			more, haveInstr, data = component.decompile(data, glyfTable)
+			haveInstructions = haveInstructions | haveInstr
+			self.components.append(component)
+		if haveInstructions:
+			numInstructions, = struct.unpack(">h", data[:2])
+			data = data[2:]
+			self.instructions = data[:numInstructions]
+			data = data[numInstructions:]
+			assert len(data) in (0, 1), "bad composite data"
+	
+	def decompileCoordinates(self, data):
+		endPtsOfContours = array.array("h")
+		endPtsOfContours.fromstring(data[:2*self.numberOfContours])
+		if ttLib.endian <> "big":
+			endPtsOfContours.byteswap()
+		self.endPtsOfContours = endPtsOfContours.tolist()
+		
+		data = data[2*self.numberOfContours:]
+		
+		instructionLength, = struct.unpack(">h", data[:2])
+		data = data[2:]
+		self.instructions = data[:instructionLength]
+		data = data[instructionLength:]
+		nCoordinates = self.endPtsOfContours[-1] + 1
+		flags, xCoordinates, yCoordinates = \
+				self.decompileCoordinatesRaw(nCoordinates, data)
+		
+		# fill in repetitions and apply signs
+		coordinates = Numeric.zeros((nCoordinates, 2), Numeric.Int16)
+		xIndex = 0
+		yIndex = 0
+		for i in range(nCoordinates):
+			flag = flags[i]
+			# x coordinate
+			if flag & flagXShort:
+				if flag & flagXsame:
+					x = xCoordinates[xIndex]
+				else:
+					x = -xCoordinates[xIndex]
+				xIndex = xIndex + 1
+			elif flag & flagXsame:
+				x = 0
+			else:
+				x = xCoordinates[xIndex]
+				xIndex = xIndex + 1
+			# y coordinate
+			if flag & flagYShort:
+				if flag & flagYsame:
+					y = yCoordinates[yIndex]
+				else:
+					y = -yCoordinates[yIndex]
+				yIndex = yIndex + 1
+			elif flag & flagYsame:
+				y = 0
+			else:
+				y = yCoordinates[yIndex]
+				yIndex = yIndex + 1
+			coordinates[i] = (x, y)
+		assert xIndex == len(xCoordinates)
+		assert yIndex == len(yCoordinates)
+		# convert relative to absolute coordinates
+		self.coordinates = Numeric.add.accumulate(coordinates)
+		# discard all flags but for "flagOnCurve"
+		if hasattr(Numeric, "__version__"):
+			self.flags = Numeric.bitwise_and(flags, flagOnCurve).astype(Numeric.Int8)
+		else:
+			self.flags = Numeric.boolean_and(flags, flagOnCurve).astype(Numeric.Int8)
+	
+	def decompileCoordinatesRaw(self, nCoordinates, data):
+		# unpack flags and prepare unpacking of coordinates
+		flags = Numeric.array([0] * nCoordinates, Numeric.Int8)
+		# Warning: deep Python trickery going on. We use the struct module to unpack
+		# the coordinates. We build a format string based on the flags, so we can
+		# unpack the coordinates in one struct.unpack() call.
+		xFormat = ">" # big endian
+		yFormat = ">" # big endian
+		i = j = 0
+		while 1:
+			flag = ord(data[i])
+			i = i + 1
+			repeat = 1
+			if flag & flagRepeat:
+				repeat = ord(data[i]) + 1
+				i = i + 1
+			for k in range(repeat):
+				if flag & flagXShort:
+					xFormat = xFormat + 'B'
+				elif not (flag & flagXsame):
+					xFormat = xFormat + 'h'
+				if flag & flagYShort:
+					yFormat = yFormat + 'B'
+				elif not (flag & flagYsame):
+					yFormat = yFormat + 'h'
+				flags[j] = flag
+				j = j + 1
+			if j >= nCoordinates:
+				break
+		assert j == nCoordinates, "bad glyph flags"
+		data = data[i:]
+		# unpack raw coordinates, krrrrrr-tching!
+		xDataLen = struct.calcsize(xFormat)
+		yDataLen = struct.calcsize(yFormat)
+		if (len(data) - (xDataLen + yDataLen)) not in (0, 1):
+			raise ttLib.TTLibError, "bad glyph record"
+		xCoordinates = struct.unpack(xFormat, data[:xDataLen])
+		yCoordinates = struct.unpack(yFormat, data[xDataLen:xDataLen+yDataLen])
+		return flags, xCoordinates, yCoordinates
+	
+	def compileComponents(self, glyfTable):
+		data = ""
+		lastcomponent = len(self.components) - 1
+		more = 1
+		haveInstructions = 0
+		for i in range(len(self.components)):
+			if i == lastcomponent:
+				haveInstructions = hasattr(self, "instructions")
+				more = 0
+			compo = self.components[i]
+			data = data + compo.compile(more, haveInstructions, glyfTable)
+		if haveInstructions:
+			data = data + struct.pack(">h", len(self.instructions)) + self.instructions
+		return data
+			
+	
+	def compileCoordinates(self):
+		assert len(self.coordinates) == len(self.flags)
+		data = ""
+		endPtsOfContours = array.array("h", self.endPtsOfContours)
+		if ttLib.endian <> "big":
+			endPtsOfContours.byteswap()
+		data = data + endPtsOfContours.tostring()
+		data = data + struct.pack(">h", len(self.instructions))
+		data = data + self.instructions
+		nCoordinates = len(self.coordinates)
+		
+		# make a copy
+		coordinates = self.coordinates.astype(self.coordinates.typecode())
+		# absolute to relative coordinates
+		coordinates[1:] = Numeric.subtract(coordinates[1:], coordinates[:-1])
+		flags = self.flags
+		compressedflags = []
+		xPoints = []
+		yPoints = []
+		xFormat = ">"
+		yFormat = ">"
+		lastflag = None
+		repeat = 0
+		for i in range(len(coordinates)):
+			# Oh, the horrors of TrueType
+			flag = self.flags[i]
+			x, y = coordinates[i]
+			# do x
+			if x == 0:
+				flag = flag | flagXsame
+			elif -255 <= x <= 255:
+				flag = flag | flagXShort
+				if x > 0:
+					flag = flag | flagXsame
+				else:
+					x = -x
+				xPoints.append(x)
+				xFormat = xFormat + 'B'
+			else:
+				xPoints.append(x)
+				xFormat = xFormat + 'h'
+			# do y
+			if y == 0:
+				flag = flag | flagYsame
+			elif -255 <= y <= 255:
+				flag = flag | flagYShort
+				if y > 0:
+					flag = flag | flagYsame
+				else:
+					y = -y
+				yPoints.append(y)
+				yFormat = yFormat + 'B'
+			else:
+				yPoints.append(y)
+				yFormat = yFormat + 'h'
+			# handle repeating flags
+			if flag == lastflag:
+				repeat = repeat + 1
+				if repeat == 1:
+					compressedflags.append(flag)
+				elif repeat > 1:
+					compressedflags[-2] = flag | flagRepeat
+					compressedflags[-1] = repeat
+				else:
+					compressedflags[-1] = repeat
+			else:
+				repeat = 0
+				compressedflags.append(flag)
+			lastflag = flag
+		data = data + array.array("B", compressedflags).tostring()
+		data = data + apply(struct.pack, (xFormat,)+tuple(xPoints))
+		data = data + apply(struct.pack, (yFormat,)+tuple(yPoints))
+		return data
+	
+	def recalcBounds(self, glyfTable):
+		coordinates, endPts, flags = self.getCoordinates(glyfTable)
+		self.xMin, self.yMin = Numeric.minimum.reduce(coordinates)
+		self.xMax, self.yMax = Numeric.maximum.reduce(coordinates)
+	
+	def getCoordinates(self, glyfTable):
+		if self.numberOfContours > 0:
+			return self.coordinates, self.endPtsOfContours, self.flags
+		elif self.numberOfContours == -1:
+			# it's a composite
+			allCoords = None
+			allFlags = None
+			allEndPts = None
+			for compo in self.components:
+				g = glyfTable[compo.glyphName]
+				coordinates, endPts, flags = g.getCoordinates(glyfTable)
+				if hasattr(compo, "firstpt"):
+					# move according to two reference points
+					move = allCoords[compo.firstpt] - coordinates[compo.secondpt]
+				else:
+					move = compo.x, compo.y
+				
+				if not hasattr(compo, "transform"):
+					coordinates = coordinates + move  # I love NumPy!
+				else:
+					apple_way = compo.flags & SCALED_COMPONENT_OFFSET
+					ms_way = compo.flags & UNSCALED_COMPONENT_OFFSET
+					assert not (apple_way and ms_way)
+					if not (apple_way or ms_way):
+						scale_component_offset = SCALE_COMPONENT_OFFSET_DEFAULT  # see top of this file
+					else:
+						scale_component_offset = apple_way
+					if scale_component_offset:
+						# the Apple way: first move, then scale (ie. scale the component offset)
+						coordinates = coordinates + move
+						coordinates = Numeric.dot(coordinates, compo.transform)
+					else:
+						# the MS way: first scale, then move
+						coordinates = Numeric.dot(coordinates, compo.transform)
+						coordinates = coordinates + move
+					# due to the transformation the coords. are now floats;
+					# round them off nicely, and cast to short
+					coordinates = Numeric.floor(coordinates + 0.5).astype(Numeric.Int16)
+				if allCoords is None:
+					allCoords = coordinates
+					allEndPts = endPts
+					allFlags = flags
+				else:
+					allEndPts = allEndPts + (Numeric.array(endPts) + len(allCoords)).tolist()
+					allCoords = Numeric.concatenate((allCoords, coordinates))
+					allFlags = Numeric.concatenate((allFlags, flags))
+			return allCoords, allEndPts, allFlags
+		else:
+			return Numeric.array([], Numeric.Int16), [], Numeric.array([], Numeric.Int8)
+	
+	def __cmp__(self, other):
+		if self.numberOfContours <= 0:
+			return cmp(self.__dict__, other.__dict__)
+		else:
+			if cmp(len(self.coordinates), len(other.coordinates)):
+				return 1
+			ctest = Numeric.alltrue(Numeric.alltrue(Numeric.equal(self.coordinates, other.coordinates)))
+			ftest = Numeric.alltrue(Numeric.equal(self.flags, other.flags))
+			if not ctest or not ftest:
+				return 1
+			return (
+					cmp(self.endPtsOfContours, other.endPtsOfContours) or
+					cmp(self.instructions, other.instructions)
+				)
+
+
+class GlyphComponent:
+	
+	def __init__(self):
+		pass
+	
+	def decompile(self, data, glyfTable):
+		flags, glyphID = struct.unpack(">HH", data[:4])
+		self.flags = int(flags)
+		glyphID = int(glyphID)
+		self.glyphName = glyfTable.getGlyphName(int(glyphID))
+		#print ">>", reprflag(self.flags)
+		data = data[4:]
+		
+		if self.flags & ARG_1_AND_2_ARE_WORDS:
+			if self.flags & ARGS_ARE_XY_VALUES:
+				self.x, self.y = struct.unpack(">hh", data[:4])
+			else:
+				x, y = struct.unpack(">HH", data[:4])
+				self.firstpt, self.secondpt = int(x), int(y)
+			data = data[4:]
+		else:
+			if self.flags & ARGS_ARE_XY_VALUES:
+				self.x, self.y = struct.unpack(">bb", data[:2])
+			else:
+				x, y = struct.unpack(">BB", data[:4])
+				self.firstpt, self.secondpt = int(x), int(y)
+			data = data[2:]
+		
+		if self.flags & WE_HAVE_A_SCALE:
+			scale, = struct.unpack(">h", data[:2])
+			self.transform = Numeric.array(
+					[[scale, 0], [0, scale]]) / float(0x4000)  # fixed 2.14
+			data = data[2:]
+		elif self.flags & WE_HAVE_AN_X_AND_Y_SCALE:
+			xscale, yscale = struct.unpack(">hh", data[:4])
+			self.transform = Numeric.array(
+					[[xscale, 0], [0, yscale]]) / float(0x4000)  # fixed 2.14
+			data = data[4:]
+		elif self.flags & WE_HAVE_A_TWO_BY_TWO:
+			(xscale, scale01, 
+					scale10, yscale) = struct.unpack(">hhhh", data[:8])
+			self.transform = Numeric.array(
+					[[xscale, scale01], [scale10, yscale]]) / float(0x4000)  # fixed 2.14
+			data = data[8:]
+		more = self.flags & MORE_COMPONENTS
+		haveInstructions = self.flags & WE_HAVE_INSTRUCTIONS
+		self.flags = self.flags & (ROUND_XY_TO_GRID | USE_MY_METRICS | 
+				SCALED_COMPONENT_OFFSET | UNSCALED_COMPONENT_OFFSET |
+				NON_OVERLAPPING)
+		return more, haveInstructions, data
+	
+	def compile(self, more, haveInstructions, glyfTable):
+		data = ""
+		
+		# reset all flags we will calculate ourselves
+		flags = self.flags & (ROUND_XY_TO_GRID | USE_MY_METRICS | 
+				SCALED_COMPONENT_OFFSET | UNSCALED_COMPONENT_OFFSET |
+				NON_OVERLAPPING)
+		if more:
+			flags = flags | MORE_COMPONENTS
+		if haveInstructions:
+			flags = flags | WE_HAVE_INSTRUCTIONS
+		
+		if hasattr(self, "firstpt"):
+			if (0 <= self.firstpt <= 255) and (0 <= self.secondpt <= 255):
+				data = data + struct.pack(">BB", self.firstpt, self.secondpt)
+			else:
+				data = data + struct.pack(">HH", self.firstpt, self.secondpt)
+				flags = flags | ARG_1_AND_2_ARE_WORDS
+		else:
+			flags = flags | ARGS_ARE_XY_VALUES
+			if (-128 <= self.x <= 127) and (-128 <= self.y <= 127):
+				data = data + struct.pack(">bb", self.x, self.y)
+			else:
+				data = data + struct.pack(">hh", self.x, self.y)
+				flags = flags | ARG_1_AND_2_ARE_WORDS
+		
+		if hasattr(self, "transform"):
+			# XXX needs more testing
+			transform = Numeric.floor(self.transform * 0x4000 + 0.5)
+			if transform[0][1] or transform[1][0]:
+				flags = flags | WE_HAVE_A_TWO_BY_TWO
+				data = data + struct.pack(">hhhh", 
+						transform[0][0], transform[0][1],
+						transform[1][0], transform[1][1])
+			elif transform[0][0] <> transform[1][1]:
+				flags = flags | WE_HAVE_AN_X_AND_Y_SCALE
+				data = data + struct.pack(">hh", 
+						transform[0][0], transform[1][1])
+			else:
+				flags = flags | WE_HAVE_A_SCALE
+				data = data + struct.pack(">h", 
+						transform[0][0])
+		
+		glyphID = glyfTable.getGlyphID(self.glyphName)
+		return struct.pack(">HH", flags, glyphID) + data
+	
+	def toXML(self, writer, ttFont):
+		attrs = [("glyphName", self.glyphName)]
+		if not hasattr(self, "firstpt"):
+			attrs = attrs + [("x", self.x), ("y", self.y)]
+		else:
+			attrs = attrs + [("firstpt", self.firstpt), ("secondpt", self.secondpt)]
+		
+		if hasattr(self, "transform"):
+			# XXX needs more testing
+			transform = self.transform
+			if transform[0][1] or transform[1][0]:
+				attrs = attrs + [
+						("scalex", transform[0][0]), ("scale01", transform[0][1]),
+						("scale10", transform[1][0]), ("scaley", transform[1][1]),
+						]
+			elif transform[0][0] <> transform[1][1]:
+				attrs = attrs + [
+						("scalex", transform[0][0]), ("scaley", transform[1][1]),
+						]
+			else:
+				attrs = attrs + [("scale", transform[0][0])]
+		attrs = attrs + [("flags", hex(self.flags))]
+		writer.simpletag("component", attrs)
+		writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		self.glyphName = attrs["glyphName"]
+		if attrs.has_key("firstpt"):
+			self.firstpt = safeEval(attrs["firstpt"])
+			self.secondpt = safeEval(attrs["secondpt"])
+		else:
+			self.x = safeEval(attrs["x"])
+			self.y = safeEval(attrs["y"])
+		if attrs.has_key("scale01"):
+			scalex = safeEval(attrs["scalex"])
+			scale01 = safeEval(attrs["scale01"])
+			scale10 = safeEval(attrs["scale10"])
+			scaley = safeEval(attrs["scaley"])
+			self.transform = Numeric.array([[scalex, scale01], [scale10, scaley]])
+		elif attrs.has_key("scalex"):
+			scalex = safeEval(attrs["scalex"])
+			scaley = safeEval(attrs["scaley"])
+			self.transform = Numeric.array([[scalex, 0], [0, scaley]])
+		elif attrs.has_key("scale"):
+			scale = safeEval(attrs["scale"])
+			self.transform = Numeric.array([[scale, 0], [0, scale]])
+		self.flags = safeEval(attrs["flags"])
+	
+	def __cmp__(self, other):
+		if hasattr(self, "transform"):
+			if Numeric.alltrue(Numeric.equal(self.transform, other.transform)):
+				selfdict = self.__dict__.copy()
+				otherdict = other.__dict__.copy()
+				del selfdict["transform"]
+				del otherdict["transform"]
+				return cmp(selfdict, otherdict)
+			else:
+				return 1
+		else:
+			return cmp(self.__dict__, other.__dict__)
+
+
+def reprflag(flag):
+	bin = ""
+	if type(flag) == types.StringType:
+		flag = ord(flag)
+	while flag:
+		if flag & 0x01:
+			bin = "1" + bin
+		else:
+			bin = "0" + bin
+		flag = flag >> 1
+	bin = (14 - len(bin)) * "0" + bin
+	return bin
+
diff --git a/Lib/fontTools/ttLib/tables/_h_d_m_x.py b/Lib/fontTools/ttLib/tables/_h_d_m_x.py
new file mode 100644
index 0000000..e5c396c
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/_h_d_m_x.py
@@ -0,0 +1,95 @@
+import DefaultTable
+import sstruct
+import string
+
+hdmxHeaderFormat = """
+	version:	H
+	numRecords:	H
+	recordSize:	l
+"""
+
+class table__h_d_m_x(DefaultTable.DefaultTable):
+	
+	def decompile(self, data, ttFont):
+		numGlyphs = ttFont['maxp'].numGlyphs
+		glyphOrder = ttFont.getGlyphOrder()
+		dummy, data = sstruct.unpack2(hdmxHeaderFormat, data, self)
+		self.hdmx = {}
+		for i in range(self.numRecords):
+			ppem = ord(data[0])
+			maxSize = ord(data[1])
+			widths = {}
+			for glyphID in range(numGlyphs):
+				widths[glyphOrder[glyphID]] = ord(data[glyphID+2])
+			self.hdmx[ppem] = widths
+			data = data[self.recordSize:]
+		assert len(data) == 0, "too much hdmx data"
+	
+	def compile(self, ttFont):
+		self.version = 0
+		numGlyphs = ttFont['maxp'].numGlyphs
+		glyphOrder = ttFont.getGlyphOrder()
+		self.recordSize = 4 * ((2 + numGlyphs + 3) / 4)
+		pad = (self.recordSize - 2 - numGlyphs) * "\0"
+		self.numRecords = len(self.hdmx)
+		data = sstruct.pack(hdmxHeaderFormat, self)
+		items = self.hdmx.items()
+		items.sort()
+		for ppem, widths in items:
+			data = data + chr(ppem) + chr(max(widths.values()))
+			for glyphID in range(len(glyphOrder)):
+				width = widths[glyphOrder[glyphID]]
+				data = data + chr(width)
+			data = data + pad
+		return data
+	
+	def toXML(self, writer, ttFont):
+		writer.begintag("hdmxData")
+		writer.newline()
+		ppems = self.hdmx.keys()
+		ppems.sort()
+		records = []
+		format = ""
+		for ppem in ppems:
+			widths = self.hdmx[ppem]
+			records.append(widths)
+			format = format + "%4d"
+		glyphNames = ttFont.getGlyphOrder()[:]
+		glyphNames.sort()
+		maxNameLen = max(map(len, glyphNames))
+		format = "%" + `maxNameLen` + 's:' + format + ' ;'
+		writer.write(format % (("ppem",) + tuple(ppems)))
+		writer.newline()
+		writer.newline()
+		for glyphName in glyphNames:
+			row = []
+			for ppem in ppems:
+				widths = self.hdmx[ppem]
+				row.append(widths[glyphName])
+			writer.write(format % ((glyphName,) + tuple(row)))
+			writer.newline()
+		writer.endtag("hdmxData")
+		writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		if name <> "hdmxData":
+			return
+		content = string.join(content, " ")
+		lines = string.split(content, ";")
+		topRow = string.split(lines[0])
+		assert topRow[0] == "ppem:", "illegal hdmx format"
+		ppems = map(int, topRow[1:])
+		self.hdmx = hdmx = {}
+		for ppem in ppems:
+			hdmx[ppem] = {}
+		lines = map(string.split, lines[1:])
+		for line in lines:
+			if not line:
+				continue
+			assert line[0][-1] == ":", "illegal hdmx format"
+			glyphName = line[0][:-1]
+			line = map(int, line[1:])
+			assert len(line) == len(ppems), "illegal hdmx format"
+			for i in range(len(ppems)):
+				hdmx[ppems[i]][glyphName] = line[i]
+
diff --git a/Lib/fontTools/ttLib/tables/_h_e_a_d.py b/Lib/fontTools/ttLib/tables/_h_e_a_d.py
new file mode 100644
index 0000000..fc33edb
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/_h_e_a_d.py
@@ -0,0 +1,136 @@
+import DefaultTable
+import sstruct
+import time
+import string
+import calendar
+from fontTools.misc.textTools import safeEval, num2binary, binary2num
+
+
+headFormat = """
+		>	# big endian
+		tableVersion:		16.16F
+		fontRevision:		16.16F
+		checkSumAdjustment:	l
+		magicNumber:		l
+							x	# pad byte
+		flags:				b
+		unitsPerEm:			H
+		created:			8s
+		modified:			8s
+		xMin:				h
+		yMin:				h
+		xMax:				h
+		yMax:				h
+		macStyle:			H
+		lowestRecPPEM:		H
+		fontDirectionHint:	h
+		indexToLocFormat:	h
+		glyphDataFormat:	h
+"""
+
+class table__h_e_a_d(DefaultTable.DefaultTable):
+	
+	dependencies = ['maxp', 'loca']
+	
+	def decompile(self, data, ttFont):
+		sstruct.unpack(headFormat, data, self)
+		self.unitsPerEm = int(self.unitsPerEm)
+		self.strings2dates()
+	
+	def compile(self, ttFont):
+		self.modified = long(time.time() - mac_epoch_diff)
+		self.dates2strings()
+		data = sstruct.pack(headFormat, self)
+		self.strings2dates()
+		return data
+	
+	def strings2dates(self):
+		self.created = bin2long(self.created)
+		self.modified = bin2long(self.modified)
+	
+	def dates2strings(self):
+		self.created = long2bin(self.created)
+		self.modified = long2bin(self.modified)
+	
+	def toXML(self, writer, ttFont):
+		writer.comment("Most of this table will be recalculated by the compiler")
+		writer.newline()
+		formatstring, names, fixes = sstruct.getformat(headFormat)
+		for name in names:
+			value = getattr(self, name)
+			if name in ("created", "modified"):
+				value = time.asctime(time.gmtime(max(0, value + mac_epoch_diff)))
+			if type(value) == type(0L):
+				value=int(value)
+			if name in ("magicNumber", "checkSumAdjustment"):
+				value = hex(value)
+			elif name == "flags":
+				value = num2binary(value, 16)
+			writer.simpletag(name, value=value)
+			writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		value = attrs["value"]
+		if name in ("created", "modified"):
+			value = parse_date(value) - mac_epoch_diff
+		elif name == "flags":
+			value = binary2num(value)
+		else:
+			value = safeEval(value)
+		setattr(self, name, value)
+	
+	def __cmp__(self, other):
+		selfdict = self.__dict__.copy()
+		otherdict = other.__dict__.copy()
+		# for testing purposes, compare without the modified and checkSumAdjustment
+		# fields, since they are allowed to be different.
+		for key in ["modified", "checkSumAdjustment"]:
+			del selfdict[key]
+			del otherdict[key]
+		return cmp(selfdict, otherdict)
+
+
+def calc_mac_epoch_diff():
+	"""calculate the difference between the original Mac epoch (1904)
+	to the epoch on this machine.
+	"""
+	safe_epoch_t = (1971, 1, 1, 0, 0, 0, 0, 0, 0)
+	safe_epoch = time.mktime(safe_epoch_t) - time.timezone
+	assert time.gmtime(safe_epoch)[:6] == safe_epoch_t[:6]
+	seconds1904to1971 = 60 * 60 * 24 * (365 * (1971-1904) + 17) # thanks, Laurence!
+	return long(safe_epoch - seconds1904to1971)
+
+mac_epoch_diff = calc_mac_epoch_diff()
+
+
+_months = map(string.lower, calendar.month_abbr)
+_weekdays = map(string.lower, calendar.day_abbr)
+
+def parse_date(datestring):
+	datestring = string.lower(datestring)
+	weekday, month, day, tim, year = string.split(datestring)
+	weekday = _weekdays.index(weekday)
+	month = _months.index(month)
+	year = int(year)
+	day = int(day)
+	hour, minute, second = map(int, string.split(tim, ":"))
+	t = (year, month, day, hour, minute, second, weekday, 0, 0)
+	return long(time.mktime(t) - time.timezone)
+
+
+def bin2long(data):
+	# thanks </F>!
+	v = 0L
+	for i in map(ord, data):
+	    v = v<<8 | i
+	return v
+
+def long2bin(v, bytes=8):
+	data = ""
+	while v:
+		data = chr(v & 0xff) + data
+		v = v >> 8
+	data = (bytes - len(data)) * "\0" + data
+	assert len(data) == 8, "long too long"
+	return data
+
diff --git a/Lib/fontTools/ttLib/tables/_h_h_e_a.py b/Lib/fontTools/ttLib/tables/_h_h_e_a.py
new file mode 100644
index 0000000..fca75cb
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/_h_h_e_a.py
@@ -0,0 +1,78 @@
+import DefaultTable
+import sstruct
+from fontTools.misc.textTools import safeEval
+
+hheaFormat = """
+		>	# big endian
+		tableVersion:			16.16F
+		ascent:					h
+		descent:				h
+		lineGap:				h
+		advanceWidthMax:		H
+		minLeftSideBearing:		h
+		minRightSideBearing:	h
+		xMaxExtent:				h
+		caretSlopeRise:			h
+		caretSlopeRun:			h
+		reserved0:				h
+		reserved1:				h
+		reserved2:				h
+		reserved3:				h
+		reserved4:				h
+		metricDataFormat:		h
+		numberOfHMetrics:		H
+"""
+
+class table__h_h_e_a(DefaultTable.DefaultTable):
+	
+	dependencies = ['hmtx', 'glyf']
+	
+	def decompile(self, data, ttFont):
+		sstruct.unpack(hheaFormat, data, self)
+	
+	def compile(self, ttFont):
+		self.recalc(ttFont)
+		return sstruct.pack(hheaFormat, self)
+	
+	def recalc(self, ttFont):
+		hmtxTable = ttFont['hmtx']
+		if ttFont.has_key('glyf'):
+			if not ttFont.isLoaded('glyf'):
+				return
+			glyfTable = ttFont['glyf']
+			advanceWidthMax = -100000    # arbitrary big negative number
+			minLeftSideBearing = 100000  # arbitrary big number
+			minRightSideBearing = 100000 # arbitrary big number
+			xMaxExtent = -100000         # arbitrary big negative number
+			
+			for name in ttFont.getGlyphOrder():
+				width, lsb = hmtxTable[name]
+				g = glyfTable[name]
+				if g.numberOfContours <= 0:
+					continue
+				advanceWidthMax = max(advanceWidthMax, width)
+				minLeftSideBearing = min(minLeftSideBearing, lsb)
+				rsb = width - lsb - (g.xMax - g.xMin)
+				minRightSideBearing = min(minRightSideBearing, rsb)
+				extent = lsb + (g.xMax - g.xMin)
+				xMaxExtent = max(xMaxExtent, extent)
+			self.advanceWidthMax = advanceWidthMax
+			self.minLeftSideBearing = minLeftSideBearing
+			self.minRightSideBearing = minRightSideBearing
+			self.xMaxExtent = xMaxExtent
+		else:
+			# XXX CFF recalc...
+			pass
+	
+	def toXML(self, writer, ttFont):
+		formatstring, names, fixes = sstruct.getformat(hheaFormat)
+		for name in names:
+			value = getattr(self, name)
+			if type(value) == type(0L):
+				value = int(value)
+			writer.simpletag(name, value=value)
+			writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		setattr(self, name, safeEval(attrs["value"]))
+
diff --git a/Lib/fontTools/ttLib/tables/_h_m_t_x.py b/Lib/fontTools/ttLib/tables/_h_m_t_x.py
new file mode 100644
index 0000000..35fa8cd
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/_h_m_t_x.py
@@ -0,0 +1,94 @@
+import DefaultTable
+import Numeric
+from fontTools import ttLib
+from fontTools.misc.textTools import safeEval
+
+
+class table__h_m_t_x(DefaultTable.DefaultTable):
+	
+	headerTag = 'hhea'
+	advanceName = 'width'
+	sideBearingName = 'lsb'
+	numberOfMetricsName = 'numberOfHMetrics'
+	
+	def decompile(self, data, ttFont):
+		numberOfMetrics = int(getattr(ttFont[self.headerTag], self.numberOfMetricsName))
+		metrics = Numeric.fromstring(data[:4 * numberOfMetrics], 
+				Numeric.Int16)
+		if ttLib.endian <> "big":
+			metrics = metrics.byteswapped()
+		metrics.shape = (numberOfMetrics, 2)
+		data = data[4 * numberOfMetrics:]
+		numberOfSideBearings = ttFont['maxp'].numGlyphs - numberOfMetrics
+		numberOfSideBearings = int(numberOfSideBearings)
+		if numberOfSideBearings:
+			assert numberOfSideBearings > 0, "bad hmtx/vmtx table"
+			lastAdvance = metrics[-1][0]
+			advances = Numeric.array([lastAdvance] * numberOfSideBearings, 
+					Numeric.Int16)
+			sideBearings = Numeric.fromstring(data[:2 * numberOfSideBearings], 
+					Numeric.Int16)
+			if ttLib.endian <> "big":
+				sideBearings = sideBearings.byteswapped()
+			data = data[2 * numberOfSideBearings:]
+			additionalMetrics = Numeric.array([advances, sideBearings], 
+					Numeric.Int16)
+			metrics = Numeric.concatenate((metrics, 
+					Numeric.transpose(additionalMetrics)))
+		if data:
+			raise  ttLib.TTLibError, "too much data for hmtx/vmtx table"
+		metrics = metrics.tolist()
+		self.metrics = {}
+		for i in range(len(metrics)):
+			glyphName = ttFont.getGlyphName(i)
+			self.metrics[glyphName] = metrics[i]
+	
+	def compile(self, ttFont):
+		metrics = []
+		for glyphName in ttFont.getGlyphOrder():
+			metrics.append(self.metrics[glyphName])
+		lastAdvance = metrics[-1][0]
+		lastIndex = len(metrics)
+		while metrics[lastIndex-2][0] == lastAdvance:
+			lastIndex = lastIndex - 1
+		additionalMetrics = metrics[lastIndex:]
+		additionalMetrics = map(lambda (advance, sb): sb, additionalMetrics)
+		metrics = metrics[:lastIndex]
+		setattr(ttFont[self.headerTag], self.numberOfMetricsName, len(metrics))
+		
+		metrics = Numeric.array(metrics, Numeric.Int16)
+		if ttLib.endian <> "big":
+			metrics = metrics.byteswapped()
+		data = metrics.tostring()
+		
+		additionalMetrics = Numeric.array(additionalMetrics, Numeric.Int16)
+		if ttLib.endian <> "big":
+			additionalMetrics = additionalMetrics.byteswapped()
+		data = data + additionalMetrics.tostring()
+		return data
+	
+	def toXML(self, writer, ttFont):
+		names = self.metrics.keys()
+		names.sort()
+		for glyphName in names:
+			advance, sb = self.metrics[glyphName]
+			writer.simpletag("mtx", [
+					("name", glyphName), 
+					(self.advanceName, advance), 
+					(self.sideBearingName, sb),
+					])
+			writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		if not hasattr(self, "metrics"):
+			self.metrics = {}
+		if name == "mtx":
+			self.metrics[attrs["name"]] = [safeEval(attrs[self.advanceName]), 
+					safeEval(attrs[self.sideBearingName])]
+	
+	def __getitem__(self, glyphName):
+		return self.metrics[glyphName]
+	
+	def __setitem__(self, glyphName, (advance, sb)):
+		self.metrics[glyphName] = advance, sb
+
diff --git a/Lib/fontTools/ttLib/tables/_k_e_r_n.py b/Lib/fontTools/ttLib/tables/_k_e_r_n.py
new file mode 100644
index 0000000..283c52f
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/_k_e_r_n.py
@@ -0,0 +1,186 @@
+import DefaultTable
+import struct
+import ttLib.sfnt
+from fontTools.misc.textTools import safeEval, readHex
+
+
+class table__k_e_r_n(DefaultTable.DefaultTable):
+	
+	def getkern(self, format):
+		for subtable in self.kernTables:
+			if subtable.version == format:
+				return subtable
+		return None  # not found
+	
+	def decompile(self, data, ttFont):
+		version, nTables = struct.unpack(">HH", data[:4])
+		if version == 1:
+			# Apple's new format. Hm.
+			version, nTables = struct.unpack(">ll", data[:8])
+			self.version = version / float(0x10000)
+			data = data[8:]
+		else:
+			self.version = version
+			data = data[4:]
+		tablesIndex = []
+		self.kernTables = []
+		for i in range(nTables):
+			version, length = struct.unpack(">HH", data[:4])
+			length = int(length)
+			if not kern_classes.has_key(version):
+				subtable = KernTable_format_unkown()
+			else:
+				subtable = kern_classes[version]()
+			subtable.decompile(data[:length], ttFont)
+			self.kernTables.append(subtable)
+			data = data[length:]
+	
+	def compile(self, ttFont):
+		nTables = len(self.kernTables)
+		if self.version == 1.0:
+			# Apple's new format.
+			data = struct.pack(">ll", self.version * 0x1000, nTables)
+		else:
+			data = struct.pack(">HH", self.version, nTables)
+		for subtable in self.kernTables:
+			data = data + subtable.compile(ttFont)
+		return data
+	
+	def toXML(self, writer, ttFont):
+		writer.simpletag("version", value=self.version)
+		writer.newline()
+		for subtable in self.kernTables:
+			subtable.toXML(writer, ttFont)
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		if name == "version":
+			self.version = safeEval(attrs["value"])
+			return
+		if name <> "kernsubtable":
+			return
+		if not hasattr(self, "kernTables"):
+			self.kernTables = []
+		format = safeEval(attrs["format"])
+		if not kern_classes.has_key(format):
+			subtable = KernTable_format_unkown()
+		else:
+			subtable = kern_classes[format]()
+		self.kernTables.append(subtable)
+		subtable.fromXML((name, attrs, content), ttFont)
+
+
+class KernTable_format_0:
+	
+	def decompile(self, data, ttFont):
+		version, length, coverage = struct.unpack(">HHH", data[:6])
+		self.version, self.coverage = int(version), int(coverage)
+		data = data[6:]
+		
+		self.kernTable = kernTable = {}
+		
+		nPairs, searchRange, entrySelector, rangeShift = struct.unpack(">HHHH", data[:8])
+		data = data[8:]
+		
+		for k in range(nPairs):
+			left, right, value = struct.unpack(">HHh", data[:6])
+			data = data[6:]
+			left, right = int(left), int(right)
+			kernTable[(ttFont.getGlyphName(left), ttFont.getGlyphName(right))] = value
+		assert len(data) == 0
+	
+	def compile(self, ttFont):
+		nPairs = len(self.kernTable)
+		entrySelector = ttLib.sfnt.maxpoweroftwo(nPairs)
+		searchRange = (2 ** entrySelector) * 6
+		rangeShift = (nPairs - (2 ** entrySelector)) * 6
+		data = struct.pack(">HHHH", nPairs, searchRange, entrySelector, rangeShift)
+		
+		# yeehee! (I mean, turn names into indices)
+		kernTable = map(lambda ((left, right), value), getGlyphID=ttFont.getGlyphID:
+					(getGlyphID(left), getGlyphID(right), value), 
+				self.kernTable.items())
+		kernTable.sort()
+		for left, right, value in kernTable:
+			data = data + struct.pack(">HHh", left, right, value)
+		return struct.pack(">HHH", self.version, len(data) + 6, self.coverage) + data
+	
+	def toXML(self, writer, ttFont):
+		writer.begintag("kernsubtable", coverage=self.coverage, format=0)
+		writer.newline()
+		items = self.kernTable.items()
+		items.sort()
+		for (left, right), value in items:
+			writer.simpletag("pair", [
+					("l", left),
+					("r", right),
+					("v", value)
+					])
+			writer.newline()
+		writer.endtag("kernsubtable")
+		writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		self.coverage = safeEval(attrs["coverage"])
+		self.version = safeEval(attrs["format"])
+		if not hasattr(self, "kernTable"):
+			self.kernTable = {}
+		for element in content:
+			if type(element) <> type(()):
+				continue
+			name, attrs, content = element
+			self.kernTable[(attrs["l"], attrs["r"])] = safeEval(attrs["v"])
+	
+	def __getitem__(self, pair):
+		return self.kernTable[pair]
+	
+	def __setitem__(self, pair, value):
+		self.kernTable[pair] = value
+	
+	def __delitem__(self, pair):
+		del self.kernTable[pair]
+	
+	def __cmp__(self, other):
+		return cmp(self.__dict__, other.__dict__)
+
+
+class KernTable_format_2:
+	
+	def decompile(self, data, ttFont):
+		self.data = data
+	
+	def compile(self, ttFont, ttFont):
+		return data
+	
+	def toXML(self, writer):
+		writer.begintag("kernsubtable", format=2)
+		writer.newline()
+		writer.dumphex(self.data)
+		writer.endtag("kernsubtable")
+		writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		self.decompile(readHex(content))
+
+
+class KernTable_format_unkown:
+	
+	def decompile(self, data, ttFont):
+		self.data = data
+	
+	def compile(self, ttFont):
+		return data
+	
+	def toXML(self, writer, ttFont):
+		writer.begintag("kernsubtable", format="-1")
+		writer.newline()
+		writer.comment("unknown 'kern' subtable format")
+		writer.dumphex(self.data)
+		writer.endtag("kernsubtable")
+		writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		self.decompile(readHex(content))
+
+
+
+kern_classes = {0: KernTable_format_0, 1: KernTable_format_2}
diff --git a/Lib/fontTools/ttLib/tables/_l_o_c_a.py b/Lib/fontTools/ttLib/tables/_l_o_c_a.py
new file mode 100644
index 0000000..332a708
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/_l_o_c_a.py
@@ -0,0 +1,55 @@
+import DefaultTable
+import array
+import Numeric
+from fontTools import ttLib
+import struct
+
+class table__l_o_c_a(DefaultTable.DefaultTable):
+	
+	dependencies = ['glyf']
+	
+	def decompile(self, data, ttFont):
+		longFormat = ttFont['head'].indexToLocFormat
+		if longFormat:
+			format = "l"
+		else:
+			format = "H"
+		locations = array.array(format)
+		locations.fromstring(data)
+		if ttLib.endian <> "big":
+			locations.byteswap()
+		locations = Numeric.array(locations, Numeric.Int32)
+		if not longFormat:
+			locations = locations * 2
+		if len(locations) <> (ttFont['maxp'].numGlyphs + 1):
+			raise  ttLib.TTLibError, "corrupt 'loca' table"
+		self.locations = locations
+	
+	def compile(self, ttFont):
+		locations = self.locations
+		if max(locations) < 0x20000:
+			locations = locations / 2
+			locations = locations.astype(Numeric.Int16)
+			ttFont['head'].indexToLocFormat = 0
+		else:
+			ttFont['head'].indexToLocFormat = 1
+		if ttLib.endian <> "big":
+			locations = locations.byteswapped()
+		return locations.tostring()
+	
+	def set(self, locations):
+		self.locations = Numeric.array(locations, Numeric.Int32)
+	
+	def toXML(self, writer, ttFont):
+		writer.comment("The 'loca' table will be calculated by the compiler")
+		writer.newline()
+	
+	def __getitem__(self, index):
+		return self.locations[index]
+	
+	def __len__(self):
+		return len(self.locations)
+	
+	def __cmp__(self, other):
+		return cmp(len(self), len(other)) or not Numeric.alltrue(Numeric.equal(self.locations, other.locations))
+
diff --git a/Lib/fontTools/ttLib/tables/_m_a_x_p.py b/Lib/fontTools/ttLib/tables/_m_a_x_p.py
new file mode 100644
index 0000000..1c75e6d
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/_m_a_x_p.py
@@ -0,0 +1,138 @@
+import DefaultTable
+import sstruct
+from fontTools.misc.textTools import safeEval
+
+maxpFormat_0_5 = """
+		>	# big endian
+		tableVersion:			i
+		numGlyphs:				H
+"""
+
+maxpFormat_1_0_add = """
+		>	# big endian
+		maxPoints:				H
+		maxContours:			H
+		maxCompositePoints:		H
+		maxCompositeContours:	H
+		maxZones:				H
+		maxTwilightPoints:		H
+		maxStorage:				H
+		maxFunctionDefs:		H
+		maxInstructionDefs:		H
+		maxStackElements:		H
+		maxSizeOfInstructions:	H
+		maxComponentElements:	H
+		maxComponentDepth:		H
+"""
+
+
+class table__m_a_x_p(DefaultTable.DefaultTable):
+	
+	dependencies = ['glyf']
+	
+	def decompile(self, data, ttFont):
+		dummy, data = sstruct.unpack2(maxpFormat_0_5, data, self)
+		self.numGlyphs = int(self.numGlyphs)
+		if self.tableVersion == 0x00010000:
+			dummy, data = sstruct.unpack2(maxpFormat_1_0_add, data, self)
+		else:
+			assert self.tableVersion == 0x00005000, "unknown 'maxp' format: %x" % self.tableVersion
+		assert len(data) == 0
+	
+	def compile(self, ttFont):
+		if ttFont.has_key('glyf'):
+			if ttFont.isLoaded('glyf'):
+				self.recalc(ttFont)
+		else:
+			pass # XXX CFF!!!
+		data = sstruct.pack(maxpFormat_0_5, self)
+		if self.tableVersion == 0x00010000:
+			data = data + sstruct.pack(maxpFormat_1_0_add, self)
+		else:
+			assert self.tableVersion == 0x00005000, "unknown 'maxp' format: %f" % self.tableVersion
+		return data
+	
+	def recalc(self, ttFont):
+		"""Recalculate the font bounding box, and most other maxp values except
+		for the TT instructions values. Also recalculate the value of bit 1
+		of the flags field of the 'head' table.
+		"""
+		glyfTable = ttFont['glyf']
+		hmtxTable = ttFont['hmtx']
+		headTable = ttFont['head']
+		self.numGlyphs = len(glyfTable)
+		xMin = 100000
+		yMin = 100000
+		xMax = -100000
+		yMax = -100000
+		maxPoints = 0
+		maxContours = 0
+		maxCompositePoints = 0
+		maxCompositeContours = 0
+		maxComponentElements = 0
+		maxComponentDepth = 0
+		allXMaxIsLsb = 1
+		for glyphName in ttFont.getGlyphOrder():
+			g = glyfTable[glyphName]
+			if g.numberOfContours:
+				if hmtxTable[glyphName][1] <> g.xMin:
+					allXMaxIsLsb = 0
+				xMin = min(xMin, g.xMin)
+				yMin = min(yMin, g.yMin)
+				xMax = max(xMax, g.xMax)
+				yMax = max(yMax, g.yMax)
+				if g.numberOfContours > 0:
+					nPoints, nContours = g.getMaxpValues()
+					maxPoints = max(maxPoints, nPoints)
+					maxContours = max(maxContours, nContours)
+				else:
+					nPoints, nContours, componentDepth = g.getCompositeMaxpValues(glyfTable)
+					maxCompositePoints = max(maxCompositePoints, nPoints)
+					maxCompositeContours = max(maxCompositeContours, nContours)
+					maxComponentElements = max(maxComponentElements, len(g.components))
+					maxComponentDepth = max(maxComponentDepth, componentDepth)
+		self.xMin = xMin
+		self.yMin = yMin
+		self.xMax = xMax
+		self.yMax = yMax
+		self.maxPoints = maxPoints
+		self.maxContours = maxContours
+		self.maxCompositePoints = maxCompositePoints
+		self.maxCompositeContours = maxCompositeContours
+		self.maxComponentDepth = maxComponentDepth
+		if allXMaxIsLsb:
+			headTable.flags = headTable.flags | 0x2
+		else:
+			headTable.flags = headTable.flags & ~0x2
+	
+	def testrepr(self):
+		items = self.__dict__.items()
+		items.sort()
+		print ". . . . . . . . ."
+		for combo in items:
+			print "  %s: %s" % combo
+		print ". . . . . . . . ."
+	
+	def toXML(self, writer, ttFont):
+		if self.tableVersion <> 0x00005000:
+			writer.comment("Most of this table will be recalculated by the compiler")
+			writer.newline()
+		formatstring, names, fixes = sstruct.getformat(maxpFormat_0_5)
+		if self.tableVersion == 0x00010000:
+			formatstring, names_1_0, fixes = sstruct.getformat(maxpFormat_1_0_add)
+			names = names + names_1_0
+		else:
+			assert self.tableVersion == 0x00005000, "unknown 'maxp' format: %f" % self.tableVersion
+		for name in names:
+			value = getattr(self, name)
+			if type(value) == type(0L):
+				value=int(value)
+			if name == "tableVersion":
+				value = hex(value)
+			writer.simpletag(name, value=value)
+			writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		setattr(self, name, safeEval(attrs["value"]))
+		
+
diff --git a/Lib/fontTools/ttLib/tables/_n_a_m_e.py b/Lib/fontTools/ttLib/tables/_n_a_m_e.py
new file mode 100644
index 0000000..05cde33
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/_n_a_m_e.py
@@ -0,0 +1,136 @@
+import DefaultTable
+import struct, sstruct
+from fontTools.misc.textTools import safeEval
+import string
+import types
+
+nameRecordFormat = """
+		>	# big endian
+		platformID:	H
+		platEncID:	H
+		langID:		H
+		nameID:		H
+		length:		H
+		offset:		H
+"""
+
+class table__n_a_m_e(DefaultTable.DefaultTable):
+	
+	def decompile(self, data, ttFont):
+		format, n, stringoffset = struct.unpack(">HHH", data[:6])
+		stringoffset = int(stringoffset)
+		stringData = data[stringoffset:]
+		data = data[6:stringoffset]
+		self.names = []
+		for i in range(n):
+			name, data = sstruct.unpack2(nameRecordFormat, data, NameRecord())
+			name.fixlongs()
+			name.string = stringData[name.offset:name.offset+name.length]
+			del name.offset, name.length
+			self.names.append(name)
+	
+	def compile(self, ttFont):
+		self.names.sort()  # sort according to the spec; see NameRecord.__cmp__()
+		stringData = ""
+		format = 0
+		n = len(self.names)
+		stringoffset = 6 + n * sstruct.calcsize(nameRecordFormat)
+		data = struct.pack(">HHH", format, n, stringoffset)
+		lastoffset = 0
+		done = {}  # remember the data so we can reuse the "pointers"
+		for name in self.names:
+			if done.has_key(name.string):
+				name.offset, name.length = done[name.string]
+			else:
+				name.offset, name.length = done[name.string] = len(stringData), len(name.string)
+				stringData = stringData + name.string
+			data = data + sstruct.pack(nameRecordFormat, name)
+		return data + stringData
+	
+	def toXML(self, writer, ttFont):
+		for name in self.names:
+			name.toXML(writer, ttFont)
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		if name <> "namerecord":
+			return # ignore unknown tags
+		if not hasattr(self, "names"):
+			self.names = []
+		name = NameRecord()
+		self.names.append(name)
+		name.fromXML((name, attrs, content), ttFont)
+	
+	def getname(self, nameID, platformID, platEncID, langID=None):
+		for namerecord in self.names:
+			if (	namerecord.nameID == nameID and 
+					namerecord.platformID == platformID and 
+					namerecord.platEncID == platEncID):
+				if langID is None or namerecord.langID == langID:
+					return namerecord
+		return None # not found
+	
+	def __cmp__(self, other):
+		return cmp(self.names, other.names)
+	
+
+class NameRecord:
+	
+	def toXML(self, writer, ttFont):
+		writer.begintag("namerecord", [
+				("nameID", self.nameID),
+				("platformID", self.platformID),
+				("platEncID", self.platEncID),
+				("langID", hex(self.langID)),
+						])
+		writer.newline()
+		if self.platformID == 0 or (self.platformID == 3 and self.platEncID == 1):
+			writer.write16bit(self.string)
+		else:
+			writer.write8bit(self.string)
+		writer.newline()
+		writer.endtag("namerecord")
+		writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		self.nameID = safeEval(attrs["nameID"])
+		self.platformID = safeEval(attrs["platformID"])
+		self.platEncID = safeEval(attrs["platEncID"])
+		self.langID =  safeEval(attrs["langID"])
+		if self.platformID == 0 or (self.platformID == 3 and self.platEncID == 1):
+			from fontTools.ttLib.xmlImport import UnicodeString
+			str = UnicodeString("")
+			for element in content:
+				str = str + element
+			self.string = str.stripped().tostring()
+		else:
+			self.string = string.strip(string.join(content, ""))
+	
+	def __cmp__(self, other):
+		"""Compare method, so a list of NameRecords can be sorted
+		according to the spec by just sorting it..."""
+		selftuple = (self.platformID,
+				self.platEncID,
+				self.langID,
+				self.nameID,
+				self.string)
+		othertuple = (other.platformID,
+				other.platEncID,
+				other.langID,
+				other.nameID,
+				other.string)
+		return cmp(selftuple, othertuple)
+	
+	def __repr__(self):
+		return "<NameRecord NameID=%d; PlatformID=%d; LanguageID=%d>" % (
+				self.nameID, self.platformID, self.langID)
+	
+	def fixlongs(self):
+		"""correct effects from bug in Python 1.5.1, where "H" 
+		returns a Python Long int. 
+		This has been fixed in Python 1.5.2.
+		"""
+		for attr in dir(self):
+			val = getattr(self, attr)
+			if type(val) == types.LongType:
+				setattr(self, attr, int(val))
+
diff --git a/Lib/fontTools/ttLib/tables/_p_o_s_t.py b/Lib/fontTools/ttLib/tables/_p_o_s_t.py
new file mode 100644
index 0000000..273de79
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/_p_o_s_t.py
@@ -0,0 +1,214 @@
+from fontTools.ttLib.standardGlyphOrder import standardGlyphOrder
+import DefaultTable
+import struct, sstruct
+import array
+from fontTools import ttLib
+from fontTools.misc.textTools import safeEval, readHex
+
+
+postFormat = """
+	>
+	formatType:			16.16F
+	italicAngle:		16.16F		# italic angle in degrees			
+	underlinePosition:	h
+	underlineThickness:	h
+	isFixedPitch:		l
+	minMemType42:		l			# minimum memory if TrueType font is downloaded
+	maxMemType42:		l			# maximum memory if TrueType font is downloaded
+	minMemType1:		l			# minimum memory if Type1 font is downloaded
+	maxMemType1:		l			# maximum memory if Type1 font is downloaded
+"""
+
+postFormatSize = sstruct.calcsize(postFormat)
+
+
+class table__p_o_s_t(DefaultTable.DefaultTable):
+	
+	def decompile(self, data, ttFont):
+		sstruct.unpack(postFormat, data[:postFormatSize], self)
+		data = data[postFormatSize:]
+		if self.formatType == 1.0:
+			self.decode_format_1_0(data, ttFont)
+		elif self.formatType == 2.0:
+			self.decode_format_2_0(data, ttFont)
+		elif self.formatType == 3.0:
+			self.decode_format_3_0(data, ttFont)
+		else:
+			# supported format
+			raise ttLib.TTLibError, "'post' table format %f not supported" % self.formatType
+	
+	def compile(self, ttFont):
+		data = sstruct.pack(postFormat, self)
+		if self.formatType == 1.0:
+			pass # we're done
+		elif self.formatType == 2.0:
+			data = data + self.encode_format_2_0(ttFont)
+		elif self.formatType == 3.0:
+			pass # we're done
+		else:
+			# supported format
+			raise ttLib.TTLibError, "'post' table format %f not supported" % self.formatType
+		return data
+	
+	def getGlyphOrder(self):
+		"""This function will get called by a ttLib.TTFont instance.
+		Do not call this function yourself, use TTFont().getGlyphOrder()
+		or its relatives instead!
+		"""
+		if not hasattr(self, "glyphOrder"):
+			raise ttLib.TTLibError, "illegal use of getGlyphOrder()"
+		glyphOrder = self.glyphOrder
+		del self.glyphOrder
+		return glyphOrder
+	
+	def decode_format_1_0(self, data, ttFont):
+		self.glyphOrder = standardGlyphOrder[:]
+	
+	def decode_format_2_0(self, data, ttFont):
+		numGlyphs, = struct.unpack(">H", data[:2])
+		numGlyphs = int(numGlyphs)
+		data = data[2:]
+		indices = array.array("H")
+		indices.fromstring(data[:2*numGlyphs])
+		if ttLib.endian <> "big":
+			indices.byteswap()
+		data = data[2*numGlyphs:]
+		self.extraNames = extraNames = unpackPStrings(data)
+		self.glyphOrder = glyphOrder = [None] * int(ttFont['maxp'].numGlyphs)
+		for glyphID in range(numGlyphs):
+			index = indices[glyphID]
+			if index > 257:
+				name = extraNames[index-258]
+			else:
+				# fetch names from standard list
+				name = standardGlyphOrder[index]
+			glyphOrder[glyphID] = name
+		#AL990511: code added to handle the case of new glyphs without
+		#          entries into the 'post' table
+		if numGlyphs < ttFont['maxp'].numGlyphs:
+			for i in range(numGlyphs, ttFont['maxp'].numGlyphs):
+				glyphOrder[i] = "glyph#%.5d" % i
+				self.extraNames.append(glyphOrder[i])
+		self.build_psNameMapping(ttFont)
+	
+	def build_psNameMapping(self, ttFont):
+		mapping = {}
+		allNames = {}
+		for i in range(ttFont['maxp'].numGlyphs):
+			glyphName = psName = self.glyphOrder[i]
+			if allNames.has_key(glyphName):
+				# make up a new glyphName that's unique
+				n = 1
+				while allNames.has_key(glyphName + "#" + `n`):
+					n = n + 1
+				glyphName = glyphName + "#" + `n`
+				self.glyphOrder[i] = glyphName
+				mapping[glyphName] = psName
+			allNames[glyphName] = psName
+		self.mapping = mapping
+	
+	def decode_format_3_0(self, data, ttFont):
+		# Setting self.glyphOrder to None will cause the TTFont object
+		# try and construct glyph names from a Unicode cmap table.
+		self.glyphOrder = None
+	
+	def encode_format_2_0(self, ttFont):
+		numGlyphs = ttFont['maxp'].numGlyphs
+		glyphOrder = ttFont.getGlyphOrder()
+		assert len(glyphOrder) == numGlyphs
+		indices = array.array("H")
+		for glyphID in range(numGlyphs):
+			glyphName = glyphOrder[glyphID]
+			if self.mapping.has_key(glyphName):
+				psName = self.mapping[glyphName]
+			else:
+				psName = glyphName
+			if psName in self.extraNames:
+				index = 258 + self.extraNames.index(psName)
+			elif psName in standardGlyphOrder:
+				index = standardGlyphOrder.index(psName)
+			else:
+				index = 258 + len(self.extraNames)
+				extraNames.append(psName)
+			indices.append(index)
+		if ttLib.endian <> "big":
+			indices.byteswap()
+		return struct.pack(">H", numGlyphs) + indices.tostring() + packPStrings(self.extraNames)
+	
+	def toXML(self, writer, ttFont):
+		formatstring, names, fixes = sstruct.getformat(postFormat)
+		for name in names:
+			value = getattr(self, name)
+			writer.simpletag(name, value=value)
+			writer.newline()
+		if hasattr(self, "mapping"):
+			writer.begintag("psNames")
+			writer.newline()
+			writer.comment("This file uses unique glyph names based on the information\n"
+						"found in the 'post' table. Since these names might not be unique,\n"
+						"we have to invent artificial names in case of clashes. In order to\n"
+						"be able to retain the original information, we need a name to\n"
+						"ps name mapping for those cases where they differ. That's what\n"
+						"you see below.\n")
+			writer.newline()
+			items = self.mapping.items()
+			items.sort()
+			for name, psName in items:
+				writer.simpletag("psName", name=name, psName=psName)
+				writer.newline()
+			writer.endtag("psNames")
+			writer.newline()
+		if hasattr(self, "extraNames"):
+			writer.begintag("extraNames")
+			writer.newline()
+			writer.comment("following are the name that are not taken from the standard Mac glyph order")
+			writer.newline()
+			for name in self.extraNames:
+				writer.simpletag("psName", name=name)
+				writer.newline()
+			writer.endtag("extraNames")
+			writer.newline()
+		if hasattr(self, "data"):
+			writer.begintag("hexdata")
+			writer.newline()
+			writer.dumphex(self.data)
+			writer.endtag("hexdata")
+			writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		if name not in ("psNames", "extraNames", "hexdata"):
+			setattr(self, name, safeEval(attrs["value"]))
+		elif name == "psNames":
+			self.mapping = {}
+			for element in content:
+				if type(element) <> type(()):
+					continue
+				name, attrs, content = element
+				if name == "psName":
+					self.mapping[attrs["name"]] = attrs["psName"]
+		elif name == "extraNames":
+			self.extraNames = []
+			for element in content:
+				if type(element) <> type(()):
+					continue
+				name, attrs, content = element
+				if name == "psName":
+					self.extraNames.append(attrs["name"])
+		else:
+			self.data = readHex(content)
+
+
+def unpackPStrings(data):
+	strings = []
+	while data:
+		length = ord(data[0])
+		strings.append(data[1:1+length])
+		data = data[1+length:]
+	return strings
+
+def packPStrings(strings):
+	data = ""
+	for s in strings:
+		data = data + chr(len(s)) + s
+	return data
+
diff --git a/Lib/fontTools/ttLib/tables/_p_r_e_p.py b/Lib/fontTools/ttLib/tables/_p_r_e_p.py
new file mode 100644
index 0000000..005c8ee
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/_p_r_e_p.py
@@ -0,0 +1,14 @@
+import DefaultTable
+import array
+
+class table__p_r_e_p(DefaultTable.DefaultTable):
+	
+	def decompile(self, data, ttFont):
+		self.prep = data
+	
+	def compile(self, ttFont):
+		return self.prep
+	
+	def __len__(self):
+		return len(self.prep)
+	
diff --git a/Lib/fontTools/ttLib/tables/_v_h_e_a.py b/Lib/fontTools/ttLib/tables/_v_h_e_a.py
new file mode 100644
index 0000000..43fd614
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/_v_h_e_a.py
@@ -0,0 +1,78 @@
+import DefaultTable
+import sstruct
+from fontTools.misc.textTools import safeEval
+
+vheaFormat = """
+		>	# big endian
+		tableVersion:			16.16F
+		ascent:					h
+		descent:				h
+		lineGap:				h
+		advanceHeightMax:		H
+		minTopSideBearing:		h
+		minBottomSideBearing:	h
+		yMaxExtent:				h
+		caretSlopeRise:			h
+		caretSlopeRun:			h
+		reserved0:				h
+		reserved1:				h
+		reserved2:				h
+		reserved3:				h
+		reserved4:				h
+		metricDataFormat:		h
+		numberOfVMetrics:		H
+"""
+
+class table__v_h_e_a(DefaultTable.DefaultTable):
+	
+	dependencies = ['vmtx', 'glyf']
+	
+	def decompile(self, data, ttFont):
+		sstruct.unpack(vheaFormat, data, self)
+	
+	def compile(self, ttFont):
+		self.recalc(ttFont)
+		return sstruct.pack(vheaFormat, self)
+	
+	def recalc(self, ttFont):
+		vtmxTable = ttFont['vmtx']
+		if ttFont.has_key('glyf'):
+			if not ttFont.isLoaded('glyf'):
+				return
+			glyfTable = ttFont['glyf']
+			advanceHeightMax = -100000    # arbitrary big negative number
+			minTopSideBearing = 100000    # arbitrary big number
+			minBottomSideBearing = 100000 # arbitrary big number
+			yMaxExtent = -100000          # arbitrary big negative number
+			
+			for name in ttFont.getGlyphOrder():
+				height, tsb = vtmxTable[name]
+				g = glyfTable[name]
+				if g.numberOfContours <= 0:
+					continue
+				advanceHeightMax = max(advanceHeightMax, height)
+				minTopSideBearing = min(minTopSideBearing, tsb)
+				rsb = height - tsb - (g.yMax - g.yMin)
+				minBottomSideBearing = min(minBottomSideBearing, rsb)
+				extent = tsb + (g.yMax - g.yMin)
+				yMaxExtent = max(yMaxExtent, extent)
+			self.advanceHeightMax = advanceHeightMax
+			self.minTopSideBearing = minTopSideBearing
+			self.minBottomSideBearing = minBottomSideBearing
+			self.yMaxExtent = yMaxExtent
+		else:
+			# XXX CFF recalc...
+			pass
+	
+	def toXML(self, writer, ttFont):
+		formatstring, names, fixes = sstruct.getformat(vheaFormat)
+		for name in names:
+			value = getattr(self, name)
+			if type(value) == type(0L):
+				value = int(value)
+			writer.simpletag(name, value=value)
+			writer.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		setattr(self, name, safeEval(attrs["value"]))
+
diff --git a/Lib/fontTools/ttLib/tables/_v_m_t_x.py b/Lib/fontTools/ttLib/tables/_v_m_t_x.py
new file mode 100644
index 0000000..dabefe6
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/_v_m_t_x.py
@@ -0,0 +1,14 @@
+import DefaultTable
+import Numeric
+from fontTools import ttLib
+from fontTools.misc.textTools import safeEval
+
+superclass = ttLib.getTableClass("hmtx")
+
+class table__v_m_t_x(superclass):
+	
+	headerTag = 'vhea'
+	advanceName = 'height'
+	sideBearingName = 'tsb'
+	numberOfMetricsName = 'numberOfVMetrics'
+
diff --git a/Lib/fontTools/ttLib/tables/otCommon.py b/Lib/fontTools/ttLib/tables/otCommon.py
new file mode 100644
index 0000000..c312c63
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/otCommon.py
@@ -0,0 +1,605 @@
+"""ttLib.tables.otCommon.py -- Various data structures used by various OpenType tables.
+"""
+
+import struct, sstruct
+import DefaultTable
+from fontTools import ttLib
+
+
+class base_GPOS_GSUB(DefaultTable.DefaultTable):
+	
+	"""Base class for GPOS and GSUB tables; they share the same high-level structure."""
+	
+	version = 0x00010000
+	
+	def decompile(self, data, otFont):
+		reader = OTTableReader(data)
+		self.version = reader.readLong()
+		if self.version <> 0x00010000:
+			raise ttLib.TTLibError, "unknown table version: 0x%8x" % self.version
+		
+		self.scriptList = reader.readTable(ScriptList, otFont, self.tableTag)
+		self.featureList = reader.readTable(FeatureList, otFont, self.tableTag)
+		self.lookupList = reader.readTable(LookupList, otFont, self.tableTag)
+	
+	def compile(self, otFont):
+		XXXXXX
+	
+	def toXML(self, xmlWriter, otFont):
+		names = [("ScriptList", "scriptList"), 
+				("FeatureList", "featureList"), 
+				("LookupList", "lookupList")]
+		for name, attr in names:
+			xmlWriter.newline()
+			xmlWriter.begintag(name)
+			xmlWriter.newline()
+			table = getattr(self, attr)
+			table.toXML(xmlWriter, otFont)
+			xmlWriter.endtag(name)
+			xmlWriter.newline()
+		xmlWriter.newline()
+	
+	def fromXML(self, (name, attrs, content), otFont):
+		xxx
+
+
+#
+# Script List and subtables
+#
+
+class ScriptList:
+	
+	def __init__(self, parentTag):
+		self.parentTag = parentTag
+	
+	def decompile(self, reader, otFont):
+		scriptCount = reader.readUShort()
+		self.scripts = reader.readTagList(scriptCount, Script, otFont)
+	
+	def compile(self, otFont):
+		XXXXXX
+	
+	def toXML(self, xmlWriter, otFont):
+		for tag, script in self.scripts:
+			xmlWriter.begintag("Script", tag=tag)
+			xmlWriter.newline()
+			script.toXML(xmlWriter, otFont)
+			xmlWriter.endtag("Script")
+			xmlWriter.newline()
+	
+	def fromXML(self, (name, attrs, content), otFont):
+		xxx
+
+
+class Script:
+	
+	def decompile(self, reader, otFont):
+		self.defaultLangSystem = None
+		self.defaultLangSystem = reader.readTable(LanguageSystem, otFont)
+		langSysCount = reader.readUShort()
+		self.languageSystems = reader.readTagList(langSysCount, LanguageSystem, otFont)
+	
+	def compile(self, otFont):
+		XXXXX
+	
+	def toXML(self, xmlWriter, otFont):
+		xmlWriter.begintag("DefaultLanguageSystem")
+		xmlWriter.newline()
+		self.defaultLangSystem.toXML(xmlWriter, otFont)
+		xmlWriter.endtag("DefaultLanguageSystem")
+		xmlWriter.newline()
+		for tag, langSys in self.languageSystems:
+			xmlWriter.begintag("LanguageSystem", tag=tag)
+			xmlWriter.newline()
+			langSys.toXML(xmlWriter, otFont)
+			xmlWriter.endtag("LanguageSystem")
+			xmlWriter.newline()
+
+
+class LanguageSystem:
+	
+	def decompile(self, reader, otFont):
+		self.lookupOrder = reader.readUShort()
+		self.reqFeatureIndex = reader.readUShort()
+		featureCount = reader.readUShort()
+		self.featureIndex = reader.readUShortArray(featureCount)
+	
+	def compile(self, otFont):
+		xxx
+	
+	def toXML(self, xmlWriter, otFont):
+		xmlWriter.simpletag("LookupOrder", value=self.lookupOrder)
+		xmlWriter.newline()
+		xmlWriter.simpletag("ReqFeature", index=hex(self.reqFeatureIndex))
+		xmlWriter.newline()
+		for index in self.featureIndex:
+			xmlWriter.simpletag("Feature", index=index)
+			xmlWriter.newline()
+
+
+#
+# Feature List and subtables
+#
+
+class FeatureList:
+	
+	def __init__(self, parentTag):
+		self.parentTag = parentTag
+	
+	def decompile(self, reader, otFont):
+		featureCount = reader.readUShort()
+		self.features = reader.readTagList(featureCount, Feature, otFont)
+	
+	def compile(self, otFont):
+		XXXXX
+	
+	def toXML(self, xmlWriter, otFont):
+		for index in range(len(self.features)):
+			tag, feature = self.features[index]
+			xmlWriter.begintag("Feature", index=index, tag=tag)
+			xmlWriter.newline()
+			feature.toXML(xmlWriter, otFont)
+			xmlWriter.endtag("Feature")
+			xmlWriter.newline()
+			
+	def fromXML(self, (name, attrs, content), otFont):
+		xxx
+
+
+class Feature:
+	
+	def decompile(self, reader, otFont):
+		self.featureParams = reader.readUShort()
+		lookupCount = reader.readUShort()
+		self.lookupListIndex = reader.readUShortArray(lookupCount)
+	
+	def compile(self, otFont):
+		XXXXX
+	
+	def toXML(self, xmlWriter, otFont):
+		xmlWriter.simpletag("FeatureParams", value=hex(self.featureParams))
+		xmlWriter.newline()
+		for lookupIndex in self.lookupListIndex:
+			xmlWriter.simpletag("LookupTable", index=lookupIndex)
+			xmlWriter.newline()
+	
+	def fromXML(self, (name, attrs, content), otFont):
+		xxx
+
+
+#
+# Lookup List and subtables
+#
+
+class LookupList:
+	
+	def __init__(self, parentTag):
+		self.parentTag = parentTag
+	
+	def decompile(self, reader, otFont):
+		lookupCount = reader.readUShort()
+		self.lookup = lookup = []
+		for i in range(lookupCount):
+			lookup.append(reader.readTable(LookupTable, otFont, self.parentTag))
+	
+	def compile(self, otFont):
+		XXXXX
+	
+	def toXML(self, xmlWriter, otFont):
+		for i in range(len(self.lookup)):
+			xmlWriter.newline()
+			lookupTable = self.lookup[i]
+			xmlWriter.begintag("LookupTable", index=i)
+			xmlWriter.newline()
+			lookupTable.toXML(xmlWriter, otFont)
+			xmlWriter.endtag("LookupTable")
+			xmlWriter.newline()
+		xmlWriter.newline()
+		
+	def fromXML(self, (name, attrs, content), otFont):
+		xxx
+
+
+class LookupTable:
+	
+	def __init__(self, parentTag):
+		self.parentTag = parentTag
+	
+	def decompile(self, reader, otFont):
+		parentTable = otFont[self.parentTag]
+		self.lookupType = reader.readUShort()
+		self.lookupFlag = reader.readUShort()
+		subTableCount = reader.readUShort()
+		self.subTables = subTables = []
+		lookupTypeClass = parentTable.getLookupTypeClass(self.lookupType)
+		for i in range(subTableCount):
+			subTables.append(reader.readTable(lookupTypeClass, otFont))
+	
+	def compile(self, otFont):
+		XXXXXX
+	
+	def __repr__(self):
+		if not hasattr(self, "lookupTypeName"):
+			m = ttLib.getTableModule(self.parentTag)
+			self.lookupTypeName = m.lookupTypeClasses[self.lookupType].__name__
+		return "<%s LookupTable at %x>" % (self.lookupTypeName, id(self))
+	
+	def toXML(self, xmlWriter, otFont):
+		xmlWriter.simpletag("LookupFlag", value=hex(self.lookupFlag))
+		xmlWriter.newline()
+		for subTable in self.subTables:
+			name = subTable.__class__.__name__
+			xmlWriter.begintag(name)
+			xmlWriter.newline()
+			subTable.toXML(xmlWriter, otFont)
+			xmlWriter.endtag(name)
+			xmlWriter.newline()
+	
+	def fromXML(self, (name, attrs, content), otFont):
+		xxx
+
+
+#
+# Other common formats
+#
+
+class CoverageTable:
+	
+	def getGlyphIDs(self):
+		return self.glyphIDs
+	
+	def getGlyphNames(self):
+		return self.glyphNames
+	
+	def makeGlyphNames(self, otFont):
+		self.glyphNames = map(lambda i, o=otFont.getGlyphOrder(): o[i], self.glyphIDs)
+	
+	def decompile(self, reader, otFont):
+		format = reader.readUShort()
+		if format == 1:
+			self.decompileFormat1(reader, otFont)
+		elif format == 2:
+			self.decompileFormat2(reader, otFont)
+		else:
+			raise ttLib.TTLibError, "unknown Coverage table format: %d" % format
+		self.makeGlyphNames(otFont)
+	
+	def decompileFormat1(self, reader, otFont):
+		glyphCount = reader.readUShort()
+		self.glyphIDs = glyphIDs = []
+		for i in range(glyphCount):
+			glyphID = reader.readUShort()
+			glyphIDs.append(glyphID)
+	
+	def decompileFormat2(self, reader, otFont):
+		rangeCount = reader.readUShort()
+		self.glyphIDs = glyphIDs = []
+		for i in range(rangeCount):
+			startID = reader.readUShort()
+			endID = reader.readUShort()
+			startCoverageIndex = reader.readUShort()
+			for glyphID in range(startID, endID + 1):
+				glyphIDs.append(glyphID)
+	
+	def compile(self, otFont):
+		# brute force ;-)
+		data1 = self.compileFormat1(otFont)
+		data2 = self.compileFormat2(otFont)
+		if len(data1) <= len(data2):
+			format = 1
+			reader = data1
+		else:
+			format = 2
+			reader = data2
+		return struct.pack(">H", format) + reader
+	
+	def compileFormat1(self, otFont):
+		xxxxx
+		glyphIDs = map(otFont.getGlyphID, self.glyphNames)
+		data = pack(">H", len(glyphIDs))
+		pack = struct.pack
+		for glyphID in glyphIDs:
+			data = data + pack(">H", glyphID)
+		return data
+	
+	def compileFormat2(self, otFont):
+		xxxxx
+		glyphIDs = map(otFont.getGlyphID, self.glyphNames)
+		ranges = []
+		lastID = startID = glyphIDs[0]
+		startCoverageIndex = 0
+		glyphCount = len(glyphIDs)
+		for i in range(1, glyphCount+1):
+			if i == glyphCount:
+				glyphID = 0x1ffff  # arbitrary, but larger than 0x10000
+			else:
+				glyphID = glyphIDs[i]
+			if glyphID <> (lastID + 1):
+				ranges.append((startID, lastID, startCoverageIndex))
+				startCoverageIndex = i
+				startID = glyphID
+			lastID = glyphID
+		ranges.sort()  # sort by startID
+		rangeData = ""
+		for startID, endID, startCoverageIndex in ranges:
+			rangeData = rangeData + struct.pack(">HHH", startID, endID, startCoverageIndex)
+		return pack(">H", len(ranges)) + rangeData
+
+
+class ClassDefinitionTable:
+	
+	def decompile(self, reader, otFont):
+		format = reader.readUShort()
+		if format == 1:
+			self.decompileFormat1(reader, otFont)
+		elif format == 2:
+			self.decompileFormat2(reader, otFont)
+		else:
+			raise ttLib.TTLibError, "unknown Class table format: %d" % format
+		self.reverse()
+	
+	def reverse(self):
+		classDefs = {}
+		for glyphName, classCode in self.classDefs:
+			try:
+				classDefs[classCode].append(glyphName)
+			except KeyError:
+				classDefs[classCode] = [glyphName]
+		self.classDefs = classDefs
+	
+	def decompileFormat1(self, reader, otFont):
+		self.classDefs = classDefs = []
+		startGlyphID = reader.readUShort()
+		glyphCount = reader.readUShort()
+		for i in range(glyphCount):
+			glyphName = otFont.getglyphName(startGlyphID + i)
+			classValue = reader.readUShort()
+			if classValue:
+				classDefs.append((glyphName, classValue))
+	
+	def decompileFormat2(self, reader, otFont):
+		self.classDefs = classDefs = []
+		classRangeCount = reader.readUShort()
+		for i in range(classRangeCount):
+			startID = reader.readUShort()
+			endID = reader.readUShort()
+			classValue = reader.readUShort()
+			for glyphID in range(startID, endID + 1):
+				if classValue:
+					glyphName = otFont.getGlyphName(glyphID)
+					classDefs.append((glyphName, classValue))
+	
+	def compile(self, otFont):
+		# brute force again
+		data1 = self.compileFormat1(otFont)
+		data2 = self.compileFormat2(otFont)
+		if len(data1) <= len(data2):
+			format = 1
+			data = data1
+		else:
+			format = 2
+			data = data2
+		return struct.pack(">H", format) + data
+	
+	def compileFormat1(self, otFont):
+		items = map(lambda (glyphName, classValue), getGlyphID=otFont.getGlyphID:
+				(getGlyphID(glyphName), classValue), self.glyphs.items())
+		items.sort()
+		startGlyphID = items[0][0]
+		endGlyphID = items[-1][0]
+		data = ""
+		lastID = startGlyphID
+		for glyphID, classValue in items:
+			for i in range(lastID + 1, glyphID - 1):
+				data = data + "\0\0"  # 0 == default class
+			data = data + struct.pack(">H", classValue)
+			lastID = glyphID
+		return struct.pack(">H", endGlyphID - startGlyphID + 1) + data
+	
+	def compileFormat2(self, otFont):
+		items = map(lambda (glyphName, classValue), getGlyphID=otFont.getGlyphID:
+				(getGlyphID(glyphName), classValue), self.glyphs.items())
+		items.sort()
+		ranges = []
+		lastID, lastClassValue = items[0][0]
+		startID = lastID
+		itemCount = len(items)
+		for i in range(1, itemCount+1):
+			if i == itemCount:
+				glyphID = 0x1ffff  # arbitrary, but larger than 0x10000
+				classValue = 0
+			else:
+				glyphID, classValue = items[i]
+			if glyphID <> (lastID + 1) or lastClassValue <> classValue:
+				ranges.append((startID, lastID, lastClassValue))
+				startID = glyphID
+				lastClassValue = classValue
+			lastID = glyphID
+			lastClassValue = classValue
+		rangeData = ""
+		for startID, endID, classValue in ranges:
+			rangeData = rangeData + struct.pack(">HHH", startID, endID, classValue)
+		return pack(">H", len(ranges)) + rangeData
+	
+	def __getitem__(self, glyphName):
+		if self.glyphs.has_key(glyphName):
+			return self.glyphs[glyphName]
+		else:
+			return 0  # default class
+
+
+class DeviceTable:
+	
+	def decompile(self, reader, otFont):
+		xxxxxx
+		self.startSize = unpack_uint16(reader[:2])
+		endSize = unpack_uint16(reader[2:4])
+		deltaFormat = unpack_uint16(reader[4:6])
+		reader = reader[6:]
+		if deltaFormat == 1:
+			bits = 2
+		elif deltaFormat == 2:
+			bits = 4
+		elif deltaFormat == 3:
+			bits = 8
+		else:
+			raise ttLib.TTLibError, "unknown Device table delta format: %d" % deltaFormat
+		numCount = 16 / bits
+		deltaCount = endSize - self.startSize + 1
+		deltaValues = []
+		mask = (1 << bits) - 1
+		threshold = (1 << bits) / 2
+		shift = 1 << bits
+		for i in range(0, deltaCount, numCount):
+			offset = 2*i/numCount
+			chunk = unpack_uint16(reader[offset:offset+2])
+			deltas = []
+			for j in range(numCount):
+				delta = chunk & mask
+				if delta >= threshold:
+					delta = delta - shift
+				deltas.append(delta)
+				chunk = chunk >> bits
+			deltas.reverse()
+			deltaValues = deltaValues + deltas
+		self.deltaValues = deltaValues[:deltaCount]
+	
+	def compile(self, otFont):
+		deltaValues = self.deltaValues
+		startSize = self.startSize
+		endSize = startSize + len(deltaValues) - 1
+		smallestDelta = min(deltas)
+		largestDelta = ma(deltas)
+		if smallestDelta >= -2 and largestDelta < 2:
+			deltaFormat = 1
+			bits = 2
+		elif smallestDelta >= -8 and largestDelta < 8:
+			deltaFormat = 2
+			bits = 4
+		elif smallestDelta >= -128 and largestDelta < 128:
+			deltaFormat = 3
+			bits = 8
+		else:
+			raise ttLib.TTLibError, "delta value too large: min=%d, max=%d" % (smallestDelta, largestDelta)
+		data = struct.pack(">HHH", startSize, endSize, deltaFormat)
+		numCount = 16 / bits
+		# pad the list to a multiple of numCount values
+		remainder = len(deltaValues) % numCount
+		if remainder:
+			deltaValues = deltaValues + [0] * (numCount - remainder)
+		deltaData = ""
+		for i in range(0, len(deltaValues), numCount):
+			chunk = 0
+			for j in range(numCount):
+				chunk = chunk << bits
+				chunk = chunk | deltaValues[i+j]
+			deltaData = deltaData + struct.pack(">H", chunk)
+		return data + deltaData
+
+
+#
+# Miscelaneous helper routines and classes
+#
+
+class OTTableReader:
+	
+	"""Data wrapper, mostly designed to make reading OT data less cumbersome."""
+	
+	def __init__(self, data, offset=0):
+		self.data = data
+		self.offset = offset
+		self.pos = offset
+	
+	def readUShort(self):
+		pos = self.pos
+		newpos = pos + 2
+		value = int(struct.unpack(">H", self.data[pos:newpos])[0])
+		self.pos = newpos
+		return value
+	
+	readOffset = readUShort
+	
+	def readShort(self):
+		pos = self.pos
+		newpos = pos + 2
+		value = int(struct.unpack(">h", self.data[pos:newpos])[0])
+		self.pos = newpos
+		return value
+	
+	def readLong(self):
+		pos = self.pos
+		newpos = pos + 4
+		value = int(struct.unpack(">l", self.data[pos:newpos])[0])
+		self.pos = newpos
+		return value
+	
+	def readTag(self):
+		pos = self.pos
+		newpos = pos + 4
+		value = self.data[pos:newpos]
+		assert len(value) == 4
+		self.pos = newpos
+		return value
+	
+	def readUShortArray(self, count):
+		return self.readArray(count, "H")
+	
+	readOffsetArray = readUShortArray
+	
+	def readShortArray(self, count):
+		return self.readArray(count, "h")
+	
+	def readArray(self, count, format):
+		assert format in "Hh"
+		from array import array
+		pos = self.pos
+		newpos = pos + 2 * count
+		a = array(format)
+		a.fromstring(self.data[pos:newpos])
+		if ttLib.endian <> 'big':
+			a.byteswap()
+		self.pos = newpos
+		return a.tolist()
+	
+	def readTable(self, tableClass, otFont, *args):
+		offset = self.readOffset()
+		if offset == 0:
+			return None
+		newReader = self.getSubString(offset)
+		table = apply(tableClass, args)
+		table.decompile(newReader, otFont)
+		return table
+	
+	def readTableArray(self, count, tableClass, otFont, *args):
+		list = []
+		for i in range(count):
+			list.append(apply(self.readTable, (tableClass, otFont) + args))
+		return list
+	
+	def readTagList(self, count, tableClass, otFont, *args):
+		list = []
+		for i in range(count):
+			tag = self.readTag()
+			table = apply(self.readTable, (tableClass, otFont) + args)
+			list.append((tag, table))
+		return list
+	
+	def readStruct(self, format, size=None):
+		if size is None:
+			size = struct.calcsize(format)
+		else:
+			assert size == struct.calcsize(format)
+		pos = self.pos
+		newpos = pos + size
+		values = struct.unpack(format, self.data[pos:newpos])
+		self.pos = newpos
+		return values
+	
+	def getSubString(self, offset):
+		return self.__class__(self.data, self.offset+offset)
+	
+	def seek(self, n):
+		"""Relative seek."""
+		self.pos = self.pos + n
+
+
diff --git a/Lib/fontTools/ttLib/tables/table_API_readme.txt b/Lib/fontTools/ttLib/tables/table_API_readme.txt
new file mode 100644
index 0000000..2c04bf8
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/table_API_readme.txt
@@ -0,0 +1,91 @@
+This folder is a subpackage of ttLib. Each module here is a 
+specialized TT/OT table converter: they can convert raw data 
+to Python objects and vice versa. Usually you don't need to 
+use the modules directly: they are imported and used 
+automatically when needed by ttLib.
+
+If you are writing you own table converter the following is 
+important.
+
+The modules here have pretty strange names: this is due to the 
+fact that we need to map TT table tags (which are case sensitive) 
+to filenames (which on Mac and Win aren't case sensitive) as well 
+as to Python identifiers. The latter means it can only contain 
+[A-Za-z0-9_] and cannot start with a number. 
+
+ttLib provides functions to expand a tag into the format used here:
+
+>>> from fontTools import ttLib
+>>> ttLib.tag2identifier("FOO ")
+'F_O_O_'
+>>> ttLib.tag2identifier("cvt ")
+'_c_v_t'
+>>> ttLib.tag2identifier("OS/2")
+'O_S_2f_2'
+>>> ttLib.tag2identifier("glyf")
+'_g_l_y_f'
+>>> 
+
+And vice versa:
+
+>>> ttLib.identifier2tag("F_O_O_")
+'FOO '
+>>> ttLib.identifier2tag("_c_v_t")
+'cvt '
+>>> ttLib.identifier2tag("O_S_2f_2")
+'OS/2'
+>>> ttLib.identifier2tag("_g_l_y_f")
+'glyf'
+>>> 
+
+Eg. the 'glyf' table converter lives in a Python file called:
+
+	_g_l_y_f.py
+
+The converter itself is a class, named "table_" + expandedtag. Eg:
+
+	class table__g_l_y_f:
+		etc.
+
+Note that if you _do_ need to use such modules or classes manually, 
+there are two convenient API functions that let you find them by tag:
+
+>>> ttLib.getTableModule('glyf')
+<module 'ttLib.tables._g_l_y_f'>
+>>> ttLib.getTableClass('glyf')
+<class ttLib.tables._g_l_y_f.table__g_l_y_f at 645f400>
+>>> 
+
+You must subclass from DefaultTable.DefaultTable. It provides some default
+behavior, as well as a constructor method (__init__) that you don't need to 
+override.
+
+Your converter should minimally provide two methods:
+
+class table_F_O_O_(DefaultTable.DefaultTable): # converter for table 'FOO '
+	
+	def decompile(self, data, ttFont):
+		# 'data' is the raw table data. Unpack it into a
+		# Python data structure.
+		# 'ttFont' is a ttLib.TTfile instance, enabling you to
+		# refer to other tables. Do ***not*** keep a reference to
+		# it: it will cause a circular reference (ttFont saves 
+		# a reference to us), and that means we'll be leaking 
+		# memory. If you need to use it in other methods, just 
+		# pass it around as a method argument.
+	
+	def compile(self, ttFont):
+		# Return the raw data, as converted from the Python
+		# data structure. 
+		# Again, 'ttFont' is there so you can access other tables.
+		# Same warning applies.
+
+If you want to support XML import/export as well, you need to provide two
+additional methods:
+
+	def toXML(self, writer, ttFont):
+		# XXX
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		# XXX
+
diff --git a/Lib/fontTools/ttLib/tables/ttProgram.py b/Lib/fontTools/ttLib/tables/ttProgram.py
new file mode 100644
index 0000000..8dd9faa
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/ttProgram.py
@@ -0,0 +1,249 @@
+"""ttLib.tables.ttProgram.py -- Assembler/disassembler for TrueType bytecode programs."""
+
+import array
+
+
+# first, the list of instructions that eat bytes or words from the instruction stream
+
+streamInstructions = [
+#	------  -----------  -----  ------------------------ ---  ------  ----------------------------------  --------------
+#	opcode     mnemonic argbits         descriptive name pops pushes        eats from instruction stream          pushes
+#	------  -----------  -----  ------------------------ ---  ------  ----------------------------------  --------------
+	(0x40,    'NPUSHB',     0,             'PushNBytes',  0, -1), #                      n, b1, b2,...bn      b1,b2...bn
+	(0x41,    'NPUSHW',     0,             'PushNWords',  0, -1), #                       n, w1, w2,...w      w1,w2...wn
+	(0xb0,     'PUSHB',     3,              'PushBytes',  0, -1), #                          b0, b1,..bn  b0, b1, ...,bn
+	(0xb8,     'PUSHW',     3,              'PushWords',  0, -1), #                           w0,w1,..wn   w0 ,w1, ...wn
+#	------  -----------  -----  ------------------------ ---  ------  ----------------------------------  --------------
+]
+
+
+# next, the list of "normal" instructions
+
+instructions = [
+#	------  -----------  -----  ------------------------ ---  ------  ----------------------------------  --------------
+#	opcode     mnemonic  argbits        descriptive name pops pushes                                pops          pushes
+#	------  -----------  -----  ------------------------ ---  ------  ----------------------------------  --------------
+	(0x7f,        'AA',     0,            'AdjustAngle',  1,  0), #                                    p               -
+	(0x64,       'ABS',     0,               'Absolute',  1,  1), #                                    n             |n|
+	(0x60,       'ADD',     0,                    'Add',  2,  1), #                               n2, n1       (n1 + n2)
+	(0x27,  'ALIGNPTS',     0,               'AlignPts',  2,  0), #                               p2, p1               -
+	(0x3c,   'ALIGNRP',     0,        'AlignRelativePt', -1,  0), #             p1, p2, ... , ploopvalue               -
+	(0x5a,       'AND',     0,             'LogicalAnd',  2,  1), #                               e2, e1               b
+	(0x2b,      'CALL',     0,           'CallFunction',  1,  0), #                                    f               -
+	(0x67,   'CEILING',     0,                'Ceiling',  1,  1), #                                    n         ceil(n)
+	(0x25,    'CINDEX',     0,        'CopyXToTopStack',  1,  1), #                                    k              ek
+	(0x22,     'CLEAR',     0,             'ClearStack', -1,  0), #               all items on the stack               -
+	(0x4f,     'DEBUG',     0,              'DebugCall',  1,  0), #                                    n               -
+	(0x73,   'DELTAC1',     0,       'DeltaExceptionC1', -1,  0), #    argn, cn, argn-1,cn-1, , arg1, c1               -
+	(0x74,   'DELTAC2',     0,       'DeltaExceptionC2', -1,  0), #    argn, cn, argn-1,cn-1, , arg1, c1               -
+	(0x75,   'DELTAC3',     0,       'DeltaExceptionC3', -1,  0), #    argn, cn, argn-1,cn-1, , arg1, c1               -
+	(0x5d,   'DELTAP1',     0,       'DeltaExceptionP1', -1,  0), #   argn, pn, argn-1, pn-1, , arg1, p1               -
+	(0x71,   'DELTAP2',     0,       'DeltaExceptionP2', -1,  0), #   argn, pn, argn-1, pn-1, , arg1, p1               -
+	(0x72,   'DELTAP3',     0,       'DeltaExceptionP3', -1,  0), #   argn, pn, argn-1, pn-1, , arg1, p1               -
+	(0x24,     'DEPTH',     0,          'GetDepthStack',  0,  1), #                                    -               n
+	(0x62,       'DIV',     0,                 'Divide',  2,  1), #                               n2, n1   (n1 * 64)/ n2
+	(0x20,       'DUP',     0,      'DuplicateTopStack',  1,  2), #                                    e            e, e
+	(0x59,       'EIF',     0,                  'EndIf',  0,  0), #                                    -               -
+	(0x1b,      'ELSE',     0,                   'Else',  0,  0), #                                    -               -
+	(0x2d,      'ENDF',     0,  'EndFunctionDefinition',  0,  0), #                                    -               -
+	(0x54,        'EQ',     0,                  'Equal',  2,  1), #                               e2, e1               b
+	(0x57,      'EVEN',     0,                   'Even',  1,  1), #                                    e               b
+	(0x2c,      'FDEF',     0,     'FunctionDefinition',  1,  0), #                                    f               -
+	(0x4e,   'FLIPOFF',     0,         'SetAutoFlipOff',  0,  0), #                                    -               -
+	(0x4d,    'FLIPON',     0,          'SetAutoFlipOn',  0,  0), #                                    -               -
+	(0x80,    'FLIPPT',     0,              'FlipPoint', -1,  0), #              p1, p2, ..., ploopvalue               -
+	(0x82, 'FLIPRGOFF',     0,           'FlipRangeOff',  2,  0), #                                 h, l               -
+	(0x81,  'FLIPRGON',     0,            'FlipRangeOn',  2,  0), #                                 h, l               -
+	(0x66,     'FLOOR',     0,                  'Floor',  1,  1), #                                    n        floor(n)
+	(0x46,        'GC',     1,      'GetCoordOnPVector',  1,  1), #                                    p               c
+	(0x88,   'GETINFO',     0,                'GetInfo',  1,  1), #                             selector          result
+	(0x0d,       'GFV',     0,             'GetFVector',  0,  2), #                                    -          px, py
+	(0x0c,       'GPV',     0,             'GetPVector',  0,  2), #                                    -          px, py
+	(0x52,        'GT',     0,            'GreaterThan',  2,  1), #                               e2, e1               b
+	(0x53,      'GTEQ',     0,     'GreaterThanOrEqual',  2,  1), #                               e2, e1               b
+	(0x89,      'IDEF',     0,  'InstructionDefinition',  1,  0), #                                    f               -
+	(0x58,        'IF',     0,                     'If',  1,  0), #                                    e               -
+	(0x8e,  'INSTCTRL',     0,    'SetInstrExecControl',  2,  0), #                                 s, v               -
+	(0x39,        'IP',     0,         'InterpolatePts', -1,  0), #             p1, p2, ... , ploopvalue               -
+	(0x0f,     'ISECT',     0,      'MovePtToIntersect',  5,  0), #                    a1, a0, b1, b0, p               -
+	(0x30,       'IUP',     1,      'InterpolateUntPts',  0,  0), #                                    -               -
+	(0x1c,      'JMPR',     0,                   'Jump',  1,  0), #                               offset               -
+	(0x79,      'JROF',     0,    'JumpRelativeOnFalse',  2,  0), #                            e, offset               -
+	(0x78,      'JROT',     0,     'JumpRelativeOnTrue',  2,  0), #                            e, offset               -
+	(0x2a,  'LOOPCALL',     0,    'LoopAndCallFunction',  2,  0), #                             f, count               -
+	(0x50,        'LT',     0,               'LessThan',  2,  1), #                               e2, e1               b
+	(0x51,      'LTEQ',     0,        'LessThenOrEqual',  2,  1), #                               e2, e1               b
+	(0x8b,       'MAX',     0,                'Maximum',  2,  1), #                               e2, e1     max(e1, e2)
+	(0x49,        'MD',     1,        'MeasureDistance',  2,  1), #                                p2,p1               d
+	(0x2e,      'MDAP',     1,        'MoveDirectAbsPt',  1,  0), #                                    p               -
+	(0xc0,      'MDRP',     5,        'MoveDirectRelPt',  1,  0), #                                    p               -
+	(0x3e,      'MIAP',     1,      'MoveIndirectAbsPt',  2,  0), #                                 n, p               -
+	(0x8c,       'MIN',     0,                'Minimum',  2,  1), #                               e2, e1     min(e1, e2)
+	(0x26,    'MINDEX',     0,        'MoveXToTopStack',  2,  1), #                                    k              ek
+	(0xe0,      'MIRP',     5,      'MoveIndirectRelPt',  1,  0), #                                 n, p               -
+	(0x4b,     'MPPEM',     0,      'MeasurePixelPerEm',  0,  1), #                                    -            ppem
+	(0x4c,       'MPS',     0,       'MeasurePointSize',  0,  1), #                                    -       pointSize
+	(0x3a,     'MSIRP',     1,    'MoveStackIndirRelPt',  2,  0), #                                 d, p               -
+	(0x63,       'MUL',     0,               'Multiply',  2,  1), #                               n2, n1    (n1 * n2)/64
+	(0x65,       'NEG',     0,                 'Negate',  1,  1), #                                    n              -n
+	(0x55,       'NEQ',     0,               'NotEqual',  2,  1), #                               e2, e1               b
+	(0x5c,       'NOT',     0,             'LogicalNot',  1,  1), #                                    e       ( not e )
+	(0x6c,    'NROUND',     2,                'NoRound',  1,  1), #                                   n1              n2
+	(0x56,       'ODD',     0,                    'Odd',  1,  1), #                                    e               b
+	(0x5b,        'OR',     0,              'LogicalOr',  2,  1), #                               e2, e1               b
+	(0x21,       'POP',     0,            'PopTopStack',  1,  0), #                                    e               -
+	(0x45,      'RCVT',     0,                'ReadCVT',  1,  1), #                             location           value
+	(0x7d,      'RDTG',     0,        'RoundDownToGrid',  0,  0), #                                    -               -
+	(0x7a,      'ROFF',     0,               'RoundOff',  0,  0), #                                    -               -
+	(0x8a,      'ROLL',     0,      'RollTopThreeStack',  3,  3), #                                a,b,c           b,a,c
+	(0x68,     'ROUND',     2,                  'Round',  1,  1), #                                   n1              n2
+	(0x43,        'RS',     0,              'ReadStore',  1,  1), #                                    n               v
+	(0x3d,      'RTDG',     0,      'RoundToDoubleGrid',  0,  0), #                                    -               -
+	(0x18,       'RTG',     0,            'RoundToGrid',  0,  0), #                                    -               -
+	(0x19,      'RTHG',     0,        'RoundToHalfGrid',  0,  0), #                                    -               -
+	(0x7c,      'RUTG',     0,          'RoundUpToGrid',  0,  0), #                                    -               -
+	(0x77,  'S45ROUND',     0,    'SuperRound45Degrees',  1,  0), #                                    n               -
+	(0x7e,     'SANGW',     0,         'SetAngleWeight',  1,  0), #                               weight               -
+	(0x85,  'SCANCTRL',     0,  'ScanConversionControl',  1,  0), #                                    n               -
+	(0x8d,  'SCANTYPE',     0,               'ScanType',  1,  0), #                                    n               -
+	(0x48,      'SCFS',     0,    'SetCoordFromStackFP',  2,  0), #                                 c, p               -
+	(0x1d,    'SCVTCI',     0,            'SetCVTCutIn',  1,  0), #                                    n               -
+	(0x5e,       'SDB',     0,   'SetDeltaBaseInGState',  1,  0), #                                    n               -
+	(0x86,    'SDPVTL',     1,   'SetDualPVectorToLine',  2,  0), #                               p2, p1               -
+	(0x5f,       'SDS',     0,  'SetDeltaShiftInGState',  1,  0), #                                    n               -
+	(0x0b,     'SFVFS',     0,    'SetFVectorFromStack',  2,  0), #                                 y, x               -
+	(0x04,    'SFVTCA',     1,       'SetFVectorToAxis',  0,  0), #                                    -               -
+	(0x08,     'SFVTL',     1,       'SetFVectorToLine',  2,  0), #                               p2, p1               -
+	(0x0e,    'SFVTPV',     0,    'SetFVectorToPVector',  0,  0), #                                    -               -
+	(0x34,       'SHC',     1,   'ShiftContourByLastPt',  1,  0), #                                    c               -
+	(0x32,       'SHP',     1,  'ShiftPointByLastPoint', -1,  0), #              p1, p2, ..., ploopvalue               -
+	(0x38,     'SHPIX',     0,       'ShiftZoneByPixel', -1,  0), #           d, p1, p2, ..., ploopvalue               -
+	(0x36,       'SHZ',     1,   'ShiftZoneByLastPoint',  1,  0), #                                    e               -
+	(0x17,     'SLOOP',     0,        'SetLoopVariable',  1,  0), #                                    n               -
+	(0x1a,       'SMD',     0,     'SetMinimumDistance',  1,  0), #                             distance               -
+	(0x0a,     'SPVFS',     0,    'SetPVectorFromStack',  2,  0), #                                 y, x               -
+	(0x02,    'SPVTCA',     1,       'SetPVectorToAxis',  0,  0), #                                    -               -
+	(0x06,     'SPVTL',     1,       'SetPVectorToLine',  2,  0), #                               p2, p1               -
+	(0x76,    'SROUND',     0,             'SuperRound',  1,  0), #                                    n               -
+	(0x10,      'SRP0',     0,           'SetRefPoint0',  1,  0), #                                    p               -
+	(0x11,      'SRP1',     0,           'SetRefPoint1',  1,  0), #                                    p               -
+	(0x12,      'SRP2',     0,           'SetRefPoint2',  1,  0), #                                    p               -
+	(0x1f,       'SSW',     0,         'SetSingleWidth',  1,  0), #                                    n               -
+	(0x1e,     'SSWCI',     0,    'SetSingleWidthCutIn',  1,  0), #                                    n               -
+	(0x61,       'SUB',     0,               'Subtract',  2,  1), #                               n2, n1       (n1 - n2)
+	(0x00,     'SVTCA',     1,      'SetFPVectorToAxis',  0,  0), #                                    -               -
+	(0x23,      'SWAP',     0,           'SwapTopStack',  2,  2), #                               e2, e1          e1, e2
+	(0x13,      'SZP0',     0,        'SetZonePointer0',  1,  0), #                                    n               -
+	(0x14,      'SZP1',     0,        'SetZonePointer1',  1,  0), #                                    n               -
+	(0x15,      'SZP2',     0,        'SetZonePointer2',  1,  0), #                                    n               -
+	(0x16,      'SZPS',     0,        'SetZonePointerS',  1,  0), #                                    n               -
+	(0x29,       'UTP',     0,              'UnTouchPt',  1,  0), #                                    p               -
+	(0x70,     'WCVTF',     0,       'WriteCVTInFUnits',  2,  0), #                                 n, l               -
+	(0x44,     'WCVTP',     0,       'WriteCVTInPixels',  2,  0), #                                 v, l               -
+	(0x42,        'WS',     0,             'WriteStore',  2,  0), #                                 v, l               -
+#	------  -----------  -----  ------------------------ ---  ------  ----------------------------------  --------------
+]
+
+
+def bitRepr(value, bits):
+	s = ""
+	for i in range(bits):
+		s = "01"[value & 0x1] + s
+		value = value >> 1
+	return s
+
+def makeOpcodeDict(instructionList):
+	opcodeDict = {}
+	for op, mnemonic, argbits, name, pops, pushes in instructionList:
+		if argbits:
+			argoffset = op
+			for i in range(1 << argbits):
+				opcodeDict[op+i] = mnemonic, argbits, argoffset, name
+		else:
+				opcodeDict[op] = mnemonic, 0, 0, name
+	return opcodeDict
+
+streamOpcodeDict = makeOpcodeDict(streamInstructions)
+opcodeDict = makeOpcodeDict(instructions)
+
+tt_instructions_error = "TT instructions error"
+
+
+class Program:
+	
+	def __init__(self):
+		pass
+	
+	def fromBytecode(self, bytecode):
+		self.bytecode = array.array("B")
+		self.bytecode.fromstring(bytecode)
+	
+	def fromAssembly(self, assembly):
+		self.assembly = assembly
+	
+	def getBytecode(self):
+		if not hasattr(self, "bytecode"):
+			self._assemble()
+		return self.bytecode.tostring()
+	
+	def getAssembly(self):
+		if not hasattr(self, "assembly"):
+			self._disassemble()
+		return self.assembly
+	
+	def _assemble(self):
+		xxx
+	
+	def _disassemble(self):
+		assembly = []
+		i = 0
+		bytecode = self.bytecode
+		numBytecode = len(bytecode)
+		while i < numBytecode:
+			op = bytecode[i]
+			arg = 0
+			try:
+				mnemonic, argbits, argoffset, name = opcodeDict[op]
+			except KeyError:
+				try:
+					mnemonic, argbits, argoffset, name = streamOpcodeDict[op]
+				except KeyError:
+					raise tt_instructions_error, "illegal opcode: 0x%.2x" % op
+				pushbytes = pushwords = 0
+				if argbits:
+					if mnemonic == "PUSHB":
+						pushbytes = op - argoffset + 1
+					else:
+						pushwords = op - argoffset + 1
+				else:
+					i = i + 1
+					if mnemonic == "NPUSHB":
+						pushbytes = bytecode[i]
+					else:
+						pushwords = bytecode[i]
+				i = i + 1
+				assembly.append(mnemonic + "[ ]")
+				for j in range(pushbytes):
+					assembly.append(`bytecode[i]`)
+					i = i + 1
+				for j in range(0, pushwords, 2):
+					assembly.append(`(bytecode[i] << 8) + bytecode[i+1]`)
+					i = i + 2
+			else:
+				if argbits:
+					assembly.append(mnemonic + "[%s]" % bitRepr(op - argoffset, argbits))
+				else:
+					assembly.append(mnemonic + "[ ]")
+				i = i + 1
+		self.assembly = assembly
+		del self.bytecode
+
+
+fpgm = '@\01476&%\037\023\022\015\014\005\004\002, \260\003%E#E#ah\212 Eh \212#D`D-,KRXED\033!!Y-,  EhD \260\001` E\260Fvh\030\212E`D-,\260\022+\260\002%E\260\002%Ej\260@\213`\260\002%#D!!!-,\260\023+\260\002%E\260\002%Ej\270\377\300\214`\260\002%#D!!!-,\261\000\003%EhTX\260\003%E\260\003%E`h \260\004%#D\260\004%#D\033\260\003% Eh \212#D\260\003%Eh`\260\003%#DY-,\260\003% Eh \212#D\260\003%Eh`\260\003%#D-,KRXED\033!!Y-,F#F`\212\212F# F\212`\212a\270\377\200b# \020#\212\261KK\212pE` \260\000PX\260\001a\270\377\272\213\033\260F\214Y\260\020`h\001:-, E\260\003%FRX?\033!\021Y-,KS#KQZX E\212`D\033!!Y-,KS#KQZX8\033!!Y-'
+gpgm = '@\022\011\003\207@\005\200\004\207\000\010\007\202\001\010\004\202\000\010\000\020\320\355\020\336\355\001\020\336\375\032}\336\032\030\375\31610'
+
+p = Program()
+p.fromBytecode(fpgm)
+for line in p.getAssembly():
+	print line
+
diff --git a/Lib/fontTools/ttLib/test/ttBrowser.py b/Lib/fontTools/ttLib/test/ttBrowser.py
new file mode 100644
index 0000000..1c54375
--- /dev/null
+++ b/Lib/fontTools/ttLib/test/ttBrowser.py
@@ -0,0 +1,332 @@
+from fontTools import ttLib
+from fontTools.ttLib import macUtils
+import macfs
+import PyBrowser
+import W, Lists
+import os
+import ATM
+import Numeric
+import Qd
+from rf.views.wGlyphList import GlyphList
+
+
+class TableBrowser:
+	
+	def __init__(self, path=None, ttFont=None, res_index=None):
+		W.SetCursor('watch')
+		if path is None:
+			self.ttFont = ttFont
+			self.filename = "????"
+		else:
+			self.ttFont = ttLib.TTFont(path, res_index)
+			if res_index is None:
+				self.filename = os.path.basename(path)
+			else:
+				self.filename = os.path.basename(path) + " - " + str(res_index)
+		self.currentglyph = None
+		self.glyphs = {}
+		self.buildinterface()
+	
+	def buildinterface(self):
+		buttonwidth = 120
+		glyphlistwidth = 150
+		hmargin = 10
+		vmargin = 8
+		title = self.filename
+		tables = self.ttFont.keys()
+		tables.sort()
+		self.w = w = W.Window((500, 300), title, minsize = (400, 200))
+		w.browsetablebutton = W.Button((hmargin, 32, buttonwidth, 16), "Browse tableŠ", 
+				self.browsetable)
+		w.browsefontbutton = W.Button((hmargin, vmargin, buttonwidth, 16), "Browse fontŠ", 
+				self.browsefont)
+		w.tablelist = W.List((hmargin, 56, buttonwidth, -128), tables, self.tablelisthit)
+		
+		w.divline1 = W.VerticalLine((buttonwidth + 2 * hmargin, vmargin, 1, -vmargin))
+		
+		gleft = buttonwidth + 3 * hmargin + 1
+		
+		hasGlyfTable = self.ttFont.has_key('glyf')
+		
+		glyphnames = self.ttFont.getGlyphNames2()  # caselessly sorted glyph names
+		
+		if hasGlyfTable:
+			w.glyphlist = GlyphList((gleft, 56, glyphlistwidth, -vmargin), 
+					glyphnames, self.glyphlisthit)
+			
+			w.divline2 = W.VerticalLine((buttonwidth + glyphlistwidth + 4 * hmargin + 2, 
+					vmargin, 1, -vmargin))
+			
+			yMin = self.ttFont['head'].yMin
+			yMax = self.ttFont['head'].yMax
+			w.gviewer = GlyphViewer((buttonwidth + glyphlistwidth + 5 * hmargin + 3, 
+					vmargin, -hmargin, -vmargin), yMin, yMax)
+			
+			w.showpoints = W.CheckBox((gleft, vmargin, glyphlistwidth, 16), "Show points", 
+					self.w.gviewer.toggleshowpoints)
+			w.showpoints.set(self.w.gviewer.showpoints)
+			w.showlines = W.CheckBox((gleft, vmargin + 24, glyphlistwidth, 16), "Show lines",
+					self.w.gviewer.toggleshowlines)
+			w.showlines.set(self.w.gviewer.showlines)
+		else:
+			w.glyphlist = GlyphList((gleft, 56, glyphlistwidth, -vmargin), 
+					glyphnames)
+			w.noGlyphTable = W.TextBox((gleft, vmargin, -20, 20), "no 'glyf' table found")
+		
+		
+		w.setdefaultbutton(w.browsetablebutton)
+		
+		w.tocurrentfont = W.Button((hmargin, -120, buttonwidth, 16), "Copy to current font", self.copytocurrentfont)
+		w.fromcurrentfont = W.Button((hmargin, -96, buttonwidth, 16), "Copy from current font", self.copyfromcurrentfont)
+		w.saveflat = W.Button((hmargin, -72, buttonwidth, 16), "Save as flat fileŠ", self.saveflat)
+		w.savesuitcasebutton = W.Button((hmargin, -48, buttonwidth, 16), "Save as suitcaseŠ", self.savesuitcase)
+		w.savexmlbutton = W.Button((hmargin, -24, buttonwidth, 16), "Save as XMLŠ", self.saveXML)
+		
+		w.open()
+		w.browsetablebutton.enable(0)
+	
+	def browsetable(self):
+		self.tablelisthit(1)
+	
+	def browsefont(self):
+		PyBrowser.Browser(self.ttFont)
+	
+	def copytocurrentfont(self):
+		pass
+		
+	def copyfromcurrentfont(self):
+		pass
+		
+	def saveflat(self):
+		path = putfile("Save font as flat file:", self.filename, ".TTF")
+		if path:
+			W.SetCursor('watch')
+			self.ttFont.save(path)
+	
+	def savesuitcase(self):
+		path = putfile("Save font as suitcase:", self.filename, ".suit")
+		if path:
+			W.SetCursor('watch')
+			self.ttFont.save(path, 1)
+	
+	def saveXML(self):
+		path = putfile("Save font as XML text file:", self.filename, ".xml")
+		if path:
+			W.SetCursor('watch')
+			pb = macUtils.ProgressBar("Saving %s as XMLŠ" % self.filename)
+			try:
+				self.ttFont.saveXML(path, pb)
+			finally:
+				pb.close()
+	
+	def glyphlisthit(self, isDbl):
+		sel = self.w.glyphlist.getselectedobjects()
+		if not sel or sel[0] == self.currentglyph:
+			return
+		self.currentglyph = sel[0]
+		if self.glyphs.has_key(self.currentglyph):
+			g = self.glyphs[self.currentglyph]
+		else:
+			g = Glyph(self.ttFont, self.currentglyph)
+			self.glyphs[self.currentglyph] = g
+		self.w.gviewer.setglyph(g)
+	
+	def tablelisthit(self, isdbl):
+		if isdbl:
+			for tag in self.w.tablelist.getselectedobjects():
+				table = self.ttFont[tag]
+				if tag == 'glyf':
+					W.SetCursor('watch')
+					for glyphname in self.ttFont.getGlyphOrder():
+						try:
+							glyph = table[glyphname]
+						except KeyError:
+							pass # incomplete font, oh well.
+				PyBrowser.Browser(table)
+		else:
+			sel = self.w.tablelist.getselection()
+			if sel:
+				self.w.browsetablebutton.enable(1)
+			else:
+				self.w.browsetablebutton.enable(0)
+
+
+class Glyph:
+	
+	def __init__(self, ttFont, glyphName):
+		ttglyph = ttFont['glyf'][glyphName]
+		self.iscomposite = ttglyph.numberOfContours == -1
+		self.width, self.lsb = ttFont['hmtx'][glyphName]
+		if ttglyph.numberOfContours == 0:
+			self.xMin = 0
+			self.contours = []
+			return
+		self.xMin = ttglyph.xMin
+		coordinates, endPts, flags = ttglyph.getCoordinates(ttFont['glyf'])
+		self.contours = []
+		self.flags = []
+		startpt = 0
+		for endpt in endPts:
+			self.contours.append(Numeric.array(coordinates[startpt:endpt+1]))
+			self.flags.append(flags[startpt:endpt+1])
+			startpt = endpt + 1
+	
+	def getcontours(self, scale, move):
+		contours = []
+		for i in range(len(self.contours)):
+			contours.append((self.contours[i] * Numeric.array(scale) + move), self.flags[i])
+		return contours
+
+
+class GlyphViewer(W.Widget):
+	
+	def __init__(self, possize, yMin, yMax):
+		W.Widget.__init__(self, possize)
+		self.glyph = None
+		extra = 0.02 * (yMax-yMin)
+		self.yMin, self.yMax = yMin - extra, yMax + extra
+		self.showpoints = 1
+		self.showlines = 1
+	
+	def toggleshowpoints(self, onoff):
+		self.showpoints = onoff
+		self.SetPort()
+		self.draw()
+	
+	def toggleshowlines(self, onoff):
+		self.showlines = onoff
+		self.SetPort()
+		self.draw()
+	
+	def setglyph(self, glyph):
+		self.glyph = glyph
+		self.SetPort()
+		self.draw()
+		
+	def draw(self, visRgn=None):
+		# This a HELL of a routine, but it's pretty damn fast...
+		import Qd
+		if not self._visible:
+			return
+		Qd.EraseRect(Qd.InsetRect(self._bounds, 1, 1))
+		cliprgn = Qd.NewRgn()
+		savergn = Qd.NewRgn()
+		Qd.RectRgn(cliprgn, self._bounds)
+		Qd.GetClip(savergn)
+		Qd.SetClip(cliprgn)
+		try:
+			if self.glyph:
+				l, t, r, b = Qd.InsetRect(self._bounds, 1, 1)
+				height = b - t
+				scale = float(height) / (self.yMax - self.yMin)
+				topoffset = t + scale * self.yMax
+				width = scale * self.glyph.width
+				lsb = scale * self.glyph.lsb
+				xMin = scale * self.glyph.xMin
+				# XXXX this is not correct when USE_MY_METRICS is set in component!
+				leftoffset = l + 0.5 * (r - l - width)
+				gleftoffset = leftoffset - xMin + lsb
+				if self.showlines:
+					Qd.RGBForeColor((0xafff, 0xafff, 0xafff))
+					# left sidebearing
+					Qd.MoveTo(leftoffset, t)
+					Qd.LineTo(leftoffset, b - 1)
+					# right sidebearing
+					Qd.MoveTo(leftoffset + width, t)
+					Qd.LineTo(leftoffset + width, b - 1)
+					# baseline
+					Qd.MoveTo(l, topoffset)
+					Qd.LineTo(r - 1, topoffset)
+					
+					# origin
+					Qd.RGBForeColor((0x5fff, 0, 0))
+					Qd.MoveTo(gleftoffset, topoffset - 16)
+					Qd.LineTo(gleftoffset, topoffset + 16)
+					# reset color
+					Qd.RGBForeColor((0, 0, 0))
+				
+				if self.glyph.iscomposite:
+					Qd.RGBForeColor((0x7fff, 0x7fff, 0x7fff))
+				
+				ATM.startFillATM()
+				contours = self.glyph.getcontours((scale, -scale), (gleftoffset, topoffset))
+				for contour, flags in contours:
+					currentpoint = None
+					done_moveto = 0
+					i = 0
+					nPoints = len(contour)
+					while i < nPoints:
+						pt = contour[i]
+						if flags[i]:
+							# onCurve
+							currentpoint = lineto(pt, done_moveto)
+						else:
+							if not currentpoint:
+								if not flags[i-1]:
+									currentpoint = 0.5 * (contour[i-1] + pt)
+								else:
+									currentpoint = contour[i-1]
+							if not flags[(i+1) % nPoints]:
+								endPt = 0.5 * (pt + contour[(i+1) % nPoints])
+							else:
+								endPt = contour[(i+1) % nPoints]
+								i = i + 1
+							# offCurve
+							currentpoint = qcurveto(currentpoint, 
+									pt, endPt, done_moveto)
+						done_moveto = 1
+						i = i + 1
+					ATM.fillClosePathATM()
+				ATM.endFillATM()
+				# draw point markers
+				if self.showpoints:
+					for contour, flags in contours:
+						Qd.RGBForeColor((0, 0xffff, 0))
+						for i in range(len(contour)):
+							(x, y) = contour[i]
+							onCurve = flags[i] & 0x1
+							if onCurve:
+								Qd.PaintRect(Qd.InsetRect((x, y, x, y), -2, -2))
+							else:
+								Qd.PaintOval(Qd.InsetRect((x, y, x, y), -2, -2))
+							Qd.RGBForeColor((0xffff, 0, 0))
+						Qd.RGBForeColor((0, 0, 0))
+			Qd.FrameRect(self._bounds)
+		finally:
+			Qd.SetClip(savergn)
+			Qd.DisposeRgn(cliprgn)
+			Qd.DisposeRgn(savergn)
+
+
+extensions = [".suit", ".xml", ".TTF", ".ttf"]
+
+def putfile(prompt, filename, newextension):
+	for ext in extensions:
+		if filename[-len(ext):] == ext:
+			filename = filename[:-len(ext)] + newextension
+			break
+	else:
+		filename = filename + newextension
+	fss, ok = macfs.StandardPutFile(prompt, filename)
+	if ok:
+		return fss.as_pathname()
+
+
+def lineto(pt, done_moveto):
+	x, y = pt
+	if done_moveto:
+		ATM.fillLineToATM((x, y))
+	else:
+		ATM.fillMoveToATM((x, y))
+	return pt
+
+def qcurveto(pt0, pt1, pt2, done_moveto):
+	if not done_moveto:
+		x0, y0 = pt0
+		ATM.fillMoveToATM((x0, y0))
+	x1a, y1a = pt0 + 0.6666666666667 * (pt1 - pt0)
+	x1b, y1b = pt2 + 0.6666666666667 * (pt1 - pt2)
+	x2, y2 = pt2
+	ATM.fillCurveToATM((x1a, y1a), (x1b, y1b), (x2, y2))
+	return pt2
+
diff --git a/Lib/fontTools/ttLib/xmlImport.py b/Lib/fontTools/ttLib/xmlImport.py
new file mode 100644
index 0000000..92d3b42
--- /dev/null
+++ b/Lib/fontTools/ttLib/xmlImport.py
@@ -0,0 +1,196 @@
+from fontTools import ttLib
+from fontTools.misc.textTools import safeEval
+import types
+import string
+import Numeric, array
+from xml.parsers.xmlproc import xmlproc
+
+
+xmlerror = "xmlerror"
+xml_parse_error = "XML parse error"
+
+
+class UnicodeString:
+	
+	def __init__(self, value):
+		if isinstance(value, UnicodeString):
+			self.value = value.value
+		else:
+			if type(value) == types.StringType:
+				# Since Numeric interprets char codes as *signed*,
+				# we feed it through the array module.
+				value = array.array("B", value)
+			self.value = Numeric.array(value, Numeric.Int16)
+	
+	def __len__(self):
+		return len(self.value)
+	
+	#def __hash__(self):
+	#	return hash(self.value.tostring())
+	#
+	#def __cmp__(self, other):
+	#	if not isinstance(other, UnicodeString):
+	#		return 1
+	#	else:
+	#		return not Numeric.alltrue(
+	#				Numeric.equal(self.value, other.value))
+	
+	def __add__(self, other):
+		if not isinstance(other, UnicodeString):
+			other = self.__class__(other)
+		return self.__class__(Numeric.concatenate((self.value, other.value)))
+	
+	def __radd__(self, other):
+		if not isinstance(other, UnicodeString):
+			other = self.__class__(other)
+		return self.__class__(Numeric.concatenate((other.value, self.value)))
+	
+	def __getslice__(self, i, j):
+		return self.__class__(self.value[i:j])
+	
+	def __getitem__(self, i):
+		return self.__class__(self.value[i:i+1])
+	
+	def tostring(self):
+		value = self.value
+		if ttLib.endian <> "big":
+			value = value.byteswapped()
+		return value.tostring()
+	
+	def stripped(self):
+		value = self.value
+		i = 0
+		for i in range(len(value)):
+			if value[i] not in (0xa, 0xd, 0x9, 0x20):
+				break
+		value = value[i:]
+		i = 0
+		for i in range(len(value)-1, -1, -1):
+			if value[i] not in (0xa, 0xd, 0x9, 0x20):
+				break
+		value = value[:i+1]
+		return self.__class__(value)
+	
+	def __repr__(self):
+		return "<%s %s at %x>" % (self.__class__.__name__, `self.value.tostring()`, id(self))
+
+
+class UnicodeProcessor(xmlproc.XMLProcessor):
+	
+	def parse_charref(self):
+		"Parses a character reference."
+		
+		if self.now_at("x"):
+			digs=unhex(self.get_match(xmlproc.reg_hex_digits))
+		else:
+			try:
+				digs=string.atoi(self.get_match(xmlproc.reg_digits))
+			except ValueError,e:
+				self.report_error(3027)
+				digs=None
+		if digs == 169:
+			pass
+		if not self.now_at(";"): self.report_error(3005,";")
+		if digs==None: return
+		
+		if not (digs==9 or digs==10 or digs==13 or \
+				(digs>=32 and digs<=255)):
+			if digs>255:
+				self.app.handle_data(UnicodeString([digs]),0,1)
+			else:
+				# hrm, I need to let some null bytes go through...
+				self.app.handle_data(chr(digs),0,1)
+				#self.report_error(3018,digs)
+		else:
+			if self.stack==[]:
+				self.report_error(3028)
+			self.app.handle_data(chr(digs),0,1)
+
+
+class XMLErrorHandler(xmlproc.ErrorHandler):
+	
+	def fatal(self, msg):
+		"Handles a fatal error message."
+		# we don't want no stinkin' sys.exit(1)
+		raise xml_parse_error, msg
+
+
+class XMLApplication(xmlproc.Application):
+	
+	def __init__(self, ttFont, progress=None):
+		self.ttFont = ttFont
+		self.progress = progress
+		self.root = None
+		self.content_stack = []
+		self.lastpos = 0
+	
+	def handle_start_tag(self, name, attrs):
+		if self.progress:
+			pos = self.locator.pos + self.locator.block_offset
+			if (pos - self.lastpos) > 4000:
+				self.progress.set(pos / 100)
+				self.lastpos = pos
+		stack = self.locator.stack
+		stacksize = len(stack)
+		if not stacksize:
+			if name <> "ttFont":
+				raise xml_parse_error, "illegal root tag: %s" % name
+			sfntVersion = attrs.get("sfntVersion", "\000\001\000\000")
+			if len(sfntVersion) <> 4:
+				sfntVersion = safeEval('"' + sfntVersion + '"')
+			self.ttFont.sfntVersion = sfntVersion
+			self.content_stack.append([])
+		elif stacksize == 1:
+			msg = "Parsing '%s' table..." % ttLib.xmltag2tag(name)
+			if self.progress:
+				self.progress.setlabel(msg)
+			elif self.ttFont.verbose:
+				ttLib.debugmsg(msg)
+			else:
+				print msg
+			tag = ttLib.xmltag2tag(name)
+			tableclass = ttLib.getTableClass(tag)
+			if tableclass is None:
+				from fontTools.ttLib.tables.DefaultTable import DefaultTable
+				tableclass = DefaultTable
+			self.current_table = tableclass(tag)
+			self.ttFont[tag] = self.current_table
+			self.content_stack.append([])
+		elif stacksize == 2:
+			self.content_stack.append([])
+			self.root = (name, attrs, self.content_stack[-1])
+		else:
+			list = []
+			self.content_stack[-1].append(name, attrs, list)
+			self.content_stack.append(list)
+	
+	def handle_data(self, data, start, end):
+		if len(self.locator.stack) > 1:
+			self.content_stack[-1].append(data[start:end])
+	
+	def handle_end_tag(self, name):
+		del self.content_stack[-1]
+		stack = self.locator.stack
+		stacksize = len(stack)
+		if stacksize == 1:
+			self.root = None
+		elif stacksize == 2:
+			self.current_table.fromXML(self.root, self.ttFont)
+			self.root = None
+
+
+class ProgressPrinter:
+	
+	def __init__(self, title, maxval=100):
+		print title
+	
+	def set(self, val, maxval=None):
+		pass
+	
+	def increment(self, val=1):
+		pass
+	
+	def setlabel(self, text):
+		print text
+
+
diff --git a/Lib/fontTools/unicode.py b/Lib/fontTools/unicode.py
new file mode 100644
index 0000000..dc6ba0c
--- /dev/null
+++ b/Lib/fontTools/unicode.py
@@ -0,0 +1,6646 @@
+"""Unicode version 2.1.2"""
+
+_unicode = """\
+0000	<control>
+0001	<control>
+0002	<control>
+0003	<control>
+0004	<control>
+0005	<control>
+0006	<control>
+0007	<control>
+0008	<control>
+0009	<control>
+000A	<control>
+000B	<control>
+000C	<control>
+000D	<control>
+000E	<control>
+000F	<control>
+0010	<control>
+0011	<control>
+0012	<control>
+0013	<control>
+0014	<control>
+0015	<control>
+0016	<control>
+0017	<control>
+0018	<control>
+0019	<control>
+001A	<control>
+001B	<control>
+001C	<control>
+001D	<control>
+001E	<control>
+001F	<control>
+0020	SPACE
+0021	EXCLAMATION MARK
+0022	QUOTATION MARK
+0023	NUMBER SIGN
+0024	DOLLAR SIGN
+0025	PERCENT SIGN
+0026	AMPERSAND
+0027	APOSTROPHE
+0028	LEFT PARENTHESIS
+0029	RIGHT PARENTHESIS
+002A	ASTERISK
+002B	PLUS SIGN
+002C	COMMA
+002D	HYPHEN-MINUS
+002E	FULL STOP
+002F	SOLIDUS
+0030	DIGIT ZERO
+0031	DIGIT ONE
+0032	DIGIT TWO
+0033	DIGIT THREE
+0034	DIGIT FOUR
+0035	DIGIT FIVE
+0036	DIGIT SIX
+0037	DIGIT SEVEN
+0038	DIGIT EIGHT
+0039	DIGIT NINE
+003A	COLON
+003B	SEMICOLON
+003C	LESS-THAN SIGN
+003D	EQUALS SIGN
+003E	GREATER-THAN SIGN
+003F	QUESTION MARK
+0040	COMMERCIAL AT
+0041	LATIN CAPITAL LETTER A
+0042	LATIN CAPITAL LETTER B
+0043	LATIN CAPITAL LETTER C
+0044	LATIN CAPITAL LETTER D
+0045	LATIN CAPITAL LETTER E
+0046	LATIN CAPITAL LETTER F
+0047	LATIN CAPITAL LETTER G
+0048	LATIN CAPITAL LETTER H
+0049	LATIN CAPITAL LETTER I
+004A	LATIN CAPITAL LETTER J
+004B	LATIN CAPITAL LETTER K
+004C	LATIN CAPITAL LETTER L
+004D	LATIN CAPITAL LETTER M
+004E	LATIN CAPITAL LETTER N
+004F	LATIN CAPITAL LETTER O
+0050	LATIN CAPITAL LETTER P
+0051	LATIN CAPITAL LETTER Q
+0052	LATIN CAPITAL LETTER R
+0053	LATIN CAPITAL LETTER S
+0054	LATIN CAPITAL LETTER T
+0055	LATIN CAPITAL LETTER U
+0056	LATIN CAPITAL LETTER V
+0057	LATIN CAPITAL LETTER W
+0058	LATIN CAPITAL LETTER X
+0059	LATIN CAPITAL LETTER Y
+005A	LATIN CAPITAL LETTER Z
+005B	LEFT SQUARE BRACKET
+005C	REVERSE SOLIDUS
+005D	RIGHT SQUARE BRACKET
+005E	CIRCUMFLEX ACCENT
+005F	LOW LINE
+0060	GRAVE ACCENT
+0061	LATIN SMALL LETTER A
+0062	LATIN SMALL LETTER B
+0063	LATIN SMALL LETTER C
+0064	LATIN SMALL LETTER D
+0065	LATIN SMALL LETTER E
+0066	LATIN SMALL LETTER F
+0067	LATIN SMALL LETTER G
+0068	LATIN SMALL LETTER H
+0069	LATIN SMALL LETTER I
+006A	LATIN SMALL LETTER J
+006B	LATIN SMALL LETTER K
+006C	LATIN SMALL LETTER L
+006D	LATIN SMALL LETTER M
+006E	LATIN SMALL LETTER N
+006F	LATIN SMALL LETTER O
+0070	LATIN SMALL LETTER P
+0071	LATIN SMALL LETTER Q
+0072	LATIN SMALL LETTER R
+0073	LATIN SMALL LETTER S
+0074	LATIN SMALL LETTER T
+0075	LATIN SMALL LETTER U
+0076	LATIN SMALL LETTER V
+0077	LATIN SMALL LETTER W
+0078	LATIN SMALL LETTER X
+0079	LATIN SMALL LETTER Y
+007A	LATIN SMALL LETTER Z
+007B	LEFT CURLY BRACKET
+007C	VERTICAL LINE
+007D	RIGHT CURLY BRACKET
+007E	TILDE
+007F	<control>
+0080	<control>
+0081	<control>
+0082	<control>
+0083	<control>
+0084	<control>
+0085	<control>
+0086	<control>
+0087	<control>
+0088	<control>
+0089	<control>
+008A	<control>
+008B	<control>
+008C	<control>
+008D	<control>
+008E	<control>
+008F	<control>
+0090	<control>
+0091	<control>
+0092	<control>
+0093	<control>
+0094	<control>
+0095	<control>
+0096	<control>
+0097	<control>
+0098	<control>
+0099	<control>
+009A	<control>
+009B	<control>
+009C	<control>
+009D	<control>
+009E	<control>
+009F	<control>
+00A0	NO-BREAK SPACE
+00A1	INVERTED EXCLAMATION MARK
+00A2	CENT SIGN
+00A3	POUND SIGN
+00A4	CURRENCY SIGN
+00A5	YEN SIGN
+00A6	BROKEN BAR
+00A7	SECTION SIGN
+00A8	DIAERESIS
+00A9	COPYRIGHT SIGN
+00AA	FEMININE ORDINAL INDICATOR
+00AB	LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+00AC	NOT SIGN
+00AD	SOFT HYPHEN
+00AE	REGISTERED SIGN
+00AF	MACRON
+00B0	DEGREE SIGN
+00B1	PLUS-MINUS SIGN
+00B2	SUPERSCRIPT TWO
+00B3	SUPERSCRIPT THREE
+00B4	ACUTE ACCENT
+00B5	MICRO SIGN
+00B6	PILCROW SIGN
+00B7	MIDDLE DOT
+00B8	CEDILLA
+00B9	SUPERSCRIPT ONE
+00BA	MASCULINE ORDINAL INDICATOR
+00BB	RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+00BC	VULGAR FRACTION ONE QUARTER
+00BD	VULGAR FRACTION ONE HALF
+00BE	VULGAR FRACTION THREE QUARTERS
+00BF	INVERTED QUESTION MARK
+00C0	LATIN CAPITAL LETTER A WITH GRAVE
+00C1	LATIN CAPITAL LETTER A WITH ACUTE
+00C2	LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+00C3	LATIN CAPITAL LETTER A WITH TILDE
+00C4	LATIN CAPITAL LETTER A WITH DIAERESIS
+00C5	LATIN CAPITAL LETTER A WITH RING ABOVE
+00C6	LATIN CAPITAL LETTER AE
+00C7	LATIN CAPITAL LETTER C WITH CEDILLA
+00C8	LATIN CAPITAL LETTER E WITH GRAVE
+00C9	LATIN CAPITAL LETTER E WITH ACUTE
+00CA	LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+00CB	LATIN CAPITAL LETTER E WITH DIAERESIS
+00CC	LATIN CAPITAL LETTER I WITH GRAVE
+00CD	LATIN CAPITAL LETTER I WITH ACUTE
+00CE	LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+00CF	LATIN CAPITAL LETTER I WITH DIAERESIS
+00D0	LATIN CAPITAL LETTER ETH
+00D1	LATIN CAPITAL LETTER N WITH TILDE
+00D2	LATIN CAPITAL LETTER O WITH GRAVE
+00D3	LATIN CAPITAL LETTER O WITH ACUTE
+00D4	LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+00D5	LATIN CAPITAL LETTER O WITH TILDE
+00D6	LATIN CAPITAL LETTER O WITH DIAERESIS
+00D7	MULTIPLICATION SIGN
+00D8	LATIN CAPITAL LETTER O WITH STROKE
+00D9	LATIN CAPITAL LETTER U WITH GRAVE
+00DA	LATIN CAPITAL LETTER U WITH ACUTE
+00DB	LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+00DC	LATIN CAPITAL LETTER U WITH DIAERESIS
+00DD	LATIN CAPITAL LETTER Y WITH ACUTE
+00DE	LATIN CAPITAL LETTER THORN
+00DF	LATIN SMALL LETTER SHARP S
+00E0	LATIN SMALL LETTER A WITH GRAVE
+00E1	LATIN SMALL LETTER A WITH ACUTE
+00E2	LATIN SMALL LETTER A WITH CIRCUMFLEX
+00E3	LATIN SMALL LETTER A WITH TILDE
+00E4	LATIN SMALL LETTER A WITH DIAERESIS
+00E5	LATIN SMALL LETTER A WITH RING ABOVE
+00E6	LATIN SMALL LETTER AE
+00E7	LATIN SMALL LETTER C WITH CEDILLA
+00E8	LATIN SMALL LETTER E WITH GRAVE
+00E9	LATIN SMALL LETTER E WITH ACUTE
+00EA	LATIN SMALL LETTER E WITH CIRCUMFLEX
+00EB	LATIN SMALL LETTER E WITH DIAERESIS
+00EC	LATIN SMALL LETTER I WITH GRAVE
+00ED	LATIN SMALL LETTER I WITH ACUTE
+00EE	LATIN SMALL LETTER I WITH CIRCUMFLEX
+00EF	LATIN SMALL LETTER I WITH DIAERESIS
+00F0	LATIN SMALL LETTER ETH
+00F1	LATIN SMALL LETTER N WITH TILDE
+00F2	LATIN SMALL LETTER O WITH GRAVE
+00F3	LATIN SMALL LETTER O WITH ACUTE
+00F4	LATIN SMALL LETTER O WITH CIRCUMFLEX
+00F5	LATIN SMALL LETTER O WITH TILDE
+00F6	LATIN SMALL LETTER O WITH DIAERESIS
+00F7	DIVISION SIGN
+00F8	LATIN SMALL LETTER O WITH STROKE
+00F9	LATIN SMALL LETTER U WITH GRAVE
+00FA	LATIN SMALL LETTER U WITH ACUTE
+00FB	LATIN SMALL LETTER U WITH CIRCUMFLEX
+00FC	LATIN SMALL LETTER U WITH DIAERESIS
+00FD	LATIN SMALL LETTER Y WITH ACUTE
+00FE	LATIN SMALL LETTER THORN
+00FF	LATIN SMALL LETTER Y WITH DIAERESIS
+0100	LATIN CAPITAL LETTER A WITH MACRON
+0101	LATIN SMALL LETTER A WITH MACRON
+0102	LATIN CAPITAL LETTER A WITH BREVE
+0103	LATIN SMALL LETTER A WITH BREVE
+0104	LATIN CAPITAL LETTER A WITH OGONEK
+0105	LATIN SMALL LETTER A WITH OGONEK
+0106	LATIN CAPITAL LETTER C WITH ACUTE
+0107	LATIN SMALL LETTER C WITH ACUTE
+0108	LATIN CAPITAL LETTER C WITH CIRCUMFLEX
+0109	LATIN SMALL LETTER C WITH CIRCUMFLEX
+010A	LATIN CAPITAL LETTER C WITH DOT ABOVE
+010B	LATIN SMALL LETTER C WITH DOT ABOVE
+010C	LATIN CAPITAL LETTER C WITH CARON
+010D	LATIN SMALL LETTER C WITH CARON
+010E	LATIN CAPITAL LETTER D WITH CARON
+010F	LATIN SMALL LETTER D WITH CARON
+0110	LATIN CAPITAL LETTER D WITH STROKE
+0111	LATIN SMALL LETTER D WITH STROKE
+0112	LATIN CAPITAL LETTER E WITH MACRON
+0113	LATIN SMALL LETTER E WITH MACRON
+0114	LATIN CAPITAL LETTER E WITH BREVE
+0115	LATIN SMALL LETTER E WITH BREVE
+0116	LATIN CAPITAL LETTER E WITH DOT ABOVE
+0117	LATIN SMALL LETTER E WITH DOT ABOVE
+0118	LATIN CAPITAL LETTER E WITH OGONEK
+0119	LATIN SMALL LETTER E WITH OGONEK
+011A	LATIN CAPITAL LETTER E WITH CARON
+011B	LATIN SMALL LETTER E WITH CARON
+011C	LATIN CAPITAL LETTER G WITH CIRCUMFLEX
+011D	LATIN SMALL LETTER G WITH CIRCUMFLEX
+011E	LATIN CAPITAL LETTER G WITH BREVE
+011F	LATIN SMALL LETTER G WITH BREVE
+0120	LATIN CAPITAL LETTER G WITH DOT ABOVE
+0121	LATIN SMALL LETTER G WITH DOT ABOVE
+0122	LATIN CAPITAL LETTER G WITH CEDILLA
+0123	LATIN SMALL LETTER G WITH CEDILLA
+0124	LATIN CAPITAL LETTER H WITH CIRCUMFLEX
+0125	LATIN SMALL LETTER H WITH CIRCUMFLEX
+0126	LATIN CAPITAL LETTER H WITH STROKE
+0127	LATIN SMALL LETTER H WITH STROKE
+0128	LATIN CAPITAL LETTER I WITH TILDE
+0129	LATIN SMALL LETTER I WITH TILDE
+012A	LATIN CAPITAL LETTER I WITH MACRON
+012B	LATIN SMALL LETTER I WITH MACRON
+012C	LATIN CAPITAL LETTER I WITH BREVE
+012D	LATIN SMALL LETTER I WITH BREVE
+012E	LATIN CAPITAL LETTER I WITH OGONEK
+012F	LATIN SMALL LETTER I WITH OGONEK
+0130	LATIN CAPITAL LETTER I WITH DOT ABOVE
+0131	LATIN SMALL LETTER DOTLESS I
+0132	LATIN CAPITAL LIGATURE IJ
+0133	LATIN SMALL LIGATURE IJ
+0134	LATIN CAPITAL LETTER J WITH CIRCUMFLEX
+0135	LATIN SMALL LETTER J WITH CIRCUMFLEX
+0136	LATIN CAPITAL LETTER K WITH CEDILLA
+0137	LATIN SMALL LETTER K WITH CEDILLA
+0138	LATIN SMALL LETTER KRA
+0139	LATIN CAPITAL LETTER L WITH ACUTE
+013A	LATIN SMALL LETTER L WITH ACUTE
+013B	LATIN CAPITAL LETTER L WITH CEDILLA
+013C	LATIN SMALL LETTER L WITH CEDILLA
+013D	LATIN CAPITAL LETTER L WITH CARON
+013E	LATIN SMALL LETTER L WITH CARON
+013F	LATIN CAPITAL LETTER L WITH MIDDLE DOT
+0140	LATIN SMALL LETTER L WITH MIDDLE DOT
+0141	LATIN CAPITAL LETTER L WITH STROKE
+0142	LATIN SMALL LETTER L WITH STROKE
+0143	LATIN CAPITAL LETTER N WITH ACUTE
+0144	LATIN SMALL LETTER N WITH ACUTE
+0145	LATIN CAPITAL LETTER N WITH CEDILLA
+0146	LATIN SMALL LETTER N WITH CEDILLA
+0147	LATIN CAPITAL LETTER N WITH CARON
+0148	LATIN SMALL LETTER N WITH CARON
+0149	LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
+014A	LATIN CAPITAL LETTER ENG
+014B	LATIN SMALL LETTER ENG
+014C	LATIN CAPITAL LETTER O WITH MACRON
+014D	LATIN SMALL LETTER O WITH MACRON
+014E	LATIN CAPITAL LETTER O WITH BREVE
+014F	LATIN SMALL LETTER O WITH BREVE
+0150	LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+0151	LATIN SMALL LETTER O WITH DOUBLE ACUTE
+0152	LATIN CAPITAL LIGATURE OE
+0153	LATIN SMALL LIGATURE OE
+0154	LATIN CAPITAL LETTER R WITH ACUTE
+0155	LATIN SMALL LETTER R WITH ACUTE
+0156	LATIN CAPITAL LETTER R WITH CEDILLA
+0157	LATIN SMALL LETTER R WITH CEDILLA
+0158	LATIN CAPITAL LETTER R WITH CARON
+0159	LATIN SMALL LETTER R WITH CARON
+015A	LATIN CAPITAL LETTER S WITH ACUTE
+015B	LATIN SMALL LETTER S WITH ACUTE
+015C	LATIN CAPITAL LETTER S WITH CIRCUMFLEX
+015D	LATIN SMALL LETTER S WITH CIRCUMFLEX
+015E	LATIN CAPITAL LETTER S WITH CEDILLA
+015F	LATIN SMALL LETTER S WITH CEDILLA
+0160	LATIN CAPITAL LETTER S WITH CARON
+0161	LATIN SMALL LETTER S WITH CARON
+0162	LATIN CAPITAL LETTER T WITH CEDILLA
+0163	LATIN SMALL LETTER T WITH CEDILLA
+0164	LATIN CAPITAL LETTER T WITH CARON
+0165	LATIN SMALL LETTER T WITH CARON
+0166	LATIN CAPITAL LETTER T WITH STROKE
+0167	LATIN SMALL LETTER T WITH STROKE
+0168	LATIN CAPITAL LETTER U WITH TILDE
+0169	LATIN SMALL LETTER U WITH TILDE
+016A	LATIN CAPITAL LETTER U WITH MACRON
+016B	LATIN SMALL LETTER U WITH MACRON
+016C	LATIN CAPITAL LETTER U WITH BREVE
+016D	LATIN SMALL LETTER U WITH BREVE
+016E	LATIN CAPITAL LETTER U WITH RING ABOVE
+016F	LATIN SMALL LETTER U WITH RING ABOVE
+0170	LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+0171	LATIN SMALL LETTER U WITH DOUBLE ACUTE
+0172	LATIN CAPITAL LETTER U WITH OGONEK
+0173	LATIN SMALL LETTER U WITH OGONEK
+0174	LATIN CAPITAL LETTER W WITH CIRCUMFLEX
+0175	LATIN SMALL LETTER W WITH CIRCUMFLEX
+0176	LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
+0177	LATIN SMALL LETTER Y WITH CIRCUMFLEX
+0178	LATIN CAPITAL LETTER Y WITH DIAERESIS
+0179	LATIN CAPITAL LETTER Z WITH ACUTE
+017A	LATIN SMALL LETTER Z WITH ACUTE
+017B	LATIN CAPITAL LETTER Z WITH DOT ABOVE
+017C	LATIN SMALL LETTER Z WITH DOT ABOVE
+017D	LATIN CAPITAL LETTER Z WITH CARON
+017E	LATIN SMALL LETTER Z WITH CARON
+017F	LATIN SMALL LETTER LONG S
+0180	LATIN SMALL LETTER B WITH STROKE
+0181	LATIN CAPITAL LETTER B WITH HOOK
+0182	LATIN CAPITAL LETTER B WITH TOPBAR
+0183	LATIN SMALL LETTER B WITH TOPBAR
+0184	LATIN CAPITAL LETTER TONE SIX
+0185	LATIN SMALL LETTER TONE SIX
+0186	LATIN CAPITAL LETTER OPEN O
+0187	LATIN CAPITAL LETTER C WITH HOOK
+0188	LATIN SMALL LETTER C WITH HOOK
+0189	LATIN CAPITAL LETTER AFRICAN D
+018A	LATIN CAPITAL LETTER D WITH HOOK
+018B	LATIN CAPITAL LETTER D WITH TOPBAR
+018C	LATIN SMALL LETTER D WITH TOPBAR
+018D	LATIN SMALL LETTER TURNED DELTA
+018E	LATIN CAPITAL LETTER REVERSED E
+018F	LATIN CAPITAL LETTER SCHWA
+0190	LATIN CAPITAL LETTER OPEN E
+0191	LATIN CAPITAL LETTER F WITH HOOK
+0192	LATIN SMALL LETTER F WITH HOOK
+0193	LATIN CAPITAL LETTER G WITH HOOK
+0194	LATIN CAPITAL LETTER GAMMA
+0195	LATIN SMALL LETTER HV
+0196	LATIN CAPITAL LETTER IOTA
+0197	LATIN CAPITAL LETTER I WITH STROKE
+0198	LATIN CAPITAL LETTER K WITH HOOK
+0199	LATIN SMALL LETTER K WITH HOOK
+019A	LATIN SMALL LETTER L WITH BAR
+019B	LATIN SMALL LETTER LAMBDA WITH STROKE
+019C	LATIN CAPITAL LETTER TURNED M
+019D	LATIN CAPITAL LETTER N WITH LEFT HOOK
+019E	LATIN SMALL LETTER N WITH LONG RIGHT LEG
+019F	LATIN CAPITAL LETTER O WITH MIDDLE TILDE
+01A0	LATIN CAPITAL LETTER O WITH HORN
+01A1	LATIN SMALL LETTER O WITH HORN
+01A2	LATIN CAPITAL LETTER OI
+01A3	LATIN SMALL LETTER OI
+01A4	LATIN CAPITAL LETTER P WITH HOOK
+01A5	LATIN SMALL LETTER P WITH HOOK
+01A6	LATIN LETTER YR
+01A7	LATIN CAPITAL LETTER TONE TWO
+01A8	LATIN SMALL LETTER TONE TWO
+01A9	LATIN CAPITAL LETTER ESH
+01AA	LATIN LETTER REVERSED ESH LOOP
+01AB	LATIN SMALL LETTER T WITH PALATAL HOOK
+01AC	LATIN CAPITAL LETTER T WITH HOOK
+01AD	LATIN SMALL LETTER T WITH HOOK
+01AE	LATIN CAPITAL LETTER T WITH RETROFLEX HOOK
+01AF	LATIN CAPITAL LETTER U WITH HORN
+01B0	LATIN SMALL LETTER U WITH HORN
+01B1	LATIN CAPITAL LETTER UPSILON
+01B2	LATIN CAPITAL LETTER V WITH HOOK
+01B3	LATIN CAPITAL LETTER Y WITH HOOK
+01B4	LATIN SMALL LETTER Y WITH HOOK
+01B5	LATIN CAPITAL LETTER Z WITH STROKE
+01B6	LATIN SMALL LETTER Z WITH STROKE
+01B7	LATIN CAPITAL LETTER EZH
+01B8	LATIN CAPITAL LETTER EZH REVERSED
+01B9	LATIN SMALL LETTER EZH REVERSED
+01BA	LATIN SMALL LETTER EZH WITH TAIL
+01BB	LATIN LETTER TWO WITH STROKE
+01BC	LATIN CAPITAL LETTER TONE FIVE
+01BD	LATIN SMALL LETTER TONE FIVE
+01BE	LATIN LETTER INVERTED GLOTTAL STOP WITH STROKE
+01BF	LATIN LETTER WYNN
+01C0	LATIN LETTER DENTAL CLICK
+01C1	LATIN LETTER LATERAL CLICK
+01C2	LATIN LETTER ALVEOLAR CLICK
+01C3	LATIN LETTER RETROFLEX CLICK
+01C4	LATIN CAPITAL LETTER DZ WITH CARON
+01C5	LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON
+01C6	LATIN SMALL LETTER DZ WITH CARON
+01C7	LATIN CAPITAL LETTER LJ
+01C8	LATIN CAPITAL LETTER L WITH SMALL LETTER J
+01C9	LATIN SMALL LETTER LJ
+01CA	LATIN CAPITAL LETTER NJ
+01CB	LATIN CAPITAL LETTER N WITH SMALL LETTER J
+01CC	LATIN SMALL LETTER NJ
+01CD	LATIN CAPITAL LETTER A WITH CARON
+01CE	LATIN SMALL LETTER A WITH CARON
+01CF	LATIN CAPITAL LETTER I WITH CARON
+01D0	LATIN SMALL LETTER I WITH CARON
+01D1	LATIN CAPITAL LETTER O WITH CARON
+01D2	LATIN SMALL LETTER O WITH CARON
+01D3	LATIN CAPITAL LETTER U WITH CARON
+01D4	LATIN SMALL LETTER U WITH CARON
+01D5	LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON
+01D6	LATIN SMALL LETTER U WITH DIAERESIS AND MACRON
+01D7	LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE
+01D8	LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE
+01D9	LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON
+01DA	LATIN SMALL LETTER U WITH DIAERESIS AND CARON
+01DB	LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE
+01DC	LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE
+01DD	LATIN SMALL LETTER TURNED E
+01DE	LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON
+01DF	LATIN SMALL LETTER A WITH DIAERESIS AND MACRON
+01E0	LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON
+01E1	LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON
+01E2	LATIN CAPITAL LETTER AE WITH MACRON
+01E3	LATIN SMALL LETTER AE WITH MACRON
+01E4	LATIN CAPITAL LETTER G WITH STROKE
+01E5	LATIN SMALL LETTER G WITH STROKE
+01E6	LATIN CAPITAL LETTER G WITH CARON
+01E7	LATIN SMALL LETTER G WITH CARON
+01E8	LATIN CAPITAL LETTER K WITH CARON
+01E9	LATIN SMALL LETTER K WITH CARON
+01EA	LATIN CAPITAL LETTER O WITH OGONEK
+01EB	LATIN SMALL LETTER O WITH OGONEK
+01EC	LATIN CAPITAL LETTER O WITH OGONEK AND MACRON
+01ED	LATIN SMALL LETTER O WITH OGONEK AND MACRON
+01EE	LATIN CAPITAL LETTER EZH WITH CARON
+01EF	LATIN SMALL LETTER EZH WITH CARON
+01F0	LATIN SMALL LETTER J WITH CARON
+01F1	LATIN CAPITAL LETTER DZ
+01F2	LATIN CAPITAL LETTER D WITH SMALL LETTER Z
+01F3	LATIN SMALL LETTER DZ
+01F4	LATIN CAPITAL LETTER G WITH ACUTE
+01F5	LATIN SMALL LETTER G WITH ACUTE
+01FA	LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE
+01FB	LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE
+01FC	LATIN CAPITAL LETTER AE WITH ACUTE
+01FD	LATIN SMALL LETTER AE WITH ACUTE
+01FE	LATIN CAPITAL LETTER O WITH STROKE AND ACUTE
+01FF	LATIN SMALL LETTER O WITH STROKE AND ACUTE
+0200	LATIN CAPITAL LETTER A WITH DOUBLE GRAVE
+0201	LATIN SMALL LETTER A WITH DOUBLE GRAVE
+0202	LATIN CAPITAL LETTER A WITH INVERTED BREVE
+0203	LATIN SMALL LETTER A WITH INVERTED BREVE
+0204	LATIN CAPITAL LETTER E WITH DOUBLE GRAVE
+0205	LATIN SMALL LETTER E WITH DOUBLE GRAVE
+0206	LATIN CAPITAL LETTER E WITH INVERTED BREVE
+0207	LATIN SMALL LETTER E WITH INVERTED BREVE
+0208	LATIN CAPITAL LETTER I WITH DOUBLE GRAVE
+0209	LATIN SMALL LETTER I WITH DOUBLE GRAVE
+020A	LATIN CAPITAL LETTER I WITH INVERTED BREVE
+020B	LATIN SMALL LETTER I WITH INVERTED BREVE
+020C	LATIN CAPITAL LETTER O WITH DOUBLE GRAVE
+020D	LATIN SMALL LETTER O WITH DOUBLE GRAVE
+020E	LATIN CAPITAL LETTER O WITH INVERTED BREVE
+020F	LATIN SMALL LETTER O WITH INVERTED BREVE
+0210	LATIN CAPITAL LETTER R WITH DOUBLE GRAVE
+0211	LATIN SMALL LETTER R WITH DOUBLE GRAVE
+0212	LATIN CAPITAL LETTER R WITH INVERTED BREVE
+0213	LATIN SMALL LETTER R WITH INVERTED BREVE
+0214	LATIN CAPITAL LETTER U WITH DOUBLE GRAVE
+0215	LATIN SMALL LETTER U WITH DOUBLE GRAVE
+0216	LATIN CAPITAL LETTER U WITH INVERTED BREVE
+0217	LATIN SMALL LETTER U WITH INVERTED BREVE
+0250	LATIN SMALL LETTER TURNED A
+0251	LATIN SMALL LETTER ALPHA
+0252	LATIN SMALL LETTER TURNED ALPHA
+0253	LATIN SMALL LETTER B WITH HOOK
+0254	LATIN SMALL LETTER OPEN O
+0255	LATIN SMALL LETTER C WITH CURL
+0256	LATIN SMALL LETTER D WITH TAIL
+0257	LATIN SMALL LETTER D WITH HOOK
+0258	LATIN SMALL LETTER REVERSED E
+0259	LATIN SMALL LETTER SCHWA
+025A	LATIN SMALL LETTER SCHWA WITH HOOK
+025B	LATIN SMALL LETTER OPEN E
+025C	LATIN SMALL LETTER REVERSED OPEN E
+025D	LATIN SMALL LETTER REVERSED OPEN E WITH HOOK
+025E	LATIN SMALL LETTER CLOSED REVERSED OPEN E
+025F	LATIN SMALL LETTER DOTLESS J WITH STROKE
+0260	LATIN SMALL LETTER G WITH HOOK
+0261	LATIN SMALL LETTER SCRIPT G
+0262	LATIN LETTER SMALL CAPITAL G
+0263	LATIN SMALL LETTER GAMMA
+0264	LATIN SMALL LETTER RAMS HORN
+0265	LATIN SMALL LETTER TURNED H
+0266	LATIN SMALL LETTER H WITH HOOK
+0267	LATIN SMALL LETTER HENG WITH HOOK
+0268	LATIN SMALL LETTER I WITH STROKE
+0269	LATIN SMALL LETTER IOTA
+026A	LATIN LETTER SMALL CAPITAL I
+026B	LATIN SMALL LETTER L WITH MIDDLE TILDE
+026C	LATIN SMALL LETTER L WITH BELT
+026D	LATIN SMALL LETTER L WITH RETROFLEX HOOK
+026E	LATIN SMALL LETTER LEZH
+026F	LATIN SMALL LETTER TURNED M
+0270	LATIN SMALL LETTER TURNED M WITH LONG LEG
+0271	LATIN SMALL LETTER M WITH HOOK
+0272	LATIN SMALL LETTER N WITH LEFT HOOK
+0273	LATIN SMALL LETTER N WITH RETROFLEX HOOK
+0274	LATIN LETTER SMALL CAPITAL N
+0275	LATIN SMALL LETTER BARRED O
+0276	LATIN LETTER SMALL CAPITAL OE
+0277	LATIN SMALL LETTER CLOSED OMEGA
+0278	LATIN SMALL LETTER PHI
+0279	LATIN SMALL LETTER TURNED R
+027A	LATIN SMALL LETTER TURNED R WITH LONG LEG
+027B	LATIN SMALL LETTER TURNED R WITH HOOK
+027C	LATIN SMALL LETTER R WITH LONG LEG
+027D	LATIN SMALL LETTER R WITH TAIL
+027E	LATIN SMALL LETTER R WITH FISHHOOK
+027F	LATIN SMALL LETTER REVERSED R WITH FISHHOOK
+0280	LATIN LETTER SMALL CAPITAL R
+0281	LATIN LETTER SMALL CAPITAL INVERTED R
+0282	LATIN SMALL LETTER S WITH HOOK
+0283	LATIN SMALL LETTER ESH
+0284	LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK
+0285	LATIN SMALL LETTER SQUAT REVERSED ESH
+0286	LATIN SMALL LETTER ESH WITH CURL
+0287	LATIN SMALL LETTER TURNED T
+0288	LATIN SMALL LETTER T WITH RETROFLEX HOOK
+0289	LATIN SMALL LETTER U BAR
+028A	LATIN SMALL LETTER UPSILON
+028B	LATIN SMALL LETTER V WITH HOOK
+028C	LATIN SMALL LETTER TURNED V
+028D	LATIN SMALL LETTER TURNED W
+028E	LATIN SMALL LETTER TURNED Y
+028F	LATIN LETTER SMALL CAPITAL Y
+0290	LATIN SMALL LETTER Z WITH RETROFLEX HOOK
+0291	LATIN SMALL LETTER Z WITH CURL
+0292	LATIN SMALL LETTER EZH
+0293	LATIN SMALL LETTER EZH WITH CURL
+0294	LATIN LETTER GLOTTAL STOP
+0295	LATIN LETTER PHARYNGEAL VOICED FRICATIVE
+0296	LATIN LETTER INVERTED GLOTTAL STOP
+0297	LATIN LETTER STRETCHED C
+0298	LATIN LETTER BILABIAL CLICK
+0299	LATIN LETTER SMALL CAPITAL B
+029A	LATIN SMALL LETTER CLOSED OPEN E
+029B	LATIN LETTER SMALL CAPITAL G WITH HOOK
+029C	LATIN LETTER SMALL CAPITAL H
+029D	LATIN SMALL LETTER J WITH CROSSED-TAIL
+029E	LATIN SMALL LETTER TURNED K
+029F	LATIN LETTER SMALL CAPITAL L
+02A0	LATIN SMALL LETTER Q WITH HOOK
+02A1	LATIN LETTER GLOTTAL STOP WITH STROKE
+02A2	LATIN LETTER REVERSED GLOTTAL STOP WITH STROKE
+02A3	LATIN SMALL LETTER DZ DIGRAPH
+02A4	LATIN SMALL LETTER DEZH DIGRAPH
+02A5	LATIN SMALL LETTER DZ DIGRAPH WITH CURL
+02A6	LATIN SMALL LETTER TS DIGRAPH
+02A7	LATIN SMALL LETTER TESH DIGRAPH
+02A8	LATIN SMALL LETTER TC DIGRAPH WITH CURL
+02B0	MODIFIER LETTER SMALL H
+02B1	MODIFIER LETTER SMALL H WITH HOOK
+02B2	MODIFIER LETTER SMALL J
+02B3	MODIFIER LETTER SMALL R
+02B4	MODIFIER LETTER SMALL TURNED R
+02B5	MODIFIER LETTER SMALL TURNED R WITH HOOK
+02B6	MODIFIER LETTER SMALL CAPITAL INVERTED R
+02B7	MODIFIER LETTER SMALL W
+02B8	MODIFIER LETTER SMALL Y
+02B9	MODIFIER LETTER PRIME
+02BA	MODIFIER LETTER DOUBLE PRIME
+02BB	MODIFIER LETTER TURNED COMMA
+02BC	MODIFIER LETTER APOSTROPHE
+02BD	MODIFIER LETTER REVERSED COMMA
+02BE	MODIFIER LETTER RIGHT HALF RING
+02BF	MODIFIER LETTER LEFT HALF RING
+02C0	MODIFIER LETTER GLOTTAL STOP
+02C1	MODIFIER LETTER REVERSED GLOTTAL STOP
+02C2	MODIFIER LETTER LEFT ARROWHEAD
+02C3	MODIFIER LETTER RIGHT ARROWHEAD
+02C4	MODIFIER LETTER UP ARROWHEAD
+02C5	MODIFIER LETTER DOWN ARROWHEAD
+02C6	MODIFIER LETTER CIRCUMFLEX ACCENT
+02C7	CARON
+02C8	MODIFIER LETTER VERTICAL LINE
+02C9	MODIFIER LETTER MACRON
+02CA	MODIFIER LETTER ACUTE ACCENT
+02CB	MODIFIER LETTER GRAVE ACCENT
+02CC	MODIFIER LETTER LOW VERTICAL LINE
+02CD	MODIFIER LETTER LOW MACRON
+02CE	MODIFIER LETTER LOW GRAVE ACCENT
+02CF	MODIFIER LETTER LOW ACUTE ACCENT
+02D0	MODIFIER LETTER TRIANGULAR COLON
+02D1	MODIFIER LETTER HALF TRIANGULAR COLON
+02D2	MODIFIER LETTER CENTRED RIGHT HALF RING
+02D3	MODIFIER LETTER CENTRED LEFT HALF RING
+02D4	MODIFIER LETTER UP TACK
+02D5	MODIFIER LETTER DOWN TACK
+02D6	MODIFIER LETTER PLUS SIGN
+02D7	MODIFIER LETTER MINUS SIGN
+02D8	BREVE
+02D9	DOT ABOVE
+02DA	RING ABOVE
+02DB	OGONEK
+02DC	SMALL TILDE
+02DD	DOUBLE ACUTE ACCENT
+02DE	MODIFIER LETTER RHOTIC HOOK
+02E0	MODIFIER LETTER SMALL GAMMA
+02E1	MODIFIER LETTER SMALL L
+02E2	MODIFIER LETTER SMALL S
+02E3	MODIFIER LETTER SMALL X
+02E4	MODIFIER LETTER SMALL REVERSED GLOTTAL STOP
+02E5	MODIFIER LETTER EXTRA-HIGH TONE BAR
+02E6	MODIFIER LETTER HIGH TONE BAR
+02E7	MODIFIER LETTER MID TONE BAR
+02E8	MODIFIER LETTER LOW TONE BAR
+02E9	MODIFIER LETTER EXTRA-LOW TONE BAR
+0300	COMBINING GRAVE ACCENT
+0301	COMBINING ACUTE ACCENT
+0302	COMBINING CIRCUMFLEX ACCENT
+0303	COMBINING TILDE
+0304	COMBINING MACRON
+0305	COMBINING OVERLINE
+0306	COMBINING BREVE
+0307	COMBINING DOT ABOVE
+0308	COMBINING DIAERESIS
+0309	COMBINING HOOK ABOVE
+030A	COMBINING RING ABOVE
+030B	COMBINING DOUBLE ACUTE ACCENT
+030C	COMBINING CARON
+030D	COMBINING VERTICAL LINE ABOVE
+030E	COMBINING DOUBLE VERTICAL LINE ABOVE
+030F	COMBINING DOUBLE GRAVE ACCENT
+0310	COMBINING CANDRABINDU
+0311	COMBINING INVERTED BREVE
+0312	COMBINING TURNED COMMA ABOVE
+0313	COMBINING COMMA ABOVE
+0314	COMBINING REVERSED COMMA ABOVE
+0315	COMBINING COMMA ABOVE RIGHT
+0316	COMBINING GRAVE ACCENT BELOW
+0317	COMBINING ACUTE ACCENT BELOW
+0318	COMBINING LEFT TACK BELOW
+0319	COMBINING RIGHT TACK BELOW
+031A	COMBINING LEFT ANGLE ABOVE
+031B	COMBINING HORN
+031C	COMBINING LEFT HALF RING BELOW
+031D	COMBINING UP TACK BELOW
+031E	COMBINING DOWN TACK BELOW
+031F	COMBINING PLUS SIGN BELOW
+0320	COMBINING MINUS SIGN BELOW
+0321	COMBINING PALATALIZED HOOK BELOW
+0322	COMBINING RETROFLEX HOOK BELOW
+0323	COMBINING DOT BELOW
+0324	COMBINING DIAERESIS BELOW
+0325	COMBINING RING BELOW
+0326	COMBINING COMMA BELOW
+0327	COMBINING CEDILLA
+0328	COMBINING OGONEK
+0329	COMBINING VERTICAL LINE BELOW
+032A	COMBINING BRIDGE BELOW
+032B	COMBINING INVERTED DOUBLE ARCH BELOW
+032C	COMBINING CARON BELOW
+032D	COMBINING CIRCUMFLEX ACCENT BELOW
+032E	COMBINING BREVE BELOW
+032F	COMBINING INVERTED BREVE BELOW
+0330	COMBINING TILDE BELOW
+0331	COMBINING MACRON BELOW
+0332	COMBINING LOW LINE
+0333	COMBINING DOUBLE LOW LINE
+0334	COMBINING TILDE OVERLAY
+0335	COMBINING SHORT STROKE OVERLAY
+0336	COMBINING LONG STROKE OVERLAY
+0337	COMBINING SHORT SOLIDUS OVERLAY
+0338	COMBINING LONG SOLIDUS OVERLAY
+0339	COMBINING RIGHT HALF RING BELOW
+033A	COMBINING INVERTED BRIDGE BELOW
+033B	COMBINING SQUARE BELOW
+033C	COMBINING SEAGULL BELOW
+033D	COMBINING X ABOVE
+033E	COMBINING VERTICAL TILDE
+033F	COMBINING DOUBLE OVERLINE
+0340	COMBINING GRAVE TONE MARK
+0341	COMBINING ACUTE TONE MARK
+0342	COMBINING GREEK PERISPOMENI
+0343	COMBINING GREEK KORONIS
+0344	COMBINING GREEK DIALYTIKA TONOS
+0345	COMBINING GREEK YPOGEGRAMMENI
+0360	COMBINING DOUBLE TILDE
+0361	COMBINING DOUBLE INVERTED BREVE
+0374	GREEK NUMERAL SIGN
+0375	GREEK LOWER NUMERAL SIGN
+037A	GREEK YPOGEGRAMMENI
+037E	GREEK QUESTION MARK
+0384	GREEK TONOS
+0385	GREEK DIALYTIKA TONOS
+0386	GREEK CAPITAL LETTER ALPHA WITH TONOS
+0387	GREEK ANO TELEIA
+0388	GREEK CAPITAL LETTER EPSILON WITH TONOS
+0389	GREEK CAPITAL LETTER ETA WITH TONOS
+038A	GREEK CAPITAL LETTER IOTA WITH TONOS
+038C	GREEK CAPITAL LETTER OMICRON WITH TONOS
+038E	GREEK CAPITAL LETTER UPSILON WITH TONOS
+038F	GREEK CAPITAL LETTER OMEGA WITH TONOS
+0390	GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+0391	GREEK CAPITAL LETTER ALPHA
+0392	GREEK CAPITAL LETTER BETA
+0393	GREEK CAPITAL LETTER GAMMA
+0394	GREEK CAPITAL LETTER DELTA
+0395	GREEK CAPITAL LETTER EPSILON
+0396	GREEK CAPITAL LETTER ZETA
+0397	GREEK CAPITAL LETTER ETA
+0398	GREEK CAPITAL LETTER THETA
+0399	GREEK CAPITAL LETTER IOTA
+039A	GREEK CAPITAL LETTER KAPPA
+039B	GREEK CAPITAL LETTER LAMDA
+039C	GREEK CAPITAL LETTER MU
+039D	GREEK CAPITAL LETTER NU
+039E	GREEK CAPITAL LETTER XI
+039F	GREEK CAPITAL LETTER OMICRON
+03A0	GREEK CAPITAL LETTER PI
+03A1	GREEK CAPITAL LETTER RHO
+03A3	GREEK CAPITAL LETTER SIGMA
+03A4	GREEK CAPITAL LETTER TAU
+03A5	GREEK CAPITAL LETTER UPSILON
+03A6	GREEK CAPITAL LETTER PHI
+03A7	GREEK CAPITAL LETTER CHI
+03A8	GREEK CAPITAL LETTER PSI
+03A9	GREEK CAPITAL LETTER OMEGA
+03AA	GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+03AB	GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+03AC	GREEK SMALL LETTER ALPHA WITH TONOS
+03AD	GREEK SMALL LETTER EPSILON WITH TONOS
+03AE	GREEK SMALL LETTER ETA WITH TONOS
+03AF	GREEK SMALL LETTER IOTA WITH TONOS
+03B0	GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+03B1	GREEK SMALL LETTER ALPHA
+03B2	GREEK SMALL LETTER BETA
+03B3	GREEK SMALL LETTER GAMMA
+03B4	GREEK SMALL LETTER DELTA
+03B5	GREEK SMALL LETTER EPSILON
+03B6	GREEK SMALL LETTER ZETA
+03B7	GREEK SMALL LETTER ETA
+03B8	GREEK SMALL LETTER THETA
+03B9	GREEK SMALL LETTER IOTA
+03BA	GREEK SMALL LETTER KAPPA
+03BB	GREEK SMALL LETTER LAMDA
+03BC	GREEK SMALL LETTER MU
+03BD	GREEK SMALL LETTER NU
+03BE	GREEK SMALL LETTER XI
+03BF	GREEK SMALL LETTER OMICRON
+03C0	GREEK SMALL LETTER PI
+03C1	GREEK SMALL LETTER RHO
+03C2	GREEK SMALL LETTER FINAL SIGMA
+03C3	GREEK SMALL LETTER SIGMA
+03C4	GREEK SMALL LETTER TAU
+03C5	GREEK SMALL LETTER UPSILON
+03C6	GREEK SMALL LETTER PHI
+03C7	GREEK SMALL LETTER CHI
+03C8	GREEK SMALL LETTER PSI
+03C9	GREEK SMALL LETTER OMEGA
+03CA	GREEK SMALL LETTER IOTA WITH DIALYTIKA
+03CB	GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+03CC	GREEK SMALL LETTER OMICRON WITH TONOS
+03CD	GREEK SMALL LETTER UPSILON WITH TONOS
+03CE	GREEK SMALL LETTER OMEGA WITH TONOS
+03D0	GREEK BETA SYMBOL
+03D1	GREEK THETA SYMBOL
+03D2	GREEK UPSILON WITH HOOK SYMBOL
+03D3	GREEK UPSILON WITH ACUTE AND HOOK SYMBOL
+03D4	GREEK UPSILON WITH DIAERESIS AND HOOK SYMBOL
+03D5	GREEK PHI SYMBOL
+03D6	GREEK PI SYMBOL
+03DA	GREEK LETTER STIGMA
+03DC	GREEK LETTER DIGAMMA
+03DE	GREEK LETTER KOPPA
+03E0	GREEK LETTER SAMPI
+03E2	COPTIC CAPITAL LETTER SHEI
+03E3	COPTIC SMALL LETTER SHEI
+03E4	COPTIC CAPITAL LETTER FEI
+03E5	COPTIC SMALL LETTER FEI
+03E6	COPTIC CAPITAL LETTER KHEI
+03E7	COPTIC SMALL LETTER KHEI
+03E8	COPTIC CAPITAL LETTER HORI
+03E9	COPTIC SMALL LETTER HORI
+03EA	COPTIC CAPITAL LETTER GANGIA
+03EB	COPTIC SMALL LETTER GANGIA
+03EC	COPTIC CAPITAL LETTER SHIMA
+03ED	COPTIC SMALL LETTER SHIMA
+03EE	COPTIC CAPITAL LETTER DEI
+03EF	COPTIC SMALL LETTER DEI
+03F0	GREEK KAPPA SYMBOL
+03F1	GREEK RHO SYMBOL
+03F2	GREEK LUNATE SIGMA SYMBOL
+03F3	GREEK LETTER YOT
+0401	CYRILLIC CAPITAL LETTER IO
+0402	CYRILLIC CAPITAL LETTER DJE
+0403	CYRILLIC CAPITAL LETTER GJE
+0404	CYRILLIC CAPITAL LETTER UKRAINIAN IE
+0405	CYRILLIC CAPITAL LETTER DZE
+0406	CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+0407	CYRILLIC CAPITAL LETTER YI
+0408	CYRILLIC CAPITAL LETTER JE
+0409	CYRILLIC CAPITAL LETTER LJE
+040A	CYRILLIC CAPITAL LETTER NJE
+040B	CYRILLIC CAPITAL LETTER TSHE
+040C	CYRILLIC CAPITAL LETTER KJE
+040E	CYRILLIC CAPITAL LETTER SHORT U
+040F	CYRILLIC CAPITAL LETTER DZHE
+0410	CYRILLIC CAPITAL LETTER A
+0411	CYRILLIC CAPITAL LETTER BE
+0412	CYRILLIC CAPITAL LETTER VE
+0413	CYRILLIC CAPITAL LETTER GHE
+0414	CYRILLIC CAPITAL LETTER DE
+0415	CYRILLIC CAPITAL LETTER IE
+0416	CYRILLIC CAPITAL LETTER ZHE
+0417	CYRILLIC CAPITAL LETTER ZE
+0418	CYRILLIC CAPITAL LETTER I
+0419	CYRILLIC CAPITAL LETTER SHORT I
+041A	CYRILLIC CAPITAL LETTER KA
+041B	CYRILLIC CAPITAL LETTER EL
+041C	CYRILLIC CAPITAL LETTER EM
+041D	CYRILLIC CAPITAL LETTER EN
+041E	CYRILLIC CAPITAL LETTER O
+041F	CYRILLIC CAPITAL LETTER PE
+0420	CYRILLIC CAPITAL LETTER ER
+0421	CYRILLIC CAPITAL LETTER ES
+0422	CYRILLIC CAPITAL LETTER TE
+0423	CYRILLIC CAPITAL LETTER U
+0424	CYRILLIC CAPITAL LETTER EF
+0425	CYRILLIC CAPITAL LETTER HA
+0426	CYRILLIC CAPITAL LETTER TSE
+0427	CYRILLIC CAPITAL LETTER CHE
+0428	CYRILLIC CAPITAL LETTER SHA
+0429	CYRILLIC CAPITAL LETTER SHCHA
+042A	CYRILLIC CAPITAL LETTER HARD SIGN
+042B	CYRILLIC CAPITAL LETTER YERU
+042C	CYRILLIC CAPITAL LETTER SOFT SIGN
+042D	CYRILLIC CAPITAL LETTER E
+042E	CYRILLIC CAPITAL LETTER YU
+042F	CYRILLIC CAPITAL LETTER YA
+0430	CYRILLIC SMALL LETTER A
+0431	CYRILLIC SMALL LETTER BE
+0432	CYRILLIC SMALL LETTER VE
+0433	CYRILLIC SMALL LETTER GHE
+0434	CYRILLIC SMALL LETTER DE
+0435	CYRILLIC SMALL LETTER IE
+0436	CYRILLIC SMALL LETTER ZHE
+0437	CYRILLIC SMALL LETTER ZE
+0438	CYRILLIC SMALL LETTER I
+0439	CYRILLIC SMALL LETTER SHORT I
+043A	CYRILLIC SMALL LETTER KA
+043B	CYRILLIC SMALL LETTER EL
+043C	CYRILLIC SMALL LETTER EM
+043D	CYRILLIC SMALL LETTER EN
+043E	CYRILLIC SMALL LETTER O
+043F	CYRILLIC SMALL LETTER PE
+0440	CYRILLIC SMALL LETTER ER
+0441	CYRILLIC SMALL LETTER ES
+0442	CYRILLIC SMALL LETTER TE
+0443	CYRILLIC SMALL LETTER U
+0444	CYRILLIC SMALL LETTER EF
+0445	CYRILLIC SMALL LETTER HA
+0446	CYRILLIC SMALL LETTER TSE
+0447	CYRILLIC SMALL LETTER CHE
+0448	CYRILLIC SMALL LETTER SHA
+0449	CYRILLIC SMALL LETTER SHCHA
+044A	CYRILLIC SMALL LETTER HARD SIGN
+044B	CYRILLIC SMALL LETTER YERU
+044C	CYRILLIC SMALL LETTER SOFT SIGN
+044D	CYRILLIC SMALL LETTER E
+044E	CYRILLIC SMALL LETTER YU
+044F	CYRILLIC SMALL LETTER YA
+0451	CYRILLIC SMALL LETTER IO
+0452	CYRILLIC SMALL LETTER DJE
+0453	CYRILLIC SMALL LETTER GJE
+0454	CYRILLIC SMALL LETTER UKRAINIAN IE
+0455	CYRILLIC SMALL LETTER DZE
+0456	CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+0457	CYRILLIC SMALL LETTER YI
+0458	CYRILLIC SMALL LETTER JE
+0459	CYRILLIC SMALL LETTER LJE
+045A	CYRILLIC SMALL LETTER NJE
+045B	CYRILLIC SMALL LETTER TSHE
+045C	CYRILLIC SMALL LETTER KJE
+045E	CYRILLIC SMALL LETTER SHORT U
+045F	CYRILLIC SMALL LETTER DZHE
+0460	CYRILLIC CAPITAL LETTER OMEGA
+0461	CYRILLIC SMALL LETTER OMEGA
+0462	CYRILLIC CAPITAL LETTER YAT
+0463	CYRILLIC SMALL LETTER YAT
+0464	CYRILLIC CAPITAL LETTER IOTIFIED E
+0465	CYRILLIC SMALL LETTER IOTIFIED E
+0466	CYRILLIC CAPITAL LETTER LITTLE YUS
+0467	CYRILLIC SMALL LETTER LITTLE YUS
+0468	CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS
+0469	CYRILLIC SMALL LETTER IOTIFIED LITTLE YUS
+046A	CYRILLIC CAPITAL LETTER BIG YUS
+046B	CYRILLIC SMALL LETTER BIG YUS
+046C	CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS
+046D	CYRILLIC SMALL LETTER IOTIFIED BIG YUS
+046E	CYRILLIC CAPITAL LETTER KSI
+046F	CYRILLIC SMALL LETTER KSI
+0470	CYRILLIC CAPITAL LETTER PSI
+0471	CYRILLIC SMALL LETTER PSI
+0472	CYRILLIC CAPITAL LETTER FITA
+0473	CYRILLIC SMALL LETTER FITA
+0474	CYRILLIC CAPITAL LETTER IZHITSA
+0475	CYRILLIC SMALL LETTER IZHITSA
+0476	CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT
+0477	CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT
+0478	CYRILLIC CAPITAL LETTER UK
+0479	CYRILLIC SMALL LETTER UK
+047A	CYRILLIC CAPITAL LETTER ROUND OMEGA
+047B	CYRILLIC SMALL LETTER ROUND OMEGA
+047C	CYRILLIC CAPITAL LETTER OMEGA WITH TITLO
+047D	CYRILLIC SMALL LETTER OMEGA WITH TITLO
+047E	CYRILLIC CAPITAL LETTER OT
+047F	CYRILLIC SMALL LETTER OT
+0480	CYRILLIC CAPITAL LETTER KOPPA
+0481	CYRILLIC SMALL LETTER KOPPA
+0482	CYRILLIC THOUSANDS SIGN
+0483	COMBINING CYRILLIC TITLO
+0484	COMBINING CYRILLIC PALATALIZATION
+0485	COMBINING CYRILLIC DASIA PNEUMATA
+0486	COMBINING CYRILLIC PSILI PNEUMATA
+0490	CYRILLIC CAPITAL LETTER GHE WITH UPTURN
+0491	CYRILLIC SMALL LETTER GHE WITH UPTURN
+0492	CYRILLIC CAPITAL LETTER GHE WITH STROKE
+0493	CYRILLIC SMALL LETTER GHE WITH STROKE
+0494	CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK
+0495	CYRILLIC SMALL LETTER GHE WITH MIDDLE HOOK
+0496	CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER
+0497	CYRILLIC SMALL LETTER ZHE WITH DESCENDER
+0498	CYRILLIC CAPITAL LETTER ZE WITH DESCENDER
+0499	CYRILLIC SMALL LETTER ZE WITH DESCENDER
+049A	CYRILLIC CAPITAL LETTER KA WITH DESCENDER
+049B	CYRILLIC SMALL LETTER KA WITH DESCENDER
+049C	CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE
+049D	CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE
+049E	CYRILLIC CAPITAL LETTER KA WITH STROKE
+049F	CYRILLIC SMALL LETTER KA WITH STROKE
+04A0	CYRILLIC CAPITAL LETTER BASHKIR KA
+04A1	CYRILLIC SMALL LETTER BASHKIR KA
+04A2	CYRILLIC CAPITAL LETTER EN WITH DESCENDER
+04A3	CYRILLIC SMALL LETTER EN WITH DESCENDER
+04A4	CYRILLIC CAPITAL LIGATURE EN GHE
+04A5	CYRILLIC SMALL LIGATURE EN GHE
+04A6	CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK
+04A7	CYRILLIC SMALL LETTER PE WITH MIDDLE HOOK
+04A8	CYRILLIC CAPITAL LETTER ABKHASIAN HA
+04A9	CYRILLIC SMALL LETTER ABKHASIAN HA
+04AA	CYRILLIC CAPITAL LETTER ES WITH DESCENDER
+04AB	CYRILLIC SMALL LETTER ES WITH DESCENDER
+04AC	CYRILLIC CAPITAL LETTER TE WITH DESCENDER
+04AD	CYRILLIC SMALL LETTER TE WITH DESCENDER
+04AE	CYRILLIC CAPITAL LETTER STRAIGHT U
+04AF	CYRILLIC SMALL LETTER STRAIGHT U
+04B0	CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE
+04B1	CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE
+04B2	CYRILLIC CAPITAL LETTER HA WITH DESCENDER
+04B3	CYRILLIC SMALL LETTER HA WITH DESCENDER
+04B4	CYRILLIC CAPITAL LIGATURE TE TSE
+04B5	CYRILLIC SMALL LIGATURE TE TSE
+04B6	CYRILLIC CAPITAL LETTER CHE WITH DESCENDER
+04B7	CYRILLIC SMALL LETTER CHE WITH DESCENDER
+04B8	CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE
+04B9	CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE
+04BA	CYRILLIC CAPITAL LETTER SHHA
+04BB	CYRILLIC SMALL LETTER SHHA
+04BC	CYRILLIC CAPITAL LETTER ABKHASIAN CHE
+04BD	CYRILLIC SMALL LETTER ABKHASIAN CHE
+04BE	CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER
+04BF	CYRILLIC SMALL LETTER ABKHASIAN CHE WITH DESCENDER
+04C0	CYRILLIC LETTER PALOCHKA
+04C1	CYRILLIC CAPITAL LETTER ZHE WITH BREVE
+04C2	CYRILLIC SMALL LETTER ZHE WITH BREVE
+04C3	CYRILLIC CAPITAL LETTER KA WITH HOOK
+04C4	CYRILLIC SMALL LETTER KA WITH HOOK
+04C7	CYRILLIC CAPITAL LETTER EN WITH HOOK
+04C8	CYRILLIC SMALL LETTER EN WITH HOOK
+04CB	CYRILLIC CAPITAL LETTER KHAKASSIAN CHE
+04CC	CYRILLIC SMALL LETTER KHAKASSIAN CHE
+04D0	CYRILLIC CAPITAL LETTER A WITH BREVE
+04D1	CYRILLIC SMALL LETTER A WITH BREVE
+04D2	CYRILLIC CAPITAL LETTER A WITH DIAERESIS
+04D3	CYRILLIC SMALL LETTER A WITH DIAERESIS
+04D4	CYRILLIC CAPITAL LIGATURE A IE
+04D5	CYRILLIC SMALL LIGATURE A IE
+04D6	CYRILLIC CAPITAL LETTER IE WITH BREVE
+04D7	CYRILLIC SMALL LETTER IE WITH BREVE
+04D8	CYRILLIC CAPITAL LETTER SCHWA
+04D9	CYRILLIC SMALL LETTER SCHWA
+04DA	CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS
+04DB	CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS
+04DC	CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS
+04DD	CYRILLIC SMALL LETTER ZHE WITH DIAERESIS
+04DE	CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS
+04DF	CYRILLIC SMALL LETTER ZE WITH DIAERESIS
+04E0	CYRILLIC CAPITAL LETTER ABKHASIAN DZE
+04E1	CYRILLIC SMALL LETTER ABKHASIAN DZE
+04E2	CYRILLIC CAPITAL LETTER I WITH MACRON
+04E3	CYRILLIC SMALL LETTER I WITH MACRON
+04E4	CYRILLIC CAPITAL LETTER I WITH DIAERESIS
+04E5	CYRILLIC SMALL LETTER I WITH DIAERESIS
+04E6	CYRILLIC CAPITAL LETTER O WITH DIAERESIS
+04E7	CYRILLIC SMALL LETTER O WITH DIAERESIS
+04E8	CYRILLIC CAPITAL LETTER BARRED O
+04E9	CYRILLIC SMALL LETTER BARRED O
+04EA	CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS
+04EB	CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS
+04EE	CYRILLIC CAPITAL LETTER U WITH MACRON
+04EF	CYRILLIC SMALL LETTER U WITH MACRON
+04F0	CYRILLIC CAPITAL LETTER U WITH DIAERESIS
+04F1	CYRILLIC SMALL LETTER U WITH DIAERESIS
+04F2	CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE
+04F3	CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE
+04F4	CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS
+04F5	CYRILLIC SMALL LETTER CHE WITH DIAERESIS
+04F8	CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS
+04F9	CYRILLIC SMALL LETTER YERU WITH DIAERESIS
+0531	ARMENIAN CAPITAL LETTER AYB
+0532	ARMENIAN CAPITAL LETTER BEN
+0533	ARMENIAN CAPITAL LETTER GIM
+0534	ARMENIAN CAPITAL LETTER DA
+0535	ARMENIAN CAPITAL LETTER ECH
+0536	ARMENIAN CAPITAL LETTER ZA
+0537	ARMENIAN CAPITAL LETTER EH
+0538	ARMENIAN CAPITAL LETTER ET
+0539	ARMENIAN CAPITAL LETTER TO
+053A	ARMENIAN CAPITAL LETTER ZHE
+053B	ARMENIAN CAPITAL LETTER INI
+053C	ARMENIAN CAPITAL LETTER LIWN
+053D	ARMENIAN CAPITAL LETTER XEH
+053E	ARMENIAN CAPITAL LETTER CA
+053F	ARMENIAN CAPITAL LETTER KEN
+0540	ARMENIAN CAPITAL LETTER HO
+0541	ARMENIAN CAPITAL LETTER JA
+0542	ARMENIAN CAPITAL LETTER GHAD
+0543	ARMENIAN CAPITAL LETTER CHEH
+0544	ARMENIAN CAPITAL LETTER MEN
+0545	ARMENIAN CAPITAL LETTER YI
+0546	ARMENIAN CAPITAL LETTER NOW
+0547	ARMENIAN CAPITAL LETTER SHA
+0548	ARMENIAN CAPITAL LETTER VO
+0549	ARMENIAN CAPITAL LETTER CHA
+054A	ARMENIAN CAPITAL LETTER PEH
+054B	ARMENIAN CAPITAL LETTER JHEH
+054C	ARMENIAN CAPITAL LETTER RA
+054D	ARMENIAN CAPITAL LETTER SEH
+054E	ARMENIAN CAPITAL LETTER VEW
+054F	ARMENIAN CAPITAL LETTER TIWN
+0550	ARMENIAN CAPITAL LETTER REH
+0551	ARMENIAN CAPITAL LETTER CO
+0552	ARMENIAN CAPITAL LETTER YIWN
+0553	ARMENIAN CAPITAL LETTER PIWR
+0554	ARMENIAN CAPITAL LETTER KEH
+0555	ARMENIAN CAPITAL LETTER OH
+0556	ARMENIAN CAPITAL LETTER FEH
+0559	ARMENIAN MODIFIER LETTER LEFT HALF RING
+055A	ARMENIAN APOSTROPHE
+055B	ARMENIAN EMPHASIS MARK
+055C	ARMENIAN EXCLAMATION MARK
+055D	ARMENIAN COMMA
+055E	ARMENIAN QUESTION MARK
+055F	ARMENIAN ABBREVIATION MARK
+0561	ARMENIAN SMALL LETTER AYB
+0562	ARMENIAN SMALL LETTER BEN
+0563	ARMENIAN SMALL LETTER GIM
+0564	ARMENIAN SMALL LETTER DA
+0565	ARMENIAN SMALL LETTER ECH
+0566	ARMENIAN SMALL LETTER ZA
+0567	ARMENIAN SMALL LETTER EH
+0568	ARMENIAN SMALL LETTER ET
+0569	ARMENIAN SMALL LETTER TO
+056A	ARMENIAN SMALL LETTER ZHE
+056B	ARMENIAN SMALL LETTER INI
+056C	ARMENIAN SMALL LETTER LIWN
+056D	ARMENIAN SMALL LETTER XEH
+056E	ARMENIAN SMALL LETTER CA
+056F	ARMENIAN SMALL LETTER KEN
+0570	ARMENIAN SMALL LETTER HO
+0571	ARMENIAN SMALL LETTER JA
+0572	ARMENIAN SMALL LETTER GHAD
+0573	ARMENIAN SMALL LETTER CHEH
+0574	ARMENIAN SMALL LETTER MEN
+0575	ARMENIAN SMALL LETTER YI
+0576	ARMENIAN SMALL LETTER NOW
+0577	ARMENIAN SMALL LETTER SHA
+0578	ARMENIAN SMALL LETTER VO
+0579	ARMENIAN SMALL LETTER CHA
+057A	ARMENIAN SMALL LETTER PEH
+057B	ARMENIAN SMALL LETTER JHEH
+057C	ARMENIAN SMALL LETTER RA
+057D	ARMENIAN SMALL LETTER SEH
+057E	ARMENIAN SMALL LETTER VEW
+057F	ARMENIAN SMALL LETTER TIWN
+0580	ARMENIAN SMALL LETTER REH
+0581	ARMENIAN SMALL LETTER CO
+0582	ARMENIAN SMALL LETTER YIWN
+0583	ARMENIAN SMALL LETTER PIWR
+0584	ARMENIAN SMALL LETTER KEH
+0585	ARMENIAN SMALL LETTER OH
+0586	ARMENIAN SMALL LETTER FEH
+0587	ARMENIAN SMALL LIGATURE ECH YIWN
+0589	ARMENIAN FULL STOP
+0591	HEBREW ACCENT ETNAHTA
+0592	HEBREW ACCENT SEGOL
+0593	HEBREW ACCENT SHALSHELET
+0594	HEBREW ACCENT ZAQEF QATAN
+0595	HEBREW ACCENT ZAQEF GADOL
+0596	HEBREW ACCENT TIPEHA
+0597	HEBREW ACCENT REVIA
+0598	HEBREW ACCENT ZARQA
+0599	HEBREW ACCENT PASHTA
+059A	HEBREW ACCENT YETIV
+059B	HEBREW ACCENT TEVIR
+059C	HEBREW ACCENT GERESH
+059D	HEBREW ACCENT GERESH MUQDAM
+059E	HEBREW ACCENT GERSHAYIM
+059F	HEBREW ACCENT QARNEY PARA
+05A0	HEBREW ACCENT TELISHA GEDOLA
+05A1	HEBREW ACCENT PAZER
+05A3	HEBREW ACCENT MUNAH
+05A4	HEBREW ACCENT MAHAPAKH
+05A5	HEBREW ACCENT MERKHA
+05A6	HEBREW ACCENT MERKHA KEFULA
+05A7	HEBREW ACCENT DARGA
+05A8	HEBREW ACCENT QADMA
+05A9	HEBREW ACCENT TELISHA QETANA
+05AA	HEBREW ACCENT YERAH BEN YOMO
+05AB	HEBREW ACCENT OLE
+05AC	HEBREW ACCENT ILUY
+05AD	HEBREW ACCENT DEHI
+05AE	HEBREW ACCENT ZINOR
+05AF	HEBREW MARK MASORA CIRCLE
+05B0	HEBREW POINT SHEVA
+05B1	HEBREW POINT HATAF SEGOL
+05B2	HEBREW POINT HATAF PATAH
+05B3	HEBREW POINT HATAF QAMATS
+05B4	HEBREW POINT HIRIQ
+05B5	HEBREW POINT TSERE
+05B6	HEBREW POINT SEGOL
+05B7	HEBREW POINT PATAH
+05B8	HEBREW POINT QAMATS
+05B9	HEBREW POINT HOLAM
+05BB	HEBREW POINT QUBUTS
+05BC	HEBREW POINT DAGESH OR MAPIQ
+05BD	HEBREW POINT METEG
+05BE	HEBREW PUNCTUATION MAQAF
+05BF	HEBREW POINT RAFE
+05C0	HEBREW PUNCTUATION PASEQ
+05C1	HEBREW POINT SHIN DOT
+05C2	HEBREW POINT SIN DOT
+05C3	HEBREW PUNCTUATION SOF PASUQ
+05C4	HEBREW MARK UPPER DOT
+05D0	HEBREW LETTER ALEF
+05D1	HEBREW LETTER BET
+05D2	HEBREW LETTER GIMEL
+05D3	HEBREW LETTER DALET
+05D4	HEBREW LETTER HE
+05D5	HEBREW LETTER VAV
+05D6	HEBREW LETTER ZAYIN
+05D7	HEBREW LETTER HET
+05D8	HEBREW LETTER TET
+05D9	HEBREW LETTER YOD
+05DA	HEBREW LETTER FINAL KAF
+05DB	HEBREW LETTER KAF
+05DC	HEBREW LETTER LAMED
+05DD	HEBREW LETTER FINAL MEM
+05DE	HEBREW LETTER MEM
+05DF	HEBREW LETTER FINAL NUN
+05E0	HEBREW LETTER NUN
+05E1	HEBREW LETTER SAMEKH
+05E2	HEBREW LETTER AYIN
+05E3	HEBREW LETTER FINAL PE
+05E4	HEBREW LETTER PE
+05E5	HEBREW LETTER FINAL TSADI
+05E6	HEBREW LETTER TSADI
+05E7	HEBREW LETTER QOF
+05E8	HEBREW LETTER RESH
+05E9	HEBREW LETTER SHIN
+05EA	HEBREW LETTER TAV
+05F0	HEBREW LIGATURE YIDDISH DOUBLE VAV
+05F1	HEBREW LIGATURE YIDDISH VAV YOD
+05F2	HEBREW LIGATURE YIDDISH DOUBLE YOD
+05F3	HEBREW PUNCTUATION GERESH
+05F4	HEBREW PUNCTUATION GERSHAYIM
+060C	ARABIC COMMA
+061B	ARABIC SEMICOLON
+061F	ARABIC QUESTION MARK
+0621	ARABIC LETTER HAMZA
+0622	ARABIC LETTER ALEF WITH MADDA ABOVE
+0623	ARABIC LETTER ALEF WITH HAMZA ABOVE
+0624	ARABIC LETTER WAW WITH HAMZA ABOVE
+0625	ARABIC LETTER ALEF WITH HAMZA BELOW
+0626	ARABIC LETTER YEH WITH HAMZA ABOVE
+0627	ARABIC LETTER ALEF
+0628	ARABIC LETTER BEH
+0629	ARABIC LETTER TEH MARBUTA
+062A	ARABIC LETTER TEH
+062B	ARABIC LETTER THEH
+062C	ARABIC LETTER JEEM
+062D	ARABIC LETTER HAH
+062E	ARABIC LETTER KHAH
+062F	ARABIC LETTER DAL
+0630	ARABIC LETTER THAL
+0631	ARABIC LETTER REH
+0632	ARABIC LETTER ZAIN
+0633	ARABIC LETTER SEEN
+0634	ARABIC LETTER SHEEN
+0635	ARABIC LETTER SAD
+0636	ARABIC LETTER DAD
+0637	ARABIC LETTER TAH
+0638	ARABIC LETTER ZAH
+0639	ARABIC LETTER AIN
+063A	ARABIC LETTER GHAIN
+0640	ARABIC TATWEEL
+0641	ARABIC LETTER FEH
+0642	ARABIC LETTER QAF
+0643	ARABIC LETTER KAF
+0644	ARABIC LETTER LAM
+0645	ARABIC LETTER MEEM
+0646	ARABIC LETTER NOON
+0647	ARABIC LETTER HEH
+0648	ARABIC LETTER WAW
+0649	ARABIC LETTER ALEF MAKSURA
+064A	ARABIC LETTER YEH
+064B	ARABIC FATHATAN
+064C	ARABIC DAMMATAN
+064D	ARABIC KASRATAN
+064E	ARABIC FATHA
+064F	ARABIC DAMMA
+0650	ARABIC KASRA
+0651	ARABIC SHADDA
+0652	ARABIC SUKUN
+0660	ARABIC-INDIC DIGIT ZERO
+0661	ARABIC-INDIC DIGIT ONE
+0662	ARABIC-INDIC DIGIT TWO
+0663	ARABIC-INDIC DIGIT THREE
+0664	ARABIC-INDIC DIGIT FOUR
+0665	ARABIC-INDIC DIGIT FIVE
+0666	ARABIC-INDIC DIGIT SIX
+0667	ARABIC-INDIC DIGIT SEVEN
+0668	ARABIC-INDIC DIGIT EIGHT
+0669	ARABIC-INDIC DIGIT NINE
+066A	ARABIC PERCENT SIGN
+066B	ARABIC DECIMAL SEPARATOR
+066C	ARABIC THOUSANDS SEPARATOR
+066D	ARABIC FIVE POINTED STAR
+0670	ARABIC LETTER SUPERSCRIPT ALEF
+0671	ARABIC LETTER ALEF WASLA
+0672	ARABIC LETTER ALEF WITH WAVY HAMZA ABOVE
+0673	ARABIC LETTER ALEF WITH WAVY HAMZA BELOW
+0674	ARABIC LETTER HIGH HAMZA
+0675	ARABIC LETTER HIGH HAMZA ALEF
+0676	ARABIC LETTER HIGH HAMZA WAW
+0677	ARABIC LETTER U WITH HAMZA ABOVE
+0678	ARABIC LETTER HIGH HAMZA YEH
+0679	ARABIC LETTER TTEH
+067A	ARABIC LETTER TTEHEH
+067B	ARABIC LETTER BEEH
+067C	ARABIC LETTER TEH WITH RING
+067D	ARABIC LETTER TEH WITH THREE DOTS ABOVE DOWNWARDS
+067E	ARABIC LETTER PEH
+067F	ARABIC LETTER TEHEH
+0680	ARABIC LETTER BEHEH
+0681	ARABIC LETTER HAH WITH HAMZA ABOVE
+0682	ARABIC LETTER HAH WITH TWO DOTS VERTICAL ABOVE
+0683	ARABIC LETTER NYEH
+0684	ARABIC LETTER DYEH
+0685	ARABIC LETTER HAH WITH THREE DOTS ABOVE
+0686	ARABIC LETTER TCHEH
+0687	ARABIC LETTER TCHEHEH
+0688	ARABIC LETTER DDAL
+0689	ARABIC LETTER DAL WITH RING
+068A	ARABIC LETTER DAL WITH DOT BELOW
+068B	ARABIC LETTER DAL WITH DOT BELOW AND SMALL TAH
+068C	ARABIC LETTER DAHAL
+068D	ARABIC LETTER DDAHAL
+068E	ARABIC LETTER DUL
+068F	ARABIC LETTER DAL WITH THREE DOTS ABOVE DOWNWARDS
+0690	ARABIC LETTER DAL WITH FOUR DOTS ABOVE
+0691	ARABIC LETTER RREH
+0692	ARABIC LETTER REH WITH SMALL V
+0693	ARABIC LETTER REH WITH RING
+0694	ARABIC LETTER REH WITH DOT BELOW
+0695	ARABIC LETTER REH WITH SMALL V BELOW
+0696	ARABIC LETTER REH WITH DOT BELOW AND DOT ABOVE
+0697	ARABIC LETTER REH WITH TWO DOTS ABOVE
+0698	ARABIC LETTER JEH
+0699	ARABIC LETTER REH WITH FOUR DOTS ABOVE
+069A	ARABIC LETTER SEEN WITH DOT BELOW AND DOT ABOVE
+069B	ARABIC LETTER SEEN WITH THREE DOTS BELOW
+069C	ARABIC LETTER SEEN WITH THREE DOTS BELOW AND THREE DOTS ABOVE
+069D	ARABIC LETTER SAD WITH TWO DOTS BELOW
+069E	ARABIC LETTER SAD WITH THREE DOTS ABOVE
+069F	ARABIC LETTER TAH WITH THREE DOTS ABOVE
+06A0	ARABIC LETTER AIN WITH THREE DOTS ABOVE
+06A1	ARABIC LETTER DOTLESS FEH
+06A2	ARABIC LETTER FEH WITH DOT MOVED BELOW
+06A3	ARABIC LETTER FEH WITH DOT BELOW
+06A4	ARABIC LETTER VEH
+06A5	ARABIC LETTER FEH WITH THREE DOTS BELOW
+06A6	ARABIC LETTER PEHEH
+06A7	ARABIC LETTER QAF WITH DOT ABOVE
+06A8	ARABIC LETTER QAF WITH THREE DOTS ABOVE
+06A9	ARABIC LETTER KEHEH
+06AA	ARABIC LETTER SWASH KAF
+06AB	ARABIC LETTER KAF WITH RING
+06AC	ARABIC LETTER KAF WITH DOT ABOVE
+06AD	ARABIC LETTER NG
+06AE	ARABIC LETTER KAF WITH THREE DOTS BELOW
+06AF	ARABIC LETTER GAF
+06B0	ARABIC LETTER GAF WITH RING
+06B1	ARABIC LETTER NGOEH
+06B2	ARABIC LETTER GAF WITH TWO DOTS BELOW
+06B3	ARABIC LETTER GUEH
+06B4	ARABIC LETTER GAF WITH THREE DOTS ABOVE
+06B5	ARABIC LETTER LAM WITH SMALL V
+06B6	ARABIC LETTER LAM WITH DOT ABOVE
+06B7	ARABIC LETTER LAM WITH THREE DOTS ABOVE
+06BA	ARABIC LETTER NOON GHUNNA
+06BB	ARABIC LETTER RNOON
+06BC	ARABIC LETTER NOON WITH RING
+06BD	ARABIC LETTER NOON WITH THREE DOTS ABOVE
+06BE	ARABIC LETTER HEH DOACHASHMEE
+06C0	ARABIC LETTER HEH WITH YEH ABOVE
+06C1	ARABIC LETTER HEH GOAL
+06C2	ARABIC LETTER HEH GOAL WITH HAMZA ABOVE
+06C3	ARABIC LETTER TEH MARBUTA GOAL
+06C4	ARABIC LETTER WAW WITH RING
+06C5	ARABIC LETTER KIRGHIZ OE
+06C6	ARABIC LETTER OE
+06C7	ARABIC LETTER U
+06C8	ARABIC LETTER YU
+06C9	ARABIC LETTER KIRGHIZ YU
+06CA	ARABIC LETTER WAW WITH TWO DOTS ABOVE
+06CB	ARABIC LETTER VE
+06CC	ARABIC LETTER FARSI YEH
+06CD	ARABIC LETTER YEH WITH TAIL
+06CE	ARABIC LETTER YEH WITH SMALL V
+06D0	ARABIC LETTER E
+06D1	ARABIC LETTER YEH WITH THREE DOTS BELOW
+06D2	ARABIC LETTER YEH BARREE
+06D3	ARABIC LETTER YEH BARREE WITH HAMZA ABOVE
+06D4	ARABIC FULL STOP
+06D5	ARABIC LETTER AE
+06D6	ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA
+06D7	ARABIC SMALL HIGH LIGATURE QAF WITH LAM WITH ALEF MAKSURA
+06D8	ARABIC SMALL HIGH MEEM INITIAL FORM
+06D9	ARABIC SMALL HIGH LAM ALEF
+06DA	ARABIC SMALL HIGH JEEM
+06DB	ARABIC SMALL HIGH THREE DOTS
+06DC	ARABIC SMALL HIGH SEEN
+06DD	ARABIC END OF AYAH
+06DE	ARABIC START OF RUB EL HIZB
+06DF	ARABIC SMALL HIGH ROUNDED ZERO
+06E0	ARABIC SMALL HIGH UPRIGHT RECTANGULAR ZERO
+06E1	ARABIC SMALL HIGH DOTLESS HEAD OF KHAH
+06E2	ARABIC SMALL HIGH MEEM ISOLATED FORM
+06E3	ARABIC SMALL LOW SEEN
+06E4	ARABIC SMALL HIGH MADDA
+06E5	ARABIC SMALL WAW
+06E6	ARABIC SMALL YEH
+06E7	ARABIC SMALL HIGH YEH
+06E8	ARABIC SMALL HIGH NOON
+06E9	ARABIC PLACE OF SAJDAH
+06EA	ARABIC EMPTY CENTRE LOW STOP
+06EB	ARABIC EMPTY CENTRE HIGH STOP
+06EC	ARABIC ROUNDED HIGH STOP WITH FILLED CENTRE
+06ED	ARABIC SMALL LOW MEEM
+06F0	EXTENDED ARABIC-INDIC DIGIT ZERO
+06F1	EXTENDED ARABIC-INDIC DIGIT ONE
+06F2	EXTENDED ARABIC-INDIC DIGIT TWO
+06F3	EXTENDED ARABIC-INDIC DIGIT THREE
+06F4	EXTENDED ARABIC-INDIC DIGIT FOUR
+06F5	EXTENDED ARABIC-INDIC DIGIT FIVE
+06F6	EXTENDED ARABIC-INDIC DIGIT SIX
+06F7	EXTENDED ARABIC-INDIC DIGIT SEVEN
+06F8	EXTENDED ARABIC-INDIC DIGIT EIGHT
+06F9	EXTENDED ARABIC-INDIC DIGIT NINE
+0901	DEVANAGARI SIGN CANDRABINDU
+0902	DEVANAGARI SIGN ANUSVARA
+0903	DEVANAGARI SIGN VISARGA
+0905	DEVANAGARI LETTER A
+0906	DEVANAGARI LETTER AA
+0907	DEVANAGARI LETTER I
+0908	DEVANAGARI LETTER II
+0909	DEVANAGARI LETTER U
+090A	DEVANAGARI LETTER UU
+090B	DEVANAGARI LETTER VOCALIC R
+090C	DEVANAGARI LETTER VOCALIC L
+090D	DEVANAGARI LETTER CANDRA E
+090E	DEVANAGARI LETTER SHORT E
+090F	DEVANAGARI LETTER E
+0910	DEVANAGARI LETTER AI
+0911	DEVANAGARI LETTER CANDRA O
+0912	DEVANAGARI LETTER SHORT O
+0913	DEVANAGARI LETTER O
+0914	DEVANAGARI LETTER AU
+0915	DEVANAGARI LETTER KA
+0916	DEVANAGARI LETTER KHA
+0917	DEVANAGARI LETTER GA
+0918	DEVANAGARI LETTER GHA
+0919	DEVANAGARI LETTER NGA
+091A	DEVANAGARI LETTER CA
+091B	DEVANAGARI LETTER CHA
+091C	DEVANAGARI LETTER JA
+091D	DEVANAGARI LETTER JHA
+091E	DEVANAGARI LETTER NYA
+091F	DEVANAGARI LETTER TTA
+0920	DEVANAGARI LETTER TTHA
+0921	DEVANAGARI LETTER DDA
+0922	DEVANAGARI LETTER DDHA
+0923	DEVANAGARI LETTER NNA
+0924	DEVANAGARI LETTER TA
+0925	DEVANAGARI LETTER THA
+0926	DEVANAGARI LETTER DA
+0927	DEVANAGARI LETTER DHA
+0928	DEVANAGARI LETTER NA
+0929	DEVANAGARI LETTER NNNA
+092A	DEVANAGARI LETTER PA
+092B	DEVANAGARI LETTER PHA
+092C	DEVANAGARI LETTER BA
+092D	DEVANAGARI LETTER BHA
+092E	DEVANAGARI LETTER MA
+092F	DEVANAGARI LETTER YA
+0930	DEVANAGARI LETTER RA
+0931	DEVANAGARI LETTER RRA
+0932	DEVANAGARI LETTER LA
+0933	DEVANAGARI LETTER LLA
+0934	DEVANAGARI LETTER LLLA
+0935	DEVANAGARI LETTER VA
+0936	DEVANAGARI LETTER SHA
+0937	DEVANAGARI LETTER SSA
+0938	DEVANAGARI LETTER SA
+0939	DEVANAGARI LETTER HA
+093C	DEVANAGARI SIGN NUKTA
+093D	DEVANAGARI SIGN AVAGRAHA
+093E	DEVANAGARI VOWEL SIGN AA
+093F	DEVANAGARI VOWEL SIGN I
+0940	DEVANAGARI VOWEL SIGN II
+0941	DEVANAGARI VOWEL SIGN U
+0942	DEVANAGARI VOWEL SIGN UU
+0943	DEVANAGARI VOWEL SIGN VOCALIC R
+0944	DEVANAGARI VOWEL SIGN VOCALIC RR
+0945	DEVANAGARI VOWEL SIGN CANDRA E
+0946	DEVANAGARI VOWEL SIGN SHORT E
+0947	DEVANAGARI VOWEL SIGN E
+0948	DEVANAGARI VOWEL SIGN AI
+0949	DEVANAGARI VOWEL SIGN CANDRA O
+094A	DEVANAGARI VOWEL SIGN SHORT O
+094B	DEVANAGARI VOWEL SIGN O
+094C	DEVANAGARI VOWEL SIGN AU
+094D	DEVANAGARI SIGN VIRAMA
+0950	DEVANAGARI OM
+0951	DEVANAGARI STRESS SIGN UDATTA
+0952	DEVANAGARI STRESS SIGN ANUDATTA
+0953	DEVANAGARI GRAVE ACCENT
+0954	DEVANAGARI ACUTE ACCENT
+0958	DEVANAGARI LETTER QA
+0959	DEVANAGARI LETTER KHHA
+095A	DEVANAGARI LETTER GHHA
+095B	DEVANAGARI LETTER ZA
+095C	DEVANAGARI LETTER DDDHA
+095D	DEVANAGARI LETTER RHA
+095E	DEVANAGARI LETTER FA
+095F	DEVANAGARI LETTER YYA
+0960	DEVANAGARI LETTER VOCALIC RR
+0961	DEVANAGARI LETTER VOCALIC LL
+0962	DEVANAGARI VOWEL SIGN VOCALIC L
+0963	DEVANAGARI VOWEL SIGN VOCALIC LL
+0964	DEVANAGARI DANDA
+0965	DEVANAGARI DOUBLE DANDA
+0966	DEVANAGARI DIGIT ZERO
+0967	DEVANAGARI DIGIT ONE
+0968	DEVANAGARI DIGIT TWO
+0969	DEVANAGARI DIGIT THREE
+096A	DEVANAGARI DIGIT FOUR
+096B	DEVANAGARI DIGIT FIVE
+096C	DEVANAGARI DIGIT SIX
+096D	DEVANAGARI DIGIT SEVEN
+096E	DEVANAGARI DIGIT EIGHT
+096F	DEVANAGARI DIGIT NINE
+0970	DEVANAGARI ABBREVIATION SIGN
+0981	BENGALI SIGN CANDRABINDU
+0982	BENGALI SIGN ANUSVARA
+0983	BENGALI SIGN VISARGA
+0985	BENGALI LETTER A
+0986	BENGALI LETTER AA
+0987	BENGALI LETTER I
+0988	BENGALI LETTER II
+0989	BENGALI LETTER U
+098A	BENGALI LETTER UU
+098B	BENGALI LETTER VOCALIC R
+098C	BENGALI LETTER VOCALIC L
+098F	BENGALI LETTER E
+0990	BENGALI LETTER AI
+0993	BENGALI LETTER O
+0994	BENGALI LETTER AU
+0995	BENGALI LETTER KA
+0996	BENGALI LETTER KHA
+0997	BENGALI LETTER GA
+0998	BENGALI LETTER GHA
+0999	BENGALI LETTER NGA
+099A	BENGALI LETTER CA
+099B	BENGALI LETTER CHA
+099C	BENGALI LETTER JA
+099D	BENGALI LETTER JHA
+099E	BENGALI LETTER NYA
+099F	BENGALI LETTER TTA
+09A0	BENGALI LETTER TTHA
+09A1	BENGALI LETTER DDA
+09A2	BENGALI LETTER DDHA
+09A3	BENGALI LETTER NNA
+09A4	BENGALI LETTER TA
+09A5	BENGALI LETTER THA
+09A6	BENGALI LETTER DA
+09A7	BENGALI LETTER DHA
+09A8	BENGALI LETTER NA
+09AA	BENGALI LETTER PA
+09AB	BENGALI LETTER PHA
+09AC	BENGALI LETTER BA
+09AD	BENGALI LETTER BHA
+09AE	BENGALI LETTER MA
+09AF	BENGALI LETTER YA
+09B0	BENGALI LETTER RA
+09B2	BENGALI LETTER LA
+09B6	BENGALI LETTER SHA
+09B7	BENGALI LETTER SSA
+09B8	BENGALI LETTER SA
+09B9	BENGALI LETTER HA
+09BC	BENGALI SIGN NUKTA
+09BE	BENGALI VOWEL SIGN AA
+09BF	BENGALI VOWEL SIGN I
+09C0	BENGALI VOWEL SIGN II
+09C1	BENGALI VOWEL SIGN U
+09C2	BENGALI VOWEL SIGN UU
+09C3	BENGALI VOWEL SIGN VOCALIC R
+09C4	BENGALI VOWEL SIGN VOCALIC RR
+09C7	BENGALI VOWEL SIGN E
+09C8	BENGALI VOWEL SIGN AI
+09CB	BENGALI VOWEL SIGN O
+09CC	BENGALI VOWEL SIGN AU
+09CD	BENGALI SIGN VIRAMA
+09D7	BENGALI AU LENGTH MARK
+09DC	BENGALI LETTER RRA
+09DD	BENGALI LETTER RHA
+09DF	BENGALI LETTER YYA
+09E0	BENGALI LETTER VOCALIC RR
+09E1	BENGALI LETTER VOCALIC LL
+09E2	BENGALI VOWEL SIGN VOCALIC L
+09E3	BENGALI VOWEL SIGN VOCALIC LL
+09E6	BENGALI DIGIT ZERO
+09E7	BENGALI DIGIT ONE
+09E8	BENGALI DIGIT TWO
+09E9	BENGALI DIGIT THREE
+09EA	BENGALI DIGIT FOUR
+09EB	BENGALI DIGIT FIVE
+09EC	BENGALI DIGIT SIX
+09ED	BENGALI DIGIT SEVEN
+09EE	BENGALI DIGIT EIGHT
+09EF	BENGALI DIGIT NINE
+09F0	BENGALI LETTER RA WITH MIDDLE DIAGONAL
+09F1	BENGALI LETTER RA WITH LOWER DIAGONAL
+09F2	BENGALI RUPEE MARK
+09F3	BENGALI RUPEE SIGN
+09F4	BENGALI CURRENCY NUMERATOR ONE
+09F5	BENGALI CURRENCY NUMERATOR TWO
+09F6	BENGALI CURRENCY NUMERATOR THREE
+09F7	BENGALI CURRENCY NUMERATOR FOUR
+09F8	BENGALI CURRENCY NUMERATOR ONE LESS THAN THE DENOMINATOR
+09F9	BENGALI CURRENCY DENOMINATOR SIXTEEN
+09FA	BENGALI ISSHAR
+0A02	GURMUKHI SIGN BINDI
+0A05	GURMUKHI LETTER A
+0A06	GURMUKHI LETTER AA
+0A07	GURMUKHI LETTER I
+0A08	GURMUKHI LETTER II
+0A09	GURMUKHI LETTER U
+0A0A	GURMUKHI LETTER UU
+0A0F	GURMUKHI LETTER EE
+0A10	GURMUKHI LETTER AI
+0A13	GURMUKHI LETTER OO
+0A14	GURMUKHI LETTER AU
+0A15	GURMUKHI LETTER KA
+0A16	GURMUKHI LETTER KHA
+0A17	GURMUKHI LETTER GA
+0A18	GURMUKHI LETTER GHA
+0A19	GURMUKHI LETTER NGA
+0A1A	GURMUKHI LETTER CA
+0A1B	GURMUKHI LETTER CHA
+0A1C	GURMUKHI LETTER JA
+0A1D	GURMUKHI LETTER JHA
+0A1E	GURMUKHI LETTER NYA
+0A1F	GURMUKHI LETTER TTA
+0A20	GURMUKHI LETTER TTHA
+0A21	GURMUKHI LETTER DDA
+0A22	GURMUKHI LETTER DDHA
+0A23	GURMUKHI LETTER NNA
+0A24	GURMUKHI LETTER TA
+0A25	GURMUKHI LETTER THA
+0A26	GURMUKHI LETTER DA
+0A27	GURMUKHI LETTER DHA
+0A28	GURMUKHI LETTER NA
+0A2A	GURMUKHI LETTER PA
+0A2B	GURMUKHI LETTER PHA
+0A2C	GURMUKHI LETTER BA
+0A2D	GURMUKHI LETTER BHA
+0A2E	GURMUKHI LETTER MA
+0A2F	GURMUKHI LETTER YA
+0A30	GURMUKHI LETTER RA
+0A32	GURMUKHI LETTER LA
+0A33	GURMUKHI LETTER LLA
+0A35	GURMUKHI LETTER VA
+0A36	GURMUKHI LETTER SHA
+0A38	GURMUKHI LETTER SA
+0A39	GURMUKHI LETTER HA
+0A3C	GURMUKHI SIGN NUKTA
+0A3E	GURMUKHI VOWEL SIGN AA
+0A3F	GURMUKHI VOWEL SIGN I
+0A40	GURMUKHI VOWEL SIGN II
+0A41	GURMUKHI VOWEL SIGN U
+0A42	GURMUKHI VOWEL SIGN UU
+0A47	GURMUKHI VOWEL SIGN EE
+0A48	GURMUKHI VOWEL SIGN AI
+0A4B	GURMUKHI VOWEL SIGN OO
+0A4C	GURMUKHI VOWEL SIGN AU
+0A4D	GURMUKHI SIGN VIRAMA
+0A59	GURMUKHI LETTER KHHA
+0A5A	GURMUKHI LETTER GHHA
+0A5B	GURMUKHI LETTER ZA
+0A5C	GURMUKHI LETTER RRA
+0A5E	GURMUKHI LETTER FA
+0A66	GURMUKHI DIGIT ZERO
+0A67	GURMUKHI DIGIT ONE
+0A68	GURMUKHI DIGIT TWO
+0A69	GURMUKHI DIGIT THREE
+0A6A	GURMUKHI DIGIT FOUR
+0A6B	GURMUKHI DIGIT FIVE
+0A6C	GURMUKHI DIGIT SIX
+0A6D	GURMUKHI DIGIT SEVEN
+0A6E	GURMUKHI DIGIT EIGHT
+0A6F	GURMUKHI DIGIT NINE
+0A70	GURMUKHI TIPPI
+0A71	GURMUKHI ADDAK
+0A72	GURMUKHI IRI
+0A73	GURMUKHI URA
+0A74	GURMUKHI EK ONKAR
+0A81	GUJARATI SIGN CANDRABINDU
+0A82	GUJARATI SIGN ANUSVARA
+0A83	GUJARATI SIGN VISARGA
+0A85	GUJARATI LETTER A
+0A86	GUJARATI LETTER AA
+0A87	GUJARATI LETTER I
+0A88	GUJARATI LETTER II
+0A89	GUJARATI LETTER U
+0A8A	GUJARATI LETTER UU
+0A8B	GUJARATI LETTER VOCALIC R
+0A8D	GUJARATI VOWEL CANDRA E
+0A8F	GUJARATI LETTER E
+0A90	GUJARATI LETTER AI
+0A91	GUJARATI VOWEL CANDRA O
+0A93	GUJARATI LETTER O
+0A94	GUJARATI LETTER AU
+0A95	GUJARATI LETTER KA
+0A96	GUJARATI LETTER KHA
+0A97	GUJARATI LETTER GA
+0A98	GUJARATI LETTER GHA
+0A99	GUJARATI LETTER NGA
+0A9A	GUJARATI LETTER CA
+0A9B	GUJARATI LETTER CHA
+0A9C	GUJARATI LETTER JA
+0A9D	GUJARATI LETTER JHA
+0A9E	GUJARATI LETTER NYA
+0A9F	GUJARATI LETTER TTA
+0AA0	GUJARATI LETTER TTHA
+0AA1	GUJARATI LETTER DDA
+0AA2	GUJARATI LETTER DDHA
+0AA3	GUJARATI LETTER NNA
+0AA4	GUJARATI LETTER TA
+0AA5	GUJARATI LETTER THA
+0AA6	GUJARATI LETTER DA
+0AA7	GUJARATI LETTER DHA
+0AA8	GUJARATI LETTER NA
+0AAA	GUJARATI LETTER PA
+0AAB	GUJARATI LETTER PHA
+0AAC	GUJARATI LETTER BA
+0AAD	GUJARATI LETTER BHA
+0AAE	GUJARATI LETTER MA
+0AAF	GUJARATI LETTER YA
+0AB0	GUJARATI LETTER RA
+0AB2	GUJARATI LETTER LA
+0AB3	GUJARATI LETTER LLA
+0AB5	GUJARATI LETTER VA
+0AB6	GUJARATI LETTER SHA
+0AB7	GUJARATI LETTER SSA
+0AB8	GUJARATI LETTER SA
+0AB9	GUJARATI LETTER HA
+0ABC	GUJARATI SIGN NUKTA
+0ABD	GUJARATI SIGN AVAGRAHA
+0ABE	GUJARATI VOWEL SIGN AA
+0ABF	GUJARATI VOWEL SIGN I
+0AC0	GUJARATI VOWEL SIGN II
+0AC1	GUJARATI VOWEL SIGN U
+0AC2	GUJARATI VOWEL SIGN UU
+0AC3	GUJARATI VOWEL SIGN VOCALIC R
+0AC4	GUJARATI VOWEL SIGN VOCALIC RR
+0AC5	GUJARATI VOWEL SIGN CANDRA E
+0AC7	GUJARATI VOWEL SIGN E
+0AC8	GUJARATI VOWEL SIGN AI
+0AC9	GUJARATI VOWEL SIGN CANDRA O
+0ACB	GUJARATI VOWEL SIGN O
+0ACC	GUJARATI VOWEL SIGN AU
+0ACD	GUJARATI SIGN VIRAMA
+0AD0	GUJARATI OM
+0AE0	GUJARATI LETTER VOCALIC RR
+0AE6	GUJARATI DIGIT ZERO
+0AE7	GUJARATI DIGIT ONE
+0AE8	GUJARATI DIGIT TWO
+0AE9	GUJARATI DIGIT THREE
+0AEA	GUJARATI DIGIT FOUR
+0AEB	GUJARATI DIGIT FIVE
+0AEC	GUJARATI DIGIT SIX
+0AED	GUJARATI DIGIT SEVEN
+0AEE	GUJARATI DIGIT EIGHT
+0AEF	GUJARATI DIGIT NINE
+0B01	ORIYA SIGN CANDRABINDU
+0B02	ORIYA SIGN ANUSVARA
+0B03	ORIYA SIGN VISARGA
+0B05	ORIYA LETTER A
+0B06	ORIYA LETTER AA
+0B07	ORIYA LETTER I
+0B08	ORIYA LETTER II
+0B09	ORIYA LETTER U
+0B0A	ORIYA LETTER UU
+0B0B	ORIYA LETTER VOCALIC R
+0B0C	ORIYA LETTER VOCALIC L
+0B0F	ORIYA LETTER E
+0B10	ORIYA LETTER AI
+0B13	ORIYA LETTER O
+0B14	ORIYA LETTER AU
+0B15	ORIYA LETTER KA
+0B16	ORIYA LETTER KHA
+0B17	ORIYA LETTER GA
+0B18	ORIYA LETTER GHA
+0B19	ORIYA LETTER NGA
+0B1A	ORIYA LETTER CA
+0B1B	ORIYA LETTER CHA
+0B1C	ORIYA LETTER JA
+0B1D	ORIYA LETTER JHA
+0B1E	ORIYA LETTER NYA
+0B1F	ORIYA LETTER TTA
+0B20	ORIYA LETTER TTHA
+0B21	ORIYA LETTER DDA
+0B22	ORIYA LETTER DDHA
+0B23	ORIYA LETTER NNA
+0B24	ORIYA LETTER TA
+0B25	ORIYA LETTER THA
+0B26	ORIYA LETTER DA
+0B27	ORIYA LETTER DHA
+0B28	ORIYA LETTER NA
+0B2A	ORIYA LETTER PA
+0B2B	ORIYA LETTER PHA
+0B2C	ORIYA LETTER BA
+0B2D	ORIYA LETTER BHA
+0B2E	ORIYA LETTER MA
+0B2F	ORIYA LETTER YA
+0B30	ORIYA LETTER RA
+0B32	ORIYA LETTER LA
+0B33	ORIYA LETTER LLA
+0B36	ORIYA LETTER SHA
+0B37	ORIYA LETTER SSA
+0B38	ORIYA LETTER SA
+0B39	ORIYA LETTER HA
+0B3C	ORIYA SIGN NUKTA
+0B3D	ORIYA SIGN AVAGRAHA
+0B3E	ORIYA VOWEL SIGN AA
+0B3F	ORIYA VOWEL SIGN I
+0B40	ORIYA VOWEL SIGN II
+0B41	ORIYA VOWEL SIGN U
+0B42	ORIYA VOWEL SIGN UU
+0B43	ORIYA VOWEL SIGN VOCALIC R
+0B47	ORIYA VOWEL SIGN E
+0B48	ORIYA VOWEL SIGN AI
+0B4B	ORIYA VOWEL SIGN O
+0B4C	ORIYA VOWEL SIGN AU
+0B4D	ORIYA SIGN VIRAMA
+0B56	ORIYA AI LENGTH MARK
+0B57	ORIYA AU LENGTH MARK
+0B5C	ORIYA LETTER RRA
+0B5D	ORIYA LETTER RHA
+0B5F	ORIYA LETTER YYA
+0B60	ORIYA LETTER VOCALIC RR
+0B61	ORIYA LETTER VOCALIC LL
+0B66	ORIYA DIGIT ZERO
+0B67	ORIYA DIGIT ONE
+0B68	ORIYA DIGIT TWO
+0B69	ORIYA DIGIT THREE
+0B6A	ORIYA DIGIT FOUR
+0B6B	ORIYA DIGIT FIVE
+0B6C	ORIYA DIGIT SIX
+0B6D	ORIYA DIGIT SEVEN
+0B6E	ORIYA DIGIT EIGHT
+0B6F	ORIYA DIGIT NINE
+0B70	ORIYA ISSHAR
+0B82	TAMIL SIGN ANUSVARA
+0B83	TAMIL SIGN VISARGA
+0B85	TAMIL LETTER A
+0B86	TAMIL LETTER AA
+0B87	TAMIL LETTER I
+0B88	TAMIL LETTER II
+0B89	TAMIL LETTER U
+0B8A	TAMIL LETTER UU
+0B8E	TAMIL LETTER E
+0B8F	TAMIL LETTER EE
+0B90	TAMIL LETTER AI
+0B92	TAMIL LETTER O
+0B93	TAMIL LETTER OO
+0B94	TAMIL LETTER AU
+0B95	TAMIL LETTER KA
+0B99	TAMIL LETTER NGA
+0B9A	TAMIL LETTER CA
+0B9C	TAMIL LETTER JA
+0B9E	TAMIL LETTER NYA
+0B9F	TAMIL LETTER TTA
+0BA3	TAMIL LETTER NNA
+0BA4	TAMIL LETTER TA
+0BA8	TAMIL LETTER NA
+0BA9	TAMIL LETTER NNNA
+0BAA	TAMIL LETTER PA
+0BAE	TAMIL LETTER MA
+0BAF	TAMIL LETTER YA
+0BB0	TAMIL LETTER RA
+0BB1	TAMIL LETTER RRA
+0BB2	TAMIL LETTER LA
+0BB3	TAMIL LETTER LLA
+0BB4	TAMIL LETTER LLLA
+0BB5	TAMIL LETTER VA
+0BB7	TAMIL LETTER SSA
+0BB8	TAMIL LETTER SA
+0BB9	TAMIL LETTER HA
+0BBE	TAMIL VOWEL SIGN AA
+0BBF	TAMIL VOWEL SIGN I
+0BC0	TAMIL VOWEL SIGN II
+0BC1	TAMIL VOWEL SIGN U
+0BC2	TAMIL VOWEL SIGN UU
+0BC6	TAMIL VOWEL SIGN E
+0BC7	TAMIL VOWEL SIGN EE
+0BC8	TAMIL VOWEL SIGN AI
+0BCA	TAMIL VOWEL SIGN O
+0BCB	TAMIL VOWEL SIGN OO
+0BCC	TAMIL VOWEL SIGN AU
+0BCD	TAMIL SIGN VIRAMA
+0BD7	TAMIL AU LENGTH MARK
+0BE7	TAMIL DIGIT ONE
+0BE8	TAMIL DIGIT TWO
+0BE9	TAMIL DIGIT THREE
+0BEA	TAMIL DIGIT FOUR
+0BEB	TAMIL DIGIT FIVE
+0BEC	TAMIL DIGIT SIX
+0BED	TAMIL DIGIT SEVEN
+0BEE	TAMIL DIGIT EIGHT
+0BEF	TAMIL DIGIT NINE
+0BF0	TAMIL NUMBER TEN
+0BF1	TAMIL NUMBER ONE HUNDRED
+0BF2	TAMIL NUMBER ONE THOUSAND
+0C01	TELUGU SIGN CANDRABINDU
+0C02	TELUGU SIGN ANUSVARA
+0C03	TELUGU SIGN VISARGA
+0C05	TELUGU LETTER A
+0C06	TELUGU LETTER AA
+0C07	TELUGU LETTER I
+0C08	TELUGU LETTER II
+0C09	TELUGU LETTER U
+0C0A	TELUGU LETTER UU
+0C0B	TELUGU LETTER VOCALIC R
+0C0C	TELUGU LETTER VOCALIC L
+0C0E	TELUGU LETTER E
+0C0F	TELUGU LETTER EE
+0C10	TELUGU LETTER AI
+0C12	TELUGU LETTER O
+0C13	TELUGU LETTER OO
+0C14	TELUGU LETTER AU
+0C15	TELUGU LETTER KA
+0C16	TELUGU LETTER KHA
+0C17	TELUGU LETTER GA
+0C18	TELUGU LETTER GHA
+0C19	TELUGU LETTER NGA
+0C1A	TELUGU LETTER CA
+0C1B	TELUGU LETTER CHA
+0C1C	TELUGU LETTER JA
+0C1D	TELUGU LETTER JHA
+0C1E	TELUGU LETTER NYA
+0C1F	TELUGU LETTER TTA
+0C20	TELUGU LETTER TTHA
+0C21	TELUGU LETTER DDA
+0C22	TELUGU LETTER DDHA
+0C23	TELUGU LETTER NNA
+0C24	TELUGU LETTER TA
+0C25	TELUGU LETTER THA
+0C26	TELUGU LETTER DA
+0C27	TELUGU LETTER DHA
+0C28	TELUGU LETTER NA
+0C2A	TELUGU LETTER PA
+0C2B	TELUGU LETTER PHA
+0C2C	TELUGU LETTER BA
+0C2D	TELUGU LETTER BHA
+0C2E	TELUGU LETTER MA
+0C2F	TELUGU LETTER YA
+0C30	TELUGU LETTER RA
+0C31	TELUGU LETTER RRA
+0C32	TELUGU LETTER LA
+0C33	TELUGU LETTER LLA
+0C35	TELUGU LETTER VA
+0C36	TELUGU LETTER SHA
+0C37	TELUGU LETTER SSA
+0C38	TELUGU LETTER SA
+0C39	TELUGU LETTER HA
+0C3E	TELUGU VOWEL SIGN AA
+0C3F	TELUGU VOWEL SIGN I
+0C40	TELUGU VOWEL SIGN II
+0C41	TELUGU VOWEL SIGN U
+0C42	TELUGU VOWEL SIGN UU
+0C43	TELUGU VOWEL SIGN VOCALIC R
+0C44	TELUGU VOWEL SIGN VOCALIC RR
+0C46	TELUGU VOWEL SIGN E
+0C47	TELUGU VOWEL SIGN EE
+0C48	TELUGU VOWEL SIGN AI
+0C4A	TELUGU VOWEL SIGN O
+0C4B	TELUGU VOWEL SIGN OO
+0C4C	TELUGU VOWEL SIGN AU
+0C4D	TELUGU SIGN VIRAMA
+0C55	TELUGU LENGTH MARK
+0C56	TELUGU AI LENGTH MARK
+0C60	TELUGU LETTER VOCALIC RR
+0C61	TELUGU LETTER VOCALIC LL
+0C66	TELUGU DIGIT ZERO
+0C67	TELUGU DIGIT ONE
+0C68	TELUGU DIGIT TWO
+0C69	TELUGU DIGIT THREE
+0C6A	TELUGU DIGIT FOUR
+0C6B	TELUGU DIGIT FIVE
+0C6C	TELUGU DIGIT SIX
+0C6D	TELUGU DIGIT SEVEN
+0C6E	TELUGU DIGIT EIGHT
+0C6F	TELUGU DIGIT NINE
+0C82	KANNADA SIGN ANUSVARA
+0C83	KANNADA SIGN VISARGA
+0C85	KANNADA LETTER A
+0C86	KANNADA LETTER AA
+0C87	KANNADA LETTER I
+0C88	KANNADA LETTER II
+0C89	KANNADA LETTER U
+0C8A	KANNADA LETTER UU
+0C8B	KANNADA LETTER VOCALIC R
+0C8C	KANNADA LETTER VOCALIC L
+0C8E	KANNADA LETTER E
+0C8F	KANNADA LETTER EE
+0C90	KANNADA LETTER AI
+0C92	KANNADA LETTER O
+0C93	KANNADA LETTER OO
+0C94	KANNADA LETTER AU
+0C95	KANNADA LETTER KA
+0C96	KANNADA LETTER KHA
+0C97	KANNADA LETTER GA
+0C98	KANNADA LETTER GHA
+0C99	KANNADA LETTER NGA
+0C9A	KANNADA LETTER CA
+0C9B	KANNADA LETTER CHA
+0C9C	KANNADA LETTER JA
+0C9D	KANNADA LETTER JHA
+0C9E	KANNADA LETTER NYA
+0C9F	KANNADA LETTER TTA
+0CA0	KANNADA LETTER TTHA
+0CA1	KANNADA LETTER DDA
+0CA2	KANNADA LETTER DDHA
+0CA3	KANNADA LETTER NNA
+0CA4	KANNADA LETTER TA
+0CA5	KANNADA LETTER THA
+0CA6	KANNADA LETTER DA
+0CA7	KANNADA LETTER DHA
+0CA8	KANNADA LETTER NA
+0CAA	KANNADA LETTER PA
+0CAB	KANNADA LETTER PHA
+0CAC	KANNADA LETTER BA
+0CAD	KANNADA LETTER BHA
+0CAE	KANNADA LETTER MA
+0CAF	KANNADA LETTER YA
+0CB0	KANNADA LETTER RA
+0CB1	KANNADA LETTER RRA
+0CB2	KANNADA LETTER LA
+0CB3	KANNADA LETTER LLA
+0CB5	KANNADA LETTER VA
+0CB6	KANNADA LETTER SHA
+0CB7	KANNADA LETTER SSA
+0CB8	KANNADA LETTER SA
+0CB9	KANNADA LETTER HA
+0CBE	KANNADA VOWEL SIGN AA
+0CBF	KANNADA VOWEL SIGN I
+0CC0	KANNADA VOWEL SIGN II
+0CC1	KANNADA VOWEL SIGN U
+0CC2	KANNADA VOWEL SIGN UU
+0CC3	KANNADA VOWEL SIGN VOCALIC R
+0CC4	KANNADA VOWEL SIGN VOCALIC RR
+0CC6	KANNADA VOWEL SIGN E
+0CC7	KANNADA VOWEL SIGN EE
+0CC8	KANNADA VOWEL SIGN AI
+0CCA	KANNADA VOWEL SIGN O
+0CCB	KANNADA VOWEL SIGN OO
+0CCC	KANNADA VOWEL SIGN AU
+0CCD	KANNADA SIGN VIRAMA
+0CD5	KANNADA LENGTH MARK
+0CD6	KANNADA AI LENGTH MARK
+0CDE	KANNADA LETTER FA
+0CE0	KANNADA LETTER VOCALIC RR
+0CE1	KANNADA LETTER VOCALIC LL
+0CE6	KANNADA DIGIT ZERO
+0CE7	KANNADA DIGIT ONE
+0CE8	KANNADA DIGIT TWO
+0CE9	KANNADA DIGIT THREE
+0CEA	KANNADA DIGIT FOUR
+0CEB	KANNADA DIGIT FIVE
+0CEC	KANNADA DIGIT SIX
+0CED	KANNADA DIGIT SEVEN
+0CEE	KANNADA DIGIT EIGHT
+0CEF	KANNADA DIGIT NINE
+0D02	MALAYALAM SIGN ANUSVARA
+0D03	MALAYALAM SIGN VISARGA
+0D05	MALAYALAM LETTER A
+0D06	MALAYALAM LETTER AA
+0D07	MALAYALAM LETTER I
+0D08	MALAYALAM LETTER II
+0D09	MALAYALAM LETTER U
+0D0A	MALAYALAM LETTER UU
+0D0B	MALAYALAM LETTER VOCALIC R
+0D0C	MALAYALAM LETTER VOCALIC L
+0D0E	MALAYALAM LETTER E
+0D0F	MALAYALAM LETTER EE
+0D10	MALAYALAM LETTER AI
+0D12	MALAYALAM LETTER O
+0D13	MALAYALAM LETTER OO
+0D14	MALAYALAM LETTER AU
+0D15	MALAYALAM LETTER KA
+0D16	MALAYALAM LETTER KHA
+0D17	MALAYALAM LETTER GA
+0D18	MALAYALAM LETTER GHA
+0D19	MALAYALAM LETTER NGA
+0D1A	MALAYALAM LETTER CA
+0D1B	MALAYALAM LETTER CHA
+0D1C	MALAYALAM LETTER JA
+0D1D	MALAYALAM LETTER JHA
+0D1E	MALAYALAM LETTER NYA
+0D1F	MALAYALAM LETTER TTA
+0D20	MALAYALAM LETTER TTHA
+0D21	MALAYALAM LETTER DDA
+0D22	MALAYALAM LETTER DDHA
+0D23	MALAYALAM LETTER NNA
+0D24	MALAYALAM LETTER TA
+0D25	MALAYALAM LETTER THA
+0D26	MALAYALAM LETTER DA
+0D27	MALAYALAM LETTER DHA
+0D28	MALAYALAM LETTER NA
+0D2A	MALAYALAM LETTER PA
+0D2B	MALAYALAM LETTER PHA
+0D2C	MALAYALAM LETTER BA
+0D2D	MALAYALAM LETTER BHA
+0D2E	MALAYALAM LETTER MA
+0D2F	MALAYALAM LETTER YA
+0D30	MALAYALAM LETTER RA
+0D31	MALAYALAM LETTER RRA
+0D32	MALAYALAM LETTER LA
+0D33	MALAYALAM LETTER LLA
+0D34	MALAYALAM LETTER LLLA
+0D35	MALAYALAM LETTER VA
+0D36	MALAYALAM LETTER SHA
+0D37	MALAYALAM LETTER SSA
+0D38	MALAYALAM LETTER SA
+0D39	MALAYALAM LETTER HA
+0D3E	MALAYALAM VOWEL SIGN AA
+0D3F	MALAYALAM VOWEL SIGN I
+0D40	MALAYALAM VOWEL SIGN II
+0D41	MALAYALAM VOWEL SIGN U
+0D42	MALAYALAM VOWEL SIGN UU
+0D43	MALAYALAM VOWEL SIGN VOCALIC R
+0D46	MALAYALAM VOWEL SIGN E
+0D47	MALAYALAM VOWEL SIGN EE
+0D48	MALAYALAM VOWEL SIGN AI
+0D4A	MALAYALAM VOWEL SIGN O
+0D4B	MALAYALAM VOWEL SIGN OO
+0D4C	MALAYALAM VOWEL SIGN AU
+0D4D	MALAYALAM SIGN VIRAMA
+0D57	MALAYALAM AU LENGTH MARK
+0D60	MALAYALAM LETTER VOCALIC RR
+0D61	MALAYALAM LETTER VOCALIC LL
+0D66	MALAYALAM DIGIT ZERO
+0D67	MALAYALAM DIGIT ONE
+0D68	MALAYALAM DIGIT TWO
+0D69	MALAYALAM DIGIT THREE
+0D6A	MALAYALAM DIGIT FOUR
+0D6B	MALAYALAM DIGIT FIVE
+0D6C	MALAYALAM DIGIT SIX
+0D6D	MALAYALAM DIGIT SEVEN
+0D6E	MALAYALAM DIGIT EIGHT
+0D6F	MALAYALAM DIGIT NINE
+0E01	THAI CHARACTER KO KAI
+0E02	THAI CHARACTER KHO KHAI
+0E03	THAI CHARACTER KHO KHUAT
+0E04	THAI CHARACTER KHO KHWAI
+0E05	THAI CHARACTER KHO KHON
+0E06	THAI CHARACTER KHO RAKHANG
+0E07	THAI CHARACTER NGO NGU
+0E08	THAI CHARACTER CHO CHAN
+0E09	THAI CHARACTER CHO CHING
+0E0A	THAI CHARACTER CHO CHANG
+0E0B	THAI CHARACTER SO SO
+0E0C	THAI CHARACTER CHO CHOE
+0E0D	THAI CHARACTER YO YING
+0E0E	THAI CHARACTER DO CHADA
+0E0F	THAI CHARACTER TO PATAK
+0E10	THAI CHARACTER THO THAN
+0E11	THAI CHARACTER THO NANGMONTHO
+0E12	THAI CHARACTER THO PHUTHAO
+0E13	THAI CHARACTER NO NEN
+0E14	THAI CHARACTER DO DEK
+0E15	THAI CHARACTER TO TAO
+0E16	THAI CHARACTER THO THUNG
+0E17	THAI CHARACTER THO THAHAN
+0E18	THAI CHARACTER THO THONG
+0E19	THAI CHARACTER NO NU
+0E1A	THAI CHARACTER BO BAIMAI
+0E1B	THAI CHARACTER PO PLA
+0E1C	THAI CHARACTER PHO PHUNG
+0E1D	THAI CHARACTER FO FA
+0E1E	THAI CHARACTER PHO PHAN
+0E1F	THAI CHARACTER FO FAN
+0E20	THAI CHARACTER PHO SAMPHAO
+0E21	THAI CHARACTER MO MA
+0E22	THAI CHARACTER YO YAK
+0E23	THAI CHARACTER RO RUA
+0E24	THAI CHARACTER RU
+0E25	THAI CHARACTER LO LING
+0E26	THAI CHARACTER LU
+0E27	THAI CHARACTER WO WAEN
+0E28	THAI CHARACTER SO SALA
+0E29	THAI CHARACTER SO RUSI
+0E2A	THAI CHARACTER SO SUA
+0E2B	THAI CHARACTER HO HIP
+0E2C	THAI CHARACTER LO CHULA
+0E2D	THAI CHARACTER O ANG
+0E2E	THAI CHARACTER HO NOKHUK
+0E2F	THAI CHARACTER PAIYANNOI
+0E30	THAI CHARACTER SARA A
+0E31	THAI CHARACTER MAI HAN-AKAT
+0E32	THAI CHARACTER SARA AA
+0E33	THAI CHARACTER SARA AM
+0E34	THAI CHARACTER SARA I
+0E35	THAI CHARACTER SARA II
+0E36	THAI CHARACTER SARA UE
+0E37	THAI CHARACTER SARA UEE
+0E38	THAI CHARACTER SARA U
+0E39	THAI CHARACTER SARA UU
+0E3A	THAI CHARACTER PHINTHU
+0E3F	THAI CURRENCY SYMBOL BAHT
+0E40	THAI CHARACTER SARA E
+0E41	THAI CHARACTER SARA AE
+0E42	THAI CHARACTER SARA O
+0E43	THAI CHARACTER SARA AI MAIMUAN
+0E44	THAI CHARACTER SARA AI MAIMALAI
+0E45	THAI CHARACTER LAKKHANGYAO
+0E46	THAI CHARACTER MAIYAMOK
+0E47	THAI CHARACTER MAITAIKHU
+0E48	THAI CHARACTER MAI EK
+0E49	THAI CHARACTER MAI THO
+0E4A	THAI CHARACTER MAI TRI
+0E4B	THAI CHARACTER MAI CHATTAWA
+0E4C	THAI CHARACTER THANTHAKHAT
+0E4D	THAI CHARACTER NIKHAHIT
+0E4E	THAI CHARACTER YAMAKKAN
+0E4F	THAI CHARACTER FONGMAN
+0E50	THAI DIGIT ZERO
+0E51	THAI DIGIT ONE
+0E52	THAI DIGIT TWO
+0E53	THAI DIGIT THREE
+0E54	THAI DIGIT FOUR
+0E55	THAI DIGIT FIVE
+0E56	THAI DIGIT SIX
+0E57	THAI DIGIT SEVEN
+0E58	THAI DIGIT EIGHT
+0E59	THAI DIGIT NINE
+0E5A	THAI CHARACTER ANGKHANKHU
+0E5B	THAI CHARACTER KHOMUT
+0E81	LAO LETTER KO
+0E82	LAO LETTER KHO SUNG
+0E84	LAO LETTER KHO TAM
+0E87	LAO LETTER NGO
+0E88	LAO LETTER CO
+0E8A	LAO LETTER SO TAM
+0E8D	LAO LETTER NYO
+0E94	LAO LETTER DO
+0E95	LAO LETTER TO
+0E96	LAO LETTER THO SUNG
+0E97	LAO LETTER THO TAM
+0E99	LAO LETTER NO
+0E9A	LAO LETTER BO
+0E9B	LAO LETTER PO
+0E9C	LAO LETTER PHO SUNG
+0E9D	LAO LETTER FO TAM
+0E9E	LAO LETTER PHO TAM
+0E9F	LAO LETTER FO SUNG
+0EA1	LAO LETTER MO
+0EA2	LAO LETTER YO
+0EA3	LAO LETTER LO LING
+0EA5	LAO LETTER LO LOOT
+0EA7	LAO LETTER WO
+0EAA	LAO LETTER SO SUNG
+0EAB	LAO LETTER HO SUNG
+0EAD	LAO LETTER O
+0EAE	LAO LETTER HO TAM
+0EAF	LAO ELLIPSIS
+0EB0	LAO VOWEL SIGN A
+0EB1	LAO VOWEL SIGN MAI KAN
+0EB2	LAO VOWEL SIGN AA
+0EB3	LAO VOWEL SIGN AM
+0EB4	LAO VOWEL SIGN I
+0EB5	LAO VOWEL SIGN II
+0EB6	LAO VOWEL SIGN Y
+0EB7	LAO VOWEL SIGN YY
+0EB8	LAO VOWEL SIGN U
+0EB9	LAO VOWEL SIGN UU
+0EBB	LAO VOWEL SIGN MAI KON
+0EBC	LAO SEMIVOWEL SIGN LO
+0EBD	LAO SEMIVOWEL SIGN NYO
+0EC0	LAO VOWEL SIGN E
+0EC1	LAO VOWEL SIGN EI
+0EC2	LAO VOWEL SIGN O
+0EC3	LAO VOWEL SIGN AY
+0EC4	LAO VOWEL SIGN AI
+0EC6	LAO KO LA
+0EC8	LAO TONE MAI EK
+0EC9	LAO TONE MAI THO
+0ECA	LAO TONE MAI TI
+0ECB	LAO TONE MAI CATAWA
+0ECC	LAO CANCELLATION MARK
+0ECD	LAO NIGGAHITA
+0ED0	LAO DIGIT ZERO
+0ED1	LAO DIGIT ONE
+0ED2	LAO DIGIT TWO
+0ED3	LAO DIGIT THREE
+0ED4	LAO DIGIT FOUR
+0ED5	LAO DIGIT FIVE
+0ED6	LAO DIGIT SIX
+0ED7	LAO DIGIT SEVEN
+0ED8	LAO DIGIT EIGHT
+0ED9	LAO DIGIT NINE
+0EDC	LAO HO NO
+0EDD	LAO HO MO
+0F00	TIBETAN SYLLABLE OM
+0F01	TIBETAN MARK GTER YIG MGO TRUNCATED A
+0F02	TIBETAN MARK GTER YIG MGO -UM RNAM BCAD MA
+0F03	TIBETAN MARK GTER YIG MGO -UM GTER TSHEG MA
+0F04	TIBETAN MARK INITIAL YIG MGO MDUN MA
+0F05	TIBETAN MARK CLOSING YIG MGO SGAB MA
+0F06	TIBETAN MARK CARET YIG MGO PHUR SHAD MA
+0F07	TIBETAN MARK YIG MGO TSHEG SHAD MA
+0F08	TIBETAN MARK SBRUL SHAD
+0F09	TIBETAN MARK BSKUR YIG MGO
+0F0A	TIBETAN MARK BKA- SHOG YIG MGO
+0F0B	TIBETAN MARK INTERSYLLABIC TSHEG
+0F0C	TIBETAN MARK DELIMITER TSHEG BSTAR
+0F0D	TIBETAN MARK SHAD
+0F0E	TIBETAN MARK NYIS SHAD
+0F0F	TIBETAN MARK TSHEG SHAD
+0F10	TIBETAN MARK NYIS TSHEG SHAD
+0F11	TIBETAN MARK RIN CHEN SPUNGS SHAD
+0F12	TIBETAN MARK RGYA GRAM SHAD
+0F13	TIBETAN MARK CARET -DZUD RTAGS ME LONG CAN
+0F14	TIBETAN MARK GTER TSHEG
+0F15	TIBETAN LOGOTYPE SIGN CHAD RTAGS
+0F16	TIBETAN LOGOTYPE SIGN LHAG RTAGS
+0F17	TIBETAN ASTROLOGICAL SIGN SGRA GCAN -CHAR RTAGS
+0F18	TIBETAN ASTROLOGICAL SIGN -KHYUD PA
+0F19	TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS
+0F1A	TIBETAN SIGN RDEL DKAR GCIG
+0F1B	TIBETAN SIGN RDEL DKAR GNYIS
+0F1C	TIBETAN SIGN RDEL DKAR GSUM
+0F1D	TIBETAN SIGN RDEL NAG GCIG
+0F1E	TIBETAN SIGN RDEL NAG GNYIS
+0F1F	TIBETAN SIGN RDEL DKAR RDEL NAG
+0F20	TIBETAN DIGIT ZERO
+0F21	TIBETAN DIGIT ONE
+0F22	TIBETAN DIGIT TWO
+0F23	TIBETAN DIGIT THREE
+0F24	TIBETAN DIGIT FOUR
+0F25	TIBETAN DIGIT FIVE
+0F26	TIBETAN DIGIT SIX
+0F27	TIBETAN DIGIT SEVEN
+0F28	TIBETAN DIGIT EIGHT
+0F29	TIBETAN DIGIT NINE
+0F2A	TIBETAN DIGIT HALF ONE
+0F2B	TIBETAN DIGIT HALF TWO
+0F2C	TIBETAN DIGIT HALF THREE
+0F2D	TIBETAN DIGIT HALF FOUR
+0F2E	TIBETAN DIGIT HALF FIVE
+0F2F	TIBETAN DIGIT HALF SIX
+0F30	TIBETAN DIGIT HALF SEVEN
+0F31	TIBETAN DIGIT HALF EIGHT
+0F32	TIBETAN DIGIT HALF NINE
+0F33	TIBETAN DIGIT HALF ZERO
+0F34	TIBETAN MARK BSDUS RTAGS
+0F35	TIBETAN MARK NGAS BZUNG NYI ZLA
+0F36	TIBETAN MARK CARET -DZUD RTAGS BZHI MIG CAN
+0F37	TIBETAN MARK NGAS BZUNG SGOR RTAGS
+0F38	TIBETAN MARK CHE MGO
+0F39	TIBETAN MARK TSA -PHRU
+0F3A	TIBETAN MARK GUG RTAGS GYON
+0F3B	TIBETAN MARK GUG RTAGS GYAS
+0F3C	TIBETAN MARK ANG KHANG GYON
+0F3D	TIBETAN MARK ANG KHANG GYAS
+0F3E	TIBETAN SIGN YAR TSHES
+0F3F	TIBETAN SIGN MAR TSHES
+0F40	TIBETAN LETTER KA
+0F41	TIBETAN LETTER KHA
+0F42	TIBETAN LETTER GA
+0F43	TIBETAN LETTER GHA
+0F44	TIBETAN LETTER NGA
+0F45	TIBETAN LETTER CA
+0F46	TIBETAN LETTER CHA
+0F47	TIBETAN LETTER JA
+0F49	TIBETAN LETTER NYA
+0F4A	TIBETAN LETTER TTA
+0F4B	TIBETAN LETTER TTHA
+0F4C	TIBETAN LETTER DDA
+0F4D	TIBETAN LETTER DDHA
+0F4E	TIBETAN LETTER NNA
+0F4F	TIBETAN LETTER TA
+0F50	TIBETAN LETTER THA
+0F51	TIBETAN LETTER DA
+0F52	TIBETAN LETTER DHA
+0F53	TIBETAN LETTER NA
+0F54	TIBETAN LETTER PA
+0F55	TIBETAN LETTER PHA
+0F56	TIBETAN LETTER BA
+0F57	TIBETAN LETTER BHA
+0F58	TIBETAN LETTER MA
+0F59	TIBETAN LETTER TSA
+0F5A	TIBETAN LETTER TSHA
+0F5B	TIBETAN LETTER DZA
+0F5C	TIBETAN LETTER DZHA
+0F5D	TIBETAN LETTER WA
+0F5E	TIBETAN LETTER ZHA
+0F5F	TIBETAN LETTER ZA
+0F60	TIBETAN LETTER -A
+0F61	TIBETAN LETTER YA
+0F62	TIBETAN LETTER RA
+0F63	TIBETAN LETTER LA
+0F64	TIBETAN LETTER SHA
+0F65	TIBETAN LETTER SSA
+0F66	TIBETAN LETTER SA
+0F67	TIBETAN LETTER HA
+0F68	TIBETAN LETTER A
+0F69	TIBETAN LETTER KSSA
+0F71	TIBETAN VOWEL SIGN AA
+0F72	TIBETAN VOWEL SIGN I
+0F73	TIBETAN VOWEL SIGN II
+0F74	TIBETAN VOWEL SIGN U
+0F75	TIBETAN VOWEL SIGN UU
+0F76	TIBETAN VOWEL SIGN VOCALIC R
+0F77	TIBETAN VOWEL SIGN VOCALIC RR
+0F78	TIBETAN VOWEL SIGN VOCALIC L
+0F79	TIBETAN VOWEL SIGN VOCALIC LL
+0F7A	TIBETAN VOWEL SIGN E
+0F7B	TIBETAN VOWEL SIGN EE
+0F7C	TIBETAN VOWEL SIGN O
+0F7D	TIBETAN VOWEL SIGN OO
+0F7E	TIBETAN SIGN RJES SU NGA RO
+0F7F	TIBETAN SIGN RNAM BCAD
+0F80	TIBETAN VOWEL SIGN REVERSED I
+0F81	TIBETAN VOWEL SIGN REVERSED II
+0F82	TIBETAN SIGN NYI ZLA NAA DA
+0F83	TIBETAN SIGN SNA LDAN
+0F84	TIBETAN MARK HALANTA
+0F85	TIBETAN MARK PALUTA
+0F86	TIBETAN SIGN LCI RTAGS
+0F87	TIBETAN SIGN YANG RTAGS
+0F88	TIBETAN SIGN LCE TSA CAN
+0F89	TIBETAN SIGN MCHU CAN
+0F8A	TIBETAN SIGN GRU CAN RGYINGS
+0F8B	TIBETAN SIGN GRU MED RGYINGS
+0F90	TIBETAN SUBJOINED LETTER KA
+0F91	TIBETAN SUBJOINED LETTER KHA
+0F92	TIBETAN SUBJOINED LETTER GA
+0F93	TIBETAN SUBJOINED LETTER GHA
+0F94	TIBETAN SUBJOINED LETTER NGA
+0F95	TIBETAN SUBJOINED LETTER CA
+0F97	TIBETAN SUBJOINED LETTER JA
+0F99	TIBETAN SUBJOINED LETTER NYA
+0F9A	TIBETAN SUBJOINED LETTER TTA
+0F9B	TIBETAN SUBJOINED LETTER TTHA
+0F9C	TIBETAN SUBJOINED LETTER DDA
+0F9D	TIBETAN SUBJOINED LETTER DDHA
+0F9E	TIBETAN SUBJOINED LETTER NNA
+0F9F	TIBETAN SUBJOINED LETTER TA
+0FA0	TIBETAN SUBJOINED LETTER THA
+0FA1	TIBETAN SUBJOINED LETTER DA
+0FA2	TIBETAN SUBJOINED LETTER DHA
+0FA3	TIBETAN SUBJOINED LETTER NA
+0FA4	TIBETAN SUBJOINED LETTER PA
+0FA5	TIBETAN SUBJOINED LETTER PHA
+0FA6	TIBETAN SUBJOINED LETTER BA
+0FA7	TIBETAN SUBJOINED LETTER BHA
+0FA8	TIBETAN SUBJOINED LETTER MA
+0FA9	TIBETAN SUBJOINED LETTER TSA
+0FAA	TIBETAN SUBJOINED LETTER TSHA
+0FAB	TIBETAN SUBJOINED LETTER DZA
+0FAC	TIBETAN SUBJOINED LETTER DZHA
+0FAD	TIBETAN SUBJOINED LETTER WA
+0FB1	TIBETAN SUBJOINED LETTER YA
+0FB2	TIBETAN SUBJOINED LETTER RA
+0FB3	TIBETAN SUBJOINED LETTER LA
+0FB4	TIBETAN SUBJOINED LETTER SHA
+0FB5	TIBETAN SUBJOINED LETTER SSA
+0FB6	TIBETAN SUBJOINED LETTER SA
+0FB7	TIBETAN SUBJOINED LETTER HA
+0FB9	TIBETAN SUBJOINED LETTER KSSA
+10A0	GEORGIAN CAPITAL LETTER AN
+10A1	GEORGIAN CAPITAL LETTER BAN
+10A2	GEORGIAN CAPITAL LETTER GAN
+10A3	GEORGIAN CAPITAL LETTER DON
+10A4	GEORGIAN CAPITAL LETTER EN
+10A5	GEORGIAN CAPITAL LETTER VIN
+10A6	GEORGIAN CAPITAL LETTER ZEN
+10A7	GEORGIAN CAPITAL LETTER TAN
+10A8	GEORGIAN CAPITAL LETTER IN
+10A9	GEORGIAN CAPITAL LETTER KAN
+10AA	GEORGIAN CAPITAL LETTER LAS
+10AB	GEORGIAN CAPITAL LETTER MAN
+10AC	GEORGIAN CAPITAL LETTER NAR
+10AD	GEORGIAN CAPITAL LETTER ON
+10AE	GEORGIAN CAPITAL LETTER PAR
+10AF	GEORGIAN CAPITAL LETTER ZHAR
+10B0	GEORGIAN CAPITAL LETTER RAE
+10B1	GEORGIAN CAPITAL LETTER SAN
+10B2	GEORGIAN CAPITAL LETTER TAR
+10B3	GEORGIAN CAPITAL LETTER UN
+10B4	GEORGIAN CAPITAL LETTER PHAR
+10B5	GEORGIAN CAPITAL LETTER KHAR
+10B6	GEORGIAN CAPITAL LETTER GHAN
+10B7	GEORGIAN CAPITAL LETTER QAR
+10B8	GEORGIAN CAPITAL LETTER SHIN
+10B9	GEORGIAN CAPITAL LETTER CHIN
+10BA	GEORGIAN CAPITAL LETTER CAN
+10BB	GEORGIAN CAPITAL LETTER JIL
+10BC	GEORGIAN CAPITAL LETTER CIL
+10BD	GEORGIAN CAPITAL LETTER CHAR
+10BE	GEORGIAN CAPITAL LETTER XAN
+10BF	GEORGIAN CAPITAL LETTER JHAN
+10C0	GEORGIAN CAPITAL LETTER HAE
+10C1	GEORGIAN CAPITAL LETTER HE
+10C2	GEORGIAN CAPITAL LETTER HIE
+10C3	GEORGIAN CAPITAL LETTER WE
+10C4	GEORGIAN CAPITAL LETTER HAR
+10C5	GEORGIAN CAPITAL LETTER HOE
+10D0	GEORGIAN LETTER AN
+10D1	GEORGIAN LETTER BAN
+10D2	GEORGIAN LETTER GAN
+10D3	GEORGIAN LETTER DON
+10D4	GEORGIAN LETTER EN
+10D5	GEORGIAN LETTER VIN
+10D6	GEORGIAN LETTER ZEN
+10D7	GEORGIAN LETTER TAN
+10D8	GEORGIAN LETTER IN
+10D9	GEORGIAN LETTER KAN
+10DA	GEORGIAN LETTER LAS
+10DB	GEORGIAN LETTER MAN
+10DC	GEORGIAN LETTER NAR
+10DD	GEORGIAN LETTER ON
+10DE	GEORGIAN LETTER PAR
+10DF	GEORGIAN LETTER ZHAR
+10E0	GEORGIAN LETTER RAE
+10E1	GEORGIAN LETTER SAN
+10E2	GEORGIAN LETTER TAR
+10E3	GEORGIAN LETTER UN
+10E4	GEORGIAN LETTER PHAR
+10E5	GEORGIAN LETTER KHAR
+10E6	GEORGIAN LETTER GHAN
+10E7	GEORGIAN LETTER QAR
+10E8	GEORGIAN LETTER SHIN
+10E9	GEORGIAN LETTER CHIN
+10EA	GEORGIAN LETTER CAN
+10EB	GEORGIAN LETTER JIL
+10EC	GEORGIAN LETTER CIL
+10ED	GEORGIAN LETTER CHAR
+10EE	GEORGIAN LETTER XAN
+10EF	GEORGIAN LETTER JHAN
+10F0	GEORGIAN LETTER HAE
+10F1	GEORGIAN LETTER HE
+10F2	GEORGIAN LETTER HIE
+10F3	GEORGIAN LETTER WE
+10F4	GEORGIAN LETTER HAR
+10F5	GEORGIAN LETTER HOE
+10F6	GEORGIAN LETTER FI
+10FB	GEORGIAN PARAGRAPH SEPARATOR
+1100	HANGUL CHOSEONG KIYEOK
+1101	HANGUL CHOSEONG SSANGKIYEOK
+1102	HANGUL CHOSEONG NIEUN
+1103	HANGUL CHOSEONG TIKEUT
+1104	HANGUL CHOSEONG SSANGTIKEUT
+1105	HANGUL CHOSEONG RIEUL
+1106	HANGUL CHOSEONG MIEUM
+1107	HANGUL CHOSEONG PIEUP
+1108	HANGUL CHOSEONG SSANGPIEUP
+1109	HANGUL CHOSEONG SIOS
+110A	HANGUL CHOSEONG SSANGSIOS
+110B	HANGUL CHOSEONG IEUNG
+110C	HANGUL CHOSEONG CIEUC
+110D	HANGUL CHOSEONG SSANGCIEUC
+110E	HANGUL CHOSEONG CHIEUCH
+110F	HANGUL CHOSEONG KHIEUKH
+1110	HANGUL CHOSEONG THIEUTH
+1111	HANGUL CHOSEONG PHIEUPH
+1112	HANGUL CHOSEONG HIEUH
+1113	HANGUL CHOSEONG NIEUN-KIYEOK
+1114	HANGUL CHOSEONG SSANGNIEUN
+1115	HANGUL CHOSEONG NIEUN-TIKEUT
+1116	HANGUL CHOSEONG NIEUN-PIEUP
+1117	HANGUL CHOSEONG TIKEUT-KIYEOK
+1118	HANGUL CHOSEONG RIEUL-NIEUN
+1119	HANGUL CHOSEONG SSANGRIEUL
+111A	HANGUL CHOSEONG RIEUL-HIEUH
+111B	HANGUL CHOSEONG KAPYEOUNRIEUL
+111C	HANGUL CHOSEONG MIEUM-PIEUP
+111D	HANGUL CHOSEONG KAPYEOUNMIEUM
+111E	HANGUL CHOSEONG PIEUP-KIYEOK
+111F	HANGUL CHOSEONG PIEUP-NIEUN
+1120	HANGUL CHOSEONG PIEUP-TIKEUT
+1121	HANGUL CHOSEONG PIEUP-SIOS
+1122	HANGUL CHOSEONG PIEUP-SIOS-KIYEOK
+1123	HANGUL CHOSEONG PIEUP-SIOS-TIKEUT
+1124	HANGUL CHOSEONG PIEUP-SIOS-PIEUP
+1125	HANGUL CHOSEONG PIEUP-SSANGSIOS
+1126	HANGUL CHOSEONG PIEUP-SIOS-CIEUC
+1127	HANGUL CHOSEONG PIEUP-CIEUC
+1128	HANGUL CHOSEONG PIEUP-CHIEUCH
+1129	HANGUL CHOSEONG PIEUP-THIEUTH
+112A	HANGUL CHOSEONG PIEUP-PHIEUPH
+112B	HANGUL CHOSEONG KAPYEOUNPIEUP
+112C	HANGUL CHOSEONG KAPYEOUNSSANGPIEUP
+112D	HANGUL CHOSEONG SIOS-KIYEOK
+112E	HANGUL CHOSEONG SIOS-NIEUN
+112F	HANGUL CHOSEONG SIOS-TIKEUT
+1130	HANGUL CHOSEONG SIOS-RIEUL
+1131	HANGUL CHOSEONG SIOS-MIEUM
+1132	HANGUL CHOSEONG SIOS-PIEUP
+1133	HANGUL CHOSEONG SIOS-PIEUP-KIYEOK
+1134	HANGUL CHOSEONG SIOS-SSANGSIOS
+1135	HANGUL CHOSEONG SIOS-IEUNG
+1136	HANGUL CHOSEONG SIOS-CIEUC
+1137	HANGUL CHOSEONG SIOS-CHIEUCH
+1138	HANGUL CHOSEONG SIOS-KHIEUKH
+1139	HANGUL CHOSEONG SIOS-THIEUTH
+113A	HANGUL CHOSEONG SIOS-PHIEUPH
+113B	HANGUL CHOSEONG SIOS-HIEUH
+113C	HANGUL CHOSEONG CHITUEUMSIOS
+113D	HANGUL CHOSEONG CHITUEUMSSANGSIOS
+113E	HANGUL CHOSEONG CEONGCHIEUMSIOS
+113F	HANGUL CHOSEONG CEONGCHIEUMSSANGSIOS
+1140	HANGUL CHOSEONG PANSIOS
+1141	HANGUL CHOSEONG IEUNG-KIYEOK
+1142	HANGUL CHOSEONG IEUNG-TIKEUT
+1143	HANGUL CHOSEONG IEUNG-MIEUM
+1144	HANGUL CHOSEONG IEUNG-PIEUP
+1145	HANGUL CHOSEONG IEUNG-SIOS
+1146	HANGUL CHOSEONG IEUNG-PANSIOS
+1147	HANGUL CHOSEONG SSANGIEUNG
+1148	HANGUL CHOSEONG IEUNG-CIEUC
+1149	HANGUL CHOSEONG IEUNG-CHIEUCH
+114A	HANGUL CHOSEONG IEUNG-THIEUTH
+114B	HANGUL CHOSEONG IEUNG-PHIEUPH
+114C	HANGUL CHOSEONG YESIEUNG
+114D	HANGUL CHOSEONG CIEUC-IEUNG
+114E	HANGUL CHOSEONG CHITUEUMCIEUC
+114F	HANGUL CHOSEONG CHITUEUMSSANGCIEUC
+1150	HANGUL CHOSEONG CEONGCHIEUMCIEUC
+1151	HANGUL CHOSEONG CEONGCHIEUMSSANGCIEUC
+1152	HANGUL CHOSEONG CHIEUCH-KHIEUKH
+1153	HANGUL CHOSEONG CHIEUCH-HIEUH
+1154	HANGUL CHOSEONG CHITUEUMCHIEUCH
+1155	HANGUL CHOSEONG CEONGCHIEUMCHIEUCH
+1156	HANGUL CHOSEONG PHIEUPH-PIEUP
+1157	HANGUL CHOSEONG KAPYEOUNPHIEUPH
+1158	HANGUL CHOSEONG SSANGHIEUH
+1159	HANGUL CHOSEONG YEORINHIEUH
+115F	HANGUL CHOSEONG FILLER
+1160	HANGUL JUNGSEONG FILLER
+1161	HANGUL JUNGSEONG A
+1162	HANGUL JUNGSEONG AE
+1163	HANGUL JUNGSEONG YA
+1164	HANGUL JUNGSEONG YAE
+1165	HANGUL JUNGSEONG EO
+1166	HANGUL JUNGSEONG E
+1167	HANGUL JUNGSEONG YEO
+1168	HANGUL JUNGSEONG YE
+1169	HANGUL JUNGSEONG O
+116A	HANGUL JUNGSEONG WA
+116B	HANGUL JUNGSEONG WAE
+116C	HANGUL JUNGSEONG OE
+116D	HANGUL JUNGSEONG YO
+116E	HANGUL JUNGSEONG U
+116F	HANGUL JUNGSEONG WEO
+1170	HANGUL JUNGSEONG WE
+1171	HANGUL JUNGSEONG WI
+1172	HANGUL JUNGSEONG YU
+1173	HANGUL JUNGSEONG EU
+1174	HANGUL JUNGSEONG YI
+1175	HANGUL JUNGSEONG I
+1176	HANGUL JUNGSEONG A-O
+1177	HANGUL JUNGSEONG A-U
+1178	HANGUL JUNGSEONG YA-O
+1179	HANGUL JUNGSEONG YA-YO
+117A	HANGUL JUNGSEONG EO-O
+117B	HANGUL JUNGSEONG EO-U
+117C	HANGUL JUNGSEONG EO-EU
+117D	HANGUL JUNGSEONG YEO-O
+117E	HANGUL JUNGSEONG YEO-U
+117F	HANGUL JUNGSEONG O-EO
+1180	HANGUL JUNGSEONG O-E
+1181	HANGUL JUNGSEONG O-YE
+1182	HANGUL JUNGSEONG O-O
+1183	HANGUL JUNGSEONG O-U
+1184	HANGUL JUNGSEONG YO-YA
+1185	HANGUL JUNGSEONG YO-YAE
+1186	HANGUL JUNGSEONG YO-YEO
+1187	HANGUL JUNGSEONG YO-O
+1188	HANGUL JUNGSEONG YO-I
+1189	HANGUL JUNGSEONG U-A
+118A	HANGUL JUNGSEONG U-AE
+118B	HANGUL JUNGSEONG U-EO-EU
+118C	HANGUL JUNGSEONG U-YE
+118D	HANGUL JUNGSEONG U-U
+118E	HANGUL JUNGSEONG YU-A
+118F	HANGUL JUNGSEONG YU-EO
+1190	HANGUL JUNGSEONG YU-E
+1191	HANGUL JUNGSEONG YU-YEO
+1192	HANGUL JUNGSEONG YU-YE
+1193	HANGUL JUNGSEONG YU-U
+1194	HANGUL JUNGSEONG YU-I
+1195	HANGUL JUNGSEONG EU-U
+1196	HANGUL JUNGSEONG EU-EU
+1197	HANGUL JUNGSEONG YI-U
+1198	HANGUL JUNGSEONG I-A
+1199	HANGUL JUNGSEONG I-YA
+119A	HANGUL JUNGSEONG I-O
+119B	HANGUL JUNGSEONG I-U
+119C	HANGUL JUNGSEONG I-EU
+119D	HANGUL JUNGSEONG I-ARAEA
+119E	HANGUL JUNGSEONG ARAEA
+119F	HANGUL JUNGSEONG ARAEA-EO
+11A0	HANGUL JUNGSEONG ARAEA-U
+11A1	HANGUL JUNGSEONG ARAEA-I
+11A2	HANGUL JUNGSEONG SSANGARAEA
+11A8	HANGUL JONGSEONG KIYEOK
+11A9	HANGUL JONGSEONG SSANGKIYEOK
+11AA	HANGUL JONGSEONG KIYEOK-SIOS
+11AB	HANGUL JONGSEONG NIEUN
+11AC	HANGUL JONGSEONG NIEUN-CIEUC
+11AD	HANGUL JONGSEONG NIEUN-HIEUH
+11AE	HANGUL JONGSEONG TIKEUT
+11AF	HANGUL JONGSEONG RIEUL
+11B0	HANGUL JONGSEONG RIEUL-KIYEOK
+11B1	HANGUL JONGSEONG RIEUL-MIEUM
+11B2	HANGUL JONGSEONG RIEUL-PIEUP
+11B3	HANGUL JONGSEONG RIEUL-SIOS
+11B4	HANGUL JONGSEONG RIEUL-THIEUTH
+11B5	HANGUL JONGSEONG RIEUL-PHIEUPH
+11B6	HANGUL JONGSEONG RIEUL-HIEUH
+11B7	HANGUL JONGSEONG MIEUM
+11B8	HANGUL JONGSEONG PIEUP
+11B9	HANGUL JONGSEONG PIEUP-SIOS
+11BA	HANGUL JONGSEONG SIOS
+11BB	HANGUL JONGSEONG SSANGSIOS
+11BC	HANGUL JONGSEONG IEUNG
+11BD	HANGUL JONGSEONG CIEUC
+11BE	HANGUL JONGSEONG CHIEUCH
+11BF	HANGUL JONGSEONG KHIEUKH
+11C0	HANGUL JONGSEONG THIEUTH
+11C1	HANGUL JONGSEONG PHIEUPH
+11C2	HANGUL JONGSEONG HIEUH
+11C3	HANGUL JONGSEONG KIYEOK-RIEUL
+11C4	HANGUL JONGSEONG KIYEOK-SIOS-KIYEOK
+11C5	HANGUL JONGSEONG NIEUN-KIYEOK
+11C6	HANGUL JONGSEONG NIEUN-TIKEUT
+11C7	HANGUL JONGSEONG NIEUN-SIOS
+11C8	HANGUL JONGSEONG NIEUN-PANSIOS
+11C9	HANGUL JONGSEONG NIEUN-THIEUTH
+11CA	HANGUL JONGSEONG TIKEUT-KIYEOK
+11CB	HANGUL JONGSEONG TIKEUT-RIEUL
+11CC	HANGUL JONGSEONG RIEUL-KIYEOK-SIOS
+11CD	HANGUL JONGSEONG RIEUL-NIEUN
+11CE	HANGUL JONGSEONG RIEUL-TIKEUT
+11CF	HANGUL JONGSEONG RIEUL-TIKEUT-HIEUH
+11D0	HANGUL JONGSEONG SSANGRIEUL
+11D1	HANGUL JONGSEONG RIEUL-MIEUM-KIYEOK
+11D2	HANGUL JONGSEONG RIEUL-MIEUM-SIOS
+11D3	HANGUL JONGSEONG RIEUL-PIEUP-SIOS
+11D4	HANGUL JONGSEONG RIEUL-PIEUP-HIEUH
+11D5	HANGUL JONGSEONG RIEUL-KAPYEOUNPIEUP
+11D6	HANGUL JONGSEONG RIEUL-SSANGSIOS
+11D7	HANGUL JONGSEONG RIEUL-PANSIOS
+11D8	HANGUL JONGSEONG RIEUL-KHIEUKH
+11D9	HANGUL JONGSEONG RIEUL-YEORINHIEUH
+11DA	HANGUL JONGSEONG MIEUM-KIYEOK
+11DB	HANGUL JONGSEONG MIEUM-RIEUL
+11DC	HANGUL JONGSEONG MIEUM-PIEUP
+11DD	HANGUL JONGSEONG MIEUM-SIOS
+11DE	HANGUL JONGSEONG MIEUM-SSANGSIOS
+11DF	HANGUL JONGSEONG MIEUM-PANSIOS
+11E0	HANGUL JONGSEONG MIEUM-CHIEUCH
+11E1	HANGUL JONGSEONG MIEUM-HIEUH
+11E2	HANGUL JONGSEONG KAPYEOUNMIEUM
+11E3	HANGUL JONGSEONG PIEUP-RIEUL
+11E4	HANGUL JONGSEONG PIEUP-PHIEUPH
+11E5	HANGUL JONGSEONG PIEUP-HIEUH
+11E6	HANGUL JONGSEONG KAPYEOUNPIEUP
+11E7	HANGUL JONGSEONG SIOS-KIYEOK
+11E8	HANGUL JONGSEONG SIOS-TIKEUT
+11E9	HANGUL JONGSEONG SIOS-RIEUL
+11EA	HANGUL JONGSEONG SIOS-PIEUP
+11EB	HANGUL JONGSEONG PANSIOS
+11EC	HANGUL JONGSEONG IEUNG-KIYEOK
+11ED	HANGUL JONGSEONG IEUNG-SSANGKIYEOK
+11EE	HANGUL JONGSEONG SSANGIEUNG
+11EF	HANGUL JONGSEONG IEUNG-KHIEUKH
+11F0	HANGUL JONGSEONG YESIEUNG
+11F1	HANGUL JONGSEONG YESIEUNG-SIOS
+11F2	HANGUL JONGSEONG YESIEUNG-PANSIOS
+11F3	HANGUL JONGSEONG PHIEUPH-PIEUP
+11F4	HANGUL JONGSEONG KAPYEOUNPHIEUPH
+11F5	HANGUL JONGSEONG HIEUH-NIEUN
+11F6	HANGUL JONGSEONG HIEUH-RIEUL
+11F7	HANGUL JONGSEONG HIEUH-MIEUM
+11F8	HANGUL JONGSEONG HIEUH-PIEUP
+11F9	HANGUL JONGSEONG YEORINHIEUH
+1E00	LATIN CAPITAL LETTER A WITH RING BELOW
+1E01	LATIN SMALL LETTER A WITH RING BELOW
+1E02	LATIN CAPITAL LETTER B WITH DOT ABOVE
+1E03	LATIN SMALL LETTER B WITH DOT ABOVE
+1E04	LATIN CAPITAL LETTER B WITH DOT BELOW
+1E05	LATIN SMALL LETTER B WITH DOT BELOW
+1E06	LATIN CAPITAL LETTER B WITH LINE BELOW
+1E07	LATIN SMALL LETTER B WITH LINE BELOW
+1E08	LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE
+1E09	LATIN SMALL LETTER C WITH CEDILLA AND ACUTE
+1E0A	LATIN CAPITAL LETTER D WITH DOT ABOVE
+1E0B	LATIN SMALL LETTER D WITH DOT ABOVE
+1E0C	LATIN CAPITAL LETTER D WITH DOT BELOW
+1E0D	LATIN SMALL LETTER D WITH DOT BELOW
+1E0E	LATIN CAPITAL LETTER D WITH LINE BELOW
+1E0F	LATIN SMALL LETTER D WITH LINE BELOW
+1E10	LATIN CAPITAL LETTER D WITH CEDILLA
+1E11	LATIN SMALL LETTER D WITH CEDILLA
+1E12	LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW
+1E13	LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW
+1E14	LATIN CAPITAL LETTER E WITH MACRON AND GRAVE
+1E15	LATIN SMALL LETTER E WITH MACRON AND GRAVE
+1E16	LATIN CAPITAL LETTER E WITH MACRON AND ACUTE
+1E17	LATIN SMALL LETTER E WITH MACRON AND ACUTE
+1E18	LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW
+1E19	LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW
+1E1A	LATIN CAPITAL LETTER E WITH TILDE BELOW
+1E1B	LATIN SMALL LETTER E WITH TILDE BELOW
+1E1C	LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE
+1E1D	LATIN SMALL LETTER E WITH CEDILLA AND BREVE
+1E1E	LATIN CAPITAL LETTER F WITH DOT ABOVE
+1E1F	LATIN SMALL LETTER F WITH DOT ABOVE
+1E20	LATIN CAPITAL LETTER G WITH MACRON
+1E21	LATIN SMALL LETTER G WITH MACRON
+1E22	LATIN CAPITAL LETTER H WITH DOT ABOVE
+1E23	LATIN SMALL LETTER H WITH DOT ABOVE
+1E24	LATIN CAPITAL LETTER H WITH DOT BELOW
+1E25	LATIN SMALL LETTER H WITH DOT BELOW
+1E26	LATIN CAPITAL LETTER H WITH DIAERESIS
+1E27	LATIN SMALL LETTER H WITH DIAERESIS
+1E28	LATIN CAPITAL LETTER H WITH CEDILLA
+1E29	LATIN SMALL LETTER H WITH CEDILLA
+1E2A	LATIN CAPITAL LETTER H WITH BREVE BELOW
+1E2B	LATIN SMALL LETTER H WITH BREVE BELOW
+1E2C	LATIN CAPITAL LETTER I WITH TILDE BELOW
+1E2D	LATIN SMALL LETTER I WITH TILDE BELOW
+1E2E	LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE
+1E2F	LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE
+1E30	LATIN CAPITAL LETTER K WITH ACUTE
+1E31	LATIN SMALL LETTER K WITH ACUTE
+1E32	LATIN CAPITAL LETTER K WITH DOT BELOW
+1E33	LATIN SMALL LETTER K WITH DOT BELOW
+1E34	LATIN CAPITAL LETTER K WITH LINE BELOW
+1E35	LATIN SMALL LETTER K WITH LINE BELOW
+1E36	LATIN CAPITAL LETTER L WITH DOT BELOW
+1E37	LATIN SMALL LETTER L WITH DOT BELOW
+1E38	LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON
+1E39	LATIN SMALL LETTER L WITH DOT BELOW AND MACRON
+1E3A	LATIN CAPITAL LETTER L WITH LINE BELOW
+1E3B	LATIN SMALL LETTER L WITH LINE BELOW
+1E3C	LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW
+1E3D	LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW
+1E3E	LATIN CAPITAL LETTER M WITH ACUTE
+1E3F	LATIN SMALL LETTER M WITH ACUTE
+1E40	LATIN CAPITAL LETTER M WITH DOT ABOVE
+1E41	LATIN SMALL LETTER M WITH DOT ABOVE
+1E42	LATIN CAPITAL LETTER M WITH DOT BELOW
+1E43	LATIN SMALL LETTER M WITH DOT BELOW
+1E44	LATIN CAPITAL LETTER N WITH DOT ABOVE
+1E45	LATIN SMALL LETTER N WITH DOT ABOVE
+1E46	LATIN CAPITAL LETTER N WITH DOT BELOW
+1E47	LATIN SMALL LETTER N WITH DOT BELOW
+1E48	LATIN CAPITAL LETTER N WITH LINE BELOW
+1E49	LATIN SMALL LETTER N WITH LINE BELOW
+1E4A	LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW
+1E4B	LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW
+1E4C	LATIN CAPITAL LETTER O WITH TILDE AND ACUTE
+1E4D	LATIN SMALL LETTER O WITH TILDE AND ACUTE
+1E4E	LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS
+1E4F	LATIN SMALL LETTER O WITH TILDE AND DIAERESIS
+1E50	LATIN CAPITAL LETTER O WITH MACRON AND GRAVE
+1E51	LATIN SMALL LETTER O WITH MACRON AND GRAVE
+1E52	LATIN CAPITAL LETTER O WITH MACRON AND ACUTE
+1E53	LATIN SMALL LETTER O WITH MACRON AND ACUTE
+1E54	LATIN CAPITAL LETTER P WITH ACUTE
+1E55	LATIN SMALL LETTER P WITH ACUTE
+1E56	LATIN CAPITAL LETTER P WITH DOT ABOVE
+1E57	LATIN SMALL LETTER P WITH DOT ABOVE
+1E58	LATIN CAPITAL LETTER R WITH DOT ABOVE
+1E59	LATIN SMALL LETTER R WITH DOT ABOVE
+1E5A	LATIN CAPITAL LETTER R WITH DOT BELOW
+1E5B	LATIN SMALL LETTER R WITH DOT BELOW
+1E5C	LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON
+1E5D	LATIN SMALL LETTER R WITH DOT BELOW AND MACRON
+1E5E	LATIN CAPITAL LETTER R WITH LINE BELOW
+1E5F	LATIN SMALL LETTER R WITH LINE BELOW
+1E60	LATIN CAPITAL LETTER S WITH DOT ABOVE
+1E61	LATIN SMALL LETTER S WITH DOT ABOVE
+1E62	LATIN CAPITAL LETTER S WITH DOT BELOW
+1E63	LATIN SMALL LETTER S WITH DOT BELOW
+1E64	LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE
+1E65	LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE
+1E66	LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE
+1E67	LATIN SMALL LETTER S WITH CARON AND DOT ABOVE
+1E68	LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE
+1E69	LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE
+1E6A	LATIN CAPITAL LETTER T WITH DOT ABOVE
+1E6B	LATIN SMALL LETTER T WITH DOT ABOVE
+1E6C	LATIN CAPITAL LETTER T WITH DOT BELOW
+1E6D	LATIN SMALL LETTER T WITH DOT BELOW
+1E6E	LATIN CAPITAL LETTER T WITH LINE BELOW
+1E6F	LATIN SMALL LETTER T WITH LINE BELOW
+1E70	LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW
+1E71	LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW
+1E72	LATIN CAPITAL LETTER U WITH DIAERESIS BELOW
+1E73	LATIN SMALL LETTER U WITH DIAERESIS BELOW
+1E74	LATIN CAPITAL LETTER U WITH TILDE BELOW
+1E75	LATIN SMALL LETTER U WITH TILDE BELOW
+1E76	LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW
+1E77	LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW
+1E78	LATIN CAPITAL LETTER U WITH TILDE AND ACUTE
+1E79	LATIN SMALL LETTER U WITH TILDE AND ACUTE
+1E7A	LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS
+1E7B	LATIN SMALL LETTER U WITH MACRON AND DIAERESIS
+1E7C	LATIN CAPITAL LETTER V WITH TILDE
+1E7D	LATIN SMALL LETTER V WITH TILDE
+1E7E	LATIN CAPITAL LETTER V WITH DOT BELOW
+1E7F	LATIN SMALL LETTER V WITH DOT BELOW
+1E80	LATIN CAPITAL LETTER W WITH GRAVE
+1E81	LATIN SMALL LETTER W WITH GRAVE
+1E82	LATIN CAPITAL LETTER W WITH ACUTE
+1E83	LATIN SMALL LETTER W WITH ACUTE
+1E84	LATIN CAPITAL LETTER W WITH DIAERESIS
+1E85	LATIN SMALL LETTER W WITH DIAERESIS
+1E86	LATIN CAPITAL LETTER W WITH DOT ABOVE
+1E87	LATIN SMALL LETTER W WITH DOT ABOVE
+1E88	LATIN CAPITAL LETTER W WITH DOT BELOW
+1E89	LATIN SMALL LETTER W WITH DOT BELOW
+1E8A	LATIN CAPITAL LETTER X WITH DOT ABOVE
+1E8B	LATIN SMALL LETTER X WITH DOT ABOVE
+1E8C	LATIN CAPITAL LETTER X WITH DIAERESIS
+1E8D	LATIN SMALL LETTER X WITH DIAERESIS
+1E8E	LATIN CAPITAL LETTER Y WITH DOT ABOVE
+1E8F	LATIN SMALL LETTER Y WITH DOT ABOVE
+1E90	LATIN CAPITAL LETTER Z WITH CIRCUMFLEX
+1E91	LATIN SMALL LETTER Z WITH CIRCUMFLEX
+1E92	LATIN CAPITAL LETTER Z WITH DOT BELOW
+1E93	LATIN SMALL LETTER Z WITH DOT BELOW
+1E94	LATIN CAPITAL LETTER Z WITH LINE BELOW
+1E95	LATIN SMALL LETTER Z WITH LINE BELOW
+1E96	LATIN SMALL LETTER H WITH LINE BELOW
+1E97	LATIN SMALL LETTER T WITH DIAERESIS
+1E98	LATIN SMALL LETTER W WITH RING ABOVE
+1E99	LATIN SMALL LETTER Y WITH RING ABOVE
+1E9A	LATIN SMALL LETTER A WITH RIGHT HALF RING
+1E9B	LATIN SMALL LETTER LONG S WITH DOT ABOVE
+1EA0	LATIN CAPITAL LETTER A WITH DOT BELOW
+1EA1	LATIN SMALL LETTER A WITH DOT BELOW
+1EA2	LATIN CAPITAL LETTER A WITH HOOK ABOVE
+1EA3	LATIN SMALL LETTER A WITH HOOK ABOVE
+1EA4	LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE
+1EA5	LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE
+1EA6	LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE
+1EA7	LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE
+1EA8	LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE
+1EA9	LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE
+1EAA	LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE
+1EAB	LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE
+1EAC	LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW
+1EAD	LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW
+1EAE	LATIN CAPITAL LETTER A WITH BREVE AND ACUTE
+1EAF	LATIN SMALL LETTER A WITH BREVE AND ACUTE
+1EB0	LATIN CAPITAL LETTER A WITH BREVE AND GRAVE
+1EB1	LATIN SMALL LETTER A WITH BREVE AND GRAVE
+1EB2	LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE
+1EB3	LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE
+1EB4	LATIN CAPITAL LETTER A WITH BREVE AND TILDE
+1EB5	LATIN SMALL LETTER A WITH BREVE AND TILDE
+1EB6	LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW
+1EB7	LATIN SMALL LETTER A WITH BREVE AND DOT BELOW
+1EB8	LATIN CAPITAL LETTER E WITH DOT BELOW
+1EB9	LATIN SMALL LETTER E WITH DOT BELOW
+1EBA	LATIN CAPITAL LETTER E WITH HOOK ABOVE
+1EBB	LATIN SMALL LETTER E WITH HOOK ABOVE
+1EBC	LATIN CAPITAL LETTER E WITH TILDE
+1EBD	LATIN SMALL LETTER E WITH TILDE
+1EBE	LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE
+1EBF	LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE
+1EC0	LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE
+1EC1	LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE
+1EC2	LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE
+1EC3	LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE
+1EC4	LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE
+1EC5	LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE
+1EC6	LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW
+1EC7	LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW
+1EC8	LATIN CAPITAL LETTER I WITH HOOK ABOVE
+1EC9	LATIN SMALL LETTER I WITH HOOK ABOVE
+1ECA	LATIN CAPITAL LETTER I WITH DOT BELOW
+1ECB	LATIN SMALL LETTER I WITH DOT BELOW
+1ECC	LATIN CAPITAL LETTER O WITH DOT BELOW
+1ECD	LATIN SMALL LETTER O WITH DOT BELOW
+1ECE	LATIN CAPITAL LETTER O WITH HOOK ABOVE
+1ECF	LATIN SMALL LETTER O WITH HOOK ABOVE
+1ED0	LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE
+1ED1	LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE
+1ED2	LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE
+1ED3	LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE
+1ED4	LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE
+1ED5	LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE
+1ED6	LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE
+1ED7	LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE
+1ED8	LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW
+1ED9	LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW
+1EDA	LATIN CAPITAL LETTER O WITH HORN AND ACUTE
+1EDB	LATIN SMALL LETTER O WITH HORN AND ACUTE
+1EDC	LATIN CAPITAL LETTER O WITH HORN AND GRAVE
+1EDD	LATIN SMALL LETTER O WITH HORN AND GRAVE
+1EDE	LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE
+1EDF	LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE
+1EE0	LATIN CAPITAL LETTER O WITH HORN AND TILDE
+1EE1	LATIN SMALL LETTER O WITH HORN AND TILDE
+1EE2	LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW
+1EE3	LATIN SMALL LETTER O WITH HORN AND DOT BELOW
+1EE4	LATIN CAPITAL LETTER U WITH DOT BELOW
+1EE5	LATIN SMALL LETTER U WITH DOT BELOW
+1EE6	LATIN CAPITAL LETTER U WITH HOOK ABOVE
+1EE7	LATIN SMALL LETTER U WITH HOOK ABOVE
+1EE8	LATIN CAPITAL LETTER U WITH HORN AND ACUTE
+1EE9	LATIN SMALL LETTER U WITH HORN AND ACUTE
+1EEA	LATIN CAPITAL LETTER U WITH HORN AND GRAVE
+1EEB	LATIN SMALL LETTER U WITH HORN AND GRAVE
+1EEC	LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE
+1EED	LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE
+1EEE	LATIN CAPITAL LETTER U WITH HORN AND TILDE
+1EEF	LATIN SMALL LETTER U WITH HORN AND TILDE
+1EF0	LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW
+1EF1	LATIN SMALL LETTER U WITH HORN AND DOT BELOW
+1EF2	LATIN CAPITAL LETTER Y WITH GRAVE
+1EF3	LATIN SMALL LETTER Y WITH GRAVE
+1EF4	LATIN CAPITAL LETTER Y WITH DOT BELOW
+1EF5	LATIN SMALL LETTER Y WITH DOT BELOW
+1EF6	LATIN CAPITAL LETTER Y WITH HOOK ABOVE
+1EF7	LATIN SMALL LETTER Y WITH HOOK ABOVE
+1EF8	LATIN CAPITAL LETTER Y WITH TILDE
+1EF9	LATIN SMALL LETTER Y WITH TILDE
+1F00	GREEK SMALL LETTER ALPHA WITH PSILI
+1F01	GREEK SMALL LETTER ALPHA WITH DASIA
+1F02	GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA
+1F03	GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA
+1F04	GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA
+1F05	GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA
+1F06	GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI
+1F07	GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI
+1F08	GREEK CAPITAL LETTER ALPHA WITH PSILI
+1F09	GREEK CAPITAL LETTER ALPHA WITH DASIA
+1F0A	GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA
+1F0B	GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA
+1F0C	GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA
+1F0D	GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA
+1F0E	GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI
+1F0F	GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI
+1F10	GREEK SMALL LETTER EPSILON WITH PSILI
+1F11	GREEK SMALL LETTER EPSILON WITH DASIA
+1F12	GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA
+1F13	GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA
+1F14	GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA
+1F15	GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA
+1F18	GREEK CAPITAL LETTER EPSILON WITH PSILI
+1F19	GREEK CAPITAL LETTER EPSILON WITH DASIA
+1F1A	GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA
+1F1B	GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA
+1F1C	GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA
+1F1D	GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA
+1F20	GREEK SMALL LETTER ETA WITH PSILI
+1F21	GREEK SMALL LETTER ETA WITH DASIA
+1F22	GREEK SMALL LETTER ETA WITH PSILI AND VARIA
+1F23	GREEK SMALL LETTER ETA WITH DASIA AND VARIA
+1F24	GREEK SMALL LETTER ETA WITH PSILI AND OXIA
+1F25	GREEK SMALL LETTER ETA WITH DASIA AND OXIA
+1F26	GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI
+1F27	GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI
+1F28	GREEK CAPITAL LETTER ETA WITH PSILI
+1F29	GREEK CAPITAL LETTER ETA WITH DASIA
+1F2A	GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA
+1F2B	GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA
+1F2C	GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA
+1F2D	GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA
+1F2E	GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI
+1F2F	GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI
+1F30	GREEK SMALL LETTER IOTA WITH PSILI
+1F31	GREEK SMALL LETTER IOTA WITH DASIA
+1F32	GREEK SMALL LETTER IOTA WITH PSILI AND VARIA
+1F33	GREEK SMALL LETTER IOTA WITH DASIA AND VARIA
+1F34	GREEK SMALL LETTER IOTA WITH PSILI AND OXIA
+1F35	GREEK SMALL LETTER IOTA WITH DASIA AND OXIA
+1F36	GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI
+1F37	GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI
+1F38	GREEK CAPITAL LETTER IOTA WITH PSILI
+1F39	GREEK CAPITAL LETTER IOTA WITH DASIA
+1F3A	GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA
+1F3B	GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA
+1F3C	GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA
+1F3D	GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA
+1F3E	GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI
+1F3F	GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI
+1F40	GREEK SMALL LETTER OMICRON WITH PSILI
+1F41	GREEK SMALL LETTER OMICRON WITH DASIA
+1F42	GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA
+1F43	GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA
+1F44	GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA
+1F45	GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA
+1F48	GREEK CAPITAL LETTER OMICRON WITH PSILI
+1F49	GREEK CAPITAL LETTER OMICRON WITH DASIA
+1F4A	GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA
+1F4B	GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA
+1F4C	GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA
+1F4D	GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA
+1F50	GREEK SMALL LETTER UPSILON WITH PSILI
+1F51	GREEK SMALL LETTER UPSILON WITH DASIA
+1F52	GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA
+1F53	GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA
+1F54	GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA
+1F55	GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA
+1F56	GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI
+1F57	GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI
+1F59	GREEK CAPITAL LETTER UPSILON WITH DASIA
+1F5B	GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA
+1F5D	GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA
+1F5F	GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI
+1F60	GREEK SMALL LETTER OMEGA WITH PSILI
+1F61	GREEK SMALL LETTER OMEGA WITH DASIA
+1F62	GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA
+1F63	GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA
+1F64	GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA
+1F65	GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA
+1F66	GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI
+1F67	GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI
+1F68	GREEK CAPITAL LETTER OMEGA WITH PSILI
+1F69	GREEK CAPITAL LETTER OMEGA WITH DASIA
+1F6A	GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA
+1F6B	GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA
+1F6C	GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA
+1F6D	GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA
+1F6E	GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI
+1F6F	GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI
+1F70	GREEK SMALL LETTER ALPHA WITH VARIA
+1F71	GREEK SMALL LETTER ALPHA WITH OXIA
+1F72	GREEK SMALL LETTER EPSILON WITH VARIA
+1F73	GREEK SMALL LETTER EPSILON WITH OXIA
+1F74	GREEK SMALL LETTER ETA WITH VARIA
+1F75	GREEK SMALL LETTER ETA WITH OXIA
+1F76	GREEK SMALL LETTER IOTA WITH VARIA
+1F77	GREEK SMALL LETTER IOTA WITH OXIA
+1F78	GREEK SMALL LETTER OMICRON WITH VARIA
+1F79	GREEK SMALL LETTER OMICRON WITH OXIA
+1F7A	GREEK SMALL LETTER UPSILON WITH VARIA
+1F7B	GREEK SMALL LETTER UPSILON WITH OXIA
+1F7C	GREEK SMALL LETTER OMEGA WITH VARIA
+1F7D	GREEK SMALL LETTER OMEGA WITH OXIA
+1F80	GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI
+1F81	GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI
+1F82	GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI
+1F83	GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI
+1F84	GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI
+1F85	GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI
+1F86	GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI
+1F87	GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI
+1F88	GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI
+1F89	GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI
+1F8A	GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI
+1F8B	GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI
+1F8C	GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI
+1F8D	GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI
+1F8E	GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
+1F8F	GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
+1F90	GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI
+1F91	GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI
+1F92	GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI
+1F93	GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI
+1F94	GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI
+1F95	GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI
+1F96	GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI
+1F97	GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI
+1F98	GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI
+1F99	GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI
+1F9A	GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI
+1F9B	GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI
+1F9C	GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI
+1F9D	GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI
+1F9E	GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
+1F9F	GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
+1FA0	GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI
+1FA1	GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI
+1FA2	GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI
+1FA3	GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI
+1FA4	GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI
+1FA5	GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI
+1FA6	GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI
+1FA7	GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI
+1FA8	GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI
+1FA9	GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI
+1FAA	GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI
+1FAB	GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI
+1FAC	GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI
+1FAD	GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI
+1FAE	GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
+1FAF	GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
+1FB0	GREEK SMALL LETTER ALPHA WITH VRACHY
+1FB1	GREEK SMALL LETTER ALPHA WITH MACRON
+1FB2	GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI
+1FB3	GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI
+1FB4	GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI
+1FB6	GREEK SMALL LETTER ALPHA WITH PERISPOMENI
+1FB7	GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI
+1FB8	GREEK CAPITAL LETTER ALPHA WITH VRACHY
+1FB9	GREEK CAPITAL LETTER ALPHA WITH MACRON
+1FBA	GREEK CAPITAL LETTER ALPHA WITH VARIA
+1FBB	GREEK CAPITAL LETTER ALPHA WITH OXIA
+1FBC	GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI
+1FBD	GREEK KORONIS
+1FBE	GREEK PROSGEGRAMMENI
+1FBF	GREEK PSILI
+1FC0	GREEK PERISPOMENI
+1FC1	GREEK DIALYTIKA AND PERISPOMENI
+1FC2	GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI
+1FC3	GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI
+1FC4	GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI
+1FC6	GREEK SMALL LETTER ETA WITH PERISPOMENI
+1FC7	GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI
+1FC8	GREEK CAPITAL LETTER EPSILON WITH VARIA
+1FC9	GREEK CAPITAL LETTER EPSILON WITH OXIA
+1FCA	GREEK CAPITAL LETTER ETA WITH VARIA
+1FCB	GREEK CAPITAL LETTER ETA WITH OXIA
+1FCC	GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI
+1FCD	GREEK PSILI AND VARIA
+1FCE	GREEK PSILI AND OXIA
+1FCF	GREEK PSILI AND PERISPOMENI
+1FD0	GREEK SMALL LETTER IOTA WITH VRACHY
+1FD1	GREEK SMALL LETTER IOTA WITH MACRON
+1FD2	GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA
+1FD3	GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA
+1FD6	GREEK SMALL LETTER IOTA WITH PERISPOMENI
+1FD7	GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI
+1FD8	GREEK CAPITAL LETTER IOTA WITH VRACHY
+1FD9	GREEK CAPITAL LETTER IOTA WITH MACRON
+1FDA	GREEK CAPITAL LETTER IOTA WITH VARIA
+1FDB	GREEK CAPITAL LETTER IOTA WITH OXIA
+1FDD	GREEK DASIA AND VARIA
+1FDE	GREEK DASIA AND OXIA
+1FDF	GREEK DASIA AND PERISPOMENI
+1FE0	GREEK SMALL LETTER UPSILON WITH VRACHY
+1FE1	GREEK SMALL LETTER UPSILON WITH MACRON
+1FE2	GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA
+1FE3	GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA
+1FE4	GREEK SMALL LETTER RHO WITH PSILI
+1FE5	GREEK SMALL LETTER RHO WITH DASIA
+1FE6	GREEK SMALL LETTER UPSILON WITH PERISPOMENI
+1FE7	GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI
+1FE8	GREEK CAPITAL LETTER UPSILON WITH VRACHY
+1FE9	GREEK CAPITAL LETTER UPSILON WITH MACRON
+1FEA	GREEK CAPITAL LETTER UPSILON WITH VARIA
+1FEB	GREEK CAPITAL LETTER UPSILON WITH OXIA
+1FEC	GREEK CAPITAL LETTER RHO WITH DASIA
+1FED	GREEK DIALYTIKA AND VARIA
+1FEE	GREEK DIALYTIKA AND OXIA
+1FEF	GREEK VARIA
+1FF2	GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI
+1FF3	GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI
+1FF4	GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI
+1FF6	GREEK SMALL LETTER OMEGA WITH PERISPOMENI
+1FF7	GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI
+1FF8	GREEK CAPITAL LETTER OMICRON WITH VARIA
+1FF9	GREEK CAPITAL LETTER OMICRON WITH OXIA
+1FFA	GREEK CAPITAL LETTER OMEGA WITH VARIA
+1FFB	GREEK CAPITAL LETTER OMEGA WITH OXIA
+1FFC	GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI
+1FFD	GREEK OXIA
+1FFE	GREEK DASIA
+2000	EN QUAD
+2001	EM QUAD
+2002	EN SPACE
+2003	EM SPACE
+2004	THREE-PER-EM SPACE
+2005	FOUR-PER-EM SPACE
+2006	SIX-PER-EM SPACE
+2007	FIGURE SPACE
+2008	PUNCTUATION SPACE
+2009	THIN SPACE
+200A	HAIR SPACE
+200B	ZERO WIDTH SPACE
+200C	ZERO WIDTH NON-JOINER
+200D	ZERO WIDTH JOINER
+200E	LEFT-TO-RIGHT MARK
+200F	RIGHT-TO-LEFT MARK
+2010	HYPHEN
+2011	NON-BREAKING HYPHEN
+2012	FIGURE DASH
+2013	EN DASH
+2014	EM DASH
+2015	HORIZONTAL BAR
+2016	DOUBLE VERTICAL LINE
+2017	DOUBLE LOW LINE
+2018	LEFT SINGLE QUOTATION MARK
+2019	RIGHT SINGLE QUOTATION MARK
+201A	SINGLE LOW-9 QUOTATION MARK
+201B	SINGLE HIGH-REVERSED-9 QUOTATION MARK
+201C	LEFT DOUBLE QUOTATION MARK
+201D	RIGHT DOUBLE QUOTATION MARK
+201E	DOUBLE LOW-9 QUOTATION MARK
+201F	DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+2020	DAGGER
+2021	DOUBLE DAGGER
+2022	BULLET
+2023	TRIANGULAR BULLET
+2024	ONE DOT LEADER
+2025	TWO DOT LEADER
+2026	HORIZONTAL ELLIPSIS
+2027	HYPHENATION POINT
+2028	LINE SEPARATOR
+2029	PARAGRAPH SEPARATOR
+202A	LEFT-TO-RIGHT EMBEDDING
+202B	RIGHT-TO-LEFT EMBEDDING
+202C	POP DIRECTIONAL FORMATTING
+202D	LEFT-TO-RIGHT OVERRIDE
+202E	RIGHT-TO-LEFT OVERRIDE
+2030	PER MILLE SIGN
+2031	PER TEN THOUSAND SIGN
+2032	PRIME
+2033	DOUBLE PRIME
+2034	TRIPLE PRIME
+2035	REVERSED PRIME
+2036	REVERSED DOUBLE PRIME
+2037	REVERSED TRIPLE PRIME
+2038	CARET
+2039	SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+203A	SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+203B	REFERENCE MARK
+203C	DOUBLE EXCLAMATION MARK
+203D	INTERROBANG
+203E	OVERLINE
+203F	UNDERTIE
+2040	CHARACTER TIE
+2041	CARET INSERTION POINT
+2042	ASTERISM
+2043	HYPHEN BULLET
+2044	FRACTION SLASH
+2045	LEFT SQUARE BRACKET WITH QUILL
+2046	RIGHT SQUARE BRACKET WITH QUILL
+206A	INHIBIT SYMMETRIC SWAPPING
+206B	ACTIVATE SYMMETRIC SWAPPING
+206C	INHIBIT ARABIC FORM SHAPING
+206D	ACTIVATE ARABIC FORM SHAPING
+206E	NATIONAL DIGIT SHAPES
+206F	NOMINAL DIGIT SHAPES
+2070	SUPERSCRIPT ZERO
+2074	SUPERSCRIPT FOUR
+2075	SUPERSCRIPT FIVE
+2076	SUPERSCRIPT SIX
+2077	SUPERSCRIPT SEVEN
+2078	SUPERSCRIPT EIGHT
+2079	SUPERSCRIPT NINE
+207A	SUPERSCRIPT PLUS SIGN
+207B	SUPERSCRIPT MINUS
+207C	SUPERSCRIPT EQUALS SIGN
+207D	SUPERSCRIPT LEFT PARENTHESIS
+207E	SUPERSCRIPT RIGHT PARENTHESIS
+207F	SUPERSCRIPT LATIN SMALL LETTER N
+2080	SUBSCRIPT ZERO
+2081	SUBSCRIPT ONE
+2082	SUBSCRIPT TWO
+2083	SUBSCRIPT THREE
+2084	SUBSCRIPT FOUR
+2085	SUBSCRIPT FIVE
+2086	SUBSCRIPT SIX
+2087	SUBSCRIPT SEVEN
+2088	SUBSCRIPT EIGHT
+2089	SUBSCRIPT NINE
+208A	SUBSCRIPT PLUS SIGN
+208B	SUBSCRIPT MINUS
+208C	SUBSCRIPT EQUALS SIGN
+208D	SUBSCRIPT LEFT PARENTHESIS
+208E	SUBSCRIPT RIGHT PARENTHESIS
+20A0	EURO-CURRENCY SIGN
+20A1	COLON SIGN
+20A2	CRUZEIRO SIGN
+20A3	FRENCH FRANC SIGN
+20A4	LIRA SIGN
+20A5	MILL SIGN
+20A6	NAIRA SIGN
+20A7	PESETA SIGN
+20A8	RUPEE SIGN
+20A9	WON SIGN
+20AA	NEW SHEQEL SIGN
+20AB	DONG SIGN
+20AC	EURO SIGN
+20D0	COMBINING LEFT HARPOON ABOVE
+20D1	COMBINING RIGHT HARPOON ABOVE
+20D2	COMBINING LONG VERTICAL LINE OVERLAY
+20D3	COMBINING SHORT VERTICAL LINE OVERLAY
+20D4	COMBINING ANTICLOCKWISE ARROW ABOVE
+20D5	COMBINING CLOCKWISE ARROW ABOVE
+20D6	COMBINING LEFT ARROW ABOVE
+20D7	COMBINING RIGHT ARROW ABOVE
+20D8	COMBINING RING OVERLAY
+20D9	COMBINING CLOCKWISE RING OVERLAY
+20DA	COMBINING ANTICLOCKWISE RING OVERLAY
+20DB	COMBINING THREE DOTS ABOVE
+20DC	COMBINING FOUR DOTS ABOVE
+20DD	COMBINING ENCLOSING CIRCLE
+20DE	COMBINING ENCLOSING SQUARE
+20DF	COMBINING ENCLOSING DIAMOND
+20E0	COMBINING ENCLOSING CIRCLE BACKSLASH
+20E1	COMBINING LEFT RIGHT ARROW ABOVE
+2100	ACCOUNT OF
+2101	ADDRESSED TO THE SUBJECT
+2102	DOUBLE-STRUCK CAPITAL C
+2103	DEGREE CELSIUS
+2104	CENTRE LINE SYMBOL
+2105	CARE OF
+2106	CADA UNA
+2107	EULER CONSTANT
+2108	SCRUPLE
+2109	DEGREE FAHRENHEIT
+210A	SCRIPT SMALL G
+210B	SCRIPT CAPITAL H
+210C	BLACK-LETTER CAPITAL H
+210D	DOUBLE-STRUCK CAPITAL H
+210E	PLANCK CONSTANT
+210F	PLANCK CONSTANT OVER TWO PI
+2110	SCRIPT CAPITAL I
+2111	BLACK-LETTER CAPITAL I
+2112	SCRIPT CAPITAL L
+2113	SCRIPT SMALL L
+2114	L B BAR SYMBOL
+2115	DOUBLE-STRUCK CAPITAL N
+2116	NUMERO SIGN
+2117	SOUND RECORDING COPYRIGHT
+2118	SCRIPT CAPITAL P
+2119	DOUBLE-STRUCK CAPITAL P
+211A	DOUBLE-STRUCK CAPITAL Q
+211B	SCRIPT CAPITAL R
+211C	BLACK-LETTER CAPITAL R
+211D	DOUBLE-STRUCK CAPITAL R
+211E	PRESCRIPTION TAKE
+211F	RESPONSE
+2120	SERVICE MARK
+2121	TELEPHONE SIGN
+2122	TRADE MARK SIGN
+2123	VERSICLE
+2124	DOUBLE-STRUCK CAPITAL Z
+2125	OUNCE SIGN
+2126	OHM SIGN
+2127	INVERTED OHM SIGN
+2128	BLACK-LETTER CAPITAL Z
+2129	TURNED GREEK SMALL LETTER IOTA
+212A	KELVIN SIGN
+212B	ANGSTROM SIGN
+212C	SCRIPT CAPITAL B
+212D	BLACK-LETTER CAPITAL C
+212E	ESTIMATED SYMBOL
+212F	SCRIPT SMALL E
+2130	SCRIPT CAPITAL E
+2131	SCRIPT CAPITAL F
+2132	TURNED CAPITAL F
+2133	SCRIPT CAPITAL M
+2134	SCRIPT SMALL O
+2135	ALEF SYMBOL
+2136	BET SYMBOL
+2137	GIMEL SYMBOL
+2138	DALET SYMBOL
+2153	VULGAR FRACTION ONE THIRD
+2154	VULGAR FRACTION TWO THIRDS
+2155	VULGAR FRACTION ONE FIFTH
+2156	VULGAR FRACTION TWO FIFTHS
+2157	VULGAR FRACTION THREE FIFTHS
+2158	VULGAR FRACTION FOUR FIFTHS
+2159	VULGAR FRACTION ONE SIXTH
+215A	VULGAR FRACTION FIVE SIXTHS
+215B	VULGAR FRACTION ONE EIGHTH
+215C	VULGAR FRACTION THREE EIGHTHS
+215D	VULGAR FRACTION FIVE EIGHTHS
+215E	VULGAR FRACTION SEVEN EIGHTHS
+215F	FRACTION NUMERATOR ONE
+2160	ROMAN NUMERAL ONE
+2161	ROMAN NUMERAL TWO
+2162	ROMAN NUMERAL THREE
+2163	ROMAN NUMERAL FOUR
+2164	ROMAN NUMERAL FIVE
+2165	ROMAN NUMERAL SIX
+2166	ROMAN NUMERAL SEVEN
+2167	ROMAN NUMERAL EIGHT
+2168	ROMAN NUMERAL NINE
+2169	ROMAN NUMERAL TEN
+216A	ROMAN NUMERAL ELEVEN
+216B	ROMAN NUMERAL TWELVE
+216C	ROMAN NUMERAL FIFTY
+216D	ROMAN NUMERAL ONE HUNDRED
+216E	ROMAN NUMERAL FIVE HUNDRED
+216F	ROMAN NUMERAL ONE THOUSAND
+2170	SMALL ROMAN NUMERAL ONE
+2171	SMALL ROMAN NUMERAL TWO
+2172	SMALL ROMAN NUMERAL THREE
+2173	SMALL ROMAN NUMERAL FOUR
+2174	SMALL ROMAN NUMERAL FIVE
+2175	SMALL ROMAN NUMERAL SIX
+2176	SMALL ROMAN NUMERAL SEVEN
+2177	SMALL ROMAN NUMERAL EIGHT
+2178	SMALL ROMAN NUMERAL NINE
+2179	SMALL ROMAN NUMERAL TEN
+217A	SMALL ROMAN NUMERAL ELEVEN
+217B	SMALL ROMAN NUMERAL TWELVE
+217C	SMALL ROMAN NUMERAL FIFTY
+217D	SMALL ROMAN NUMERAL ONE HUNDRED
+217E	SMALL ROMAN NUMERAL FIVE HUNDRED
+217F	SMALL ROMAN NUMERAL ONE THOUSAND
+2180	ROMAN NUMERAL ONE THOUSAND C D
+2181	ROMAN NUMERAL FIVE THOUSAND
+2182	ROMAN NUMERAL TEN THOUSAND
+2190	LEFTWARDS ARROW
+2191	UPWARDS ARROW
+2192	RIGHTWARDS ARROW
+2193	DOWNWARDS ARROW
+2194	LEFT RIGHT ARROW
+2195	UP DOWN ARROW
+2196	NORTH WEST ARROW
+2197	NORTH EAST ARROW
+2198	SOUTH EAST ARROW
+2199	SOUTH WEST ARROW
+219A	LEFTWARDS ARROW WITH STROKE
+219B	RIGHTWARDS ARROW WITH STROKE
+219C	LEFTWARDS WAVE ARROW
+219D	RIGHTWARDS WAVE ARROW
+219E	LEFTWARDS TWO HEADED ARROW
+219F	UPWARDS TWO HEADED ARROW
+21A0	RIGHTWARDS TWO HEADED ARROW
+21A1	DOWNWARDS TWO HEADED ARROW
+21A2	LEFTWARDS ARROW WITH TAIL
+21A3	RIGHTWARDS ARROW WITH TAIL
+21A4	LEFTWARDS ARROW FROM BAR
+21A5	UPWARDS ARROW FROM BAR
+21A6	RIGHTWARDS ARROW FROM BAR
+21A7	DOWNWARDS ARROW FROM BAR
+21A8	UP DOWN ARROW WITH BASE
+21A9	LEFTWARDS ARROW WITH HOOK
+21AA	RIGHTWARDS ARROW WITH HOOK
+21AB	LEFTWARDS ARROW WITH LOOP
+21AC	RIGHTWARDS ARROW WITH LOOP
+21AD	LEFT RIGHT WAVE ARROW
+21AE	LEFT RIGHT ARROW WITH STROKE
+21AF	DOWNWARDS ZIGZAG ARROW
+21B0	UPWARDS ARROW WITH TIP LEFTWARDS
+21B1	UPWARDS ARROW WITH TIP RIGHTWARDS
+21B2	DOWNWARDS ARROW WITH TIP LEFTWARDS
+21B3	DOWNWARDS ARROW WITH TIP RIGHTWARDS
+21B4	RIGHTWARDS ARROW WITH CORNER DOWNWARDS
+21B5	DOWNWARDS ARROW WITH CORNER LEFTWARDS
+21B6	ANTICLOCKWISE TOP SEMICIRCLE ARROW
+21B7	CLOCKWISE TOP SEMICIRCLE ARROW
+21B8	NORTH WEST ARROW TO LONG BAR
+21B9	LEFTWARDS ARROW TO BAR OVER RIGHTWARDS ARROW TO BAR
+21BA	ANTICLOCKWISE OPEN CIRCLE ARROW
+21BB	CLOCKWISE OPEN CIRCLE ARROW
+21BC	LEFTWARDS HARPOON WITH BARB UPWARDS
+21BD	LEFTWARDS HARPOON WITH BARB DOWNWARDS
+21BE	UPWARDS HARPOON WITH BARB RIGHTWARDS
+21BF	UPWARDS HARPOON WITH BARB LEFTWARDS
+21C0	RIGHTWARDS HARPOON WITH BARB UPWARDS
+21C1	RIGHTWARDS HARPOON WITH BARB DOWNWARDS
+21C2	DOWNWARDS HARPOON WITH BARB RIGHTWARDS
+21C3	DOWNWARDS HARPOON WITH BARB LEFTWARDS
+21C4	RIGHTWARDS ARROW OVER LEFTWARDS ARROW
+21C5	UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW
+21C6	LEFTWARDS ARROW OVER RIGHTWARDS ARROW
+21C7	LEFTWARDS PAIRED ARROWS
+21C8	UPWARDS PAIRED ARROWS
+21C9	RIGHTWARDS PAIRED ARROWS
+21CA	DOWNWARDS PAIRED ARROWS
+21CB	LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON
+21CC	RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON
+21CD	LEFTWARDS DOUBLE ARROW WITH STROKE
+21CE	LEFT RIGHT DOUBLE ARROW WITH STROKE
+21CF	RIGHTWARDS DOUBLE ARROW WITH STROKE
+21D0	LEFTWARDS DOUBLE ARROW
+21D1	UPWARDS DOUBLE ARROW
+21D2	RIGHTWARDS DOUBLE ARROW
+21D3	DOWNWARDS DOUBLE ARROW
+21D4	LEFT RIGHT DOUBLE ARROW
+21D5	UP DOWN DOUBLE ARROW
+21D6	NORTH WEST DOUBLE ARROW
+21D7	NORTH EAST DOUBLE ARROW
+21D8	SOUTH EAST DOUBLE ARROW
+21D9	SOUTH WEST DOUBLE ARROW
+21DA	LEFTWARDS TRIPLE ARROW
+21DB	RIGHTWARDS TRIPLE ARROW
+21DC	LEFTWARDS SQUIGGLE ARROW
+21DD	RIGHTWARDS SQUIGGLE ARROW
+21DE	UPWARDS ARROW WITH DOUBLE STROKE
+21DF	DOWNWARDS ARROW WITH DOUBLE STROKE
+21E0	LEFTWARDS DASHED ARROW
+21E1	UPWARDS DASHED ARROW
+21E2	RIGHTWARDS DASHED ARROW
+21E3	DOWNWARDS DASHED ARROW
+21E4	LEFTWARDS ARROW TO BAR
+21E5	RIGHTWARDS ARROW TO BAR
+21E6	LEFTWARDS WHITE ARROW
+21E7	UPWARDS WHITE ARROW
+21E8	RIGHTWARDS WHITE ARROW
+21E9	DOWNWARDS WHITE ARROW
+21EA	UPWARDS WHITE ARROW FROM BAR
+2200	FOR ALL
+2201	COMPLEMENT
+2202	PARTIAL DIFFERENTIAL
+2203	THERE EXISTS
+2204	THERE DOES NOT EXIST
+2205	EMPTY SET
+2206	INCREMENT
+2207	NABLA
+2208	ELEMENT OF
+2209	NOT AN ELEMENT OF
+220A	SMALL ELEMENT OF
+220B	CONTAINS AS MEMBER
+220C	DOES NOT CONTAIN AS MEMBER
+220D	SMALL CONTAINS AS MEMBER
+220E	END OF PROOF
+220F	N-ARY PRODUCT
+2210	N-ARY COPRODUCT
+2211	N-ARY SUMMATION
+2212	MINUS SIGN
+2213	MINUS-OR-PLUS SIGN
+2214	DOT PLUS
+2215	DIVISION SLASH
+2216	SET MINUS
+2217	ASTERISK OPERATOR
+2218	RING OPERATOR
+2219	BULLET OPERATOR
+221A	SQUARE ROOT
+221B	CUBE ROOT
+221C	FOURTH ROOT
+221D	PROPORTIONAL TO
+221E	INFINITY
+221F	RIGHT ANGLE
+2220	ANGLE
+2221	MEASURED ANGLE
+2222	SPHERICAL ANGLE
+2223	DIVIDES
+2224	DOES NOT DIVIDE
+2225	PARALLEL TO
+2226	NOT PARALLEL TO
+2227	LOGICAL AND
+2228	LOGICAL OR
+2229	INTERSECTION
+222A	UNION
+222B	INTEGRAL
+222C	DOUBLE INTEGRAL
+222D	TRIPLE INTEGRAL
+222E	CONTOUR INTEGRAL
+222F	SURFACE INTEGRAL
+2230	VOLUME INTEGRAL
+2231	CLOCKWISE INTEGRAL
+2232	CLOCKWISE CONTOUR INTEGRAL
+2233	ANTICLOCKWISE CONTOUR INTEGRAL
+2234	THEREFORE
+2235	BECAUSE
+2236	RATIO
+2237	PROPORTION
+2238	DOT MINUS
+2239	EXCESS
+223A	GEOMETRIC PROPORTION
+223B	HOMOTHETIC
+223C	TILDE OPERATOR
+223D	REVERSED TILDE
+223E	INVERTED LAZY S
+223F	SINE WAVE
+2240	WREATH PRODUCT
+2241	NOT TILDE
+2242	MINUS TILDE
+2243	ASYMPTOTICALLY EQUAL TO
+2244	NOT ASYMPTOTICALLY EQUAL TO
+2245	APPROXIMATELY EQUAL TO
+2246	APPROXIMATELY BUT NOT ACTUALLY EQUAL TO
+2247	NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO
+2248	ALMOST EQUAL TO
+2249	NOT ALMOST EQUAL TO
+224A	ALMOST EQUAL OR EQUAL TO
+224B	TRIPLE TILDE
+224C	ALL EQUAL TO
+224D	EQUIVALENT TO
+224E	GEOMETRICALLY EQUIVALENT TO
+224F	DIFFERENCE BETWEEN
+2250	APPROACHES THE LIMIT
+2251	GEOMETRICALLY EQUAL TO
+2252	APPROXIMATELY EQUAL TO OR THE IMAGE OF
+2253	IMAGE OF OR APPROXIMATELY EQUAL TO
+2254	COLON EQUALS
+2255	EQUALS COLON
+2256	RING IN EQUAL TO
+2257	RING EQUAL TO
+2258	CORRESPONDS TO
+2259	ESTIMATES
+225A	EQUIANGULAR TO
+225B	STAR EQUALS
+225C	DELTA EQUAL TO
+225D	EQUAL TO BY DEFINITION
+225E	MEASURED BY
+225F	QUESTIONED EQUAL TO
+2260	NOT EQUAL TO
+2261	IDENTICAL TO
+2262	NOT IDENTICAL TO
+2263	STRICTLY EQUIVALENT TO
+2264	LESS-THAN OR EQUAL TO
+2265	GREATER-THAN OR EQUAL TO
+2266	LESS-THAN OVER EQUAL TO
+2267	GREATER-THAN OVER EQUAL TO
+2268	LESS-THAN BUT NOT EQUAL TO
+2269	GREATER-THAN BUT NOT EQUAL TO
+226A	MUCH LESS-THAN
+226B	MUCH GREATER-THAN
+226C	BETWEEN
+226D	NOT EQUIVALENT TO
+226E	NOT LESS-THAN
+226F	NOT GREATER-THAN
+2270	NEITHER LESS-THAN NOR EQUAL TO
+2271	NEITHER GREATER-THAN NOR EQUAL TO
+2272	LESS-THAN OR EQUIVALENT TO
+2273	GREATER-THAN OR EQUIVALENT TO
+2274	NEITHER LESS-THAN NOR EQUIVALENT TO
+2275	NEITHER GREATER-THAN NOR EQUIVALENT TO
+2276	LESS-THAN OR GREATER-THAN
+2277	GREATER-THAN OR LESS-THAN
+2278	NEITHER LESS-THAN NOR GREATER-THAN
+2279	NEITHER GREATER-THAN NOR LESS-THAN
+227A	PRECEDES
+227B	SUCCEEDS
+227C	PRECEDES OR EQUAL TO
+227D	SUCCEEDS OR EQUAL TO
+227E	PRECEDES OR EQUIVALENT TO
+227F	SUCCEEDS OR EQUIVALENT TO
+2280	DOES NOT PRECEDE
+2281	DOES NOT SUCCEED
+2282	SUBSET OF
+2283	SUPERSET OF
+2284	NOT A SUBSET OF
+2285	NOT A SUPERSET OF
+2286	SUBSET OF OR EQUAL TO
+2287	SUPERSET OF OR EQUAL TO
+2288	NEITHER A SUBSET OF NOR EQUAL TO
+2289	NEITHER A SUPERSET OF NOR EQUAL TO
+228A	SUBSET OF WITH NOT EQUAL TO
+228B	SUPERSET OF WITH NOT EQUAL TO
+228C	MULTISET
+228D	MULTISET MULTIPLICATION
+228E	MULTISET UNION
+228F	SQUARE IMAGE OF
+2290	SQUARE ORIGINAL OF
+2291	SQUARE IMAGE OF OR EQUAL TO
+2292	SQUARE ORIGINAL OF OR EQUAL TO
+2293	SQUARE CAP
+2294	SQUARE CUP
+2295	CIRCLED PLUS
+2296	CIRCLED MINUS
+2297	CIRCLED TIMES
+2298	CIRCLED DIVISION SLASH
+2299	CIRCLED DOT OPERATOR
+229A	CIRCLED RING OPERATOR
+229B	CIRCLED ASTERISK OPERATOR
+229C	CIRCLED EQUALS
+229D	CIRCLED DASH
+229E	SQUARED PLUS
+229F	SQUARED MINUS
+22A0	SQUARED TIMES
+22A1	SQUARED DOT OPERATOR
+22A2	RIGHT TACK
+22A3	LEFT TACK
+22A4	DOWN TACK
+22A5	UP TACK
+22A6	ASSERTION
+22A7	MODELS
+22A8	TRUE
+22A9	FORCES
+22AA	TRIPLE VERTICAL BAR RIGHT TURNSTILE
+22AB	DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE
+22AC	DOES NOT PROVE
+22AD	NOT TRUE
+22AE	DOES NOT FORCE
+22AF	NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE
+22B0	PRECEDES UNDER RELATION
+22B1	SUCCEEDS UNDER RELATION
+22B2	NORMAL SUBGROUP OF
+22B3	CONTAINS AS NORMAL SUBGROUP
+22B4	NORMAL SUBGROUP OF OR EQUAL TO
+22B5	CONTAINS AS NORMAL SUBGROUP OR EQUAL TO
+22B6	ORIGINAL OF
+22B7	IMAGE OF
+22B8	MULTIMAP
+22B9	HERMITIAN CONJUGATE MATRIX
+22BA	INTERCALATE
+22BB	XOR
+22BC	NAND
+22BD	NOR
+22BE	RIGHT ANGLE WITH ARC
+22BF	RIGHT TRIANGLE
+22C0	N-ARY LOGICAL AND
+22C1	N-ARY LOGICAL OR
+22C2	N-ARY INTERSECTION
+22C3	N-ARY UNION
+22C4	DIAMOND OPERATOR
+22C5	DOT OPERATOR
+22C6	STAR OPERATOR
+22C7	DIVISION TIMES
+22C8	BOWTIE
+22C9	LEFT NORMAL FACTOR SEMIDIRECT PRODUCT
+22CA	RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT
+22CB	LEFT SEMIDIRECT PRODUCT
+22CC	RIGHT SEMIDIRECT PRODUCT
+22CD	REVERSED TILDE EQUALS
+22CE	CURLY LOGICAL OR
+22CF	CURLY LOGICAL AND
+22D0	DOUBLE SUBSET
+22D1	DOUBLE SUPERSET
+22D2	DOUBLE INTERSECTION
+22D3	DOUBLE UNION
+22D4	PITCHFORK
+22D5	EQUAL AND PARALLEL TO
+22D6	LESS-THAN WITH DOT
+22D7	GREATER-THAN WITH DOT
+22D8	VERY MUCH LESS-THAN
+22D9	VERY MUCH GREATER-THAN
+22DA	LESS-THAN EQUAL TO OR GREATER-THAN
+22DB	GREATER-THAN EQUAL TO OR LESS-THAN
+22DC	EQUAL TO OR LESS-THAN
+22DD	EQUAL TO OR GREATER-THAN
+22DE	EQUAL TO OR PRECEDES
+22DF	EQUAL TO OR SUCCEEDS
+22E0	DOES NOT PRECEDE OR EQUAL
+22E1	DOES NOT SUCCEED OR EQUAL
+22E2	NOT SQUARE IMAGE OF OR EQUAL TO
+22E3	NOT SQUARE ORIGINAL OF OR EQUAL TO
+22E4	SQUARE IMAGE OF OR NOT EQUAL TO
+22E5	SQUARE ORIGINAL OF OR NOT EQUAL TO
+22E6	LESS-THAN BUT NOT EQUIVALENT TO
+22E7	GREATER-THAN BUT NOT EQUIVALENT TO
+22E8	PRECEDES BUT NOT EQUIVALENT TO
+22E9	SUCCEEDS BUT NOT EQUIVALENT TO
+22EA	NOT NORMAL SUBGROUP OF
+22EB	DOES NOT CONTAIN AS NORMAL SUBGROUP
+22EC	NOT NORMAL SUBGROUP OF OR EQUAL TO
+22ED	DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL
+22EE	VERTICAL ELLIPSIS
+22EF	MIDLINE HORIZONTAL ELLIPSIS
+22F0	UP RIGHT DIAGONAL ELLIPSIS
+22F1	DOWN RIGHT DIAGONAL ELLIPSIS
+2300	DIAMETER SIGN
+2302	HOUSE
+2303	UP ARROWHEAD
+2304	DOWN ARROWHEAD
+2305	PROJECTIVE
+2306	PERSPECTIVE
+2307	WAVY LINE
+2308	LEFT CEILING
+2309	RIGHT CEILING
+230A	LEFT FLOOR
+230B	RIGHT FLOOR
+230C	BOTTOM RIGHT CROP
+230D	BOTTOM LEFT CROP
+230E	TOP RIGHT CROP
+230F	TOP LEFT CROP
+2310	REVERSED NOT SIGN
+2311	SQUARE LOZENGE
+2312	ARC
+2313	SEGMENT
+2314	SECTOR
+2315	TELEPHONE RECORDER
+2316	POSITION INDICATOR
+2317	VIEWDATA SQUARE
+2318	PLACE OF INTEREST SIGN
+2319	TURNED NOT SIGN
+231A	WATCH
+231B	HOURGLASS
+231C	TOP LEFT CORNER
+231D	TOP RIGHT CORNER
+231E	BOTTOM LEFT CORNER
+231F	BOTTOM RIGHT CORNER
+2320	TOP HALF INTEGRAL
+2321	BOTTOM HALF INTEGRAL
+2322	FROWN
+2323	SMILE
+2324	UP ARROWHEAD BETWEEN TWO HORIZONTAL BARS
+2325	OPTION KEY
+2326	ERASE TO THE RIGHT
+2327	X IN A RECTANGLE BOX
+2328	KEYBOARD
+2329	LEFT-POINTING ANGLE BRACKET
+232A	RIGHT-POINTING ANGLE BRACKET
+232B	ERASE TO THE LEFT
+232C	BENZENE RING
+232D	CYLINDRICITY
+232E	ALL AROUND-PROFILE
+232F	SYMMETRY
+2330	TOTAL RUNOUT
+2331	DIMENSION ORIGIN
+2332	CONICAL TAPER
+2333	SLOPE
+2334	COUNTERBORE
+2335	COUNTERSINK
+2336	APL FUNCTIONAL SYMBOL I-BEAM
+2337	APL FUNCTIONAL SYMBOL SQUISH QUAD
+2338	APL FUNCTIONAL SYMBOL QUAD EQUAL
+2339	APL FUNCTIONAL SYMBOL QUAD DIVIDE
+233A	APL FUNCTIONAL SYMBOL QUAD DIAMOND
+233B	APL FUNCTIONAL SYMBOL QUAD JOT
+233C	APL FUNCTIONAL SYMBOL QUAD CIRCLE
+233D	APL FUNCTIONAL SYMBOL CIRCLE STILE
+233E	APL FUNCTIONAL SYMBOL CIRCLE JOT
+233F	APL FUNCTIONAL SYMBOL SLASH BAR
+2340	APL FUNCTIONAL SYMBOL BACKSLASH BAR
+2341	APL FUNCTIONAL SYMBOL QUAD SLASH
+2342	APL FUNCTIONAL SYMBOL QUAD BACKSLASH
+2343	APL FUNCTIONAL SYMBOL QUAD LESS-THAN
+2344	APL FUNCTIONAL SYMBOL QUAD GREATER-THAN
+2345	APL FUNCTIONAL SYMBOL LEFTWARDS VANE
+2346	APL FUNCTIONAL SYMBOL RIGHTWARDS VANE
+2347	APL FUNCTIONAL SYMBOL QUAD LEFTWARDS ARROW
+2348	APL FUNCTIONAL SYMBOL QUAD RIGHTWARDS ARROW
+2349	APL FUNCTIONAL SYMBOL CIRCLE BACKSLASH
+234A	APL FUNCTIONAL SYMBOL DOWN TACK UNDERBAR
+234B	APL FUNCTIONAL SYMBOL DELTA STILE
+234C	APL FUNCTIONAL SYMBOL QUAD DOWN CARET
+234D	APL FUNCTIONAL SYMBOL QUAD DELTA
+234E	APL FUNCTIONAL SYMBOL DOWN TACK JOT
+234F	APL FUNCTIONAL SYMBOL UPWARDS VANE
+2350	APL FUNCTIONAL SYMBOL QUAD UPWARDS ARROW
+2351	APL FUNCTIONAL SYMBOL UP TACK OVERBAR
+2352	APL FUNCTIONAL SYMBOL DEL STILE
+2353	APL FUNCTIONAL SYMBOL QUAD UP CARET
+2354	APL FUNCTIONAL SYMBOL QUAD DEL
+2355	APL FUNCTIONAL SYMBOL UP TACK JOT
+2356	APL FUNCTIONAL SYMBOL DOWNWARDS VANE
+2357	APL FUNCTIONAL SYMBOL QUAD DOWNWARDS ARROW
+2358	APL FUNCTIONAL SYMBOL QUOTE UNDERBAR
+2359	APL FUNCTIONAL SYMBOL DELTA UNDERBAR
+235A	APL FUNCTIONAL SYMBOL DIAMOND UNDERBAR
+235B	APL FUNCTIONAL SYMBOL JOT UNDERBAR
+235C	APL FUNCTIONAL SYMBOL CIRCLE UNDERBAR
+235D	APL FUNCTIONAL SYMBOL UP SHOE JOT
+235E	APL FUNCTIONAL SYMBOL QUOTE QUAD
+235F	APL FUNCTIONAL SYMBOL CIRCLE STAR
+2360	APL FUNCTIONAL SYMBOL QUAD COLON
+2361	APL FUNCTIONAL SYMBOL UP TACK DIAERESIS
+2362	APL FUNCTIONAL SYMBOL DEL DIAERESIS
+2363	APL FUNCTIONAL SYMBOL STAR DIAERESIS
+2364	APL FUNCTIONAL SYMBOL JOT DIAERESIS
+2365	APL FUNCTIONAL SYMBOL CIRCLE DIAERESIS
+2366	APL FUNCTIONAL SYMBOL DOWN SHOE STILE
+2367	APL FUNCTIONAL SYMBOL LEFT SHOE STILE
+2368	APL FUNCTIONAL SYMBOL TILDE DIAERESIS
+2369	APL FUNCTIONAL SYMBOL GREATER-THAN DIAERESIS
+236A	APL FUNCTIONAL SYMBOL COMMA BAR
+236B	APL FUNCTIONAL SYMBOL DEL TILDE
+236C	APL FUNCTIONAL SYMBOL ZILDE
+236D	APL FUNCTIONAL SYMBOL STILE TILDE
+236E	APL FUNCTIONAL SYMBOL SEMICOLON UNDERBAR
+236F	APL FUNCTIONAL SYMBOL QUAD NOT EQUAL
+2370	APL FUNCTIONAL SYMBOL QUAD QUESTION
+2371	APL FUNCTIONAL SYMBOL DOWN CARET TILDE
+2372	APL FUNCTIONAL SYMBOL UP CARET TILDE
+2373	APL FUNCTIONAL SYMBOL IOTA
+2374	APL FUNCTIONAL SYMBOL RHO
+2375	APL FUNCTIONAL SYMBOL OMEGA
+2376	APL FUNCTIONAL SYMBOL ALPHA UNDERBAR
+2377	APL FUNCTIONAL SYMBOL EPSILON UNDERBAR
+2378	APL FUNCTIONAL SYMBOL IOTA UNDERBAR
+2379	APL FUNCTIONAL SYMBOL OMEGA UNDERBAR
+237A	APL FUNCTIONAL SYMBOL ALPHA
+2400	SYMBOL FOR NULL
+2401	SYMBOL FOR START OF HEADING
+2402	SYMBOL FOR START OF TEXT
+2403	SYMBOL FOR END OF TEXT
+2404	SYMBOL FOR END OF TRANSMISSION
+2405	SYMBOL FOR ENQUIRY
+2406	SYMBOL FOR ACKNOWLEDGE
+2407	SYMBOL FOR BELL
+2408	SYMBOL FOR BACKSPACE
+2409	SYMBOL FOR HORIZONTAL TABULATION
+240A	SYMBOL FOR LINE FEED
+240B	SYMBOL FOR VERTICAL TABULATION
+240C	SYMBOL FOR FORM FEED
+240D	SYMBOL FOR CARRIAGE RETURN
+240E	SYMBOL FOR SHIFT OUT
+240F	SYMBOL FOR SHIFT IN
+2410	SYMBOL FOR DATA LINK ESCAPE
+2411	SYMBOL FOR DEVICE CONTROL ONE
+2412	SYMBOL FOR DEVICE CONTROL TWO
+2413	SYMBOL FOR DEVICE CONTROL THREE
+2414	SYMBOL FOR DEVICE CONTROL FOUR
+2415	SYMBOL FOR NEGATIVE ACKNOWLEDGE
+2416	SYMBOL FOR SYNCHRONOUS IDLE
+2417	SYMBOL FOR END OF TRANSMISSION BLOCK
+2418	SYMBOL FOR CANCEL
+2419	SYMBOL FOR END OF MEDIUM
+241A	SYMBOL FOR SUBSTITUTE
+241B	SYMBOL FOR ESCAPE
+241C	SYMBOL FOR FILE SEPARATOR
+241D	SYMBOL FOR GROUP SEPARATOR
+241E	SYMBOL FOR RECORD SEPARATOR
+241F	SYMBOL FOR UNIT SEPARATOR
+2420	SYMBOL FOR SPACE
+2421	SYMBOL FOR DELETE
+2422	BLANK SYMBOL
+2423	OPEN BOX
+2424	SYMBOL FOR NEWLINE
+2440	OCR HOOK
+2441	OCR CHAIR
+2442	OCR FORK
+2443	OCR INVERTED FORK
+2444	OCR BELT BUCKLE
+2445	OCR BOW TIE
+2446	OCR BRANCH BANK IDENTIFICATION
+2447	OCR AMOUNT OF CHECK
+2448	OCR DASH
+2449	OCR CUSTOMER ACCOUNT NUMBER
+244A	OCR DOUBLE BACKSLASH
+2460	CIRCLED DIGIT ONE
+2461	CIRCLED DIGIT TWO
+2462	CIRCLED DIGIT THREE
+2463	CIRCLED DIGIT FOUR
+2464	CIRCLED DIGIT FIVE
+2465	CIRCLED DIGIT SIX
+2466	CIRCLED DIGIT SEVEN
+2467	CIRCLED DIGIT EIGHT
+2468	CIRCLED DIGIT NINE
+2469	CIRCLED NUMBER TEN
+246A	CIRCLED NUMBER ELEVEN
+246B	CIRCLED NUMBER TWELVE
+246C	CIRCLED NUMBER THIRTEEN
+246D	CIRCLED NUMBER FOURTEEN
+246E	CIRCLED NUMBER FIFTEEN
+246F	CIRCLED NUMBER SIXTEEN
+2470	CIRCLED NUMBER SEVENTEEN
+2471	CIRCLED NUMBER EIGHTEEN
+2472	CIRCLED NUMBER NINETEEN
+2473	CIRCLED NUMBER TWENTY
+2474	PARENTHESIZED DIGIT ONE
+2475	PARENTHESIZED DIGIT TWO
+2476	PARENTHESIZED DIGIT THREE
+2477	PARENTHESIZED DIGIT FOUR
+2478	PARENTHESIZED DIGIT FIVE
+2479	PARENTHESIZED DIGIT SIX
+247A	PARENTHESIZED DIGIT SEVEN
+247B	PARENTHESIZED DIGIT EIGHT
+247C	PARENTHESIZED DIGIT NINE
+247D	PARENTHESIZED NUMBER TEN
+247E	PARENTHESIZED NUMBER ELEVEN
+247F	PARENTHESIZED NUMBER TWELVE
+2480	PARENTHESIZED NUMBER THIRTEEN
+2481	PARENTHESIZED NUMBER FOURTEEN
+2482	PARENTHESIZED NUMBER FIFTEEN
+2483	PARENTHESIZED NUMBER SIXTEEN
+2484	PARENTHESIZED NUMBER SEVENTEEN
+2485	PARENTHESIZED NUMBER EIGHTEEN
+2486	PARENTHESIZED NUMBER NINETEEN
+2487	PARENTHESIZED NUMBER TWENTY
+2488	DIGIT ONE FULL STOP
+2489	DIGIT TWO FULL STOP
+248A	DIGIT THREE FULL STOP
+248B	DIGIT FOUR FULL STOP
+248C	DIGIT FIVE FULL STOP
+248D	DIGIT SIX FULL STOP
+248E	DIGIT SEVEN FULL STOP
+248F	DIGIT EIGHT FULL STOP
+2490	DIGIT NINE FULL STOP
+2491	NUMBER TEN FULL STOP
+2492	NUMBER ELEVEN FULL STOP
+2493	NUMBER TWELVE FULL STOP
+2494	NUMBER THIRTEEN FULL STOP
+2495	NUMBER FOURTEEN FULL STOP
+2496	NUMBER FIFTEEN FULL STOP
+2497	NUMBER SIXTEEN FULL STOP
+2498	NUMBER SEVENTEEN FULL STOP
+2499	NUMBER EIGHTEEN FULL STOP
+249A	NUMBER NINETEEN FULL STOP
+249B	NUMBER TWENTY FULL STOP
+249C	PARENTHESIZED LATIN SMALL LETTER A
+249D	PARENTHESIZED LATIN SMALL LETTER B
+249E	PARENTHESIZED LATIN SMALL LETTER C
+249F	PARENTHESIZED LATIN SMALL LETTER D
+24A0	PARENTHESIZED LATIN SMALL LETTER E
+24A1	PARENTHESIZED LATIN SMALL LETTER F
+24A2	PARENTHESIZED LATIN SMALL LETTER G
+24A3	PARENTHESIZED LATIN SMALL LETTER H
+24A4	PARENTHESIZED LATIN SMALL LETTER I
+24A5	PARENTHESIZED LATIN SMALL LETTER J
+24A6	PARENTHESIZED LATIN SMALL LETTER K
+24A7	PARENTHESIZED LATIN SMALL LETTER L
+24A8	PARENTHESIZED LATIN SMALL LETTER M
+24A9	PARENTHESIZED LATIN SMALL LETTER N
+24AA	PARENTHESIZED LATIN SMALL LETTER O
+24AB	PARENTHESIZED LATIN SMALL LETTER P
+24AC	PARENTHESIZED LATIN SMALL LETTER Q
+24AD	PARENTHESIZED LATIN SMALL LETTER R
+24AE	PARENTHESIZED LATIN SMALL LETTER S
+24AF	PARENTHESIZED LATIN SMALL LETTER T
+24B0	PARENTHESIZED LATIN SMALL LETTER U
+24B1	PARENTHESIZED LATIN SMALL LETTER V
+24B2	PARENTHESIZED LATIN SMALL LETTER W
+24B3	PARENTHESIZED LATIN SMALL LETTER X
+24B4	PARENTHESIZED LATIN SMALL LETTER Y
+24B5	PARENTHESIZED LATIN SMALL LETTER Z
+24B6	CIRCLED LATIN CAPITAL LETTER A
+24B7	CIRCLED LATIN CAPITAL LETTER B
+24B8	CIRCLED LATIN CAPITAL LETTER C
+24B9	CIRCLED LATIN CAPITAL LETTER D
+24BA	CIRCLED LATIN CAPITAL LETTER E
+24BB	CIRCLED LATIN CAPITAL LETTER F
+24BC	CIRCLED LATIN CAPITAL LETTER G
+24BD	CIRCLED LATIN CAPITAL LETTER H
+24BE	CIRCLED LATIN CAPITAL LETTER I
+24BF	CIRCLED LATIN CAPITAL LETTER J
+24C0	CIRCLED LATIN CAPITAL LETTER K
+24C1	CIRCLED LATIN CAPITAL LETTER L
+24C2	CIRCLED LATIN CAPITAL LETTER M
+24C3	CIRCLED LATIN CAPITAL LETTER N
+24C4	CIRCLED LATIN CAPITAL LETTER O
+24C5	CIRCLED LATIN CAPITAL LETTER P
+24C6	CIRCLED LATIN CAPITAL LETTER Q
+24C7	CIRCLED LATIN CAPITAL LETTER R
+24C8	CIRCLED LATIN CAPITAL LETTER S
+24C9	CIRCLED LATIN CAPITAL LETTER T
+24CA	CIRCLED LATIN CAPITAL LETTER U
+24CB	CIRCLED LATIN CAPITAL LETTER V
+24CC	CIRCLED LATIN CAPITAL LETTER W
+24CD	CIRCLED LATIN CAPITAL LETTER X
+24CE	CIRCLED LATIN CAPITAL LETTER Y
+24CF	CIRCLED LATIN CAPITAL LETTER Z
+24D0	CIRCLED LATIN SMALL LETTER A
+24D1	CIRCLED LATIN SMALL LETTER B
+24D2	CIRCLED LATIN SMALL LETTER C
+24D3	CIRCLED LATIN SMALL LETTER D
+24D4	CIRCLED LATIN SMALL LETTER E
+24D5	CIRCLED LATIN SMALL LETTER F
+24D6	CIRCLED LATIN SMALL LETTER G
+24D7	CIRCLED LATIN SMALL LETTER H
+24D8	CIRCLED LATIN SMALL LETTER I
+24D9	CIRCLED LATIN SMALL LETTER J
+24DA	CIRCLED LATIN SMALL LETTER K
+24DB	CIRCLED LATIN SMALL LETTER L
+24DC	CIRCLED LATIN SMALL LETTER M
+24DD	CIRCLED LATIN SMALL LETTER N
+24DE	CIRCLED LATIN SMALL LETTER O
+24DF	CIRCLED LATIN SMALL LETTER P
+24E0	CIRCLED LATIN SMALL LETTER Q
+24E1	CIRCLED LATIN SMALL LETTER R
+24E2	CIRCLED LATIN SMALL LETTER S
+24E3	CIRCLED LATIN SMALL LETTER T
+24E4	CIRCLED LATIN SMALL LETTER U
+24E5	CIRCLED LATIN SMALL LETTER V
+24E6	CIRCLED LATIN SMALL LETTER W
+24E7	CIRCLED LATIN SMALL LETTER X
+24E8	CIRCLED LATIN SMALL LETTER Y
+24E9	CIRCLED LATIN SMALL LETTER Z
+24EA	CIRCLED DIGIT ZERO
+2500	BOX DRAWINGS LIGHT HORIZONTAL
+2501	BOX DRAWINGS HEAVY HORIZONTAL
+2502	BOX DRAWINGS LIGHT VERTICAL
+2503	BOX DRAWINGS HEAVY VERTICAL
+2504	BOX DRAWINGS LIGHT TRIPLE DASH HORIZONTAL
+2505	BOX DRAWINGS HEAVY TRIPLE DASH HORIZONTAL
+2506	BOX DRAWINGS LIGHT TRIPLE DASH VERTICAL
+2507	BOX DRAWINGS HEAVY TRIPLE DASH VERTICAL
+2508	BOX DRAWINGS LIGHT QUADRUPLE DASH HORIZONTAL
+2509	BOX DRAWINGS HEAVY QUADRUPLE DASH HORIZONTAL
+250A	BOX DRAWINGS LIGHT QUADRUPLE DASH VERTICAL
+250B	BOX DRAWINGS HEAVY QUADRUPLE DASH VERTICAL
+250C	BOX DRAWINGS LIGHT DOWN AND RIGHT
+250D	BOX DRAWINGS DOWN LIGHT AND RIGHT HEAVY
+250E	BOX DRAWINGS DOWN HEAVY AND RIGHT LIGHT
+250F	BOX DRAWINGS HEAVY DOWN AND RIGHT
+2510	BOX DRAWINGS LIGHT DOWN AND LEFT
+2511	BOX DRAWINGS DOWN LIGHT AND LEFT HEAVY
+2512	BOX DRAWINGS DOWN HEAVY AND LEFT LIGHT
+2513	BOX DRAWINGS HEAVY DOWN AND LEFT
+2514	BOX DRAWINGS LIGHT UP AND RIGHT
+2515	BOX DRAWINGS UP LIGHT AND RIGHT HEAVY
+2516	BOX DRAWINGS UP HEAVY AND RIGHT LIGHT
+2517	BOX DRAWINGS HEAVY UP AND RIGHT
+2518	BOX DRAWINGS LIGHT UP AND LEFT
+2519	BOX DRAWINGS UP LIGHT AND LEFT HEAVY
+251A	BOX DRAWINGS UP HEAVY AND LEFT LIGHT
+251B	BOX DRAWINGS HEAVY UP AND LEFT
+251C	BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+251D	BOX DRAWINGS VERTICAL LIGHT AND RIGHT HEAVY
+251E	BOX DRAWINGS UP HEAVY AND RIGHT DOWN LIGHT
+251F	BOX DRAWINGS DOWN HEAVY AND RIGHT UP LIGHT
+2520	BOX DRAWINGS VERTICAL HEAVY AND RIGHT LIGHT
+2521	BOX DRAWINGS DOWN LIGHT AND RIGHT UP HEAVY
+2522	BOX DRAWINGS UP LIGHT AND RIGHT DOWN HEAVY
+2523	BOX DRAWINGS HEAVY VERTICAL AND RIGHT
+2524	BOX DRAWINGS LIGHT VERTICAL AND LEFT
+2525	BOX DRAWINGS VERTICAL LIGHT AND LEFT HEAVY
+2526	BOX DRAWINGS UP HEAVY AND LEFT DOWN LIGHT
+2527	BOX DRAWINGS DOWN HEAVY AND LEFT UP LIGHT
+2528	BOX DRAWINGS VERTICAL HEAVY AND LEFT LIGHT
+2529	BOX DRAWINGS DOWN LIGHT AND LEFT UP HEAVY
+252A	BOX DRAWINGS UP LIGHT AND LEFT DOWN HEAVY
+252B	BOX DRAWINGS HEAVY VERTICAL AND LEFT
+252C	BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+252D	BOX DRAWINGS LEFT HEAVY AND RIGHT DOWN LIGHT
+252E	BOX DRAWINGS RIGHT HEAVY AND LEFT DOWN LIGHT
+252F	BOX DRAWINGS DOWN LIGHT AND HORIZONTAL HEAVY
+2530	BOX DRAWINGS DOWN HEAVY AND HORIZONTAL LIGHT
+2531	BOX DRAWINGS RIGHT LIGHT AND LEFT DOWN HEAVY
+2532	BOX DRAWINGS LEFT LIGHT AND RIGHT DOWN HEAVY
+2533	BOX DRAWINGS HEAVY DOWN AND HORIZONTAL
+2534	BOX DRAWINGS LIGHT UP AND HORIZONTAL
+2535	BOX DRAWINGS LEFT HEAVY AND RIGHT UP LIGHT
+2536	BOX DRAWINGS RIGHT HEAVY AND LEFT UP LIGHT
+2537	BOX DRAWINGS UP LIGHT AND HORIZONTAL HEAVY
+2538	BOX DRAWINGS UP HEAVY AND HORIZONTAL LIGHT
+2539	BOX DRAWINGS RIGHT LIGHT AND LEFT UP HEAVY
+253A	BOX DRAWINGS LEFT LIGHT AND RIGHT UP HEAVY
+253B	BOX DRAWINGS HEAVY UP AND HORIZONTAL
+253C	BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+253D	BOX DRAWINGS LEFT HEAVY AND RIGHT VERTICAL LIGHT
+253E	BOX DRAWINGS RIGHT HEAVY AND LEFT VERTICAL LIGHT
+253F	BOX DRAWINGS VERTICAL LIGHT AND HORIZONTAL HEAVY
+2540	BOX DRAWINGS UP HEAVY AND DOWN HORIZONTAL LIGHT
+2541	BOX DRAWINGS DOWN HEAVY AND UP HORIZONTAL LIGHT
+2542	BOX DRAWINGS VERTICAL HEAVY AND HORIZONTAL LIGHT
+2543	BOX DRAWINGS LEFT UP HEAVY AND RIGHT DOWN LIGHT
+2544	BOX DRAWINGS RIGHT UP HEAVY AND LEFT DOWN LIGHT
+2545	BOX DRAWINGS LEFT DOWN HEAVY AND RIGHT UP LIGHT
+2546	BOX DRAWINGS RIGHT DOWN HEAVY AND LEFT UP LIGHT
+2547	BOX DRAWINGS DOWN LIGHT AND UP HORIZONTAL HEAVY
+2548	BOX DRAWINGS UP LIGHT AND DOWN HORIZONTAL HEAVY
+2549	BOX DRAWINGS RIGHT LIGHT AND LEFT VERTICAL HEAVY
+254A	BOX DRAWINGS LEFT LIGHT AND RIGHT VERTICAL HEAVY
+254B	BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL
+254C	BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL
+254D	BOX DRAWINGS HEAVY DOUBLE DASH HORIZONTAL
+254E	BOX DRAWINGS LIGHT DOUBLE DASH VERTICAL
+254F	BOX DRAWINGS HEAVY DOUBLE DASH VERTICAL
+2550	BOX DRAWINGS DOUBLE HORIZONTAL
+2551	BOX DRAWINGS DOUBLE VERTICAL
+2552	BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+2553	BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+2554	BOX DRAWINGS DOUBLE DOWN AND RIGHT
+2555	BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+2556	BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+2557	BOX DRAWINGS DOUBLE DOWN AND LEFT
+2558	BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+2559	BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+255A	BOX DRAWINGS DOUBLE UP AND RIGHT
+255B	BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+255C	BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+255D	BOX DRAWINGS DOUBLE UP AND LEFT
+255E	BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+255F	BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+2560	BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+2561	BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+2562	BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+2563	BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+2564	BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+2565	BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+2566	BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+2567	BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+2568	BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+2569	BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+256A	BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+256B	BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+256C	BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+256D	BOX DRAWINGS LIGHT ARC DOWN AND RIGHT
+256E	BOX DRAWINGS LIGHT ARC DOWN AND LEFT
+256F	BOX DRAWINGS LIGHT ARC UP AND LEFT
+2570	BOX DRAWINGS LIGHT ARC UP AND RIGHT
+2571	BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT
+2572	BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT
+2573	BOX DRAWINGS LIGHT DIAGONAL CROSS
+2574	BOX DRAWINGS LIGHT LEFT
+2575	BOX DRAWINGS LIGHT UP
+2576	BOX DRAWINGS LIGHT RIGHT
+2577	BOX DRAWINGS LIGHT DOWN
+2578	BOX DRAWINGS HEAVY LEFT
+2579	BOX DRAWINGS HEAVY UP
+257A	BOX DRAWINGS HEAVY RIGHT
+257B	BOX DRAWINGS HEAVY DOWN
+257C	BOX DRAWINGS LIGHT LEFT AND HEAVY RIGHT
+257D	BOX DRAWINGS LIGHT UP AND HEAVY DOWN
+257E	BOX DRAWINGS HEAVY LEFT AND LIGHT RIGHT
+257F	BOX DRAWINGS HEAVY UP AND LIGHT DOWN
+2580	UPPER HALF BLOCK
+2581	LOWER ONE EIGHTH BLOCK
+2582	LOWER ONE QUARTER BLOCK
+2583	LOWER THREE EIGHTHS BLOCK
+2584	LOWER HALF BLOCK
+2585	LOWER FIVE EIGHTHS BLOCK
+2586	LOWER THREE QUARTERS BLOCK
+2587	LOWER SEVEN EIGHTHS BLOCK
+2588	FULL BLOCK
+2589	LEFT SEVEN EIGHTHS BLOCK
+258A	LEFT THREE QUARTERS BLOCK
+258B	LEFT FIVE EIGHTHS BLOCK
+258C	LEFT HALF BLOCK
+258D	LEFT THREE EIGHTHS BLOCK
+258E	LEFT ONE QUARTER BLOCK
+258F	LEFT ONE EIGHTH BLOCK
+2590	RIGHT HALF BLOCK
+2591	LIGHT SHADE
+2592	MEDIUM SHADE
+2593	DARK SHADE
+2594	UPPER ONE EIGHTH BLOCK
+2595	RIGHT ONE EIGHTH BLOCK
+25A0	BLACK SQUARE
+25A1	WHITE SQUARE
+25A2	WHITE SQUARE WITH ROUNDED CORNERS
+25A3	WHITE SQUARE CONTAINING BLACK SMALL SQUARE
+25A4	SQUARE WITH HORIZONTAL FILL
+25A5	SQUARE WITH VERTICAL FILL
+25A6	SQUARE WITH ORTHOGONAL CROSSHATCH FILL
+25A7	SQUARE WITH UPPER LEFT TO LOWER RIGHT FILL
+25A8	SQUARE WITH UPPER RIGHT TO LOWER LEFT FILL
+25A9	SQUARE WITH DIAGONAL CROSSHATCH FILL
+25AA	BLACK SMALL SQUARE
+25AB	WHITE SMALL SQUARE
+25AC	BLACK RECTANGLE
+25AD	WHITE RECTANGLE
+25AE	BLACK VERTICAL RECTANGLE
+25AF	WHITE VERTICAL RECTANGLE
+25B0	BLACK PARALLELOGRAM
+25B1	WHITE PARALLELOGRAM
+25B2	BLACK UP-POINTING TRIANGLE
+25B3	WHITE UP-POINTING TRIANGLE
+25B4	BLACK UP-POINTING SMALL TRIANGLE
+25B5	WHITE UP-POINTING SMALL TRIANGLE
+25B6	BLACK RIGHT-POINTING TRIANGLE
+25B7	WHITE RIGHT-POINTING TRIANGLE
+25B8	BLACK RIGHT-POINTING SMALL TRIANGLE
+25B9	WHITE RIGHT-POINTING SMALL TRIANGLE
+25BA	BLACK RIGHT-POINTING POINTER
+25BB	WHITE RIGHT-POINTING POINTER
+25BC	BLACK DOWN-POINTING TRIANGLE
+25BD	WHITE DOWN-POINTING TRIANGLE
+25BE	BLACK DOWN-POINTING SMALL TRIANGLE
+25BF	WHITE DOWN-POINTING SMALL TRIANGLE
+25C0	BLACK LEFT-POINTING TRIANGLE
+25C1	WHITE LEFT-POINTING TRIANGLE
+25C2	BLACK LEFT-POINTING SMALL TRIANGLE
+25C3	WHITE LEFT-POINTING SMALL TRIANGLE
+25C4	BLACK LEFT-POINTING POINTER
+25C5	WHITE LEFT-POINTING POINTER
+25C6	BLACK DIAMOND
+25C7	WHITE DIAMOND
+25C8	WHITE DIAMOND CONTAINING BLACK SMALL DIAMOND
+25C9	FISHEYE
+25CA	LOZENGE
+25CB	WHITE CIRCLE
+25CC	DOTTED CIRCLE
+25CD	CIRCLE WITH VERTICAL FILL
+25CE	BULLSEYE
+25CF	BLACK CIRCLE
+25D0	CIRCLE WITH LEFT HALF BLACK
+25D1	CIRCLE WITH RIGHT HALF BLACK
+25D2	CIRCLE WITH LOWER HALF BLACK
+25D3	CIRCLE WITH UPPER HALF BLACK
+25D4	CIRCLE WITH UPPER RIGHT QUADRANT BLACK
+25D5	CIRCLE WITH ALL BUT UPPER LEFT QUADRANT BLACK
+25D6	LEFT HALF BLACK CIRCLE
+25D7	RIGHT HALF BLACK CIRCLE
+25D8	INVERSE BULLET
+25D9	INVERSE WHITE CIRCLE
+25DA	UPPER HALF INVERSE WHITE CIRCLE
+25DB	LOWER HALF INVERSE WHITE CIRCLE
+25DC	UPPER LEFT QUADRANT CIRCULAR ARC
+25DD	UPPER RIGHT QUADRANT CIRCULAR ARC
+25DE	LOWER RIGHT QUADRANT CIRCULAR ARC
+25DF	LOWER LEFT QUADRANT CIRCULAR ARC
+25E0	UPPER HALF CIRCLE
+25E1	LOWER HALF CIRCLE
+25E2	BLACK LOWER RIGHT TRIANGLE
+25E3	BLACK LOWER LEFT TRIANGLE
+25E4	BLACK UPPER LEFT TRIANGLE
+25E5	BLACK UPPER RIGHT TRIANGLE
+25E6	WHITE BULLET
+25E7	SQUARE WITH LEFT HALF BLACK
+25E8	SQUARE WITH RIGHT HALF BLACK
+25E9	SQUARE WITH UPPER LEFT DIAGONAL HALF BLACK
+25EA	SQUARE WITH LOWER RIGHT DIAGONAL HALF BLACK
+25EB	WHITE SQUARE WITH VERTICAL BISECTING LINE
+25EC	WHITE UP-POINTING TRIANGLE WITH DOT
+25ED	UP-POINTING TRIANGLE WITH LEFT HALF BLACK
+25EE	UP-POINTING TRIANGLE WITH RIGHT HALF BLACK
+25EF	LARGE CIRCLE
+2600	BLACK SUN WITH RAYS
+2601	CLOUD
+2602	UMBRELLA
+2603	SNOWMAN
+2604	COMET
+2605	BLACK STAR
+2606	WHITE STAR
+2607	LIGHTNING
+2608	THUNDERSTORM
+2609	SUN
+260A	ASCENDING NODE
+260B	DESCENDING NODE
+260C	CONJUNCTION
+260D	OPPOSITION
+260E	BLACK TELEPHONE
+260F	WHITE TELEPHONE
+2610	BALLOT BOX
+2611	BALLOT BOX WITH CHECK
+2612	BALLOT BOX WITH X
+2613	SALTIRE
+261A	BLACK LEFT POINTING INDEX
+261B	BLACK RIGHT POINTING INDEX
+261C	WHITE LEFT POINTING INDEX
+261D	WHITE UP POINTING INDEX
+261E	WHITE RIGHT POINTING INDEX
+261F	WHITE DOWN POINTING INDEX
+2620	SKULL AND CROSSBONES
+2621	CAUTION SIGN
+2622	RADIOACTIVE SIGN
+2623	BIOHAZARD SIGN
+2624	CADUCEUS
+2625	ANKH
+2626	ORTHODOX CROSS
+2627	CHI RHO
+2628	CROSS OF LORRAINE
+2629	CROSS OF JERUSALEM
+262A	STAR AND CRESCENT
+262B	FARSI SYMBOL
+262C	ADI SHAKTI
+262D	HAMMER AND SICKLE
+262E	PEACE SYMBOL
+262F	YIN YANG
+2630	TRIGRAM FOR HEAVEN
+2631	TRIGRAM FOR LAKE
+2632	TRIGRAM FOR FIRE
+2633	TRIGRAM FOR THUNDER
+2634	TRIGRAM FOR WIND
+2635	TRIGRAM FOR WATER
+2636	TRIGRAM FOR MOUNTAIN
+2637	TRIGRAM FOR EARTH
+2638	WHEEL OF DHARMA
+2639	WHITE FROWNING FACE
+263A	WHITE SMILING FACE
+263B	BLACK SMILING FACE
+263C	WHITE SUN WITH RAYS
+263D	FIRST QUARTER MOON
+263E	LAST QUARTER MOON
+263F	MERCURY
+2640	FEMALE SIGN
+2641	EARTH
+2642	MALE SIGN
+2643	JUPITER
+2644	SATURN
+2645	URANUS
+2646	NEPTUNE
+2647	PLUTO
+2648	ARIES
+2649	TAURUS
+264A	GEMINI
+264B	CANCER
+264C	LEO
+264D	VIRGO
+264E	LIBRA
+264F	SCORPIUS
+2650	SAGITTARIUS
+2651	CAPRICORN
+2652	AQUARIUS
+2653	PISCES
+2654	WHITE CHESS KING
+2655	WHITE CHESS QUEEN
+2656	WHITE CHESS ROOK
+2657	WHITE CHESS BISHOP
+2658	WHITE CHESS KNIGHT
+2659	WHITE CHESS PAWN
+265A	BLACK CHESS KING
+265B	BLACK CHESS QUEEN
+265C	BLACK CHESS ROOK
+265D	BLACK CHESS BISHOP
+265E	BLACK CHESS KNIGHT
+265F	BLACK CHESS PAWN
+2660	BLACK SPADE SUIT
+2661	WHITE HEART SUIT
+2662	WHITE DIAMOND SUIT
+2663	BLACK CLUB SUIT
+2664	WHITE SPADE SUIT
+2665	BLACK HEART SUIT
+2666	BLACK DIAMOND SUIT
+2667	WHITE CLUB SUIT
+2668	HOT SPRINGS
+2669	QUARTER NOTE
+266A	EIGHTH NOTE
+266B	BEAMED EIGHTH NOTES
+266C	BEAMED SIXTEENTH NOTES
+266D	MUSIC FLAT SIGN
+266E	MUSIC NATURAL SIGN
+266F	MUSIC SHARP SIGN
+2701	UPPER BLADE SCISSORS
+2702	BLACK SCISSORS
+2703	LOWER BLADE SCISSORS
+2704	WHITE SCISSORS
+2706	TELEPHONE LOCATION SIGN
+2707	TAPE DRIVE
+2708	AIRPLANE
+2709	ENVELOPE
+270C	VICTORY HAND
+270D	WRITING HAND
+270E	LOWER RIGHT PENCIL
+270F	PENCIL
+2710	UPPER RIGHT PENCIL
+2711	WHITE NIB
+2712	BLACK NIB
+2713	CHECK MARK
+2714	HEAVY CHECK MARK
+2715	MULTIPLICATION X
+2716	HEAVY MULTIPLICATION X
+2717	BALLOT X
+2718	HEAVY BALLOT X
+2719	OUTLINED GREEK CROSS
+271A	HEAVY GREEK CROSS
+271B	OPEN CENTRE CROSS
+271C	HEAVY OPEN CENTRE CROSS
+271D	LATIN CROSS
+271E	SHADOWED WHITE LATIN CROSS
+271F	OUTLINED LATIN CROSS
+2720	MALTESE CROSS
+2721	STAR OF DAVID
+2722	FOUR TEARDROP-SPOKED ASTERISK
+2723	FOUR BALLOON-SPOKED ASTERISK
+2724	HEAVY FOUR BALLOON-SPOKED ASTERISK
+2725	FOUR CLUB-SPOKED ASTERISK
+2726	BLACK FOUR POINTED STAR
+2727	WHITE FOUR POINTED STAR
+2729	STRESS OUTLINED WHITE STAR
+272A	CIRCLED WHITE STAR
+272B	OPEN CENTRE BLACK STAR
+272C	BLACK CENTRE WHITE STAR
+272D	OUTLINED BLACK STAR
+272E	HEAVY OUTLINED BLACK STAR
+272F	PINWHEEL STAR
+2730	SHADOWED WHITE STAR
+2731	HEAVY ASTERISK
+2732	OPEN CENTRE ASTERISK
+2733	EIGHT SPOKED ASTERISK
+2734	EIGHT POINTED BLACK STAR
+2735	EIGHT POINTED PINWHEEL STAR
+2736	SIX POINTED BLACK STAR
+2737	EIGHT POINTED RECTILINEAR BLACK STAR
+2738	HEAVY EIGHT POINTED RECTILINEAR BLACK STAR
+2739	TWELVE POINTED BLACK STAR
+273A	SIXTEEN POINTED ASTERISK
+273B	TEARDROP-SPOKED ASTERISK
+273C	OPEN CENTRE TEARDROP-SPOKED ASTERISK
+273D	HEAVY TEARDROP-SPOKED ASTERISK
+273E	SIX PETALLED BLACK AND WHITE FLORETTE
+273F	BLACK FLORETTE
+2740	WHITE FLORETTE
+2741	EIGHT PETALLED OUTLINED BLACK FLORETTE
+2742	CIRCLED OPEN CENTRE EIGHT POINTED STAR
+2743	HEAVY TEARDROP-SPOKED PINWHEEL ASTERISK
+2744	SNOWFLAKE
+2745	TIGHT TRIFOLIATE SNOWFLAKE
+2746	HEAVY CHEVRON SNOWFLAKE
+2747	SPARKLE
+2748	HEAVY SPARKLE
+2749	BALLOON-SPOKED ASTERISK
+274A	EIGHT TEARDROP-SPOKED PROPELLER ASTERISK
+274B	HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK
+274D	SHADOWED WHITE CIRCLE
+274F	LOWER RIGHT DROP-SHADOWED WHITE SQUARE
+2750	UPPER RIGHT DROP-SHADOWED WHITE SQUARE
+2751	LOWER RIGHT SHADOWED WHITE SQUARE
+2752	UPPER RIGHT SHADOWED WHITE SQUARE
+2756	BLACK DIAMOND MINUS WHITE X
+2758	LIGHT VERTICAL BAR
+2759	MEDIUM VERTICAL BAR
+275A	HEAVY VERTICAL BAR
+275B	HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT
+275C	HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT
+275D	HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT
+275E	HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT
+2761	CURVED STEM PARAGRAPH SIGN ORNAMENT
+2762	HEAVY EXCLAMATION MARK ORNAMENT
+2763	HEAVY HEART EXCLAMATION MARK ORNAMENT
+2764	HEAVY BLACK HEART
+2765	ROTATED HEAVY BLACK HEART BULLET
+2766	FLORAL HEART
+2767	ROTATED FLORAL HEART BULLET
+2776	DINGBAT NEGATIVE CIRCLED DIGIT ONE
+2777	DINGBAT NEGATIVE CIRCLED DIGIT TWO
+2778	DINGBAT NEGATIVE CIRCLED DIGIT THREE
+2779	DINGBAT NEGATIVE CIRCLED DIGIT FOUR
+277A	DINGBAT NEGATIVE CIRCLED DIGIT FIVE
+277B	DINGBAT NEGATIVE CIRCLED DIGIT SIX
+277C	DINGBAT NEGATIVE CIRCLED DIGIT SEVEN
+277D	DINGBAT NEGATIVE CIRCLED DIGIT EIGHT
+277E	DINGBAT NEGATIVE CIRCLED DIGIT NINE
+277F	DINGBAT NEGATIVE CIRCLED NUMBER TEN
+2780	DINGBAT CIRCLED SANS-SERIF DIGIT ONE
+2781	DINGBAT CIRCLED SANS-SERIF DIGIT TWO
+2782	DINGBAT CIRCLED SANS-SERIF DIGIT THREE
+2783	DINGBAT CIRCLED SANS-SERIF DIGIT FOUR
+2784	DINGBAT CIRCLED SANS-SERIF DIGIT FIVE
+2785	DINGBAT CIRCLED SANS-SERIF DIGIT SIX
+2786	DINGBAT CIRCLED SANS-SERIF DIGIT SEVEN
+2787	DINGBAT CIRCLED SANS-SERIF DIGIT EIGHT
+2788	DINGBAT CIRCLED SANS-SERIF DIGIT NINE
+2789	DINGBAT CIRCLED SANS-SERIF NUMBER TEN
+278A	DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ONE
+278B	DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TWO
+278C	DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT THREE
+278D	DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FOUR
+278E	DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FIVE
+278F	DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SIX
+2790	DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SEVEN
+2791	DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT EIGHT
+2792	DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE
+2793	DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN
+2794	HEAVY WIDE-HEADED RIGHTWARDS ARROW
+2798	HEAVY SOUTH EAST ARROW
+2799	HEAVY RIGHTWARDS ARROW
+279A	HEAVY NORTH EAST ARROW
+279B	DRAFTING POINT RIGHTWARDS ARROW
+279C	HEAVY ROUND-TIPPED RIGHTWARDS ARROW
+279D	TRIANGLE-HEADED RIGHTWARDS ARROW
+279E	HEAVY TRIANGLE-HEADED RIGHTWARDS ARROW
+279F	DASHED TRIANGLE-HEADED RIGHTWARDS ARROW
+27A0	HEAVY DASHED TRIANGLE-HEADED RIGHTWARDS ARROW
+27A1	BLACK RIGHTWARDS ARROW
+27A2	THREE-D TOP-LIGHTED RIGHTWARDS ARROWHEAD
+27A3	THREE-D BOTTOM-LIGHTED RIGHTWARDS ARROWHEAD
+27A4	BLACK RIGHTWARDS ARROWHEAD
+27A5	HEAVY BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW
+27A6	HEAVY BLACK CURVED UPWARDS AND RIGHTWARDS ARROW
+27A7	SQUAT BLACK RIGHTWARDS ARROW
+27A8	HEAVY CONCAVE-POINTED BLACK RIGHTWARDS ARROW
+27A9	RIGHT-SHADED WHITE RIGHTWARDS ARROW
+27AA	LEFT-SHADED WHITE RIGHTWARDS ARROW
+27AB	BACK-TILTED SHADOWED WHITE RIGHTWARDS ARROW
+27AC	FRONT-TILTED SHADOWED WHITE RIGHTWARDS ARROW
+27AD	HEAVY LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW
+27AE	HEAVY UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW
+27AF	NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW
+27B1	NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW
+27B2	CIRCLED HEAVY WHITE RIGHTWARDS ARROW
+27B3	WHITE-FEATHERED RIGHTWARDS ARROW
+27B4	BLACK-FEATHERED SOUTH EAST ARROW
+27B5	BLACK-FEATHERED RIGHTWARDS ARROW
+27B6	BLACK-FEATHERED NORTH EAST ARROW
+27B7	HEAVY BLACK-FEATHERED SOUTH EAST ARROW
+27B8	HEAVY BLACK-FEATHERED RIGHTWARDS ARROW
+27B9	HEAVY BLACK-FEATHERED NORTH EAST ARROW
+27BA	TEARDROP-BARBED RIGHTWARDS ARROW
+27BB	HEAVY TEARDROP-SHANKED RIGHTWARDS ARROW
+27BC	WEDGE-TAILED RIGHTWARDS ARROW
+27BD	HEAVY WEDGE-TAILED RIGHTWARDS ARROW
+27BE	OPEN-OUTLINED RIGHTWARDS ARROW
+3000	IDEOGRAPHIC SPACE
+3001	IDEOGRAPHIC COMMA
+3002	IDEOGRAPHIC FULL STOP
+3003	DITTO MARK
+3004	JAPANESE INDUSTRIAL STANDARD SYMBOL
+3005	IDEOGRAPHIC ITERATION MARK
+3006	IDEOGRAPHIC CLOSING MARK
+3007	IDEOGRAPHIC NUMBER ZERO
+3008	LEFT ANGLE BRACKET
+3009	RIGHT ANGLE BRACKET
+300A	LEFT DOUBLE ANGLE BRACKET
+300B	RIGHT DOUBLE ANGLE BRACKET
+300C	LEFT CORNER BRACKET
+300D	RIGHT CORNER BRACKET
+300E	LEFT WHITE CORNER BRACKET
+300F	RIGHT WHITE CORNER BRACKET
+3010	LEFT BLACK LENTICULAR BRACKET
+3011	RIGHT BLACK LENTICULAR BRACKET
+3012	POSTAL MARK
+3013	GETA MARK
+3014	LEFT TORTOISE SHELL BRACKET
+3015	RIGHT TORTOISE SHELL BRACKET
+3016	LEFT WHITE LENTICULAR BRACKET
+3017	RIGHT WHITE LENTICULAR BRACKET
+3018	LEFT WHITE TORTOISE SHELL BRACKET
+3019	RIGHT WHITE TORTOISE SHELL BRACKET
+301A	LEFT WHITE SQUARE BRACKET
+301B	RIGHT WHITE SQUARE BRACKET
+301C	WAVE DASH
+301D	REVERSED DOUBLE PRIME QUOTATION MARK
+301E	DOUBLE PRIME QUOTATION MARK
+301F	LOW DOUBLE PRIME QUOTATION MARK
+3020	POSTAL MARK FACE
+3021	HANGZHOU NUMERAL ONE
+3022	HANGZHOU NUMERAL TWO
+3023	HANGZHOU NUMERAL THREE
+3024	HANGZHOU NUMERAL FOUR
+3025	HANGZHOU NUMERAL FIVE
+3026	HANGZHOU NUMERAL SIX
+3027	HANGZHOU NUMERAL SEVEN
+3028	HANGZHOU NUMERAL EIGHT
+3029	HANGZHOU NUMERAL NINE
+302A	IDEOGRAPHIC LEVEL TONE MARK
+302B	IDEOGRAPHIC RISING TONE MARK
+302C	IDEOGRAPHIC DEPARTING TONE MARK
+302D	IDEOGRAPHIC ENTERING TONE MARK
+302E	HANGUL SINGLE DOT TONE MARK
+302F	HANGUL DOUBLE DOT TONE MARK
+3030	WAVY DASH
+3031	VERTICAL KANA REPEAT MARK
+3032	VERTICAL KANA REPEAT WITH VOICED SOUND MARK
+3033	VERTICAL KANA REPEAT MARK UPPER HALF
+3034	VERTICAL KANA REPEAT WITH VOICED SOUND MARK UPPER HALF
+3035	VERTICAL KANA REPEAT MARK LOWER HALF
+3036	CIRCLED POSTAL MARK
+3037	IDEOGRAPHIC TELEGRAPH LINE FEED SEPARATOR SYMBOL
+303F	IDEOGRAPHIC HALF FILL SPACE
+3041	HIRAGANA LETTER SMALL A
+3042	HIRAGANA LETTER A
+3043	HIRAGANA LETTER SMALL I
+3044	HIRAGANA LETTER I
+3045	HIRAGANA LETTER SMALL U
+3046	HIRAGANA LETTER U
+3047	HIRAGANA LETTER SMALL E
+3048	HIRAGANA LETTER E
+3049	HIRAGANA LETTER SMALL O
+304A	HIRAGANA LETTER O
+304B	HIRAGANA LETTER KA
+304C	HIRAGANA LETTER GA
+304D	HIRAGANA LETTER KI
+304E	HIRAGANA LETTER GI
+304F	HIRAGANA LETTER KU
+3050	HIRAGANA LETTER GU
+3051	HIRAGANA LETTER KE
+3052	HIRAGANA LETTER GE
+3053	HIRAGANA LETTER KO
+3054	HIRAGANA LETTER GO
+3055	HIRAGANA LETTER SA
+3056	HIRAGANA LETTER ZA
+3057	HIRAGANA LETTER SI
+3058	HIRAGANA LETTER ZI
+3059	HIRAGANA LETTER SU
+305A	HIRAGANA LETTER ZU
+305B	HIRAGANA LETTER SE
+305C	HIRAGANA LETTER ZE
+305D	HIRAGANA LETTER SO
+305E	HIRAGANA LETTER ZO
+305F	HIRAGANA LETTER TA
+3060	HIRAGANA LETTER DA
+3061	HIRAGANA LETTER TI
+3062	HIRAGANA LETTER DI
+3063	HIRAGANA LETTER SMALL TU
+3064	HIRAGANA LETTER TU
+3065	HIRAGANA LETTER DU
+3066	HIRAGANA LETTER TE
+3067	HIRAGANA LETTER DE
+3068	HIRAGANA LETTER TO
+3069	HIRAGANA LETTER DO
+306A	HIRAGANA LETTER NA
+306B	HIRAGANA LETTER NI
+306C	HIRAGANA LETTER NU
+306D	HIRAGANA LETTER NE
+306E	HIRAGANA LETTER NO
+306F	HIRAGANA LETTER HA
+3070	HIRAGANA LETTER BA
+3071	HIRAGANA LETTER PA
+3072	HIRAGANA LETTER HI
+3073	HIRAGANA LETTER BI
+3074	HIRAGANA LETTER PI
+3075	HIRAGANA LETTER HU
+3076	HIRAGANA LETTER BU
+3077	HIRAGANA LETTER PU
+3078	HIRAGANA LETTER HE
+3079	HIRAGANA LETTER BE
+307A	HIRAGANA LETTER PE
+307B	HIRAGANA LETTER HO
+307C	HIRAGANA LETTER BO
+307D	HIRAGANA LETTER PO
+307E	HIRAGANA LETTER MA
+307F	HIRAGANA LETTER MI
+3080	HIRAGANA LETTER MU
+3081	HIRAGANA LETTER ME
+3082	HIRAGANA LETTER MO
+3083	HIRAGANA LETTER SMALL YA
+3084	HIRAGANA LETTER YA
+3085	HIRAGANA LETTER SMALL YU
+3086	HIRAGANA LETTER YU
+3087	HIRAGANA LETTER SMALL YO
+3088	HIRAGANA LETTER YO
+3089	HIRAGANA LETTER RA
+308A	HIRAGANA LETTER RI
+308B	HIRAGANA LETTER RU
+308C	HIRAGANA LETTER RE
+308D	HIRAGANA LETTER RO
+308E	HIRAGANA LETTER SMALL WA
+308F	HIRAGANA LETTER WA
+3090	HIRAGANA LETTER WI
+3091	HIRAGANA LETTER WE
+3092	HIRAGANA LETTER WO
+3093	HIRAGANA LETTER N
+3094	HIRAGANA LETTER VU
+3099	COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
+309A	COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
+309B	KATAKANA-HIRAGANA VOICED SOUND MARK
+309C	KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
+309D	HIRAGANA ITERATION MARK
+309E	HIRAGANA VOICED ITERATION MARK
+30A1	KATAKANA LETTER SMALL A
+30A2	KATAKANA LETTER A
+30A3	KATAKANA LETTER SMALL I
+30A4	KATAKANA LETTER I
+30A5	KATAKANA LETTER SMALL U
+30A6	KATAKANA LETTER U
+30A7	KATAKANA LETTER SMALL E
+30A8	KATAKANA LETTER E
+30A9	KATAKANA LETTER SMALL O
+30AA	KATAKANA LETTER O
+30AB	KATAKANA LETTER KA
+30AC	KATAKANA LETTER GA
+30AD	KATAKANA LETTER KI
+30AE	KATAKANA LETTER GI
+30AF	KATAKANA LETTER KU
+30B0	KATAKANA LETTER GU
+30B1	KATAKANA LETTER KE
+30B2	KATAKANA LETTER GE
+30B3	KATAKANA LETTER KO
+30B4	KATAKANA LETTER GO
+30B5	KATAKANA LETTER SA
+30B6	KATAKANA LETTER ZA
+30B7	KATAKANA LETTER SI
+30B8	KATAKANA LETTER ZI
+30B9	KATAKANA LETTER SU
+30BA	KATAKANA LETTER ZU
+30BB	KATAKANA LETTER SE
+30BC	KATAKANA LETTER ZE
+30BD	KATAKANA LETTER SO
+30BE	KATAKANA LETTER ZO
+30BF	KATAKANA LETTER TA
+30C0	KATAKANA LETTER DA
+30C1	KATAKANA LETTER TI
+30C2	KATAKANA LETTER DI
+30C3	KATAKANA LETTER SMALL TU
+30C4	KATAKANA LETTER TU
+30C5	KATAKANA LETTER DU
+30C6	KATAKANA LETTER TE
+30C7	KATAKANA LETTER DE
+30C8	KATAKANA LETTER TO
+30C9	KATAKANA LETTER DO
+30CA	KATAKANA LETTER NA
+30CB	KATAKANA LETTER NI
+30CC	KATAKANA LETTER NU
+30CD	KATAKANA LETTER NE
+30CE	KATAKANA LETTER NO
+30CF	KATAKANA LETTER HA
+30D0	KATAKANA LETTER BA
+30D1	KATAKANA LETTER PA
+30D2	KATAKANA LETTER HI
+30D3	KATAKANA LETTER BI
+30D4	KATAKANA LETTER PI
+30D5	KATAKANA LETTER HU
+30D6	KATAKANA LETTER BU
+30D7	KATAKANA LETTER PU
+30D8	KATAKANA LETTER HE
+30D9	KATAKANA LETTER BE
+30DA	KATAKANA LETTER PE
+30DB	KATAKANA LETTER HO
+30DC	KATAKANA LETTER BO
+30DD	KATAKANA LETTER PO
+30DE	KATAKANA LETTER MA
+30DF	KATAKANA LETTER MI
+30E0	KATAKANA LETTER MU
+30E1	KATAKANA LETTER ME
+30E2	KATAKANA LETTER MO
+30E3	KATAKANA LETTER SMALL YA
+30E4	KATAKANA LETTER YA
+30E5	KATAKANA LETTER SMALL YU
+30E6	KATAKANA LETTER YU
+30E7	KATAKANA LETTER SMALL YO
+30E8	KATAKANA LETTER YO
+30E9	KATAKANA LETTER RA
+30EA	KATAKANA LETTER RI
+30EB	KATAKANA LETTER RU
+30EC	KATAKANA LETTER RE
+30ED	KATAKANA LETTER RO
+30EE	KATAKANA LETTER SMALL WA
+30EF	KATAKANA LETTER WA
+30F0	KATAKANA LETTER WI
+30F1	KATAKANA LETTER WE
+30F2	KATAKANA LETTER WO
+30F3	KATAKANA LETTER N
+30F4	KATAKANA LETTER VU
+30F5	KATAKANA LETTER SMALL KA
+30F6	KATAKANA LETTER SMALL KE
+30F7	KATAKANA LETTER VA
+30F8	KATAKANA LETTER VI
+30F9	KATAKANA LETTER VE
+30FA	KATAKANA LETTER VO
+30FB	KATAKANA MIDDLE DOT
+30FC	KATAKANA-HIRAGANA PROLONGED SOUND MARK
+30FD	KATAKANA ITERATION MARK
+30FE	KATAKANA VOICED ITERATION MARK
+3105	BOPOMOFO LETTER B
+3106	BOPOMOFO LETTER P
+3107	BOPOMOFO LETTER M
+3108	BOPOMOFO LETTER F
+3109	BOPOMOFO LETTER D
+310A	BOPOMOFO LETTER T
+310B	BOPOMOFO LETTER N
+310C	BOPOMOFO LETTER L
+310D	BOPOMOFO LETTER G
+310E	BOPOMOFO LETTER K
+310F	BOPOMOFO LETTER H
+3110	BOPOMOFO LETTER J
+3111	BOPOMOFO LETTER Q
+3112	BOPOMOFO LETTER X
+3113	BOPOMOFO LETTER ZH
+3114	BOPOMOFO LETTER CH
+3115	BOPOMOFO LETTER SH
+3116	BOPOMOFO LETTER R
+3117	BOPOMOFO LETTER Z
+3118	BOPOMOFO LETTER C
+3119	BOPOMOFO LETTER S
+311A	BOPOMOFO LETTER A
+311B	BOPOMOFO LETTER O
+311C	BOPOMOFO LETTER E
+311D	BOPOMOFO LETTER EH
+311E	BOPOMOFO LETTER AI
+311F	BOPOMOFO LETTER EI
+3120	BOPOMOFO LETTER AU
+3121	BOPOMOFO LETTER OU
+3122	BOPOMOFO LETTER AN
+3123	BOPOMOFO LETTER EN
+3124	BOPOMOFO LETTER ANG
+3125	BOPOMOFO LETTER ENG
+3126	BOPOMOFO LETTER ER
+3127	BOPOMOFO LETTER I
+3128	BOPOMOFO LETTER U
+3129	BOPOMOFO LETTER IU
+312A	BOPOMOFO LETTER V
+312B	BOPOMOFO LETTER NG
+312C	BOPOMOFO LETTER GN
+3131	HANGUL LETTER KIYEOK
+3132	HANGUL LETTER SSANGKIYEOK
+3133	HANGUL LETTER KIYEOK-SIOS
+3134	HANGUL LETTER NIEUN
+3135	HANGUL LETTER NIEUN-CIEUC
+3136	HANGUL LETTER NIEUN-HIEUH
+3137	HANGUL LETTER TIKEUT
+3138	HANGUL LETTER SSANGTIKEUT
+3139	HANGUL LETTER RIEUL
+313A	HANGUL LETTER RIEUL-KIYEOK
+313B	HANGUL LETTER RIEUL-MIEUM
+313C	HANGUL LETTER RIEUL-PIEUP
+313D	HANGUL LETTER RIEUL-SIOS
+313E	HANGUL LETTER RIEUL-THIEUTH
+313F	HANGUL LETTER RIEUL-PHIEUPH
+3140	HANGUL LETTER RIEUL-HIEUH
+3141	HANGUL LETTER MIEUM
+3142	HANGUL LETTER PIEUP
+3143	HANGUL LETTER SSANGPIEUP
+3144	HANGUL LETTER PIEUP-SIOS
+3145	HANGUL LETTER SIOS
+3146	HANGUL LETTER SSANGSIOS
+3147	HANGUL LETTER IEUNG
+3148	HANGUL LETTER CIEUC
+3149	HANGUL LETTER SSANGCIEUC
+314A	HANGUL LETTER CHIEUCH
+314B	HANGUL LETTER KHIEUKH
+314C	HANGUL LETTER THIEUTH
+314D	HANGUL LETTER PHIEUPH
+314E	HANGUL LETTER HIEUH
+314F	HANGUL LETTER A
+3150	HANGUL LETTER AE
+3151	HANGUL LETTER YA
+3152	HANGUL LETTER YAE
+3153	HANGUL LETTER EO
+3154	HANGUL LETTER E
+3155	HANGUL LETTER YEO
+3156	HANGUL LETTER YE
+3157	HANGUL LETTER O
+3158	HANGUL LETTER WA
+3159	HANGUL LETTER WAE
+315A	HANGUL LETTER OE
+315B	HANGUL LETTER YO
+315C	HANGUL LETTER U
+315D	HANGUL LETTER WEO
+315E	HANGUL LETTER WE
+315F	HANGUL LETTER WI
+3160	HANGUL LETTER YU
+3161	HANGUL LETTER EU
+3162	HANGUL LETTER YI
+3163	HANGUL LETTER I
+3164	HANGUL FILLER
+3165	HANGUL LETTER SSANGNIEUN
+3166	HANGUL LETTER NIEUN-TIKEUT
+3167	HANGUL LETTER NIEUN-SIOS
+3168	HANGUL LETTER NIEUN-PANSIOS
+3169	HANGUL LETTER RIEUL-KIYEOK-SIOS
+316A	HANGUL LETTER RIEUL-TIKEUT
+316B	HANGUL LETTER RIEUL-PIEUP-SIOS
+316C	HANGUL LETTER RIEUL-PANSIOS
+316D	HANGUL LETTER RIEUL-YEORINHIEUH
+316E	HANGUL LETTER MIEUM-PIEUP
+316F	HANGUL LETTER MIEUM-SIOS
+3170	HANGUL LETTER MIEUM-PANSIOS
+3171	HANGUL LETTER KAPYEOUNMIEUM
+3172	HANGUL LETTER PIEUP-KIYEOK
+3173	HANGUL LETTER PIEUP-TIKEUT
+3174	HANGUL LETTER PIEUP-SIOS-KIYEOK
+3175	HANGUL LETTER PIEUP-SIOS-TIKEUT
+3176	HANGUL LETTER PIEUP-CIEUC
+3177	HANGUL LETTER PIEUP-THIEUTH
+3178	HANGUL LETTER KAPYEOUNPIEUP
+3179	HANGUL LETTER KAPYEOUNSSANGPIEUP
+317A	HANGUL LETTER SIOS-KIYEOK
+317B	HANGUL LETTER SIOS-NIEUN
+317C	HANGUL LETTER SIOS-TIKEUT
+317D	HANGUL LETTER SIOS-PIEUP
+317E	HANGUL LETTER SIOS-CIEUC
+317F	HANGUL LETTER PANSIOS
+3180	HANGUL LETTER SSANGIEUNG
+3181	HANGUL LETTER YESIEUNG
+3182	HANGUL LETTER YESIEUNG-SIOS
+3183	HANGUL LETTER YESIEUNG-PANSIOS
+3184	HANGUL LETTER KAPYEOUNPHIEUPH
+3185	HANGUL LETTER SSANGHIEUH
+3186	HANGUL LETTER YEORINHIEUH
+3187	HANGUL LETTER YO-YA
+3188	HANGUL LETTER YO-YAE
+3189	HANGUL LETTER YO-I
+318A	HANGUL LETTER YU-YEO
+318B	HANGUL LETTER YU-YE
+318C	HANGUL LETTER YU-I
+318D	HANGUL LETTER ARAEA
+318E	HANGUL LETTER ARAEAE
+3190	IDEOGRAPHIC ANNOTATION LINKING MARK
+3191	IDEOGRAPHIC ANNOTATION REVERSE MARK
+3192	IDEOGRAPHIC ANNOTATION ONE MARK
+3193	IDEOGRAPHIC ANNOTATION TWO MARK
+3194	IDEOGRAPHIC ANNOTATION THREE MARK
+3195	IDEOGRAPHIC ANNOTATION FOUR MARK
+3196	IDEOGRAPHIC ANNOTATION TOP MARK
+3197	IDEOGRAPHIC ANNOTATION MIDDLE MARK
+3198	IDEOGRAPHIC ANNOTATION BOTTOM MARK
+3199	IDEOGRAPHIC ANNOTATION FIRST MARK
+319A	IDEOGRAPHIC ANNOTATION SECOND MARK
+319B	IDEOGRAPHIC ANNOTATION THIRD MARK
+319C	IDEOGRAPHIC ANNOTATION FOURTH MARK
+319D	IDEOGRAPHIC ANNOTATION HEAVEN MARK
+319E	IDEOGRAPHIC ANNOTATION EARTH MARK
+319F	IDEOGRAPHIC ANNOTATION MAN MARK
+3200	PARENTHESIZED HANGUL KIYEOK
+3201	PARENTHESIZED HANGUL NIEUN
+3202	PARENTHESIZED HANGUL TIKEUT
+3203	PARENTHESIZED HANGUL RIEUL
+3204	PARENTHESIZED HANGUL MIEUM
+3205	PARENTHESIZED HANGUL PIEUP
+3206	PARENTHESIZED HANGUL SIOS
+3207	PARENTHESIZED HANGUL IEUNG
+3208	PARENTHESIZED HANGUL CIEUC
+3209	PARENTHESIZED HANGUL CHIEUCH
+320A	PARENTHESIZED HANGUL KHIEUKH
+320B	PARENTHESIZED HANGUL THIEUTH
+320C	PARENTHESIZED HANGUL PHIEUPH
+320D	PARENTHESIZED HANGUL HIEUH
+320E	PARENTHESIZED HANGUL KIYEOK A
+320F	PARENTHESIZED HANGUL NIEUN A
+3210	PARENTHESIZED HANGUL TIKEUT A
+3211	PARENTHESIZED HANGUL RIEUL A
+3212	PARENTHESIZED HANGUL MIEUM A
+3213	PARENTHESIZED HANGUL PIEUP A
+3214	PARENTHESIZED HANGUL SIOS A
+3215	PARENTHESIZED HANGUL IEUNG A
+3216	PARENTHESIZED HANGUL CIEUC A
+3217	PARENTHESIZED HANGUL CHIEUCH A
+3218	PARENTHESIZED HANGUL KHIEUKH A
+3219	PARENTHESIZED HANGUL THIEUTH A
+321A	PARENTHESIZED HANGUL PHIEUPH A
+321B	PARENTHESIZED HANGUL HIEUH A
+321C	PARENTHESIZED HANGUL CIEUC U
+3220	PARENTHESIZED IDEOGRAPH ONE
+3221	PARENTHESIZED IDEOGRAPH TWO
+3222	PARENTHESIZED IDEOGRAPH THREE
+3223	PARENTHESIZED IDEOGRAPH FOUR
+3224	PARENTHESIZED IDEOGRAPH FIVE
+3225	PARENTHESIZED IDEOGRAPH SIX
+3226	PARENTHESIZED IDEOGRAPH SEVEN
+3227	PARENTHESIZED IDEOGRAPH EIGHT
+3228	PARENTHESIZED IDEOGRAPH NINE
+3229	PARENTHESIZED IDEOGRAPH TEN
+322A	PARENTHESIZED IDEOGRAPH MOON
+322B	PARENTHESIZED IDEOGRAPH FIRE
+322C	PARENTHESIZED IDEOGRAPH WATER
+322D	PARENTHESIZED IDEOGRAPH WOOD
+322E	PARENTHESIZED IDEOGRAPH METAL
+322F	PARENTHESIZED IDEOGRAPH EARTH
+3230	PARENTHESIZED IDEOGRAPH SUN
+3231	PARENTHESIZED IDEOGRAPH STOCK
+3232	PARENTHESIZED IDEOGRAPH HAVE
+3233	PARENTHESIZED IDEOGRAPH SOCIETY
+3234	PARENTHESIZED IDEOGRAPH NAME
+3235	PARENTHESIZED IDEOGRAPH SPECIAL
+3236	PARENTHESIZED IDEOGRAPH FINANCIAL
+3237	PARENTHESIZED IDEOGRAPH CONGRATULATION
+3238	PARENTHESIZED IDEOGRAPH LABOR
+3239	PARENTHESIZED IDEOGRAPH REPRESENT
+323A	PARENTHESIZED IDEOGRAPH CALL
+323B	PARENTHESIZED IDEOGRAPH STUDY
+323C	PARENTHESIZED IDEOGRAPH SUPERVISE
+323D	PARENTHESIZED IDEOGRAPH ENTERPRISE
+323E	PARENTHESIZED IDEOGRAPH RESOURCE
+323F	PARENTHESIZED IDEOGRAPH ALLIANCE
+3240	PARENTHESIZED IDEOGRAPH FESTIVAL
+3241	PARENTHESIZED IDEOGRAPH REST
+3242	PARENTHESIZED IDEOGRAPH SELF
+3243	PARENTHESIZED IDEOGRAPH REACH
+3260	CIRCLED HANGUL KIYEOK
+3261	CIRCLED HANGUL NIEUN
+3262	CIRCLED HANGUL TIKEUT
+3263	CIRCLED HANGUL RIEUL
+3264	CIRCLED HANGUL MIEUM
+3265	CIRCLED HANGUL PIEUP
+3266	CIRCLED HANGUL SIOS
+3267	CIRCLED HANGUL IEUNG
+3268	CIRCLED HANGUL CIEUC
+3269	CIRCLED HANGUL CHIEUCH
+326A	CIRCLED HANGUL KHIEUKH
+326B	CIRCLED HANGUL THIEUTH
+326C	CIRCLED HANGUL PHIEUPH
+326D	CIRCLED HANGUL HIEUH
+326E	CIRCLED HANGUL KIYEOK A
+326F	CIRCLED HANGUL NIEUN A
+3270	CIRCLED HANGUL TIKEUT A
+3271	CIRCLED HANGUL RIEUL A
+3272	CIRCLED HANGUL MIEUM A
+3273	CIRCLED HANGUL PIEUP A
+3274	CIRCLED HANGUL SIOS A
+3275	CIRCLED HANGUL IEUNG A
+3276	CIRCLED HANGUL CIEUC A
+3277	CIRCLED HANGUL CHIEUCH A
+3278	CIRCLED HANGUL KHIEUKH A
+3279	CIRCLED HANGUL THIEUTH A
+327A	CIRCLED HANGUL PHIEUPH A
+327B	CIRCLED HANGUL HIEUH A
+327F	KOREAN STANDARD SYMBOL
+3280	CIRCLED IDEOGRAPH ONE
+3281	CIRCLED IDEOGRAPH TWO
+3282	CIRCLED IDEOGRAPH THREE
+3283	CIRCLED IDEOGRAPH FOUR
+3284	CIRCLED IDEOGRAPH FIVE
+3285	CIRCLED IDEOGRAPH SIX
+3286	CIRCLED IDEOGRAPH SEVEN
+3287	CIRCLED IDEOGRAPH EIGHT
+3288	CIRCLED IDEOGRAPH NINE
+3289	CIRCLED IDEOGRAPH TEN
+328A	CIRCLED IDEOGRAPH MOON
+328B	CIRCLED IDEOGRAPH FIRE
+328C	CIRCLED IDEOGRAPH WATER
+328D	CIRCLED IDEOGRAPH WOOD
+328E	CIRCLED IDEOGRAPH METAL
+328F	CIRCLED IDEOGRAPH EARTH
+3290	CIRCLED IDEOGRAPH SUN
+3291	CIRCLED IDEOGRAPH STOCK
+3292	CIRCLED IDEOGRAPH HAVE
+3293	CIRCLED IDEOGRAPH SOCIETY
+3294	CIRCLED IDEOGRAPH NAME
+3295	CIRCLED IDEOGRAPH SPECIAL
+3296	CIRCLED IDEOGRAPH FINANCIAL
+3297	CIRCLED IDEOGRAPH CONGRATULATION
+3298	CIRCLED IDEOGRAPH LABOR
+3299	CIRCLED IDEOGRAPH SECRET
+329A	CIRCLED IDEOGRAPH MALE
+329B	CIRCLED IDEOGRAPH FEMALE
+329C	CIRCLED IDEOGRAPH SUITABLE
+329D	CIRCLED IDEOGRAPH EXCELLENT
+329E	CIRCLED IDEOGRAPH PRINT
+329F	CIRCLED IDEOGRAPH ATTENTION
+32A0	CIRCLED IDEOGRAPH ITEM
+32A1	CIRCLED IDEOGRAPH REST
+32A2	CIRCLED IDEOGRAPH COPY
+32A3	CIRCLED IDEOGRAPH CORRECT
+32A4	CIRCLED IDEOGRAPH HIGH
+32A5	CIRCLED IDEOGRAPH CENTRE
+32A6	CIRCLED IDEOGRAPH LOW
+32A7	CIRCLED IDEOGRAPH LEFT
+32A8	CIRCLED IDEOGRAPH RIGHT
+32A9	CIRCLED IDEOGRAPH MEDICINE
+32AA	CIRCLED IDEOGRAPH RELIGION
+32AB	CIRCLED IDEOGRAPH STUDY
+32AC	CIRCLED IDEOGRAPH SUPERVISE
+32AD	CIRCLED IDEOGRAPH ENTERPRISE
+32AE	CIRCLED IDEOGRAPH RESOURCE
+32AF	CIRCLED IDEOGRAPH ALLIANCE
+32B0	CIRCLED IDEOGRAPH NIGHT
+32C0	IDEOGRAPHIC TELEGRAPH SYMBOL FOR JANUARY
+32C1	IDEOGRAPHIC TELEGRAPH SYMBOL FOR FEBRUARY
+32C2	IDEOGRAPHIC TELEGRAPH SYMBOL FOR MARCH
+32C3	IDEOGRAPHIC TELEGRAPH SYMBOL FOR APRIL
+32C4	IDEOGRAPHIC TELEGRAPH SYMBOL FOR MAY
+32C5	IDEOGRAPHIC TELEGRAPH SYMBOL FOR JUNE
+32C6	IDEOGRAPHIC TELEGRAPH SYMBOL FOR JULY
+32C7	IDEOGRAPHIC TELEGRAPH SYMBOL FOR AUGUST
+32C8	IDEOGRAPHIC TELEGRAPH SYMBOL FOR SEPTEMBER
+32C9	IDEOGRAPHIC TELEGRAPH SYMBOL FOR OCTOBER
+32CA	IDEOGRAPHIC TELEGRAPH SYMBOL FOR NOVEMBER
+32CB	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DECEMBER
+32D0	CIRCLED KATAKANA A
+32D1	CIRCLED KATAKANA I
+32D2	CIRCLED KATAKANA U
+32D3	CIRCLED KATAKANA E
+32D4	CIRCLED KATAKANA O
+32D5	CIRCLED KATAKANA KA
+32D6	CIRCLED KATAKANA KI
+32D7	CIRCLED KATAKANA KU
+32D8	CIRCLED KATAKANA KE
+32D9	CIRCLED KATAKANA KO
+32DA	CIRCLED KATAKANA SA
+32DB	CIRCLED KATAKANA SI
+32DC	CIRCLED KATAKANA SU
+32DD	CIRCLED KATAKANA SE
+32DE	CIRCLED KATAKANA SO
+32DF	CIRCLED KATAKANA TA
+32E0	CIRCLED KATAKANA TI
+32E1	CIRCLED KATAKANA TU
+32E2	CIRCLED KATAKANA TE
+32E3	CIRCLED KATAKANA TO
+32E4	CIRCLED KATAKANA NA
+32E5	CIRCLED KATAKANA NI
+32E6	CIRCLED KATAKANA NU
+32E7	CIRCLED KATAKANA NE
+32E8	CIRCLED KATAKANA NO
+32E9	CIRCLED KATAKANA HA
+32EA	CIRCLED KATAKANA HI
+32EB	CIRCLED KATAKANA HU
+32EC	CIRCLED KATAKANA HE
+32ED	CIRCLED KATAKANA HO
+32EE	CIRCLED KATAKANA MA
+32EF	CIRCLED KATAKANA MI
+32F0	CIRCLED KATAKANA MU
+32F1	CIRCLED KATAKANA ME
+32F2	CIRCLED KATAKANA MO
+32F3	CIRCLED KATAKANA YA
+32F4	CIRCLED KATAKANA YU
+32F5	CIRCLED KATAKANA YO
+32F6	CIRCLED KATAKANA RA
+32F7	CIRCLED KATAKANA RI
+32F8	CIRCLED KATAKANA RU
+32F9	CIRCLED KATAKANA RE
+32FA	CIRCLED KATAKANA RO
+32FB	CIRCLED KATAKANA WA
+32FC	CIRCLED KATAKANA WI
+32FD	CIRCLED KATAKANA WE
+32FE	CIRCLED KATAKANA WO
+3300	SQUARE APAATO
+3301	SQUARE ARUHUA
+3302	SQUARE ANPEA
+3303	SQUARE AARU
+3304	SQUARE ININGU
+3305	SQUARE INTI
+3306	SQUARE UON
+3307	SQUARE ESUKUUDO
+3308	SQUARE EEKAA
+3309	SQUARE ONSU
+330A	SQUARE OOMU
+330B	SQUARE KAIRI
+330C	SQUARE KARATTO
+330D	SQUARE KARORII
+330E	SQUARE GARON
+330F	SQUARE GANMA
+3310	SQUARE GIGA
+3311	SQUARE GINII
+3312	SQUARE KYURII
+3313	SQUARE GIRUDAA
+3314	SQUARE KIRO
+3315	SQUARE KIROGURAMU
+3316	SQUARE KIROMEETORU
+3317	SQUARE KIROWATTO
+3318	SQUARE GURAMU
+3319	SQUARE GURAMUTON
+331A	SQUARE KURUZEIRO
+331B	SQUARE KUROONE
+331C	SQUARE KEESU
+331D	SQUARE KORUNA
+331E	SQUARE KOOPO
+331F	SQUARE SAIKURU
+3320	SQUARE SANTIIMU
+3321	SQUARE SIRINGU
+3322	SQUARE SENTI
+3323	SQUARE SENTO
+3324	SQUARE DAASU
+3325	SQUARE DESI
+3326	SQUARE DORU
+3327	SQUARE TON
+3328	SQUARE NANO
+3329	SQUARE NOTTO
+332A	SQUARE HAITU
+332B	SQUARE PAASENTO
+332C	SQUARE PAATU
+332D	SQUARE BAARERU
+332E	SQUARE PIASUTORU
+332F	SQUARE PIKURU
+3330	SQUARE PIKO
+3331	SQUARE BIRU
+3332	SQUARE HUARADDO
+3333	SQUARE HUIITO
+3334	SQUARE BUSSYERU
+3335	SQUARE HURAN
+3336	SQUARE HEKUTAARU
+3337	SQUARE PESO
+3338	SQUARE PENIHI
+3339	SQUARE HERUTU
+333A	SQUARE PENSU
+333B	SQUARE PEEZI
+333C	SQUARE BEETA
+333D	SQUARE POINTO
+333E	SQUARE BORUTO
+333F	SQUARE HON
+3340	SQUARE PONDO
+3341	SQUARE HOORU
+3342	SQUARE HOON
+3343	SQUARE MAIKURO
+3344	SQUARE MAIRU
+3345	SQUARE MAHHA
+3346	SQUARE MARUKU
+3347	SQUARE MANSYON
+3348	SQUARE MIKURON
+3349	SQUARE MIRI
+334A	SQUARE MIRIBAARU
+334B	SQUARE MEGA
+334C	SQUARE MEGATON
+334D	SQUARE MEETORU
+334E	SQUARE YAADO
+334F	SQUARE YAARU
+3350	SQUARE YUAN
+3351	SQUARE RITTORU
+3352	SQUARE RIRA
+3353	SQUARE RUPII
+3354	SQUARE RUUBURU
+3355	SQUARE REMU
+3356	SQUARE RENTOGEN
+3357	SQUARE WATTO
+3358	IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ZERO
+3359	IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ONE
+335A	IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWO
+335B	IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THREE
+335C	IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOUR
+335D	IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIVE
+335E	IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIX
+335F	IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVEN
+3360	IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHT
+3361	IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINE
+3362	IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TEN
+3363	IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ELEVEN
+3364	IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWELVE
+3365	IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THIRTEEN
+3366	IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOURTEEN
+3367	IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIFTEEN
+3368	IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIXTEEN
+3369	IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVENTEEN
+336A	IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHTEEN
+336B	IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINETEEN
+336C	IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY
+336D	IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-ONE
+336E	IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-TWO
+336F	IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-THREE
+3370	IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-FOUR
+3371	SQUARE HPA
+3372	SQUARE DA
+3373	SQUARE AU
+3374	SQUARE BAR
+3375	SQUARE OV
+3376	SQUARE PC
+337B	SQUARE ERA NAME HEISEI
+337C	SQUARE ERA NAME SYOUWA
+337D	SQUARE ERA NAME TAISYOU
+337E	SQUARE ERA NAME MEIZI
+337F	SQUARE CORPORATION
+3380	SQUARE PA AMPS
+3381	SQUARE NA
+3382	SQUARE MU A
+3383	SQUARE MA
+3384	SQUARE KA
+3385	SQUARE KB
+3386	SQUARE MB
+3387	SQUARE GB
+3388	SQUARE CAL
+3389	SQUARE KCAL
+338A	SQUARE PF
+338B	SQUARE NF
+338C	SQUARE MU F
+338D	SQUARE MU G
+338E	SQUARE MG
+338F	SQUARE KG
+3390	SQUARE HZ
+3391	SQUARE KHZ
+3392	SQUARE MHZ
+3393	SQUARE GHZ
+3394	SQUARE THZ
+3395	SQUARE MU L
+3396	SQUARE ML
+3397	SQUARE DL
+3398	SQUARE KL
+3399	SQUARE FM
+339A	SQUARE NM
+339B	SQUARE MU M
+339C	SQUARE MM
+339D	SQUARE CM
+339E	SQUARE KM
+339F	SQUARE MM SQUARED
+33A0	SQUARE CM SQUARED
+33A1	SQUARE M SQUARED
+33A2	SQUARE KM SQUARED
+33A3	SQUARE MM CUBED
+33A4	SQUARE CM CUBED
+33A5	SQUARE M CUBED
+33A6	SQUARE KM CUBED
+33A7	SQUARE M OVER S
+33A8	SQUARE M OVER S SQUARED
+33A9	SQUARE PA
+33AA	SQUARE KPA
+33AB	SQUARE MPA
+33AC	SQUARE GPA
+33AD	SQUARE RAD
+33AE	SQUARE RAD OVER S
+33AF	SQUARE RAD OVER S SQUARED
+33B0	SQUARE PS
+33B1	SQUARE NS
+33B2	SQUARE MU S
+33B3	SQUARE MS
+33B4	SQUARE PV
+33B5	SQUARE NV
+33B6	SQUARE MU V
+33B7	SQUARE MV
+33B8	SQUARE KV
+33B9	SQUARE MV MEGA
+33BA	SQUARE PW
+33BB	SQUARE NW
+33BC	SQUARE MU W
+33BD	SQUARE MW
+33BE	SQUARE KW
+33BF	SQUARE MW MEGA
+33C0	SQUARE K OHM
+33C1	SQUARE M OHM
+33C2	SQUARE AM
+33C3	SQUARE BQ
+33C4	SQUARE CC
+33C5	SQUARE CD
+33C6	SQUARE C OVER KG
+33C7	SQUARE CO
+33C8	SQUARE DB
+33C9	SQUARE GY
+33CA	SQUARE HA
+33CB	SQUARE HP
+33CC	SQUARE IN
+33CD	SQUARE KK
+33CE	SQUARE KM CAPITAL
+33CF	SQUARE KT
+33D0	SQUARE LM
+33D1	SQUARE LN
+33D2	SQUARE LOG
+33D3	SQUARE LX
+33D4	SQUARE MB SMALL
+33D5	SQUARE MIL
+33D6	SQUARE MOL
+33D7	SQUARE PH
+33D8	SQUARE PM
+33D9	SQUARE PPM
+33DA	SQUARE PR
+33DB	SQUARE SR
+33DC	SQUARE SV
+33DD	SQUARE WB
+33E0	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ONE
+33E1	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWO
+33E2	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THREE
+33E3	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOUR
+33E4	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIVE
+33E5	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIX
+33E6	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVEN
+33E7	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHT
+33E8	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINE
+33E9	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TEN
+33EA	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ELEVEN
+33EB	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWELVE
+33EC	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTEEN
+33ED	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOURTEEN
+33EE	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIFTEEN
+33EF	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIXTEEN
+33F0	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVENTEEN
+33F1	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHTEEN
+33F2	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINETEEN
+33F3	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY
+33F4	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-ONE
+33F5	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-TWO
+33F6	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-THREE
+33F7	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FOUR
+33F8	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FIVE
+33F9	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SIX
+33FA	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SEVEN
+33FB	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-EIGHT
+33FC	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-NINE
+33FD	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY
+33FE	IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY-ONE
+4E00	<CJK Ideograph, First>
+9FA5	<CJK Ideograph, Last>
+AC00	<Hangul Syllable, First>
+D7A3	<Hangul Syllable, Last>
+D800	<Unassigned High Surrogate, First>
+DB7F	<Unassigned High Surrogate, Last>
+DB80	<Private Use High Surrogate, First>
+DBFF	<Private Use High Surrogate, Last>
+DC00	<Low Surrogate, First>
+DFFF	<Low Surrogate, Last>
+E000	<Private Use, First>
+F8FF	<Private Use, Last>
+F900	<CJK Compatibility Ideograph, First>
+FA2D	<CJK Compatibility Ideograph, Last>
+FB00	LATIN SMALL LIGATURE FF
+FB01	LATIN SMALL LIGATURE FI
+FB02	LATIN SMALL LIGATURE FL
+FB03	LATIN SMALL LIGATURE FFI
+FB04	LATIN SMALL LIGATURE FFL
+FB05	LATIN SMALL LIGATURE LONG S T
+FB06	LATIN SMALL LIGATURE ST
+FB13	ARMENIAN SMALL LIGATURE MEN NOW
+FB14	ARMENIAN SMALL LIGATURE MEN ECH
+FB15	ARMENIAN SMALL LIGATURE MEN INI
+FB16	ARMENIAN SMALL LIGATURE VEW NOW
+FB17	ARMENIAN SMALL LIGATURE MEN XEH
+FB1E	HEBREW POINT JUDEO-SPANISH VARIKA
+FB1F	HEBREW LIGATURE YIDDISH YOD YOD PATAH
+FB20	HEBREW LETTER ALTERNATIVE AYIN
+FB21	HEBREW LETTER WIDE ALEF
+FB22	HEBREW LETTER WIDE DALET
+FB23	HEBREW LETTER WIDE HE
+FB24	HEBREW LETTER WIDE KAF
+FB25	HEBREW LETTER WIDE LAMED
+FB26	HEBREW LETTER WIDE FINAL MEM
+FB27	HEBREW LETTER WIDE RESH
+FB28	HEBREW LETTER WIDE TAV
+FB29	HEBREW LETTER ALTERNATIVE PLUS SIGN
+FB2A	HEBREW LETTER SHIN WITH SHIN DOT
+FB2B	HEBREW LETTER SHIN WITH SIN DOT
+FB2C	HEBREW LETTER SHIN WITH DAGESH AND SHIN DOT
+FB2D	HEBREW LETTER SHIN WITH DAGESH AND SIN DOT
+FB2E	HEBREW LETTER ALEF WITH PATAH
+FB2F	HEBREW LETTER ALEF WITH QAMATS
+FB30	HEBREW LETTER ALEF WITH MAPIQ
+FB31	HEBREW LETTER BET WITH DAGESH
+FB32	HEBREW LETTER GIMEL WITH DAGESH
+FB33	HEBREW LETTER DALET WITH DAGESH
+FB34	HEBREW LETTER HE WITH MAPIQ
+FB35	HEBREW LETTER VAV WITH DAGESH
+FB36	HEBREW LETTER ZAYIN WITH DAGESH
+FB38	HEBREW LETTER TET WITH DAGESH
+FB39	HEBREW LETTER YOD WITH DAGESH
+FB3A	HEBREW LETTER FINAL KAF WITH DAGESH
+FB3B	HEBREW LETTER KAF WITH DAGESH
+FB3C	HEBREW LETTER LAMED WITH DAGESH
+FB3E	HEBREW LETTER MEM WITH DAGESH
+FB40	HEBREW LETTER NUN WITH DAGESH
+FB41	HEBREW LETTER SAMEKH WITH DAGESH
+FB43	HEBREW LETTER FINAL PE WITH DAGESH
+FB44	HEBREW LETTER PE WITH DAGESH
+FB46	HEBREW LETTER TSADI WITH DAGESH
+FB47	HEBREW LETTER QOF WITH DAGESH
+FB48	HEBREW LETTER RESH WITH DAGESH
+FB49	HEBREW LETTER SHIN WITH DAGESH
+FB4A	HEBREW LETTER TAV WITH DAGESH
+FB4B	HEBREW LETTER VAV WITH HOLAM
+FB4C	HEBREW LETTER BET WITH RAFE
+FB4D	HEBREW LETTER KAF WITH RAFE
+FB4E	HEBREW LETTER PE WITH RAFE
+FB4F	HEBREW LIGATURE ALEF LAMED
+FB50	ARABIC LETTER ALEF WASLA ISOLATED FORM
+FB51	ARABIC LETTER ALEF WASLA FINAL FORM
+FB52	ARABIC LETTER BEEH ISOLATED FORM
+FB53	ARABIC LETTER BEEH FINAL FORM
+FB54	ARABIC LETTER BEEH INITIAL FORM
+FB55	ARABIC LETTER BEEH MEDIAL FORM
+FB56	ARABIC LETTER PEH ISOLATED FORM
+FB57	ARABIC LETTER PEH FINAL FORM
+FB58	ARABIC LETTER PEH INITIAL FORM
+FB59	ARABIC LETTER PEH MEDIAL FORM
+FB5A	ARABIC LETTER BEHEH ISOLATED FORM
+FB5B	ARABIC LETTER BEHEH FINAL FORM
+FB5C	ARABIC LETTER BEHEH INITIAL FORM
+FB5D	ARABIC LETTER BEHEH MEDIAL FORM
+FB5E	ARABIC LETTER TTEHEH ISOLATED FORM
+FB5F	ARABIC LETTER TTEHEH FINAL FORM
+FB60	ARABIC LETTER TTEHEH INITIAL FORM
+FB61	ARABIC LETTER TTEHEH MEDIAL FORM
+FB62	ARABIC LETTER TEHEH ISOLATED FORM
+FB63	ARABIC LETTER TEHEH FINAL FORM
+FB64	ARABIC LETTER TEHEH INITIAL FORM
+FB65	ARABIC LETTER TEHEH MEDIAL FORM
+FB66	ARABIC LETTER TTEH ISOLATED FORM
+FB67	ARABIC LETTER TTEH FINAL FORM
+FB68	ARABIC LETTER TTEH INITIAL FORM
+FB69	ARABIC LETTER TTEH MEDIAL FORM
+FB6A	ARABIC LETTER VEH ISOLATED FORM
+FB6B	ARABIC LETTER VEH FINAL FORM
+FB6C	ARABIC LETTER VEH INITIAL FORM
+FB6D	ARABIC LETTER VEH MEDIAL FORM
+FB6E	ARABIC LETTER PEHEH ISOLATED FORM
+FB6F	ARABIC LETTER PEHEH FINAL FORM
+FB70	ARABIC LETTER PEHEH INITIAL FORM
+FB71	ARABIC LETTER PEHEH MEDIAL FORM
+FB72	ARABIC LETTER DYEH ISOLATED FORM
+FB73	ARABIC LETTER DYEH FINAL FORM
+FB74	ARABIC LETTER DYEH INITIAL FORM
+FB75	ARABIC LETTER DYEH MEDIAL FORM
+FB76	ARABIC LETTER NYEH ISOLATED FORM
+FB77	ARABIC LETTER NYEH FINAL FORM
+FB78	ARABIC LETTER NYEH INITIAL FORM
+FB79	ARABIC LETTER NYEH MEDIAL FORM
+FB7A	ARABIC LETTER TCHEH ISOLATED FORM
+FB7B	ARABIC LETTER TCHEH FINAL FORM
+FB7C	ARABIC LETTER TCHEH INITIAL FORM
+FB7D	ARABIC LETTER TCHEH MEDIAL FORM
+FB7E	ARABIC LETTER TCHEHEH ISOLATED FORM
+FB7F	ARABIC LETTER TCHEHEH FINAL FORM
+FB80	ARABIC LETTER TCHEHEH INITIAL FORM
+FB81	ARABIC LETTER TCHEHEH MEDIAL FORM
+FB82	ARABIC LETTER DDAHAL ISOLATED FORM
+FB83	ARABIC LETTER DDAHAL FINAL FORM
+FB84	ARABIC LETTER DAHAL ISOLATED FORM
+FB85	ARABIC LETTER DAHAL FINAL FORM
+FB86	ARABIC LETTER DUL ISOLATED FORM
+FB87	ARABIC LETTER DUL FINAL FORM
+FB88	ARABIC LETTER DDAL ISOLATED FORM
+FB89	ARABIC LETTER DDAL FINAL FORM
+FB8A	ARABIC LETTER JEH ISOLATED FORM
+FB8B	ARABIC LETTER JEH FINAL FORM
+FB8C	ARABIC LETTER RREH ISOLATED FORM
+FB8D	ARABIC LETTER RREH FINAL FORM
+FB8E	ARABIC LETTER KEHEH ISOLATED FORM
+FB8F	ARABIC LETTER KEHEH FINAL FORM
+FB90	ARABIC LETTER KEHEH INITIAL FORM
+FB91	ARABIC LETTER KEHEH MEDIAL FORM
+FB92	ARABIC LETTER GAF ISOLATED FORM
+FB93	ARABIC LETTER GAF FINAL FORM
+FB94	ARABIC LETTER GAF INITIAL FORM
+FB95	ARABIC LETTER GAF MEDIAL FORM
+FB96	ARABIC LETTER GUEH ISOLATED FORM
+FB97	ARABIC LETTER GUEH FINAL FORM
+FB98	ARABIC LETTER GUEH INITIAL FORM
+FB99	ARABIC LETTER GUEH MEDIAL FORM
+FB9A	ARABIC LETTER NGOEH ISOLATED FORM
+FB9B	ARABIC LETTER NGOEH FINAL FORM
+FB9C	ARABIC LETTER NGOEH INITIAL FORM
+FB9D	ARABIC LETTER NGOEH MEDIAL FORM
+FB9E	ARABIC LETTER NOON GHUNNA ISOLATED FORM
+FB9F	ARABIC LETTER NOON GHUNNA FINAL FORM
+FBA0	ARABIC LETTER RNOON ISOLATED FORM
+FBA1	ARABIC LETTER RNOON FINAL FORM
+FBA2	ARABIC LETTER RNOON INITIAL FORM
+FBA3	ARABIC LETTER RNOON MEDIAL FORM
+FBA4	ARABIC LETTER HEH WITH YEH ABOVE ISOLATED FORM
+FBA5	ARABIC LETTER HEH WITH YEH ABOVE FINAL FORM
+FBA6	ARABIC LETTER HEH GOAL ISOLATED FORM
+FBA7	ARABIC LETTER HEH GOAL FINAL FORM
+FBA8	ARABIC LETTER HEH GOAL INITIAL FORM
+FBA9	ARABIC LETTER HEH GOAL MEDIAL FORM
+FBAA	ARABIC LETTER HEH DOACHASHMEE ISOLATED FORM
+FBAB	ARABIC LETTER HEH DOACHASHMEE FINAL FORM
+FBAC	ARABIC LETTER HEH DOACHASHMEE INITIAL FORM
+FBAD	ARABIC LETTER HEH DOACHASHMEE MEDIAL FORM
+FBAE	ARABIC LETTER YEH BARREE ISOLATED FORM
+FBAF	ARABIC LETTER YEH BARREE FINAL FORM
+FBB0	ARABIC LETTER YEH BARREE WITH HAMZA ABOVE ISOLATED FORM
+FBB1	ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM
+FBD3	ARABIC LETTER NG ISOLATED FORM
+FBD4	ARABIC LETTER NG FINAL FORM
+FBD5	ARABIC LETTER NG INITIAL FORM
+FBD6	ARABIC LETTER NG MEDIAL FORM
+FBD7	ARABIC LETTER U ISOLATED FORM
+FBD8	ARABIC LETTER U FINAL FORM
+FBD9	ARABIC LETTER OE ISOLATED FORM
+FBDA	ARABIC LETTER OE FINAL FORM
+FBDB	ARABIC LETTER YU ISOLATED FORM
+FBDC	ARABIC LETTER YU FINAL FORM
+FBDD	ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM
+FBDE	ARABIC LETTER VE ISOLATED FORM
+FBDF	ARABIC LETTER VE FINAL FORM
+FBE0	ARABIC LETTER KIRGHIZ OE ISOLATED FORM
+FBE1	ARABIC LETTER KIRGHIZ OE FINAL FORM
+FBE2	ARABIC LETTER KIRGHIZ YU ISOLATED FORM
+FBE3	ARABIC LETTER KIRGHIZ YU FINAL FORM
+FBE4	ARABIC LETTER E ISOLATED FORM
+FBE5	ARABIC LETTER E FINAL FORM
+FBE6	ARABIC LETTER E INITIAL FORM
+FBE7	ARABIC LETTER E MEDIAL FORM
+FBE8	ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA INITIAL FORM
+FBE9	ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA MEDIAL FORM
+FBEA	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF ISOLATED FORM
+FBEB	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF FINAL FORM
+FBEC	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE ISOLATED FORM
+FBED	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE FINAL FORM
+FBEE	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW ISOLATED FORM
+FBEF	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW FINAL FORM
+FBF0	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U ISOLATED FORM
+FBF1	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U FINAL FORM
+FBF2	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE ISOLATED FORM
+FBF3	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE FINAL FORM
+FBF4	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU ISOLATED FORM
+FBF5	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU FINAL FORM
+FBF6	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E ISOLATED FORM
+FBF7	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E FINAL FORM
+FBF8	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E INITIAL FORM
+FBF9	ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM
+FBFA	ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM
+FBFB	ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA INITIAL FORM
+FBFC	ARABIC LETTER FARSI YEH ISOLATED FORM
+FBFD	ARABIC LETTER FARSI YEH FINAL FORM
+FBFE	ARABIC LETTER FARSI YEH INITIAL FORM
+FBFF	ARABIC LETTER FARSI YEH MEDIAL FORM
+FC00	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM ISOLATED FORM
+FC01	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH ISOLATED FORM
+FC02	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM ISOLATED FORM
+FC03	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM
+FC04	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH ISOLATED FORM
+FC05	ARABIC LIGATURE BEH WITH JEEM ISOLATED FORM
+FC06	ARABIC LIGATURE BEH WITH HAH ISOLATED FORM
+FC07	ARABIC LIGATURE BEH WITH KHAH ISOLATED FORM
+FC08	ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM
+FC09	ARABIC LIGATURE BEH WITH ALEF MAKSURA ISOLATED FORM
+FC0A	ARABIC LIGATURE BEH WITH YEH ISOLATED FORM
+FC0B	ARABIC LIGATURE TEH WITH JEEM ISOLATED FORM
+FC0C	ARABIC LIGATURE TEH WITH HAH ISOLATED FORM
+FC0D	ARABIC LIGATURE TEH WITH KHAH ISOLATED FORM
+FC0E	ARABIC LIGATURE TEH WITH MEEM ISOLATED FORM
+FC0F	ARABIC LIGATURE TEH WITH ALEF MAKSURA ISOLATED FORM
+FC10	ARABIC LIGATURE TEH WITH YEH ISOLATED FORM
+FC11	ARABIC LIGATURE THEH WITH JEEM ISOLATED FORM
+FC12	ARABIC LIGATURE THEH WITH MEEM ISOLATED FORM
+FC13	ARABIC LIGATURE THEH WITH ALEF MAKSURA ISOLATED FORM
+FC14	ARABIC LIGATURE THEH WITH YEH ISOLATED FORM
+FC15	ARABIC LIGATURE JEEM WITH HAH ISOLATED FORM
+FC16	ARABIC LIGATURE JEEM WITH MEEM ISOLATED FORM
+FC17	ARABIC LIGATURE HAH WITH JEEM ISOLATED FORM
+FC18	ARABIC LIGATURE HAH WITH MEEM ISOLATED FORM
+FC19	ARABIC LIGATURE KHAH WITH JEEM ISOLATED FORM
+FC1A	ARABIC LIGATURE KHAH WITH HAH ISOLATED FORM
+FC1B	ARABIC LIGATURE KHAH WITH MEEM ISOLATED FORM
+FC1C	ARABIC LIGATURE SEEN WITH JEEM ISOLATED FORM
+FC1D	ARABIC LIGATURE SEEN WITH HAH ISOLATED FORM
+FC1E	ARABIC LIGATURE SEEN WITH KHAH ISOLATED FORM
+FC1F	ARABIC LIGATURE SEEN WITH MEEM ISOLATED FORM
+FC20	ARABIC LIGATURE SAD WITH HAH ISOLATED FORM
+FC21	ARABIC LIGATURE SAD WITH MEEM ISOLATED FORM
+FC22	ARABIC LIGATURE DAD WITH JEEM ISOLATED FORM
+FC23	ARABIC LIGATURE DAD WITH HAH ISOLATED FORM
+FC24	ARABIC LIGATURE DAD WITH KHAH ISOLATED FORM
+FC25	ARABIC LIGATURE DAD WITH MEEM ISOLATED FORM
+FC26	ARABIC LIGATURE TAH WITH HAH ISOLATED FORM
+FC27	ARABIC LIGATURE TAH WITH MEEM ISOLATED FORM
+FC28	ARABIC LIGATURE ZAH WITH MEEM ISOLATED FORM
+FC29	ARABIC LIGATURE AIN WITH JEEM ISOLATED FORM
+FC2A	ARABIC LIGATURE AIN WITH MEEM ISOLATED FORM
+FC2B	ARABIC LIGATURE GHAIN WITH JEEM ISOLATED FORM
+FC2C	ARABIC LIGATURE GHAIN WITH MEEM ISOLATED FORM
+FC2D	ARABIC LIGATURE FEH WITH JEEM ISOLATED FORM
+FC2E	ARABIC LIGATURE FEH WITH HAH ISOLATED FORM
+FC2F	ARABIC LIGATURE FEH WITH KHAH ISOLATED FORM
+FC30	ARABIC LIGATURE FEH WITH MEEM ISOLATED FORM
+FC31	ARABIC LIGATURE FEH WITH ALEF MAKSURA ISOLATED FORM
+FC32	ARABIC LIGATURE FEH WITH YEH ISOLATED FORM
+FC33	ARABIC LIGATURE QAF WITH HAH ISOLATED FORM
+FC34	ARABIC LIGATURE QAF WITH MEEM ISOLATED FORM
+FC35	ARABIC LIGATURE QAF WITH ALEF MAKSURA ISOLATED FORM
+FC36	ARABIC LIGATURE QAF WITH YEH ISOLATED FORM
+FC37	ARABIC LIGATURE KAF WITH ALEF ISOLATED FORM
+FC38	ARABIC LIGATURE KAF WITH JEEM ISOLATED FORM
+FC39	ARABIC LIGATURE KAF WITH HAH ISOLATED FORM
+FC3A	ARABIC LIGATURE KAF WITH KHAH ISOLATED FORM
+FC3B	ARABIC LIGATURE KAF WITH LAM ISOLATED FORM
+FC3C	ARABIC LIGATURE KAF WITH MEEM ISOLATED FORM
+FC3D	ARABIC LIGATURE KAF WITH ALEF MAKSURA ISOLATED FORM
+FC3E	ARABIC LIGATURE KAF WITH YEH ISOLATED FORM
+FC3F	ARABIC LIGATURE LAM WITH JEEM ISOLATED FORM
+FC40	ARABIC LIGATURE LAM WITH HAH ISOLATED FORM
+FC41	ARABIC LIGATURE LAM WITH KHAH ISOLATED FORM
+FC42	ARABIC LIGATURE LAM WITH MEEM ISOLATED FORM
+FC43	ARABIC LIGATURE LAM WITH ALEF MAKSURA ISOLATED FORM
+FC44	ARABIC LIGATURE LAM WITH YEH ISOLATED FORM
+FC45	ARABIC LIGATURE MEEM WITH JEEM ISOLATED FORM
+FC46	ARABIC LIGATURE MEEM WITH HAH ISOLATED FORM
+FC47	ARABIC LIGATURE MEEM WITH KHAH ISOLATED FORM
+FC48	ARABIC LIGATURE MEEM WITH MEEM ISOLATED FORM
+FC49	ARABIC LIGATURE MEEM WITH ALEF MAKSURA ISOLATED FORM
+FC4A	ARABIC LIGATURE MEEM WITH YEH ISOLATED FORM
+FC4B	ARABIC LIGATURE NOON WITH JEEM ISOLATED FORM
+FC4C	ARABIC LIGATURE NOON WITH HAH ISOLATED FORM
+FC4D	ARABIC LIGATURE NOON WITH KHAH ISOLATED FORM
+FC4E	ARABIC LIGATURE NOON WITH MEEM ISOLATED FORM
+FC4F	ARABIC LIGATURE NOON WITH ALEF MAKSURA ISOLATED FORM
+FC50	ARABIC LIGATURE NOON WITH YEH ISOLATED FORM
+FC51	ARABIC LIGATURE HEH WITH JEEM ISOLATED FORM
+FC52	ARABIC LIGATURE HEH WITH MEEM ISOLATED FORM
+FC53	ARABIC LIGATURE HEH WITH ALEF MAKSURA ISOLATED FORM
+FC54	ARABIC LIGATURE HEH WITH YEH ISOLATED FORM
+FC55	ARABIC LIGATURE YEH WITH JEEM ISOLATED FORM
+FC56	ARABIC LIGATURE YEH WITH HAH ISOLATED FORM
+FC57	ARABIC LIGATURE YEH WITH KHAH ISOLATED FORM
+FC58	ARABIC LIGATURE YEH WITH MEEM ISOLATED FORM
+FC59	ARABIC LIGATURE YEH WITH ALEF MAKSURA ISOLATED FORM
+FC5A	ARABIC LIGATURE YEH WITH YEH ISOLATED FORM
+FC5B	ARABIC LIGATURE THAL WITH SUPERSCRIPT ALEF ISOLATED FORM
+FC5C	ARABIC LIGATURE REH WITH SUPERSCRIPT ALEF ISOLATED FORM
+FC5D	ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF ISOLATED FORM
+FC5E	ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM
+FC5F	ARABIC LIGATURE SHADDA WITH KASRATAN ISOLATED FORM
+FC60	ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM
+FC61	ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM
+FC62	ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM
+FC63	ARABIC LIGATURE SHADDA WITH SUPERSCRIPT ALEF ISOLATED FORM
+FC64	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH REH FINAL FORM
+FC65	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ZAIN FINAL FORM
+FC66	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM FINAL FORM
+FC67	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH NOON FINAL FORM
+FC68	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM
+FC69	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH FINAL FORM
+FC6A	ARABIC LIGATURE BEH WITH REH FINAL FORM
+FC6B	ARABIC LIGATURE BEH WITH ZAIN FINAL FORM
+FC6C	ARABIC LIGATURE BEH WITH MEEM FINAL FORM
+FC6D	ARABIC LIGATURE BEH WITH NOON FINAL FORM
+FC6E	ARABIC LIGATURE BEH WITH ALEF MAKSURA FINAL FORM
+FC6F	ARABIC LIGATURE BEH WITH YEH FINAL FORM
+FC70	ARABIC LIGATURE TEH WITH REH FINAL FORM
+FC71	ARABIC LIGATURE TEH WITH ZAIN FINAL FORM
+FC72	ARABIC LIGATURE TEH WITH MEEM FINAL FORM
+FC73	ARABIC LIGATURE TEH WITH NOON FINAL FORM
+FC74	ARABIC LIGATURE TEH WITH ALEF MAKSURA FINAL FORM
+FC75	ARABIC LIGATURE TEH WITH YEH FINAL FORM
+FC76	ARABIC LIGATURE THEH WITH REH FINAL FORM
+FC77	ARABIC LIGATURE THEH WITH ZAIN FINAL FORM
+FC78	ARABIC LIGATURE THEH WITH MEEM FINAL FORM
+FC79	ARABIC LIGATURE THEH WITH NOON FINAL FORM
+FC7A	ARABIC LIGATURE THEH WITH ALEF MAKSURA FINAL FORM
+FC7B	ARABIC LIGATURE THEH WITH YEH FINAL FORM
+FC7C	ARABIC LIGATURE FEH WITH ALEF MAKSURA FINAL FORM
+FC7D	ARABIC LIGATURE FEH WITH YEH FINAL FORM
+FC7E	ARABIC LIGATURE QAF WITH ALEF MAKSURA FINAL FORM
+FC7F	ARABIC LIGATURE QAF WITH YEH FINAL FORM
+FC80	ARABIC LIGATURE KAF WITH ALEF FINAL FORM
+FC81	ARABIC LIGATURE KAF WITH LAM FINAL FORM
+FC82	ARABIC LIGATURE KAF WITH MEEM FINAL FORM
+FC83	ARABIC LIGATURE KAF WITH ALEF MAKSURA FINAL FORM
+FC84	ARABIC LIGATURE KAF WITH YEH FINAL FORM
+FC85	ARABIC LIGATURE LAM WITH MEEM FINAL FORM
+FC86	ARABIC LIGATURE LAM WITH ALEF MAKSURA FINAL FORM
+FC87	ARABIC LIGATURE LAM WITH YEH FINAL FORM
+FC88	ARABIC LIGATURE MEEM WITH ALEF FINAL FORM
+FC89	ARABIC LIGATURE MEEM WITH MEEM FINAL FORM
+FC8A	ARABIC LIGATURE NOON WITH REH FINAL FORM
+FC8B	ARABIC LIGATURE NOON WITH ZAIN FINAL FORM
+FC8C	ARABIC LIGATURE NOON WITH MEEM FINAL FORM
+FC8D	ARABIC LIGATURE NOON WITH NOON FINAL FORM
+FC8E	ARABIC LIGATURE NOON WITH ALEF MAKSURA FINAL FORM
+FC8F	ARABIC LIGATURE NOON WITH YEH FINAL FORM
+FC90	ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF FINAL FORM
+FC91	ARABIC LIGATURE YEH WITH REH FINAL FORM
+FC92	ARABIC LIGATURE YEH WITH ZAIN FINAL FORM
+FC93	ARABIC LIGATURE YEH WITH MEEM FINAL FORM
+FC94	ARABIC LIGATURE YEH WITH NOON FINAL FORM
+FC95	ARABIC LIGATURE YEH WITH ALEF MAKSURA FINAL FORM
+FC96	ARABIC LIGATURE YEH WITH YEH FINAL FORM
+FC97	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM INITIAL FORM
+FC98	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH INITIAL FORM
+FC99	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH KHAH INITIAL FORM
+FC9A	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM INITIAL FORM
+FC9B	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH INITIAL FORM
+FC9C	ARABIC LIGATURE BEH WITH JEEM INITIAL FORM
+FC9D	ARABIC LIGATURE BEH WITH HAH INITIAL FORM
+FC9E	ARABIC LIGATURE BEH WITH KHAH INITIAL FORM
+FC9F	ARABIC LIGATURE BEH WITH MEEM INITIAL FORM
+FCA0	ARABIC LIGATURE BEH WITH HEH INITIAL FORM
+FCA1	ARABIC LIGATURE TEH WITH JEEM INITIAL FORM
+FCA2	ARABIC LIGATURE TEH WITH HAH INITIAL FORM
+FCA3	ARABIC LIGATURE TEH WITH KHAH INITIAL FORM
+FCA4	ARABIC LIGATURE TEH WITH MEEM INITIAL FORM
+FCA5	ARABIC LIGATURE TEH WITH HEH INITIAL FORM
+FCA6	ARABIC LIGATURE THEH WITH MEEM INITIAL FORM
+FCA7	ARABIC LIGATURE JEEM WITH HAH INITIAL FORM
+FCA8	ARABIC LIGATURE JEEM WITH MEEM INITIAL FORM
+FCA9	ARABIC LIGATURE HAH WITH JEEM INITIAL FORM
+FCAA	ARABIC LIGATURE HAH WITH MEEM INITIAL FORM
+FCAB	ARABIC LIGATURE KHAH WITH JEEM INITIAL FORM
+FCAC	ARABIC LIGATURE KHAH WITH MEEM INITIAL FORM
+FCAD	ARABIC LIGATURE SEEN WITH JEEM INITIAL FORM
+FCAE	ARABIC LIGATURE SEEN WITH HAH INITIAL FORM
+FCAF	ARABIC LIGATURE SEEN WITH KHAH INITIAL FORM
+FCB0	ARABIC LIGATURE SEEN WITH MEEM INITIAL FORM
+FCB1	ARABIC LIGATURE SAD WITH HAH INITIAL FORM
+FCB2	ARABIC LIGATURE SAD WITH KHAH INITIAL FORM
+FCB3	ARABIC LIGATURE SAD WITH MEEM INITIAL FORM
+FCB4	ARABIC LIGATURE DAD WITH JEEM INITIAL FORM
+FCB5	ARABIC LIGATURE DAD WITH HAH INITIAL FORM
+FCB6	ARABIC LIGATURE DAD WITH KHAH INITIAL FORM
+FCB7	ARABIC LIGATURE DAD WITH MEEM INITIAL FORM
+FCB8	ARABIC LIGATURE TAH WITH HAH INITIAL FORM
+FCB9	ARABIC LIGATURE ZAH WITH MEEM INITIAL FORM
+FCBA	ARABIC LIGATURE AIN WITH JEEM INITIAL FORM
+FCBB	ARABIC LIGATURE AIN WITH MEEM INITIAL FORM
+FCBC	ARABIC LIGATURE GHAIN WITH JEEM INITIAL FORM
+FCBD	ARABIC LIGATURE GHAIN WITH MEEM INITIAL FORM
+FCBE	ARABIC LIGATURE FEH WITH JEEM INITIAL FORM
+FCBF	ARABIC LIGATURE FEH WITH HAH INITIAL FORM
+FCC0	ARABIC LIGATURE FEH WITH KHAH INITIAL FORM
+FCC1	ARABIC LIGATURE FEH WITH MEEM INITIAL FORM
+FCC2	ARABIC LIGATURE QAF WITH HAH INITIAL FORM
+FCC3	ARABIC LIGATURE QAF WITH MEEM INITIAL FORM
+FCC4	ARABIC LIGATURE KAF WITH JEEM INITIAL FORM
+FCC5	ARABIC LIGATURE KAF WITH HAH INITIAL FORM
+FCC6	ARABIC LIGATURE KAF WITH KHAH INITIAL FORM
+FCC7	ARABIC LIGATURE KAF WITH LAM INITIAL FORM
+FCC8	ARABIC LIGATURE KAF WITH MEEM INITIAL FORM
+FCC9	ARABIC LIGATURE LAM WITH JEEM INITIAL FORM
+FCCA	ARABIC LIGATURE LAM WITH HAH INITIAL FORM
+FCCB	ARABIC LIGATURE LAM WITH KHAH INITIAL FORM
+FCCC	ARABIC LIGATURE LAM WITH MEEM INITIAL FORM
+FCCD	ARABIC LIGATURE LAM WITH HEH INITIAL FORM
+FCCE	ARABIC LIGATURE MEEM WITH JEEM INITIAL FORM
+FCCF	ARABIC LIGATURE MEEM WITH HAH INITIAL FORM
+FCD0	ARABIC LIGATURE MEEM WITH KHAH INITIAL FORM
+FCD1	ARABIC LIGATURE MEEM WITH MEEM INITIAL FORM
+FCD2	ARABIC LIGATURE NOON WITH JEEM INITIAL FORM
+FCD3	ARABIC LIGATURE NOON WITH HAH INITIAL FORM
+FCD4	ARABIC LIGATURE NOON WITH KHAH INITIAL FORM
+FCD5	ARABIC LIGATURE NOON WITH MEEM INITIAL FORM
+FCD6	ARABIC LIGATURE NOON WITH HEH INITIAL FORM
+FCD7	ARABIC LIGATURE HEH WITH JEEM INITIAL FORM
+FCD8	ARABIC LIGATURE HEH WITH MEEM INITIAL FORM
+FCD9	ARABIC LIGATURE HEH WITH SUPERSCRIPT ALEF INITIAL FORM
+FCDA	ARABIC LIGATURE YEH WITH JEEM INITIAL FORM
+FCDB	ARABIC LIGATURE YEH WITH HAH INITIAL FORM
+FCDC	ARABIC LIGATURE YEH WITH KHAH INITIAL FORM
+FCDD	ARABIC LIGATURE YEH WITH MEEM INITIAL FORM
+FCDE	ARABIC LIGATURE YEH WITH HEH INITIAL FORM
+FCDF	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM MEDIAL FORM
+FCE0	ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH MEDIAL FORM
+FCE1	ARABIC LIGATURE BEH WITH MEEM MEDIAL FORM
+FCE2	ARABIC LIGATURE BEH WITH HEH MEDIAL FORM
+FCE3	ARABIC LIGATURE TEH WITH MEEM MEDIAL FORM
+FCE4	ARABIC LIGATURE TEH WITH HEH MEDIAL FORM
+FCE5	ARABIC LIGATURE THEH WITH MEEM MEDIAL FORM
+FCE6	ARABIC LIGATURE THEH WITH HEH MEDIAL FORM
+FCE7	ARABIC LIGATURE SEEN WITH MEEM MEDIAL FORM
+FCE8	ARABIC LIGATURE SEEN WITH HEH MEDIAL FORM
+FCE9	ARABIC LIGATURE SHEEN WITH MEEM MEDIAL FORM
+FCEA	ARABIC LIGATURE SHEEN WITH HEH MEDIAL FORM
+FCEB	ARABIC LIGATURE KAF WITH LAM MEDIAL FORM
+FCEC	ARABIC LIGATURE KAF WITH MEEM MEDIAL FORM
+FCED	ARABIC LIGATURE LAM WITH MEEM MEDIAL FORM
+FCEE	ARABIC LIGATURE NOON WITH MEEM MEDIAL FORM
+FCEF	ARABIC LIGATURE NOON WITH HEH MEDIAL FORM
+FCF0	ARABIC LIGATURE YEH WITH MEEM MEDIAL FORM
+FCF1	ARABIC LIGATURE YEH WITH HEH MEDIAL FORM
+FCF2	ARABIC LIGATURE SHADDA WITH FATHA MEDIAL FORM
+FCF3	ARABIC LIGATURE SHADDA WITH DAMMA MEDIAL FORM
+FCF4	ARABIC LIGATURE SHADDA WITH KASRA MEDIAL FORM
+FCF5	ARABIC LIGATURE TAH WITH ALEF MAKSURA ISOLATED FORM
+FCF6	ARABIC LIGATURE TAH WITH YEH ISOLATED FORM
+FCF7	ARABIC LIGATURE AIN WITH ALEF MAKSURA ISOLATED FORM
+FCF8	ARABIC LIGATURE AIN WITH YEH ISOLATED FORM
+FCF9	ARABIC LIGATURE GHAIN WITH ALEF MAKSURA ISOLATED FORM
+FCFA	ARABIC LIGATURE GHAIN WITH YEH ISOLATED FORM
+FCFB	ARABIC LIGATURE SEEN WITH ALEF MAKSURA ISOLATED FORM
+FCFC	ARABIC LIGATURE SEEN WITH YEH ISOLATED FORM
+FCFD	ARABIC LIGATURE SHEEN WITH ALEF MAKSURA ISOLATED FORM
+FCFE	ARABIC LIGATURE SHEEN WITH YEH ISOLATED FORM
+FCFF	ARABIC LIGATURE HAH WITH ALEF MAKSURA ISOLATED FORM
+FD00	ARABIC LIGATURE HAH WITH YEH ISOLATED FORM
+FD01	ARABIC LIGATURE JEEM WITH ALEF MAKSURA ISOLATED FORM
+FD02	ARABIC LIGATURE JEEM WITH YEH ISOLATED FORM
+FD03	ARABIC LIGATURE KHAH WITH ALEF MAKSURA ISOLATED FORM
+FD04	ARABIC LIGATURE KHAH WITH YEH ISOLATED FORM
+FD05	ARABIC LIGATURE SAD WITH ALEF MAKSURA ISOLATED FORM
+FD06	ARABIC LIGATURE SAD WITH YEH ISOLATED FORM
+FD07	ARABIC LIGATURE DAD WITH ALEF MAKSURA ISOLATED FORM
+FD08	ARABIC LIGATURE DAD WITH YEH ISOLATED FORM
+FD09	ARABIC LIGATURE SHEEN WITH JEEM ISOLATED FORM
+FD0A	ARABIC LIGATURE SHEEN WITH HAH ISOLATED FORM
+FD0B	ARABIC LIGATURE SHEEN WITH KHAH ISOLATED FORM
+FD0C	ARABIC LIGATURE SHEEN WITH MEEM ISOLATED FORM
+FD0D	ARABIC LIGATURE SHEEN WITH REH ISOLATED FORM
+FD0E	ARABIC LIGATURE SEEN WITH REH ISOLATED FORM
+FD0F	ARABIC LIGATURE SAD WITH REH ISOLATED FORM
+FD10	ARABIC LIGATURE DAD WITH REH ISOLATED FORM
+FD11	ARABIC LIGATURE TAH WITH ALEF MAKSURA FINAL FORM
+FD12	ARABIC LIGATURE TAH WITH YEH FINAL FORM
+FD13	ARABIC LIGATURE AIN WITH ALEF MAKSURA FINAL FORM
+FD14	ARABIC LIGATURE AIN WITH YEH FINAL FORM
+FD15	ARABIC LIGATURE GHAIN WITH ALEF MAKSURA FINAL FORM
+FD16	ARABIC LIGATURE GHAIN WITH YEH FINAL FORM
+FD17	ARABIC LIGATURE SEEN WITH ALEF MAKSURA FINAL FORM
+FD18	ARABIC LIGATURE SEEN WITH YEH FINAL FORM
+FD19	ARABIC LIGATURE SHEEN WITH ALEF MAKSURA FINAL FORM
+FD1A	ARABIC LIGATURE SHEEN WITH YEH FINAL FORM
+FD1B	ARABIC LIGATURE HAH WITH ALEF MAKSURA FINAL FORM
+FD1C	ARABIC LIGATURE HAH WITH YEH FINAL FORM
+FD1D	ARABIC LIGATURE JEEM WITH ALEF MAKSURA FINAL FORM
+FD1E	ARABIC LIGATURE JEEM WITH YEH FINAL FORM
+FD1F	ARABIC LIGATURE KHAH WITH ALEF MAKSURA FINAL FORM
+FD20	ARABIC LIGATURE KHAH WITH YEH FINAL FORM
+FD21	ARABIC LIGATURE SAD WITH ALEF MAKSURA FINAL FORM
+FD22	ARABIC LIGATURE SAD WITH YEH FINAL FORM
+FD23	ARABIC LIGATURE DAD WITH ALEF MAKSURA FINAL FORM
+FD24	ARABIC LIGATURE DAD WITH YEH FINAL FORM
+FD25	ARABIC LIGATURE SHEEN WITH JEEM FINAL FORM
+FD26	ARABIC LIGATURE SHEEN WITH HAH FINAL FORM
+FD27	ARABIC LIGATURE SHEEN WITH KHAH FINAL FORM
+FD28	ARABIC LIGATURE SHEEN WITH MEEM FINAL FORM
+FD29	ARABIC LIGATURE SHEEN WITH REH FINAL FORM
+FD2A	ARABIC LIGATURE SEEN WITH REH FINAL FORM
+FD2B	ARABIC LIGATURE SAD WITH REH FINAL FORM
+FD2C	ARABIC LIGATURE DAD WITH REH FINAL FORM
+FD2D	ARABIC LIGATURE SHEEN WITH JEEM INITIAL FORM
+FD2E	ARABIC LIGATURE SHEEN WITH HAH INITIAL FORM
+FD2F	ARABIC LIGATURE SHEEN WITH KHAH INITIAL FORM
+FD30	ARABIC LIGATURE SHEEN WITH MEEM INITIAL FORM
+FD31	ARABIC LIGATURE SEEN WITH HEH INITIAL FORM
+FD32	ARABIC LIGATURE SHEEN WITH HEH INITIAL FORM
+FD33	ARABIC LIGATURE TAH WITH MEEM INITIAL FORM
+FD34	ARABIC LIGATURE SEEN WITH JEEM MEDIAL FORM
+FD35	ARABIC LIGATURE SEEN WITH HAH MEDIAL FORM
+FD36	ARABIC LIGATURE SEEN WITH KHAH MEDIAL FORM
+FD37	ARABIC LIGATURE SHEEN WITH JEEM MEDIAL FORM
+FD38	ARABIC LIGATURE SHEEN WITH HAH MEDIAL FORM
+FD39	ARABIC LIGATURE SHEEN WITH KHAH MEDIAL FORM
+FD3A	ARABIC LIGATURE TAH WITH MEEM MEDIAL FORM
+FD3B	ARABIC LIGATURE ZAH WITH MEEM MEDIAL FORM
+FD3C	ARABIC LIGATURE ALEF WITH FATHATAN FINAL FORM
+FD3D	ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM
+FD3E	ORNATE LEFT PARENTHESIS
+FD3F	ORNATE RIGHT PARENTHESIS
+FD50	ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM
+FD51	ARABIC LIGATURE TEH WITH HAH WITH JEEM FINAL FORM
+FD52	ARABIC LIGATURE TEH WITH HAH WITH JEEM INITIAL FORM
+FD53	ARABIC LIGATURE TEH WITH HAH WITH MEEM INITIAL FORM
+FD54	ARABIC LIGATURE TEH WITH KHAH WITH MEEM INITIAL FORM
+FD55	ARABIC LIGATURE TEH WITH MEEM WITH JEEM INITIAL FORM
+FD56	ARABIC LIGATURE TEH WITH MEEM WITH HAH INITIAL FORM
+FD57	ARABIC LIGATURE TEH WITH MEEM WITH KHAH INITIAL FORM
+FD58	ARABIC LIGATURE JEEM WITH MEEM WITH HAH FINAL FORM
+FD59	ARABIC LIGATURE JEEM WITH MEEM WITH HAH INITIAL FORM
+FD5A	ARABIC LIGATURE HAH WITH MEEM WITH YEH FINAL FORM
+FD5B	ARABIC LIGATURE HAH WITH MEEM WITH ALEF MAKSURA FINAL FORM
+FD5C	ARABIC LIGATURE SEEN WITH HAH WITH JEEM INITIAL FORM
+FD5D	ARABIC LIGATURE SEEN WITH JEEM WITH HAH INITIAL FORM
+FD5E	ARABIC LIGATURE SEEN WITH JEEM WITH ALEF MAKSURA FINAL FORM
+FD5F	ARABIC LIGATURE SEEN WITH MEEM WITH HAH FINAL FORM
+FD60	ARABIC LIGATURE SEEN WITH MEEM WITH HAH INITIAL FORM
+FD61	ARABIC LIGATURE SEEN WITH MEEM WITH JEEM INITIAL FORM
+FD62	ARABIC LIGATURE SEEN WITH MEEM WITH MEEM FINAL FORM
+FD63	ARABIC LIGATURE SEEN WITH MEEM WITH MEEM INITIAL FORM
+FD64	ARABIC LIGATURE SAD WITH HAH WITH HAH FINAL FORM
+FD65	ARABIC LIGATURE SAD WITH HAH WITH HAH INITIAL FORM
+FD66	ARABIC LIGATURE SAD WITH MEEM WITH MEEM FINAL FORM
+FD67	ARABIC LIGATURE SHEEN WITH HAH WITH MEEM FINAL FORM
+FD68	ARABIC LIGATURE SHEEN WITH HAH WITH MEEM INITIAL FORM
+FD69	ARABIC LIGATURE SHEEN WITH JEEM WITH YEH FINAL FORM
+FD6A	ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH FINAL FORM
+FD6B	ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH INITIAL FORM
+FD6C	ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM FINAL FORM
+FD6D	ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM INITIAL FORM
+FD6E	ARABIC LIGATURE DAD WITH HAH WITH ALEF MAKSURA FINAL FORM
+FD6F	ARABIC LIGATURE DAD WITH KHAH WITH MEEM FINAL FORM
+FD70	ARABIC LIGATURE DAD WITH KHAH WITH MEEM INITIAL FORM
+FD71	ARABIC LIGATURE TAH WITH MEEM WITH HAH FINAL FORM
+FD72	ARABIC LIGATURE TAH WITH MEEM WITH HAH INITIAL FORM
+FD73	ARABIC LIGATURE TAH WITH MEEM WITH MEEM INITIAL FORM
+FD74	ARABIC LIGATURE TAH WITH MEEM WITH YEH FINAL FORM
+FD75	ARABIC LIGATURE AIN WITH JEEM WITH MEEM FINAL FORM
+FD76	ARABIC LIGATURE AIN WITH MEEM WITH MEEM FINAL FORM
+FD77	ARABIC LIGATURE AIN WITH MEEM WITH MEEM INITIAL FORM
+FD78	ARABIC LIGATURE AIN WITH MEEM WITH ALEF MAKSURA FINAL FORM
+FD79	ARABIC LIGATURE GHAIN WITH MEEM WITH MEEM FINAL FORM
+FD7A	ARABIC LIGATURE GHAIN WITH MEEM WITH YEH FINAL FORM
+FD7B	ARABIC LIGATURE GHAIN WITH MEEM WITH ALEF MAKSURA FINAL FORM
+FD7C	ARABIC LIGATURE FEH WITH KHAH WITH MEEM FINAL FORM
+FD7D	ARABIC LIGATURE FEH WITH KHAH WITH MEEM INITIAL FORM
+FD7E	ARABIC LIGATURE QAF WITH MEEM WITH HAH FINAL FORM
+FD7F	ARABIC LIGATURE QAF WITH MEEM WITH MEEM FINAL FORM
+FD80	ARABIC LIGATURE LAM WITH HAH WITH MEEM FINAL FORM
+FD81	ARABIC LIGATURE LAM WITH HAH WITH YEH FINAL FORM
+FD82	ARABIC LIGATURE LAM WITH HAH WITH ALEF MAKSURA FINAL FORM
+FD83	ARABIC LIGATURE LAM WITH JEEM WITH JEEM INITIAL FORM
+FD84	ARABIC LIGATURE LAM WITH JEEM WITH JEEM FINAL FORM
+FD85	ARABIC LIGATURE LAM WITH KHAH WITH MEEM FINAL FORM
+FD86	ARABIC LIGATURE LAM WITH KHAH WITH MEEM INITIAL FORM
+FD87	ARABIC LIGATURE LAM WITH MEEM WITH HAH FINAL FORM
+FD88	ARABIC LIGATURE LAM WITH MEEM WITH HAH INITIAL FORM
+FD89	ARABIC LIGATURE MEEM WITH HAH WITH JEEM INITIAL FORM
+FD8A	ARABIC LIGATURE MEEM WITH HAH WITH MEEM INITIAL FORM
+FD8B	ARABIC LIGATURE MEEM WITH HAH WITH YEH FINAL FORM
+FD8C	ARABIC LIGATURE MEEM WITH JEEM WITH HAH INITIAL FORM
+FD8D	ARABIC LIGATURE MEEM WITH JEEM WITH MEEM INITIAL FORM
+FD8E	ARABIC LIGATURE MEEM WITH KHAH WITH JEEM INITIAL FORM
+FD8F	ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM
+FD92	ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM
+FD93	ARABIC LIGATURE HEH WITH MEEM WITH JEEM INITIAL FORM
+FD94	ARABIC LIGATURE HEH WITH MEEM WITH MEEM INITIAL FORM
+FD95	ARABIC LIGATURE NOON WITH HAH WITH MEEM INITIAL FORM
+FD96	ARABIC LIGATURE NOON WITH HAH WITH ALEF MAKSURA FINAL FORM
+FD97	ARABIC LIGATURE NOON WITH JEEM WITH MEEM FINAL FORM
+FD98	ARABIC LIGATURE NOON WITH JEEM WITH MEEM INITIAL FORM
+FD99	ARABIC LIGATURE NOON WITH JEEM WITH ALEF MAKSURA FINAL FORM
+FD9A	ARABIC LIGATURE NOON WITH MEEM WITH YEH FINAL FORM
+FD9B	ARABIC LIGATURE NOON WITH MEEM WITH ALEF MAKSURA FINAL FORM
+FD9C	ARABIC LIGATURE YEH WITH MEEM WITH MEEM FINAL FORM
+FD9D	ARABIC LIGATURE YEH WITH MEEM WITH MEEM INITIAL FORM
+FD9E	ARABIC LIGATURE BEH WITH KHAH WITH YEH FINAL FORM
+FD9F	ARABIC LIGATURE TEH WITH JEEM WITH YEH FINAL FORM
+FDA0	ARABIC LIGATURE TEH WITH JEEM WITH ALEF MAKSURA FINAL FORM
+FDA1	ARABIC LIGATURE TEH WITH KHAH WITH YEH FINAL FORM
+FDA2	ARABIC LIGATURE TEH WITH KHAH WITH ALEF MAKSURA FINAL FORM
+FDA3	ARABIC LIGATURE TEH WITH MEEM WITH YEH FINAL FORM
+FDA4	ARABIC LIGATURE TEH WITH MEEM WITH ALEF MAKSURA FINAL FORM
+FDA5	ARABIC LIGATURE JEEM WITH MEEM WITH YEH FINAL FORM
+FDA6	ARABIC LIGATURE JEEM WITH HAH WITH ALEF MAKSURA FINAL FORM
+FDA7	ARABIC LIGATURE JEEM WITH MEEM WITH ALEF MAKSURA FINAL FORM
+FDA8	ARABIC LIGATURE SEEN WITH KHAH WITH ALEF MAKSURA FINAL FORM
+FDA9	ARABIC LIGATURE SAD WITH HAH WITH YEH FINAL FORM
+FDAA	ARABIC LIGATURE SHEEN WITH HAH WITH YEH FINAL FORM
+FDAB	ARABIC LIGATURE DAD WITH HAH WITH YEH FINAL FORM
+FDAC	ARABIC LIGATURE LAM WITH JEEM WITH YEH FINAL FORM
+FDAD	ARABIC LIGATURE LAM WITH MEEM WITH YEH FINAL FORM
+FDAE	ARABIC LIGATURE YEH WITH HAH WITH YEH FINAL FORM
+FDAF	ARABIC LIGATURE YEH WITH JEEM WITH YEH FINAL FORM
+FDB0	ARABIC LIGATURE YEH WITH MEEM WITH YEH FINAL FORM
+FDB1	ARABIC LIGATURE MEEM WITH MEEM WITH YEH FINAL FORM
+FDB2	ARABIC LIGATURE QAF WITH MEEM WITH YEH FINAL FORM
+FDB3	ARABIC LIGATURE NOON WITH HAH WITH YEH FINAL FORM
+FDB4	ARABIC LIGATURE QAF WITH MEEM WITH HAH INITIAL FORM
+FDB5	ARABIC LIGATURE LAM WITH HAH WITH MEEM INITIAL FORM
+FDB6	ARABIC LIGATURE AIN WITH MEEM WITH YEH FINAL FORM
+FDB7	ARABIC LIGATURE KAF WITH MEEM WITH YEH FINAL FORM
+FDB8	ARABIC LIGATURE NOON WITH JEEM WITH HAH INITIAL FORM
+FDB9	ARABIC LIGATURE MEEM WITH KHAH WITH YEH FINAL FORM
+FDBA	ARABIC LIGATURE LAM WITH JEEM WITH MEEM INITIAL FORM
+FDBB	ARABIC LIGATURE KAF WITH MEEM WITH MEEM FINAL FORM
+FDBC	ARABIC LIGATURE LAM WITH JEEM WITH MEEM FINAL FORM
+FDBD	ARABIC LIGATURE NOON WITH JEEM WITH HAH FINAL FORM
+FDBE	ARABIC LIGATURE JEEM WITH HAH WITH YEH FINAL FORM
+FDBF	ARABIC LIGATURE HAH WITH JEEM WITH YEH FINAL FORM
+FDC0	ARABIC LIGATURE MEEM WITH JEEM WITH YEH FINAL FORM
+FDC1	ARABIC LIGATURE FEH WITH MEEM WITH YEH FINAL FORM
+FDC2	ARABIC LIGATURE BEH WITH HAH WITH YEH FINAL FORM
+FDC3	ARABIC LIGATURE KAF WITH MEEM WITH MEEM INITIAL FORM
+FDC4	ARABIC LIGATURE AIN WITH JEEM WITH MEEM INITIAL FORM
+FDC5	ARABIC LIGATURE SAD WITH MEEM WITH MEEM INITIAL FORM
+FDC6	ARABIC LIGATURE SEEN WITH KHAH WITH YEH FINAL FORM
+FDC7	ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM
+FDF0	ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM
+FDF1	ARABIC LIGATURE QALA USED AS KORANIC STOP SIGN ISOLATED FORM
+FDF2	ARABIC LIGATURE ALLAH ISOLATED FORM
+FDF3	ARABIC LIGATURE AKBAR ISOLATED FORM
+FDF4	ARABIC LIGATURE MOHAMMAD ISOLATED FORM
+FDF5	ARABIC LIGATURE SALAM ISOLATED FORM
+FDF6	ARABIC LIGATURE RASOUL ISOLATED FORM
+FDF7	ARABIC LIGATURE ALAYHE ISOLATED FORM
+FDF8	ARABIC LIGATURE WASALLAM ISOLATED FORM
+FDF9	ARABIC LIGATURE SALLA ISOLATED FORM
+FDFA	ARABIC LIGATURE SALLALLAHOU ALAYHE WASALLAM
+FDFB	ARABIC LIGATURE JALLAJALALOUHOU
+FE20	COMBINING LIGATURE LEFT HALF
+FE21	COMBINING LIGATURE RIGHT HALF
+FE22	COMBINING DOUBLE TILDE LEFT HALF
+FE23	COMBINING DOUBLE TILDE RIGHT HALF
+FE30	PRESENTATION FORM FOR VERTICAL TWO DOT LEADER
+FE31	PRESENTATION FORM FOR VERTICAL EM DASH
+FE32	PRESENTATION FORM FOR VERTICAL EN DASH
+FE33	PRESENTATION FORM FOR VERTICAL LOW LINE
+FE34	PRESENTATION FORM FOR VERTICAL WAVY LOW LINE
+FE35	PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS
+FE36	PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS
+FE37	PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET
+FE38	PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET
+FE39	PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET
+FE3A	PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET
+FE3B	PRESENTATION FORM FOR VERTICAL LEFT BLACK LENTICULAR BRACKET
+FE3C	PRESENTATION FORM FOR VERTICAL RIGHT BLACK LENTICULAR BRACKET
+FE3D	PRESENTATION FORM FOR VERTICAL LEFT DOUBLE ANGLE BRACKET
+FE3E	PRESENTATION FORM FOR VERTICAL RIGHT DOUBLE ANGLE BRACKET
+FE3F	PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET
+FE40	PRESENTATION FORM FOR VERTICAL RIGHT ANGLE BRACKET
+FE41	PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET
+FE42	PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET
+FE43	PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET
+FE44	PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET
+FE49	DASHED OVERLINE
+FE4A	CENTRELINE OVERLINE
+FE4B	WAVY OVERLINE
+FE4C	DOUBLE WAVY OVERLINE
+FE4D	DASHED LOW LINE
+FE4E	CENTRELINE LOW LINE
+FE4F	WAVY LOW LINE
+FE50	SMALL COMMA
+FE51	SMALL IDEOGRAPHIC COMMA
+FE52	SMALL FULL STOP
+FE54	SMALL SEMICOLON
+FE55	SMALL COLON
+FE56	SMALL QUESTION MARK
+FE57	SMALL EXCLAMATION MARK
+FE58	SMALL EM DASH
+FE59	SMALL LEFT PARENTHESIS
+FE5A	SMALL RIGHT PARENTHESIS
+FE5B	SMALL LEFT CURLY BRACKET
+FE5C	SMALL RIGHT CURLY BRACKET
+FE5D	SMALL LEFT TORTOISE SHELL BRACKET
+FE5E	SMALL RIGHT TORTOISE SHELL BRACKET
+FE5F	SMALL NUMBER SIGN
+FE60	SMALL AMPERSAND
+FE61	SMALL ASTERISK
+FE62	SMALL PLUS SIGN
+FE63	SMALL HYPHEN-MINUS
+FE64	SMALL LESS-THAN SIGN
+FE65	SMALL GREATER-THAN SIGN
+FE66	SMALL EQUALS SIGN
+FE68	SMALL REVERSE SOLIDUS
+FE69	SMALL DOLLAR SIGN
+FE6A	SMALL PERCENT SIGN
+FE6B	SMALL COMMERCIAL AT
+FE70	ARABIC FATHATAN ISOLATED FORM
+FE71	ARABIC TATWEEL WITH FATHATAN ABOVE
+FE72	ARABIC DAMMATAN ISOLATED FORM
+FE74	ARABIC KASRATAN ISOLATED FORM
+FE76	ARABIC FATHA ISOLATED FORM
+FE77	ARABIC FATHA MEDIAL FORM
+FE78	ARABIC DAMMA ISOLATED FORM
+FE79	ARABIC DAMMA MEDIAL FORM
+FE7A	ARABIC KASRA ISOLATED FORM
+FE7B	ARABIC KASRA MEDIAL FORM
+FE7C	ARABIC SHADDA ISOLATED FORM
+FE7D	ARABIC SHADDA MEDIAL FORM
+FE7E	ARABIC SUKUN ISOLATED FORM
+FE7F	ARABIC SUKUN MEDIAL FORM
+FE80	ARABIC LETTER HAMZA ISOLATED FORM
+FE81	ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM
+FE82	ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM
+FE83	ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM
+FE84	ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM
+FE85	ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM
+FE86	ARABIC LETTER WAW WITH HAMZA ABOVE FINAL FORM
+FE87	ARABIC LETTER ALEF WITH HAMZA BELOW ISOLATED FORM
+FE88	ARABIC LETTER ALEF WITH HAMZA BELOW FINAL FORM
+FE89	ARABIC LETTER YEH WITH HAMZA ABOVE ISOLATED FORM
+FE8A	ARABIC LETTER YEH WITH HAMZA ABOVE FINAL FORM
+FE8B	ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM
+FE8C	ARABIC LETTER YEH WITH HAMZA ABOVE MEDIAL FORM
+FE8D	ARABIC LETTER ALEF ISOLATED FORM
+FE8E	ARABIC LETTER ALEF FINAL FORM
+FE8F	ARABIC LETTER BEH ISOLATED FORM
+FE90	ARABIC LETTER BEH FINAL FORM
+FE91	ARABIC LETTER BEH INITIAL FORM
+FE92	ARABIC LETTER BEH MEDIAL FORM
+FE93	ARABIC LETTER TEH MARBUTA ISOLATED FORM
+FE94	ARABIC LETTER TEH MARBUTA FINAL FORM
+FE95	ARABIC LETTER TEH ISOLATED FORM
+FE96	ARABIC LETTER TEH FINAL FORM
+FE97	ARABIC LETTER TEH INITIAL FORM
+FE98	ARABIC LETTER TEH MEDIAL FORM
+FE99	ARABIC LETTER THEH ISOLATED FORM
+FE9A	ARABIC LETTER THEH FINAL FORM
+FE9B	ARABIC LETTER THEH INITIAL FORM
+FE9C	ARABIC LETTER THEH MEDIAL FORM
+FE9D	ARABIC LETTER JEEM ISOLATED FORM
+FE9E	ARABIC LETTER JEEM FINAL FORM
+FE9F	ARABIC LETTER JEEM INITIAL FORM
+FEA0	ARABIC LETTER JEEM MEDIAL FORM
+FEA1	ARABIC LETTER HAH ISOLATED FORM
+FEA2	ARABIC LETTER HAH FINAL FORM
+FEA3	ARABIC LETTER HAH INITIAL FORM
+FEA4	ARABIC LETTER HAH MEDIAL FORM
+FEA5	ARABIC LETTER KHAH ISOLATED FORM
+FEA6	ARABIC LETTER KHAH FINAL FORM
+FEA7	ARABIC LETTER KHAH INITIAL FORM
+FEA8	ARABIC LETTER KHAH MEDIAL FORM
+FEA9	ARABIC LETTER DAL ISOLATED FORM
+FEAA	ARABIC LETTER DAL FINAL FORM
+FEAB	ARABIC LETTER THAL ISOLATED FORM
+FEAC	ARABIC LETTER THAL FINAL FORM
+FEAD	ARABIC LETTER REH ISOLATED FORM
+FEAE	ARABIC LETTER REH FINAL FORM
+FEAF	ARABIC LETTER ZAIN ISOLATED FORM
+FEB0	ARABIC LETTER ZAIN FINAL FORM
+FEB1	ARABIC LETTER SEEN ISOLATED FORM
+FEB2	ARABIC LETTER SEEN FINAL FORM
+FEB3	ARABIC LETTER SEEN INITIAL FORM
+FEB4	ARABIC LETTER SEEN MEDIAL FORM
+FEB5	ARABIC LETTER SHEEN ISOLATED FORM
+FEB6	ARABIC LETTER SHEEN FINAL FORM
+FEB7	ARABIC LETTER SHEEN INITIAL FORM
+FEB8	ARABIC LETTER SHEEN MEDIAL FORM
+FEB9	ARABIC LETTER SAD ISOLATED FORM
+FEBA	ARABIC LETTER SAD FINAL FORM
+FEBB	ARABIC LETTER SAD INITIAL FORM
+FEBC	ARABIC LETTER SAD MEDIAL FORM
+FEBD	ARABIC LETTER DAD ISOLATED FORM
+FEBE	ARABIC LETTER DAD FINAL FORM
+FEBF	ARABIC LETTER DAD INITIAL FORM
+FEC0	ARABIC LETTER DAD MEDIAL FORM
+FEC1	ARABIC LETTER TAH ISOLATED FORM
+FEC2	ARABIC LETTER TAH FINAL FORM
+FEC3	ARABIC LETTER TAH INITIAL FORM
+FEC4	ARABIC LETTER TAH MEDIAL FORM
+FEC5	ARABIC LETTER ZAH ISOLATED FORM
+FEC6	ARABIC LETTER ZAH FINAL FORM
+FEC7	ARABIC LETTER ZAH INITIAL FORM
+FEC8	ARABIC LETTER ZAH MEDIAL FORM
+FEC9	ARABIC LETTER AIN ISOLATED FORM
+FECA	ARABIC LETTER AIN FINAL FORM
+FECB	ARABIC LETTER AIN INITIAL FORM
+FECC	ARABIC LETTER AIN MEDIAL FORM
+FECD	ARABIC LETTER GHAIN ISOLATED FORM
+FECE	ARABIC LETTER GHAIN FINAL FORM
+FECF	ARABIC LETTER GHAIN INITIAL FORM
+FED0	ARABIC LETTER GHAIN MEDIAL FORM
+FED1	ARABIC LETTER FEH ISOLATED FORM
+FED2	ARABIC LETTER FEH FINAL FORM
+FED3	ARABIC LETTER FEH INITIAL FORM
+FED4	ARABIC LETTER FEH MEDIAL FORM
+FED5	ARABIC LETTER QAF ISOLATED FORM
+FED6	ARABIC LETTER QAF FINAL FORM
+FED7	ARABIC LETTER QAF INITIAL FORM
+FED8	ARABIC LETTER QAF MEDIAL FORM
+FED9	ARABIC LETTER KAF ISOLATED FORM
+FEDA	ARABIC LETTER KAF FINAL FORM
+FEDB	ARABIC LETTER KAF INITIAL FORM
+FEDC	ARABIC LETTER KAF MEDIAL FORM
+FEDD	ARABIC LETTER LAM ISOLATED FORM
+FEDE	ARABIC LETTER LAM FINAL FORM
+FEDF	ARABIC LETTER LAM INITIAL FORM
+FEE0	ARABIC LETTER LAM MEDIAL FORM
+FEE1	ARABIC LETTER MEEM ISOLATED FORM
+FEE2	ARABIC LETTER MEEM FINAL FORM
+FEE3	ARABIC LETTER MEEM INITIAL FORM
+FEE4	ARABIC LETTER MEEM MEDIAL FORM
+FEE5	ARABIC LETTER NOON ISOLATED FORM
+FEE6	ARABIC LETTER NOON FINAL FORM
+FEE7	ARABIC LETTER NOON INITIAL FORM
+FEE8	ARABIC LETTER NOON MEDIAL FORM
+FEE9	ARABIC LETTER HEH ISOLATED FORM
+FEEA	ARABIC LETTER HEH FINAL FORM
+FEEB	ARABIC LETTER HEH INITIAL FORM
+FEEC	ARABIC LETTER HEH MEDIAL FORM
+FEED	ARABIC LETTER WAW ISOLATED FORM
+FEEE	ARABIC LETTER WAW FINAL FORM
+FEEF	ARABIC LETTER ALEF MAKSURA ISOLATED FORM
+FEF0	ARABIC LETTER ALEF MAKSURA FINAL FORM
+FEF1	ARABIC LETTER YEH ISOLATED FORM
+FEF2	ARABIC LETTER YEH FINAL FORM
+FEF3	ARABIC LETTER YEH INITIAL FORM
+FEF4	ARABIC LETTER YEH MEDIAL FORM
+FEF5	ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM
+FEF6	ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM
+FEF7	ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM
+FEF8	ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM
+FEF9	ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM
+FEFA	ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM
+FEFB	ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM
+FEFC	ARABIC LIGATURE LAM WITH ALEF FINAL FORM
+FEFF	ZERO WIDTH NO-BREAK SPACE
+FF01	FULLWIDTH EXCLAMATION MARK
+FF02	FULLWIDTH QUOTATION MARK
+FF03	FULLWIDTH NUMBER SIGN
+FF04	FULLWIDTH DOLLAR SIGN
+FF05	FULLWIDTH PERCENT SIGN
+FF06	FULLWIDTH AMPERSAND
+FF07	FULLWIDTH APOSTROPHE
+FF08	FULLWIDTH LEFT PARENTHESIS
+FF09	FULLWIDTH RIGHT PARENTHESIS
+FF0A	FULLWIDTH ASTERISK
+FF0B	FULLWIDTH PLUS SIGN
+FF0C	FULLWIDTH COMMA
+FF0D	FULLWIDTH HYPHEN-MINUS
+FF0E	FULLWIDTH FULL STOP
+FF0F	FULLWIDTH SOLIDUS
+FF10	FULLWIDTH DIGIT ZERO
+FF11	FULLWIDTH DIGIT ONE
+FF12	FULLWIDTH DIGIT TWO
+FF13	FULLWIDTH DIGIT THREE
+FF14	FULLWIDTH DIGIT FOUR
+FF15	FULLWIDTH DIGIT FIVE
+FF16	FULLWIDTH DIGIT SIX
+FF17	FULLWIDTH DIGIT SEVEN
+FF18	FULLWIDTH DIGIT EIGHT
+FF19	FULLWIDTH DIGIT NINE
+FF1A	FULLWIDTH COLON
+FF1B	FULLWIDTH SEMICOLON
+FF1C	FULLWIDTH LESS-THAN SIGN
+FF1D	FULLWIDTH EQUALS SIGN
+FF1E	FULLWIDTH GREATER-THAN SIGN
+FF1F	FULLWIDTH QUESTION MARK
+FF20	FULLWIDTH COMMERCIAL AT
+FF21	FULLWIDTH LATIN CAPITAL LETTER A
+FF22	FULLWIDTH LATIN CAPITAL LETTER B
+FF23	FULLWIDTH LATIN CAPITAL LETTER C
+FF24	FULLWIDTH LATIN CAPITAL LETTER D
+FF25	FULLWIDTH LATIN CAPITAL LETTER E
+FF26	FULLWIDTH LATIN CAPITAL LETTER F
+FF27	FULLWIDTH LATIN CAPITAL LETTER G
+FF28	FULLWIDTH LATIN CAPITAL LETTER H
+FF29	FULLWIDTH LATIN CAPITAL LETTER I
+FF2A	FULLWIDTH LATIN CAPITAL LETTER J
+FF2B	FULLWIDTH LATIN CAPITAL LETTER K
+FF2C	FULLWIDTH LATIN CAPITAL LETTER L
+FF2D	FULLWIDTH LATIN CAPITAL LETTER M
+FF2E	FULLWIDTH LATIN CAPITAL LETTER N
+FF2F	FULLWIDTH LATIN CAPITAL LETTER O
+FF30	FULLWIDTH LATIN CAPITAL LETTER P
+FF31	FULLWIDTH LATIN CAPITAL LETTER Q
+FF32	FULLWIDTH LATIN CAPITAL LETTER R
+FF33	FULLWIDTH LATIN CAPITAL LETTER S
+FF34	FULLWIDTH LATIN CAPITAL LETTER T
+FF35	FULLWIDTH LATIN CAPITAL LETTER U
+FF36	FULLWIDTH LATIN CAPITAL LETTER V
+FF37	FULLWIDTH LATIN CAPITAL LETTER W
+FF38	FULLWIDTH LATIN CAPITAL LETTER X
+FF39	FULLWIDTH LATIN CAPITAL LETTER Y
+FF3A	FULLWIDTH LATIN CAPITAL LETTER Z
+FF3B	FULLWIDTH LEFT SQUARE BRACKET
+FF3C	FULLWIDTH REVERSE SOLIDUS
+FF3D	FULLWIDTH RIGHT SQUARE BRACKET
+FF3E	FULLWIDTH CIRCUMFLEX ACCENT
+FF3F	FULLWIDTH LOW LINE
+FF40	FULLWIDTH GRAVE ACCENT
+FF41	FULLWIDTH LATIN SMALL LETTER A
+FF42	FULLWIDTH LATIN SMALL LETTER B
+FF43	FULLWIDTH LATIN SMALL LETTER C
+FF44	FULLWIDTH LATIN SMALL LETTER D
+FF45	FULLWIDTH LATIN SMALL LETTER E
+FF46	FULLWIDTH LATIN SMALL LETTER F
+FF47	FULLWIDTH LATIN SMALL LETTER G
+FF48	FULLWIDTH LATIN SMALL LETTER H
+FF49	FULLWIDTH LATIN SMALL LETTER I
+FF4A	FULLWIDTH LATIN SMALL LETTER J
+FF4B	FULLWIDTH LATIN SMALL LETTER K
+FF4C	FULLWIDTH LATIN SMALL LETTER L
+FF4D	FULLWIDTH LATIN SMALL LETTER M
+FF4E	FULLWIDTH LATIN SMALL LETTER N
+FF4F	FULLWIDTH LATIN SMALL LETTER O
+FF50	FULLWIDTH LATIN SMALL LETTER P
+FF51	FULLWIDTH LATIN SMALL LETTER Q
+FF52	FULLWIDTH LATIN SMALL LETTER R
+FF53	FULLWIDTH LATIN SMALL LETTER S
+FF54	FULLWIDTH LATIN SMALL LETTER T
+FF55	FULLWIDTH LATIN SMALL LETTER U
+FF56	FULLWIDTH LATIN SMALL LETTER V
+FF57	FULLWIDTH LATIN SMALL LETTER W
+FF58	FULLWIDTH LATIN SMALL LETTER X
+FF59	FULLWIDTH LATIN SMALL LETTER Y
+FF5A	FULLWIDTH LATIN SMALL LETTER Z
+FF5B	FULLWIDTH LEFT CURLY BRACKET
+FF5C	FULLWIDTH VERTICAL LINE
+FF5D	FULLWIDTH RIGHT CURLY BRACKET
+FF5E	FULLWIDTH TILDE
+FF61	HALFWIDTH IDEOGRAPHIC FULL STOP
+FF62	HALFWIDTH LEFT CORNER BRACKET
+FF63	HALFWIDTH RIGHT CORNER BRACKET
+FF64	HALFWIDTH IDEOGRAPHIC COMMA
+FF65	HALFWIDTH KATAKANA MIDDLE DOT
+FF66	HALFWIDTH KATAKANA LETTER WO
+FF67	HALFWIDTH KATAKANA LETTER SMALL A
+FF68	HALFWIDTH KATAKANA LETTER SMALL I
+FF69	HALFWIDTH KATAKANA LETTER SMALL U
+FF6A	HALFWIDTH KATAKANA LETTER SMALL E
+FF6B	HALFWIDTH KATAKANA LETTER SMALL O
+FF6C	HALFWIDTH KATAKANA LETTER SMALL YA
+FF6D	HALFWIDTH KATAKANA LETTER SMALL YU
+FF6E	HALFWIDTH KATAKANA LETTER SMALL YO
+FF6F	HALFWIDTH KATAKANA LETTER SMALL TU
+FF70	HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK
+FF71	HALFWIDTH KATAKANA LETTER A
+FF72	HALFWIDTH KATAKANA LETTER I
+FF73	HALFWIDTH KATAKANA LETTER U
+FF74	HALFWIDTH KATAKANA LETTER E
+FF75	HALFWIDTH KATAKANA LETTER O
+FF76	HALFWIDTH KATAKANA LETTER KA
+FF77	HALFWIDTH KATAKANA LETTER KI
+FF78	HALFWIDTH KATAKANA LETTER KU
+FF79	HALFWIDTH KATAKANA LETTER KE
+FF7A	HALFWIDTH KATAKANA LETTER KO
+FF7B	HALFWIDTH KATAKANA LETTER SA
+FF7C	HALFWIDTH KATAKANA LETTER SI
+FF7D	HALFWIDTH KATAKANA LETTER SU
+FF7E	HALFWIDTH KATAKANA LETTER SE
+FF7F	HALFWIDTH KATAKANA LETTER SO
+FF80	HALFWIDTH KATAKANA LETTER TA
+FF81	HALFWIDTH KATAKANA LETTER TI
+FF82	HALFWIDTH KATAKANA LETTER TU
+FF83	HALFWIDTH KATAKANA LETTER TE
+FF84	HALFWIDTH KATAKANA LETTER TO
+FF85	HALFWIDTH KATAKANA LETTER NA
+FF86	HALFWIDTH KATAKANA LETTER NI
+FF87	HALFWIDTH KATAKANA LETTER NU
+FF88	HALFWIDTH KATAKANA LETTER NE
+FF89	HALFWIDTH KATAKANA LETTER NO
+FF8A	HALFWIDTH KATAKANA LETTER HA
+FF8B	HALFWIDTH KATAKANA LETTER HI
+FF8C	HALFWIDTH KATAKANA LETTER HU
+FF8D	HALFWIDTH KATAKANA LETTER HE
+FF8E	HALFWIDTH KATAKANA LETTER HO
+FF8F	HALFWIDTH KATAKANA LETTER MA
+FF90	HALFWIDTH KATAKANA LETTER MI
+FF91	HALFWIDTH KATAKANA LETTER MU
+FF92	HALFWIDTH KATAKANA LETTER ME
+FF93	HALFWIDTH KATAKANA LETTER MO
+FF94	HALFWIDTH KATAKANA LETTER YA
+FF95	HALFWIDTH KATAKANA LETTER YU
+FF96	HALFWIDTH KATAKANA LETTER YO
+FF97	HALFWIDTH KATAKANA LETTER RA
+FF98	HALFWIDTH KATAKANA LETTER RI
+FF99	HALFWIDTH KATAKANA LETTER RU
+FF9A	HALFWIDTH KATAKANA LETTER RE
+FF9B	HALFWIDTH KATAKANA LETTER RO
+FF9C	HALFWIDTH KATAKANA LETTER WA
+FF9D	HALFWIDTH KATAKANA LETTER N
+FF9E	HALFWIDTH KATAKANA VOICED SOUND MARK
+FF9F	HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
+FFA0	HALFWIDTH HANGUL FILLER
+FFA1	HALFWIDTH HANGUL LETTER KIYEOK
+FFA2	HALFWIDTH HANGUL LETTER SSANGKIYEOK
+FFA3	HALFWIDTH HANGUL LETTER KIYEOK-SIOS
+FFA4	HALFWIDTH HANGUL LETTER NIEUN
+FFA5	HALFWIDTH HANGUL LETTER NIEUN-CIEUC
+FFA6	HALFWIDTH HANGUL LETTER NIEUN-HIEUH
+FFA7	HALFWIDTH HANGUL LETTER TIKEUT
+FFA8	HALFWIDTH HANGUL LETTER SSANGTIKEUT
+FFA9	HALFWIDTH HANGUL LETTER RIEUL
+FFAA	HALFWIDTH HANGUL LETTER RIEUL-KIYEOK
+FFAB	HALFWIDTH HANGUL LETTER RIEUL-MIEUM
+FFAC	HALFWIDTH HANGUL LETTER RIEUL-PIEUP
+FFAD	HALFWIDTH HANGUL LETTER RIEUL-SIOS
+FFAE	HALFWIDTH HANGUL LETTER RIEUL-THIEUTH
+FFAF	HALFWIDTH HANGUL LETTER RIEUL-PHIEUPH
+FFB0	HALFWIDTH HANGUL LETTER RIEUL-HIEUH
+FFB1	HALFWIDTH HANGUL LETTER MIEUM
+FFB2	HALFWIDTH HANGUL LETTER PIEUP
+FFB3	HALFWIDTH HANGUL LETTER SSANGPIEUP
+FFB4	HALFWIDTH HANGUL LETTER PIEUP-SIOS
+FFB5	HALFWIDTH HANGUL LETTER SIOS
+FFB6	HALFWIDTH HANGUL LETTER SSANGSIOS
+FFB7	HALFWIDTH HANGUL LETTER IEUNG
+FFB8	HALFWIDTH HANGUL LETTER CIEUC
+FFB9	HALFWIDTH HANGUL LETTER SSANGCIEUC
+FFBA	HALFWIDTH HANGUL LETTER CHIEUCH
+FFBB	HALFWIDTH HANGUL LETTER KHIEUKH
+FFBC	HALFWIDTH HANGUL LETTER THIEUTH
+FFBD	HALFWIDTH HANGUL LETTER PHIEUPH
+FFBE	HALFWIDTH HANGUL LETTER HIEUH
+FFC2	HALFWIDTH HANGUL LETTER A
+FFC3	HALFWIDTH HANGUL LETTER AE
+FFC4	HALFWIDTH HANGUL LETTER YA
+FFC5	HALFWIDTH HANGUL LETTER YAE
+FFC6	HALFWIDTH HANGUL LETTER EO
+FFC7	HALFWIDTH HANGUL LETTER E
+FFCA	HALFWIDTH HANGUL LETTER YEO
+FFCB	HALFWIDTH HANGUL LETTER YE
+FFCC	HALFWIDTH HANGUL LETTER O
+FFCD	HALFWIDTH HANGUL LETTER WA
+FFCE	HALFWIDTH HANGUL LETTER WAE
+FFCF	HALFWIDTH HANGUL LETTER OE
+FFD2	HALFWIDTH HANGUL LETTER YO
+FFD3	HALFWIDTH HANGUL LETTER U
+FFD4	HALFWIDTH HANGUL LETTER WEO
+FFD5	HALFWIDTH HANGUL LETTER WE
+FFD6	HALFWIDTH HANGUL LETTER WI
+FFD7	HALFWIDTH HANGUL LETTER YU
+FFDA	HALFWIDTH HANGUL LETTER EU
+FFDB	HALFWIDTH HANGUL LETTER YI
+FFDC	HALFWIDTH HANGUL LETTER I
+FFE0	FULLWIDTH CENT SIGN
+FFE1	FULLWIDTH POUND SIGN
+FFE2	FULLWIDTH NOT SIGN
+FFE3	FULLWIDTH MACRON
+FFE4	FULLWIDTH BROKEN BAR
+FFE5	FULLWIDTH YEN SIGN
+FFE6	FULLWIDTH WON SIGN
+FFE8	HALFWIDTH FORMS LIGHT VERTICAL
+FFE9	HALFWIDTH LEFTWARDS ARROW
+FFEA	HALFWIDTH UPWARDS ARROW
+FFEB	HALFWIDTH RIGHTWARDS ARROW
+FFEC	HALFWIDTH DOWNWARDS ARROW
+FFED	HALFWIDTH BLACK SQUARE
+FFEE	HALFWIDTH WHITE CIRCLE
+FFFC	OBJECT REPLACEMENT CHARACTER
+FFFD	REPLACEMENT CHARACTER
+"""
+
+def _makeunicode():
+	from string import split, atoi
+	import re
+	firstRE = re.compile("<(.*?), First>")
+	firstREmatch = firstRE.match
+	lastRE = re.compile("<(.*?), Last>")
+	lastREmatch = lastRE.match
+	
+	lines = split(_unicode, '\n')
+	while not lines[-1]:
+		del lines[-1] # empty string
+	
+	unicode = ['????'] * 0x10000
+	i = 0
+	lenLines = len(lines)
+	while i < lenLines:
+		line = lines[i]
+		num, name = split(line, '\t')
+		num = atoi(num, 16)
+		if firstREmatch(name) is not None:
+			i = i + 1
+			line = lines[i]
+			numLast, nameLast = split(line, '\t')
+			m = lastREmatch(nameLast)
+			assert m is not None
+			name = m.group(1)
+			numLast = atoi(numLast, 16)
+			unicode[num:numLast+1] = [name] * (numLast - num + 1)
+		else:
+			unicode[num] = name
+		i = i + 1
+	while not unicode[-1]:
+		del unicode[-1] # empty string
+	return unicode
+
+
+class _Unicode:
+	
+	def __init__(self):
+		self.codes = _makeunicode()
+	
+	def __getitem__(self, charCode):
+		if charCode > 0xffff:
+			raise IndexError, "charCode out of range"
+		try:
+			return self.codes[charCode]
+		except IndexError:
+			return "????"
+
+
+Unicode = _Unicode()
diff --git a/Lib/sstruct.py b/Lib/sstruct.py
new file mode 100644
index 0000000..7bc4772
--- /dev/null
+++ b/Lib/sstruct.py
@@ -0,0 +1,204 @@
+"""sstruct.py -- SuperStruct
+
+Higher level layer on top of the struct module, enabling to 
+bind names to struct elements. The interface is similar to 
+struct, except the objects passed and returned are not tuples 
+(or argument lists), but dictionaries or instances. 
+
+Just like struct, we use format strings to describe a data 
+structure, except we use one line per element. Lines are 
+separated by newlines or semi-colons. Each line contains 
+either one of the special struct characters ('@', '=', '<', 
+'>' or '!') or a 'name:formatchar' combo (eg. 'myFloat:f'). 
+Repetitions, like the struct module offers them are not useful 
+in this context, except for fixed length strings  (eg. 'myInt:5h' 
+is not allowed but 'myString:5s' is). The 'x' format character 
+(pad byte) is treated as 'special', since it is by definition 
+anonymous. Extra whitespace is allowed everywhere.
+
+The sstruct module offers one feature that the "normal" struct
+module doesn't: support for fixed point numbers. These are spelled
+as "n.mF", where n is the number of bits before the point, and m
+the number of bits after the point. Fixed point numbers get 
+converted to floats.
+
+pack(format, object):
+	'object' is either a dictionary or an instance (or actually
+	anything that has a __dict__ attribute). If it is a dictionary, 
+	its keys are used for names. If it is an instance, it's 
+	attributes are used to grab struct elements from. Returns
+	a string containing the data.
+
+unpack(format, data, object=None)
+	If 'object' is omitted (or None), a new dictionary will be 
+	returned. If 'object' is a dictionary, it will be used to add 
+	struct elements to. If it is an instance (or in fact anything
+	that has a __dict__ attribute), an attribute will be added for 
+	each struct element. In the latter two cases, 'object' itself 
+	is returned.
+
+unpack2(format, data, object=None)
+	Convenience function. Same as unpack, except data may be longer 
+	than needed. The returned value is a tuple: (object, leftoverdata).
+
+calcsize(format)
+	like struct.calcsize(), but uses our own format strings:
+	it returns the size of the data in bytes.
+"""
+
+# XXX I would like to support pascal strings, too, but I'm not
+# sure if that's wise. Would be nice if struct supported them
+# "properly", but that would certainly break calcsize()...
+
+__version__ = "1.2"
+__copyright__ = "Copyright 1998, Just van Rossum <just@letterror.com>"
+
+import struct
+import re
+import types
+
+
+error = "sstruct.error"
+
+def pack(format, object):
+	formatstring, names, fixes = getformat(format)
+	elements = []
+	if type(object) is not types.DictType:
+		object = object.__dict__
+	for name in names:
+		value = object[name]
+		if fixes.has_key(name):
+			# fixed point conversion
+			value = int(round(value*fixes[name]))
+		elements.append(value)
+	data = apply(struct.pack, (formatstring,) + tuple(elements))
+	return data
+
+def unpack(format, data, object=None):
+	if object is None:
+		object = {}
+	formatstring, names, fixes = getformat(format)
+	if type(object) is types.DictType:
+		dict = object
+	else:
+		dict = object.__dict__
+	elements = struct.unpack(formatstring, data)
+	for i in range(len(names)):
+		name = names[i]
+		value = elements[i]
+		if fixes.has_key(name):
+			# fixed point conversion
+			value = value / fixes[name]
+		dict[name] = value
+	return object
+
+def unpack2(format, data, object=None):
+	length = calcsize(format)
+	return unpack(format, data[:length], object), data[length:]
+
+def calcsize(format):
+	formatstring, names, fixes = getformat(format)
+	return struct.calcsize(formatstring)
+
+
+# matches "name:formatchar" (whitespace is allowed)
+_elementRE = re.compile(
+		"\s*"							# whitespace
+		"([A-Za-z_][A-Za-z_0-9]*)"		# name (python identifier)
+		"\s*:\s*"						# whitespace : whitespace
+		"([cbBhHiIlLfd]|[0-9]+[ps]|"	# formatchar...
+			"([0-9]+)\.([0-9]+)(F))"	# ...formatchar
+		"\s*"							# whitespace
+		"(#.*)?$"						# [comment] + end of string
+	)
+
+# matches the special struct format chars and 'x' (pad byte)
+_extraRE = re.compile("\s*([x@=<>!])\s*(#.*)?$")
+
+# matches an "empty" string, possibly containing whitespace and/or a comment
+_emptyRE = re.compile("\s*(#.*)?$")
+
+_fixedpointmappings = {
+		8: "b",
+		16: "h",
+		32: "l"}
+
+_formatcache = {}
+
+def getformat(format):
+	try:
+		formatstring, names, fixes = _formatcache[format]
+	except KeyError:
+		lines = re.split("[\n;]", format)
+		formatstring = ""
+		names = []
+		fixes = {}
+		for line in lines:
+			if _emptyRE.match(line):
+				continue
+			m = _extraRE.match(line)
+			if m:
+				formatchar = m.group(1)
+				if formatchar <> 'x' and formatstring:
+					raise error, "a special format char must be first"
+			else:
+				m = _elementRE.match(line)
+				if not m:
+					raise error, "syntax error in format: '%s'" % line
+				name = m.group(1)
+				names.append(name)
+				formatchar = m.group(2)
+				if m.group(3):
+					# fixed point
+					before = int(m.group(3))
+					after = int(m.group(4))
+					bits = before + after
+					if bits not in [8, 16, 32]:
+						raise error, "fixed point must be 8, 16 or 32 bits long"
+					formatchar = _fixedpointmappings[bits]
+					assert m.group(5) == "F"
+					fixes[name] = float(1 << after)
+			formatstring = formatstring + formatchar
+		_formatcache[format] = formatstring, names, fixes
+	return formatstring, names, fixes
+
+def _test():
+	format = """
+		# comments are allowed
+		>  # big endian (see documentation for struct)
+		# empty lines are allowed:
+		
+		ashort: h
+		along: l
+		abyte: b	# a byte
+		achar: c
+		astr: 5s
+		afloat: f; adouble: d	# multiple "statements" are allowed
+		afixed: 16.16F
+	"""
+	
+	print 'size:', calcsize(format)
+	
+	class foo:
+		pass
+	
+	i = foo()
+	
+	i.ashort = 0x7fff
+	i.along = 0x7fffffff
+	i.abyte = 0x7f
+	i.achar = "a"
+	i.astr = "12345"
+	i.afloat = 0.5
+	i.adouble = 0.5
+	i.afixed = 1.5
+	
+	data = pack(format, i)
+	print 'data:', `data`
+	print unpack(format, data)
+	i2 = foo()
+	unpack(format, data, i2)
+	print vars(i2)
+
+if __name__ == "__main__":
+	_test()
diff --git a/Lib/xmlWriter.py b/Lib/xmlWriter.py
new file mode 100644
index 0000000..b078959
--- /dev/null
+++ b/Lib/xmlWriter.py
@@ -0,0 +1,172 @@
+"""xmlWriter.py -- Simple XML authoring class"""
+
+__author__ = "jvr"
+__version__ = "0.9"
+
+import string
+import struct
+
+INDENT = "  "
+
+class XMLWriter:
+	
+	def __init__(self, file, dtd=None, indentwhite=INDENT):
+		if type(file) == type(""):
+			self.file = open(file, "w")
+		else:
+			# assume writable file object
+			self.file = file
+		self.dtd = dtd
+		self.indentwhite = indentwhite
+		self.indentlevel = 0
+		self.stack = []
+		self.needindent = 1
+		self.writeraw("<?xml version='1.0'?>")
+		self.newline()
+		if self.dtd:
+			# DOCTYPE???
+			self.newline()
+	
+	def close(self):
+		self.file.close()
+	
+	def write(self, data):
+		self.writeraw(escape(data))
+	
+	def write_noindent(self, data):
+		self.file.write(escape(data))
+	
+	def write8bit(self, data):
+		self.writeraw(escape8bit(data))
+	
+	def write16bit(self, data):
+		self.writeraw(escape16bit(data))
+	
+	def writeraw(self, data):
+		if self.needindent:
+			self.file.write(self.indentlevel * self.indentwhite)
+			self.needindent = 0
+		self.file.write(data)
+	
+	def newline(self):
+		self.file.write("\n")
+		self.needindent = 1
+	
+	def comment(self, data):
+		data = escape(data)
+		lines = string.split(data, "\n")
+		self.writeraw("<!-- " + lines[0])
+		for line in lines[1:]:
+			self.newline()
+			self.writeraw("     " + line)
+		self.writeraw(" -->")
+	
+	def simpletag(self, _TAG_, *args, **kwargs):
+		attrdata = apply(self.stringifyattrs, args, kwargs)
+		data = "<%s%s/>" % (_TAG_, attrdata)
+		self.writeraw(data)
+	
+	def begintag(self, _TAG_, *args, **kwargs):
+		attrdata = apply(self.stringifyattrs, args, kwargs)
+		data = "<%s%s>" % (_TAG_, attrdata)
+		self.writeraw(data)
+		self.stack.append(_TAG_)
+		self.indent()
+	
+	def endtag(self, _TAG_):
+		assert self.stack and self.stack[-1] == _TAG_, "nonmatching endtag"
+		del self.stack[-1]
+		self.dedent()
+		data = "</%s>" % _TAG_
+		self.writeraw(data)
+	
+	def dumphex(self, data):
+		linelength = 16
+		hexlinelength = linelength * 2
+		chunksize = 8
+		for i in range(0, len(data), linelength):
+			hexline = hexStr(data[i:i+linelength])
+			line = ""
+			white = ""
+			for j in range(0, hexlinelength, chunksize):
+				line = line + white + hexline[j:j+chunksize]
+				white = " "
+			self.writeraw(line)
+			self.newline()
+	
+	def indent(self):
+		self.indentlevel = self.indentlevel + 1
+	
+	def dedent(self):
+		assert self.indentlevel > 0
+		self.indentlevel = self.indentlevel - 1
+	
+	def stringifyattrs(self, *args, **kwargs):
+		if kwargs:
+			assert not args
+			attributes = kwargs.items()
+			attributes.sort()
+		elif args:
+			assert len(args) == 1
+			attributes = args[0]
+		else:
+			return ""
+		data = ""
+		for attr, value in attributes:
+			data = data + ' %s="%s"' % (attr, escapeattr(str(value)))
+		return data
+	
+
+def escape(data):
+	data = string.replace(data, "&", "&amp;")
+	data = string.replace(data, "<", "&lt;")
+	return data
+
+def escapeattr(data):
+	data = string.replace(data, "&", "&amp;")
+	data = string.replace(data, "<", "&lt;")
+	data = string.replace(data, '"', "&quot;")
+	return data
+
+def escape8bit(data):
+	def escapechar(c):
+		n = ord(c)
+		if c in "<&":
+			if c == "&":
+				return "&amp;"
+			else:
+				return "&lt;"
+		elif 32 <= n <= 127:
+			return c
+		else:
+			return "&#" + `n` + ";"
+	return string.join(map(escapechar, data), "")
+
+needswap = struct.pack("h", 1) == "\001\000"
+
+def escape16bit(data):
+	import array
+	a = array.array("H")
+	a.fromstring(data)
+	if needswap:
+		a.byteswap()
+	def escapenum(n, amp=ord("&"), lt=ord("<")):
+		if n == amp:
+			return "&amp;"
+		elif n == lt:
+			return "&lt;"
+		elif 32 <= n <= 127:
+			return chr(n)
+		else:
+			return "&#" + `n` + ";"
+	return string.join(map(escapenum, a), "")
+
+
+def hexStr(s):
+	h = string.hexdigits
+	r = ''
+	for c in s:
+		i = ord(c)
+		r = r + h[(i >> 4) & 0xF] + h[i & 0xF]
+	return r
+