diff -uprN orig/fbreader-0.12.10/debug fbreader-0.12.10/debug
--- orig/fbreader-0.12.10/debug	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/debug	2012-08-12 22:52:21.247513817 +0200
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+export LD_LIBRARY_PATH="/home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core:/home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/text:/home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/ui"
+exec gdb --args /home/dannym/source/FBReader/fbreader-0.12.10/fbreader/FBReader "$@"
diff -uprN orig/fbreader-0.12.10/fbreader/data/default/config.maemo.xml fbreader-0.12.10/fbreader/data/default/config.maemo.xml
--- orig/fbreader-0.12.10/fbreader/data/default/config.maemo.xml	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/fbreader/data/default/config.maemo.xml	2011-04-05 22:55:28.000000000 +0200
@@ -6,7 +6,7 @@
 	</group>
   <group name="Options">
     <option name="Timeout" value="30"/>
-    <option name="LeftMargin" value="20"/>
+    <option name="LeftMargin" value="2"/>
     <option name="TopMargin" value="4"/>
     <option name="BookPath" value="~/MyDocs/Books:/media/mmc1/Books:/media/mmc2/Books"/>
     <option name="DownloadDirectory" value="~/MyDocs/Books"/>
diff -uprN orig/fbreader-0.12.10/fbreader/maemo/FBReader.desktop fbreader-0.12.10/fbreader/maemo/FBReader.desktop
--- orig/fbreader-0.12.10/fbreader/maemo/FBReader.desktop	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/fbreader/maemo/FBReader.desktop	2011-04-05 22:55:28.000000000 +0200
@@ -10,3 +10,4 @@ X-Window-Icon=FBReader
 X-Window-Icon-Dimmed=FBReader
 X-Osso-Service=FBReader
 X-Osso-Type=application/x-executable
+MimeType=application/pdf;text/plain;application/xhtml+xml;text/rtf;application/epub+zip;
diff -uprN orig/fbreader-0.12.10/fbreader/Makefile fbreader-0.12.10/fbreader/Makefile
--- orig/fbreader-0.12.10/fbreader/Makefile	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/fbreader/Makefile	2011-04-05 22:55:28.000000000 +0200
@@ -11,7 +11,7 @@ ALL_SUBDIRS = src src/database src/datab
 ALL_ARCHSUBDIRS = desktop pdaxrom opie zaurus maemo openzaurus pma400 win32
 
 SUBDIRS = src/database src/database/sqldb src/database/sqldb/implsqlite src/database/booksdb src/database/booksdb/runnables src/migration src/constants src/options src/library src/bookmodel \
-	src/formats src/formats/fb2 src/formats/css src/formats/html src/formats/pdb src/formats/txt src/formats/tcr src/formats/chm src/formats/xhtml src/formats/oeb src/formats/rtf src/formats/openreader src/formats/util \
+	src/formats src/formats/fb2 src/formats/css src/formats/html src/formats/pdb src/formats/txt src/formats/tcr src/formats/chm src/formats/xhtml src/formats/oeb src/formats/rtf src/formats/openreader src/formats/util src/formats/pdf \
 	src/external src/optionsDialog src/fbreader src/encodingOption src/network src/network/authentication src/network/authentication/basic src/network/atom src/network/opds src/network/authentication/litres src/blockTree src/libraryActions src/libraryTree src/networkActions src/networkTree
 
 all: .resources
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/oeb/NCXReader.cpp fbreader-0.12.10/fbreader/src/formats/oeb/NCXReader.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/oeb/NCXReader.cpp	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/fbreader/src/formats/oeb/NCXReader.cpp	2011-04-05 22:55:28.000000000 +0200
@@ -32,27 +32,41 @@ static const std::string TAG_NAVLABEL =
 static const std::string TAG_CONTENT = "content";
 static const std::string TAG_TEXT = "text";
 
+bool NCXReader::processNamespaces() const {
+	return true;
+}
+
+void NCXReader::namespaceListChangedHandler() {
+	const std::map<std::string,std::string>& namespaces = this->namespaces();
+	for (std::map<std::string,std::string>::const_iterator it = namespaces.begin(); it != namespaces.end(); ++it) {
+		if (it->second == "http://www.daisy.org/z3986/2005/ncx/") {
+			myNCXNamespacePrefix = it->first + ":";
+		}
+	}
+	
+}
+
 void NCXReader::startElementHandler(const char *tag, const char **attributes) {
 	switch (myReadState) {
 		case READ_NONE:
-			if (TAG_NAVMAP == tag) {
+			if (myNCXNamespacePrefix + TAG_NAVMAP == tag) {
 				myReadState = READ_MAP;
 			}
 			break;
 		case READ_MAP:
-			if (TAG_NAVPOINT == tag) {
+			if (myNCXNamespacePrefix + TAG_NAVPOINT == tag) {
 				const char *order = attributeValue(attributes, "playOrder");
 				myPointStack.push_back(NavPoint((order != 0) ? atoi(order) : myPlayIndex++, myPointStack.size()));
 				myReadState = READ_POINT;
 			}
 			break;
 		case READ_POINT:
-			if (TAG_NAVPOINT == tag) {
+			if (myNCXNamespacePrefix + TAG_NAVPOINT == tag) {
 				const char *order = attributeValue(attributes, "playOrder");
 				myPointStack.push_back(NavPoint((order != 0) ? atoi(order) : myPlayIndex++, myPointStack.size()));
-			} else if (TAG_NAVLABEL == tag) {
+			} else if (myNCXNamespacePrefix + TAG_NAVLABEL == tag) {
 				myReadState = READ_LABEL;
-			} else if (TAG_CONTENT == tag) {
+			} else if (myNCXNamespacePrefix + TAG_CONTENT == tag) {
 				const char *src = attributeValue(attributes, "src");
 				if (src != 0) {
 					myPointStack.back().ContentHRef = MiscUtil::decodeHtmlURL(src);
@@ -60,7 +74,7 @@ void NCXReader::startElementHandler(cons
 			}
 			break;
 		case READ_LABEL:
-			if (TAG_TEXT == tag) {
+			if (myNCXNamespacePrefix + TAG_TEXT == tag) {
 				myReadState = READ_TEXT;
 			}
 			break;
@@ -74,12 +88,12 @@ void NCXReader::endElementHandler(const
 		case READ_NONE:
 			break;
 		case READ_MAP:
-			if (TAG_NAVMAP == tag) {
+			if (myNCXNamespacePrefix + TAG_NAVMAP == tag) {
 				myReadState = READ_NONE;
 			}
 			break;
 		case READ_POINT:
-			if (TAG_NAVPOINT == tag) {
+			if (myNCXNamespacePrefix + TAG_NAVPOINT == tag) {
 				if (myPointStack.back().Text.empty()) {
 					myPointStack.back().Text = "...";
 				}
@@ -88,12 +102,12 @@ void NCXReader::endElementHandler(const
 				myReadState = myPointStack.empty() ? READ_MAP : READ_POINT;
 			}
 		case READ_LABEL:
-			if (TAG_NAVLABEL == tag) {
+			if (myNCXNamespacePrefix + TAG_NAVLABEL == tag) {
 				myReadState = READ_POINT;
 			}
 			break;
 		case READ_TEXT:
-			if (TAG_TEXT == tag) {
+			if (myNCXNamespacePrefix + TAG_TEXT == tag) {
 				myReadState = READ_LABEL;
 			}
 			break;
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/oeb/NCXReader.h fbreader-0.12.10/fbreader/src/formats/oeb/NCXReader.h
--- orig/fbreader-0.12.10/fbreader/src/formats/oeb/NCXReader.h	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/fbreader/src/formats/oeb/NCXReader.h	2011-04-05 22:55:28.000000000 +0200
@@ -44,16 +44,21 @@ public:
 	NCXReader(BookReader &modelReader);
 	const std::map<int,NavPoint> &navigationMap() const;
 
-private:
+protected:
 	void startElementHandler(const char *tag, const char **attributes);
 	void endElementHandler(const char *tag);
 	void characterDataHandler(const char *text, size_t len);
+	void namespaceListChangedHandler();
+	bool processNamespaces() const;
+
+private:
 	const std::vector<std::string> &externalDTDs() const;
 
 private:
 	BookReader &myModelReader;
 	std::map<int,NavPoint> myNavigationMap;
 	std::vector<NavPoint> myPointStack;
+	std::string myNCXNamespacePrefix;
 
 	enum {
 		READ_NONE,
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/architecture fbreader-0.12.10/fbreader/src/formats/pdf/architecture
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/architecture	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/architecture	2011-04-05 22:55:28.000000000 +0200
@@ -0,0 +1,105 @@
+The goal of the PDF format parser is to find all the text content and add it to the FBReader model via addData("<text>");
+
+It's best to understand this document by examining an example PDF file using a text editor (that doesn't support PDF). You can usually search for parts that are quoted here over there and find what we are talking about.
+
+First a few words about the PDF data types (see "PdfObject.h" for the actual ones (important file!)):
+The PDF file uses values which can be assigned the following data types:
+  PdfBooleanObject    either "true" or "false".
+  PdfIntegerObject    integer numeric value.
+  PdfRealObject       numeric value of the real numbers. Search for ".".
+  PdfStringObject     actual text string. Search for "(".
+  PdfNameObject       a unique symbol for tokens like "/Root" in the original PDF. Note that in this case the PdfNameObject contains "Root" as id() (without slash). The uniqueness means you can check for equality by pointer comparison which is faster than string comparison.
+  PdfDictionaryObject a dictionary of attributes (of an object, usually). Search for "<<".
+  PdfStreamObject     a stream of data (like an image, text, ...). Search for "stream". This provides access to its dictionary object as well (these come before the word "stream" in the original PDF).
+  PdfArrayObject      array of values ("[1 2 3 4]").
+  PdfObjectReference  reference to another pdf object (like "1501 0 R" refers to object defined by "1501 0 obj").
+These are all derived from PdfObject because PDF uses an argument-stack-based instruction layout:
+  /T1 1 Tf                        # means setFont(PdfNameObject::nameObject("T1"), 1);
+  [234 (Hello) 11 (world)] TJ     # means advance 234, print "Hello", advance 11, print "world".
+Note that the parameters can be supplied by argument values having any type (even in arrays).
+
+Registration of the PDF plugin is in file "PdfPlugin.cpp".
+The main entry point is the function PdfBookReader::readBook (in file "PdfBookReader.cpp", as is the normal convention in the entire PDF parser).
+
+All the following methods until further notice are in PdfBookReader.
+
+A PDF file contains one (or more) table of object positions at the END.
+Right before the end of the file, there's the word "startxref" which is followed by the absolute byte offset into the file where the object table starts.
+The object table contains where all the objects are and an attribute dictionary after the word "trailer".
+This dictionary contains a Name "/Prev" to find the "previous" object [position] table, if any.
+I think this splitting of tables has been done to make the PDF faster to display (can start to display the first page earlier), but not sure.
+
+In any case, readBook calls readReferenceTable to load this table and find the "/Root" object which is where the actual content will be stored (well, in subnodes).
+The value of the Name "/Pages" in the dictionary is the most interesting one, because it contains all the page data (in subnodes).
+So processPages is called to process these.
+
+processPages checks whether its an object of "/Type" "/Pages", if so:
+  finds all the "/Kids" and recursively calls itself.
+if not: 
+  calls processPage.
+
+processPage finds the dictionary values with Names "/Resources" and "/Contents".
+"/Resources" are fonts etc, it remembers those.
+The "/Contents" is where all the text resides in, so processContents is called with it (note the object is a PdfStreamObject).
+Control eventually is given to "PdfContent::parse" to parse that stream.
+
+All the following methods until further notice are in PdfContent.
+
+First, an example PdfContent source stream:
+-----
+-0.002 Tc 
+[(ISBN)-222(3-540-20210-2)]TJ
+/F2 1 Tf  
+0 -2.031 TD
+-0.0018 Tc
+[(ISBN)-222(3-540-21473-9)]TJ
+-----
+
+So the format is quite similar to the main PDF format, but simpler. There can be no substreams or dictionaries.
+The PdfContent parser reads this file and remembers all the instructions. One can later access them via the method "instructions" (in PdfContent).
+Note that an instruction with operator==opBeginText will contain an array of subinstructions (which can contain an operator opBeginText which ...) which are to be processed (partly) within their own temporary variable environment. The PDF operator for this is called "BT", if you want to look it up.
+
+In any case, eventually it's done parsing and control returns to PdfBookReader, specifically PdfBookReader::processInstructions.
+This will call PdfBookReader::processInstruction.
+
+All the following methods until further notice are in PdfBookReader.
+
+Note that all the content text is encoded in some 8-bit encoding which we don't a priori know what it is.
+PDF is actually a printing format so it didn't make much sense in the beginning to include easy-to-find character codes at all.
+Nowadays, these are included in PDFs that are searchable (you wouldn't want to draw the glyphs using the mouse to find them, would you?).
+Also, there is a table that is used for referring to glyphs of built-in Postscript fonts of printers sometimes. This one is actually standardized (yeah, right):
+See file "parseDefaultCharName.h" for a parser for them. It will return the unicode codepoint for one of those.
+
+"PdfDefaultCharMap.cpp" is the interface for getting at the Postscript default names.
+"PdfDefaultCharMapMap.cpp" is an old version that uses a dictionary. I actually wanted to do it this way (even though it's slower) because it would be more maintainable, but unfortunately GCC will use 100% CPU and then eat up 1GB RAM trying to compile it and then die (in scratchbox). Fun.
+
+"PdfDescriptionReader.cpp": Dummy.
+
+The class PdfScanner is the base class for my parsers (there's no reason that the main PdfObject parser doesn't use this as well - except laziness).
+All parsers are recursive descent parsers with 1 (8-bit) char lookahead.
+The PdfScanner::consume will consume the current lookahead and read the next character from the file (and set it as the new lookahead).
+The PdfScanner::input is the current lookahead char.
+
+= How to make sense of text =
+
+As explained above, the text itself doesn't use an encoding that is known a priori, so we have to get our hands on one defined within the PDF file.
+
+see PdfBookReader::convertStringToUnicode for how:
+  It calls PdfToUnicodeMap::nextUnicodeCodepoint repeatedly with parts of the text to get back one unicode codepoint after another.
+  By this, it eventually reconstructs the unicode string we should display (note in C++ that is UTF-8 encoded because that's standard in UNIX and FBReader and GNOME and half the internet and so on).
+
+PdfBookReader::setFont is called when the PDF font is switched (not that we support different font glyphs in FBReader, but remember, the encoding used for PDF text can change at a whim).
+Because of the real PDF files in the wild, this is done by convoluted steps (sigh):
+PdfBookReader::loadFonts prepares a fToUnicodeTablesByName entry for the respective fonts, by:
+  - try to find a font with the same pdf object ID (address), if found, use that.
+  - load new fonts by PdfBookReader::loadFont.
+
+PdfBookReader::loadFont parses the "/Encoding" table (see PdfBookReader::parseEncoding).
+Then it parses the "/ToUnicode" (if present) and, as a last resort, the "/FontFile" itself (or parts of it...).
+
+PdfToUnicodeMap <-- data class.
+PdfToUnicodeParser <-- parser for "/ToUnicode" value.
+PdfType1FontFileParser <-- parser for "/FontFile" value.
+PdfBookReader::parseEncoding <-- parser for "/Encoding" value.
+
+PdfImage tries to load images embedded in the PDF (well, at least JPEG).
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/generate-state-table fbreader-0.12.10/fbreader/src/formats/pdf/generate-state-table
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/generate-state-table	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/generate-state-table	2011-04-05 22:55:28.000000000 +0200
@@ -0,0 +1,68 @@
+#!/usr/bin/env python
+
+import re
+re_not_normal = re.compile(r"[^a-zA-Z]")
+
+def load_chars():
+	chars = {}
+	for line in open("PdfDefaultCharMapMap.cpp").readlines():
+		if not line.startswith("\tchars["):
+			continue
+		name, value = line.split("//")[0].split("=")
+		name = name.replace("\tchars[\"", "").replace("\"]", "").strip()
+		assert(not re_not_normal.match(name))
+		value = eval(value.replace(";", ""))
+		assert(isinstance(value, int))
+		chars[name] = value
+	return chars
+
+chars = load_chars()
+
+class Node(object):
+	def __init__(self):
+		self.children = {}
+		self.result = None
+
+root = Node()
+
+def add_entry(text, result):
+	node = root
+	for c in text:
+		if c not in node.children:
+			node.children[c] = Node()
+		node = node.children[c]
+	node.result = result
+
+def sorted(l): # for older Python versions.
+	c = [i for i in l]
+	c.sort()
+	return(c)
+
+keys = sorted(chars.keys())
+for key in keys:
+	assert(key.find("\0") == -1)
+	add_entry(key + "\0", chars[key])
+
+def dumpParser(node, IO_1, indentation = 1):
+	i = indentation * "\t"
+	IO_1.write(i + "switch(*inputString) {\n")
+	for k in sorted(node.children.keys()):
+		v = node.children[k]
+		IO_1.write(i + "case %r:\n" % (k, ))
+		IO_1.write(i + "\t++inputString;\n")
+		dumpParser(v, IO_1, indentation + 1)
+		IO_1.write(i + "\tbreak;\n")
+	IO_1.write(i + "default:\n")
+	IO_1.write(i + "\treturn 0x%04X;\n" % (node.result or 0))
+	IO_1.write(i + "}\n")
+
+try:
+	import StringIO
+	IO_1 = StringIO.StringIO()
+except ImportError:
+	import io
+	IO_1 = io.StringIO()
+print("static unsigned int parseDefaultCharName(const char*& inputString) {")
+dumpParser(root, IO_1)
+print(IO_1.getvalue())
+print("}")
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfBookReader.cpp fbreader-0.12.10/fbreader/src/formats/pdf/PdfBookReader.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfBookReader.cpp	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfBookReader.cpp	2011-12-30 00:04:40.257285405 +0100
@@ -18,180 +18,92 @@
  */
 
 #include <cstdlib>
+#include <string.h>
 #include <iostream>
+#include <list>
+#include <math.h>
+#include <assert.h>
 
 #include <ZLStringUtil.h>
 #include <ZLInputStream.h>
+#include <ZLUnicodeUtil.h>
 
 #include "PdfBookReader.h"
 #include "PdfObject.h"
+#include "PdfContent.h"
+#include "PdfContentParser.h"
+#include "PdfToUnicodeMap.h"
 #include "../../bookmodel/BookModel.h"
+#include "PdfImage.h"
+#include "PdfGraphicsState.h"
 
-static void readLine(ZLInputStream &stream, std::string &buffer) {
-	buffer.clear();
-	char ch;
-	while (1) {
-		if (stream.read(&ch, 1) != 1) {
-			return;
-		}
-		if ((ch == 10) || (ch == 13)) {
-			if (!buffer.empty()) {
-				return;
-			}
-		} else {
-			buffer += ch;
-		}
-	}
-}
-
-PdfBookReader::PdfBookReader(BookModel &model) : myModelReader(model) {
-}
+/* empirically determined, yay */
+#define EPSILON 0.0002
 
-PdfBookReader::~PdfBookReader() {
-}
 
-shared_ptr<PdfObject> PdfBookReader::readObjectFromLocation(ZLInputStream &stream, const std::pair<int,int> &address) {
-	std::map<std::pair<int,int>,int>::const_iterator jt = myObjectLocationMap.find(address);
-	if (jt == myObjectLocationMap.end()) {
-		return 0;
-	}
-	stream.seek(jt->second, true);
-	char ch = 0;
-	PdfObject::readToken(stream, myBuffer, ch);
-	if (address.first != atoi(myBuffer.c_str())) {
-		return 0;
-	}
-	PdfObject::readToken(stream, myBuffer, ch);
-	if (address.second != atoi(myBuffer.c_str())) {
-		return 0;
-	}
-	PdfObject::readToken(stream, myBuffer, ch);
-	if (myBuffer != "obj") {
-		return 0;
-	}
-	return PdfObject::readObject(stream, ch);
+PdfBookReader::PdfBookReader(BookModel &model) : BookReader(model), /*myModelReader(model), */fToUnicodeTable(0), myGraphicsState(1.0, 1.0) {
+	myFont = NULL;
+	myFontSize = 1;
+	myLeading = 0.0;
+	myPositionV = 0.0;
+	myPositionH = 0.0;
+	myPositionBeginningH = 0.0;
+	myTextRise = 0.0;
+	myEffectiveTextRise = 0.0;
+	myDescent = 0.0;
+	myAscent = 0.0;
+	myTextHeight = 0.0;
+	myIsFirstOnLine = true;
+	myPreviousCharacter[0] = 0;
+	myPreviousCharacter[1] = 0;
+	myPreviousCharacter[2] = 0;
+	myPreviousCharacter[3] = 0;
+	myPreviousCharacter[4] = 0;
+	myImageIndex = 0;
+	myBBoldness = false;
+	myParagraphIndentation = 0.0;
+	myTextScaleH = 1.0;
+	myTextScaleV = 0.9; // 1.0;
+	myCharSpacing = 0;
+	myWordSpacing = 0;
+	myHorizontalScaling = 100;
+	myBPendingTextMatrixReset = true;
+	myPendingTextMatrixBeginningH = 0.0;
+	myPendingTextMatrixH = 0.0;
+	myPendingTextMatrixV = 0.0;
 }
 
-shared_ptr<PdfObject> PdfBookReader::resolveReference(shared_ptr<PdfObject> ref, ZLInputStream &stream) {
-	if (ref.isNull() || (ref->type() != PdfObject::REFERENCE)) {
-		return ref;
-	}
-	const PdfObjectReference &reference = (const PdfObjectReference&)*ref;
-	const std::pair<int,int>address(reference.number(), reference.generation());
-	std::map<std::pair<int,int>,shared_ptr<PdfObject> >::const_iterator it = myObjectMap.find(address);
-	if (it != myObjectMap.end()) {
-		return it->second;
-	}
-	std::map<std::pair<int,int>,int>::const_iterator jt = myObjectLocationMap.find(address);
-	shared_ptr<PdfObject> object = readObjectFromLocation(stream, address);
-	myObjectMap.insert(std::pair<std::pair<int,int>,shared_ptr<PdfObject> >(address, object));
-	return object;
-}
-
-static void stripBuffer(std::string &buffer) {
-	int index = buffer.find('%');
-	if (index >= 0) {
-		buffer.erase(index);
-	}
-	ZLStringUtil::stripWhiteSpaces(buffer);
-}
-
-bool PdfBookReader::readReferenceTable(ZLInputStream &stream, int xrefOffset) {
-	while (true) {
-		stream.seek(xrefOffset, true);
-		readLine(stream, myBuffer);
-		stripBuffer(myBuffer);
-		if (myBuffer != "xref") {
-			return false;
-		}
-
-		while (true) {
-			readLine(stream, myBuffer);
-			stripBuffer(myBuffer);
-			if (myBuffer == "trailer") {
-				break;
-			}
-			const int index = myBuffer.find(' ');
-			const int start = atoi(myBuffer.c_str());
-			const int len = atoi(myBuffer.c_str() + index + 1);
-			for (int i = 0; i < len; ++i) {
-				readLine(stream, myBuffer);
-				stripBuffer(myBuffer);
-				if (myBuffer.length() != 18) {
-					return false;
-				}
-				const int objectOffset = atoi(myBuffer.c_str());
-				const int objectGeneration = atoi(myBuffer.c_str() + 11);
-				const bool objectInUse = myBuffer[17] == 'n';
-				if (objectInUse) {
-					myObjectLocationMap[std::pair<int,int>(start + i, objectGeneration)] = objectOffset;
-				}
-			}
-		}
-		char ch = 0;
-		shared_ptr<PdfObject> trailer = PdfObject::readObject(stream, ch);
-		if (trailer.isNull() || (trailer->type() != PdfObject::DICTIONARY)) {
-			return false;
-		}
-		if (myTrailer.isNull()) {
-			myTrailer = trailer;
-		}
-		PdfDictionaryObject &trailerDictionary = (PdfDictionaryObject&)*trailer;
-		shared_ptr<PdfObject> previous = trailerDictionary["Prev"];
-		if (previous.isNull()) {
-			return true;
-		}
-
-		if (previous->type() != PdfObject::INTEGER_NUMBER) {
-			return false;
-		}
-		xrefOffset = ((PdfIntegerObject&)*previous).value();
-	}
+PdfBookReader::~PdfBookReader() {
 }
 
 bool PdfBookReader::readBook(shared_ptr<ZLInputStream> stream) {
+	bool status;
 	if (stream.isNull() || !stream->open()) {
 		return false;
 	}
 
-	readLine(*stream, myBuffer);
-	if (!ZLStringUtil::stringStartsWith(myBuffer, "%PDF-")) {
+	char buffer[50];
+	if((*stream).read(buffer, 50) < 5)
 		return false;
-	}
-
-	std::string version = myBuffer.substr(5);
-	std::cerr << "version = " << version << "\n";
 
-	size_t eofOffset = stream->sizeOfOpened();
-	if (eofOffset < 100) {
+	if (memcmp(buffer, "%PDF-", 5) != 0) {
 		return false;
 	}
 
-	stream->seek(eofOffset - 100, true);
-	bool readXrefOffset = false;
-	size_t xrefOffset = (size_t)-1;
-	while (true) {
-		readLine(*stream, myBuffer);
-		if (myBuffer.empty()) {
-			break;
-		}
-		stripBuffer(myBuffer);
-		if (readXrefOffset) {
-			if (!myBuffer.empty()) {
-				xrefOffset = atoi(myBuffer.c_str());
-				break;
-			}
-		} else if (myBuffer == "startxref") {
-			readXrefOffset = true;
-		}
-	}
+	//std::string version = myBuffer.substr(5);
+	//std::cerr << "version = " << version << "\n";
+	/* for example: 1.3 */
+	
+	myPDF = new Pdf();
+	myParser = new PdfParser(stream, *myPDF);
+	myParser->parse();
 
-	if (!readReferenceTable(*stream, xrefOffset)) {
+	shared_ptr<PdfObject> trailerX = myPDF->trailer();
+	if(trailerX.isNull())
 		return false;
-	}
-
-	PdfDictionaryObject &trailerDictionary = (PdfDictionaryObject&)*myTrailer;
-	shared_ptr<PdfObject> root = resolveReference(trailerDictionary["Root"], *stream);
+	PdfDictionaryObject &trailerDictionary = (PdfDictionaryObject&)*trailerX;
+	//trailerDictionary.dump();
+	shared_ptr<PdfObject> root = resolveReferences(trailerDictionary["Root"], *stream);
 	if (root.isNull() || (root->type() != PdfObject::DICTIONARY)) {
 		return false;
 	}
@@ -200,12 +112,26 @@ bool PdfBookReader::readBook(shared_ptr<
 	if (rootDictionary["Type"] != PdfNameObject::nameObject("Catalog")) {
 		return false;
 	}
-	shared_ptr<PdfObject> pageRootNode = resolveReference(rootDictionary["Pages"], *stream);
-	if (pageRootNode.isNull() || (pageRootNode->type() != PdfObject::DICTIONARY)) {
+	shared_ptr<PdfObject> pageRootNode = rootDictionary["Pages"];
+
+	setMainTextModel();
+	if (isKindStackEmpty())
+		pushKind(REGULAR);
+	assert(pageRootNode->type() != PdfObject::REFERENCE);
+	status = processPages(pageRootNode, *stream);
+	std::cout << "end of book, status " << status << std::endl;
+
+	return status;
+}
+
+bool PdfBookReader::processPages(shared_ptr<PdfObject> pageRootNode, ZLInputStream &stream) {
+	//pageRootNode = resolveReference(pageRootNode, stream);
+	if(pageRootNode.isNull() || (pageRootNode->type() != PdfObject::DICTIONARY)) {
 		return false;
 	}
-	PdfDictionaryObject &pageRootNodeDictionary = (PdfDictionaryObject&)*pageRootNode;
-	if (pageRootNodeDictionary["Type"] != PdfNameObject::nameObject("Pages")) {
+	PdfDictionaryObject &pageRootNodeDictionary = (PdfDictionaryObject&)*pageRootNode;	
+	//pageRootNodeDictionary.dump();
+	if (pageRootNodeDictionary["Type"].isNull() || pageRootNodeDictionary["Type"] != PdfNameObject::nameObject("Pages")) {
 		return false;
 	}
 	
@@ -222,40 +148,839 @@ bool PdfBookReader::readBook(shared_ptr<
 	const PdfArrayObject& pagesArray = (const PdfArrayObject&)*pages;
 	const size_t pageNumber = pagesArray.size();
 	for (size_t i = 0; i < pageNumber; ++i) {
-		processPage(pagesArray[i], *stream);
+		if(!processPages(pagesArray[i], stream)) {
+			processPage(pagesArray[i], stream);
+		}
 	}
-
 	return true;
 }
 
+
+void PdfBookReader::processXObject(shared_ptr<PdfObject> nameObject) {
+	if(myLines.find(nameObject) != myLines.end()) {
+		/* probably a separator */
+		// TODO increaseEffectiveTextRise(-myEffectiveTextRise); or something.
+		if(myBBoldness) {
+			setBoldness(false);
+			addData("/");
+			setBoldness(true);
+		} else
+			addData("/");
+
+		myIsFirstOnLine = true;
+		return;
+	}
+	
+	goToNextLine();
+	/*const PdfNameObject& name = (const PdfNameObject&)*name;*/
+	shared_ptr<PdfObject> imageX = findXObject(nameObject);
+	std::string ID;
+	ZLStringUtil::appendNumber(ID, myImageIndex++);
+	//ID << reference.number() << "-" << reference.generation();
+	/* TODO check filter = DCTDecode */
+	// TODO get attribute "Subtype": "Form" or "Image".
+	// TODO scale
+	if(imageX.isNull() || imageX->type() != PdfObject::STREAM)
+		return;
+	addImageReference(ID);
+	addImage(ID, new PdfImage(imageX));
+	//std::cout << "should print XObject " << ((PdfNameObject&)*nameObject).id() << " here..." << std::endl;
+}
+
+/*findLeading(instructions, index) {
+opMoveCaretToStartOfNextLine                           
+(opMoveCaret)
+opNextLineShowString
+opNextLineSpacedShowString
+--     
+opSetTextLeading
+opMoveCaretToStartOfNextLineAndOffsetAndSetLeading 
+}
+*/
+
+
+void PdfBookReader::setFont(const shared_ptr<PdfObject>& name, unsigned fontSize) {
+	/*addData("<set font");
+	addData(((PdfNameObject&)(*name)).id());
+	addData(">");*/
+	/*std::cerr << "setting font " << ((PdfNameObject&)(*name)).id() << std::endl;*/
+	myDescent = 0.0;
+	myAscent = 0.0;
+	std::map<shared_ptr<PdfObject>, shared_ptr<PdfFont> >::const_iterator iter_fonts = fFontsByName.find(name);
+	if(iter_fonts != fFontsByName.end()) { // found font.
+		PdfFont& font = *iter_fonts->second;
+		fToUnicodeTable = font.toUnicodeTable();
+		myFont = &font;
+		myTextSpaceFromGlyphSpaceFactor = font.textSpaceFromGlyphSpaceFactor();
+		myDescent = font.descent();
+		myAscent = font.ascent();
+		if(fabs(myAscent) < EPSILON && fabs(myDescent) < EPSILON) {
+			std::cerr << "setting font " << ((PdfNameObject&)(*name)).id() << std::endl;
+			std::cerr << "setFont: warning: ascent=" << myAscent << std::endl;
+			std::cerr << "setFont: descent=" << myDescent << std::endl;
+		}
+		myFontSize = fontSize;
+		//std::cerr << "factor " << myTextSpaceFromGlyphSpaceFactor << std::endl;
+		updateTextHeight();
+		setBoldness(font.boldness());
+	} else {
+		addData("<unknown font>");
+		fToUnicodeTable = 0;
+		myFont = 0;
+	}
+}
+
+void PdfBookReader::updateTextHeight() {
+	double currentTextHeight = (myAscent - myDescent) * myTextSpaceFromGlyphSpaceFactor * myFontSize * /* fabs(myGraphicsState.CTMScaleV()) * */ fabs(myTextScaleV); 
+	if(currentTextHeight < EPSILON) {
+		std::cerr << "warning: current text height is 0." << std::endl;
+		std::cerr << "info: ^-- myAscent-myDescent is " << (myAscent - myDescent) << std::endl;
+		std::cerr << "info: ^-- myTextSpaceFromGlyphSpaceFactor is " << myTextSpaceFromGlyphSpaceFactor << std::endl;
+		std::cerr << "info: ^-- myFontSize is " << myFontSize << std::endl;
+		//std::cerr << "info: ^-- CTM scale is " << fabs(myGraphicsState.CTMScaleV()) << std::endl;
+		std::cerr << "info: ^-- myTextScaleV is " << myTextScaleV << std::endl;
+	}
+	//std::cout << "setting text height " << currentTextHeight << std::endl;
+	//if(currentTextHeight > myTextHeight)
+		myTextHeight = currentTextHeight;
+}
+
+std::string PdfBookReader::mangleTextPart(const std::string& part) {
+	if(ZLStringUtil::stringStartsWith(part, "....")) { // silly detection of table of contents "1.1 Stuff...............4711".
+		myBForceNewLine = true;
+		// shorten the run of points to maybe fit on a small screen in portrait mode.
+		const char* result_c = part.c_str();
+		while(result_c && *result_c == '.')
+			++result_c;
+		std::string result = result_c;
+		result = "...." + result;
+		return result;
+	}
+	return part;
+}
+void PdfBookReader::processInlineMovement1(int amount) {
+	myPositionH += (amount * myFontSize / 1000 + myCharSpacing/* FIXME + [T_W]*/) * myHorizontalScaling / 100;
+}
+void PdfBookReader::processInlineMovement(PdfStringObject* text) {
+	if(myFont == NULL) /* ?!?! */
+		return;
+	std::string value = text->value();
+	int size = value.length();
+	for(int i = 0; i < size; ++i) {
+		int code = (unsigned char) value.at(i);
+		if(code == 0) /* FIXME */
+			continue;
+		int W0 = myFont->width(code);
+		/* FIXME check whether the code is a space code and if so, use word spacing. */
+		myPositionH += (W0 * myFontSize / 1000 + myCharSpacing/* FIXME + [T_W]*/) * myHorizontalScaling / 100;
+	}
+}
+void PdfBookReader::processInstruction(const PdfInstruction& instruction) {
+	int i;
+	std::string result;
+	bool actual_newline = true;
+	PdfOperator operator_ = instruction.operator_();
+	/*instruction.dump();*/
+	if(operator_ == opShowString /*Tj non-array*/ ||
+	   operator_ == opNextLineShowString /*'*/ || 
+	   operator_ == opNextLineSpacedShowString /*"*/ ||
+	   operator_ == opShowStringWithVariableSpacing /*TJ*/) {
+		if(myFont && !myFont->containsUnicode()) {
+			// TODO draw symbol font.
+			return;
+		}
+
+		shared_ptr<PdfObject> item = instruction.extractFirstArgument();
+		if(item->type() == PdfObject::ARRAY) {
+			PdfArrayObject* xarray = (PdfArrayObject*)&*item;
+			int argument_count = xarray->size();
+			for(i = 0; i < argument_count; ++i) {
+				shared_ptr<PdfObject> xitem = (*xarray)[i];
+				if(xitem->type() == PdfObject::STRING) { // esp. ! number
+					PdfStringObject* stringObject = (PdfStringObject*)&*xitem;
+					result = result + mangleTextPart(fToUnicodeTable->convertStringToUnicode(stringObject->value()));
+					//result = result + ' ';
+					processInlineMovement(stringObject);
+				} else if(xitem->type() == PdfObject::INTEGER_NUMBER) {
+					PdfIntegerObject* integerObject = (PdfIntegerObject*)&*xitem;
+					if(integerObject->value() < -57) // FIXME these are textspace/1000.
+						result = result + " ";
+					processInlineMovement1(-integerObject->value());
+				} else if(xitem->type() == PdfObject::REAL_NUMBER) {
+					PdfRealObject* realObject = (PdfRealObject*)&*xitem;
+					if(realObject->value() < -57)
+						result = result + " ";
+					processInlineMovement1(-realObject->value());
+					/*debugging: else
+						result = result + "@";*/
+				}
+			};
+			//result = Copy(result, 1, Length(result) - 1);
+		} else if(item->type() == PdfObject::STRING) {
+			PdfStringObject* stringObject = (PdfStringObject*)&*item;
+			std::string v = fToUnicodeTable->convertStringToUnicode(stringObject->value());
+			if(v == "Part II: The Dilemma of Sp") {
+				std::cerr << "we will have a problem" << std::endl; /* FIXME remove */
+			}
+			result = result + v;
+			processInlineMovement(stringObject);
+		}
+
+		if(operator_ == opNextLineShowString ||
+		   operator_ == opNextLineSpacedShowString) {
+			result = result + ' '; // (char) 10;
+		}
+	} else if(operator_ == opPaintExternalObject) {
+		shared_ptr<PdfObject> item = instruction.extractFirstArgument();
+		if(item->type() == PdfObject::NAME) {
+			processXObject(item);
+		}
+	} else if(operator_ == opSetFontAndSize) {
+		const shared_ptr<PdfArrayObject>& arguments = instruction.arguments();
+		int argument_count = arguments->size();
+		if(argument_count == 0) /* !?!?! */
+			return;
+		shared_ptr<PdfObject> name = (*arguments)[0];
+		unsigned fontSize = 0;
+		if(argument_count > 1) {
+			shared_ptr<PdfObject> size = (*arguments)[1];
+			if(!size.isNull()) {
+				if(size->type() == PdfObject::INTEGER_NUMBER) {
+					fontSize = ((const PdfIntegerObject&)(*size)).value();
+				} else if(size->type() == PdfObject::REAL_NUMBER) {
+					fontSize = ((const PdfRealObject&)(*size)).value(); // TODO what about fractions?
+				} else { /* ignore junk */
+				}
+			}
+		}
+		setFont(name, fontSize);
+	} else if(operator_ == opMoveCaretToStartOfNextLineAndOffsetAndSetLeading) {
+		double horizontal_offset, vertical_offset;
+		if(instruction.extractTwoFloatArguments(horizontal_offset, vertical_offset)) {
+			//addWordSpace();
+			myLeading = -vertical_offset;
+			setPositionRelativeToBeginning(horizontal_offset, vertical_offset);
+		}
+		/*if(actual_newline) {
+			goToNextLine();
+		}
+		myPositionV -= myLeading;*/
+	} else if(operator_ == opMoveCaretToStartOfNextLine) {
+		//result = result + "\n";
+		/*goToNextLine();
+		myPositionV -= myLeading;*/
+		setPositionRelativeToBeginning(0, - myLeading);
+	} else if(operator_ == opMoveCaret) {
+		double horizontal_offset, vertical_offset;
+		if(instruction.extractTwoFloatArguments(horizontal_offset, vertical_offset)) {
+			// FIXME addWordSpace();
+			setPositionRelativeToBeginning(horizontal_offset, vertical_offset);
+		}
+		/*if(actual_newline) {
+			goToNextLine();
+		}
+		myPositionV += vertical_offset;*/
+	} else if(operator_ == opSetTextMatrix) {
+		myBPendingTextMatrixReset = false; // not cumulative.
+		std::vector<double> arguments = instruction.extractFloatArguments();
+		// coordinates (x y w) will translate to (a_0⋅x+a_2⋅y+4⋅w, a_1⋅x+a_3⋅y+a_5⋅w, w), where a are the arguments, starting with index 0.
+		if(arguments.size() >= 6) {
+			//setTextScale(arguments[0], arguments[3]);
+			// TODO complete this?
+			double verticalPosition = /*arguments[1] * horizontalPosition + */ arguments[5];
+			// not yet. setPosition(arguments[4], verticalPosition);
+			/* the reason for this indirection is that some inane PDFs start a new BT for each and every line of text. 
+			   It is good then to not take the ensuing Tm too seriously. */
+			myPendingTextMatrixH = myPendingTextMatrixBeginningH = arguments[4];
+			myPendingTextMatrixV = verticalPosition;
+			myBPendingTextMatrixReset = true;
+		} else {
+			//setTextScale(1.0, 1.0);
+			// just in case.
+			addWordSpace();
+		}
+	} else if(operator_ == opTransformationMatrixAppend) {
+		// FIXME actually concatenate.
+		std::vector<double> arguments = instruction.extractFloatArguments();
+		if(arguments.size() >= 6) {
+			myGraphicsState.setCTMScale(myGraphicsState.CTMScaleH() * arguments[0], myGraphicsState.CTMScaleV() * arguments[3]);
+		}
+	} else if(operator_ == opSetTextRise) {
+		double textRise = 0.0;
+		if(instruction.extractFloatArgument(textRise)) {
+			// arg1 > 0: superscripted.
+			setTextRise(textRise);
+		}
+	} else if(operator_ == opSetTextLeading) {
+		instruction.extractFloatArgument(myLeading);
+	} else if(operator_ == opPushGraphicsState) {
+		myGraphicsStack.push(myGraphicsState);
+	} else if(operator_ == opPopGraphicsState) {
+		if(myGraphicsStack.empty())
+			std::cerr << "warning: tried to pop element off empty graphics stack." << std::endl;
+		else {
+			myGraphicsState = myGraphicsStack.top();
+			myGraphicsStack.pop();
+		}
+	} else if(operator_ == opSetCharacterSpacing) {
+		if(!integerFromPdfObject(instruction.extractFirstArgument(), myCharSpacing))
+			myCharSpacing = 0;
+	} else if(operator_ == opSetWordSpacing) {
+		if(!integerFromPdfObject(instruction.extractFirstArgument(), myWordSpacing))
+			myWordSpacing = 0;
+	} else if(operator_ == opSetHorizontalScaling) {
+		if(!integerFromPdfObject(instruction.extractFirstArgument(), myHorizontalScaling))
+			myHorizontalScaling = 100;
+	} else if(operator_ == opEndText) {
+		/* some PDFs create a text block for each and every line. So don't do: goToNextParagraph(); */
+	}
+	if(result.length() > 0) {
+		if(myBPendingTextMatrixReset)
+			setPositionRelativeToHere(0, 0); // make sure text matrix is taken into account and un-pended.
+		/*std::cout << result;*/
+		if(result == "\342\200\242") { // U+2022 bullet and nothing else.
+			// this is probably an enumeration point so make sure we are on a new line.
+			double previousTextHeight = myTextHeight;
+			goToNextParagraph();
+			myTextHeight = previousTextHeight;
+
+		}
+		addData(result);
+		/*std::cout << result;
+		std::cout.flush();*/
+	}
+#if 0
+	if(operator_ == opShowStringWithVariableSpacing) {
+		myPositionV -= myLeading;
+		goToNextLine();
+		//setPosition(myPositionH, myPositionV - myLeading);
+	}
+#endif
+}
+
+void PdfBookReader::cancelSubscriptSuperscript() {
+	increaseEffectiveTextRise(-myEffectiveTextRise);
+	myParagraphIndentation = 0.0;
+	myTextHeight = 0.0;
+}
+
+void PdfBookReader::goToNextParagraph() {
+	increaseEffectiveTextRise(-myEffectiveTextRise);
+	goToNextLine();
+	cancelSubscriptSuperscript();
+	updateTextHeight();
+	//addData("<newpara>");
+}
+
+void PdfBookReader::setPositionRelativeToBeginning(double dX, double dY) {
+	if(myBPendingTextMatrixReset) {
+		myBPendingTextMatrixReset = false;
+		setPosition(myPendingTextMatrixBeginningH + dX, myPendingTextMatrixV + dY);
+	} else {
+		setPosition(myPositionBeginningH + dX, myPositionV + dY);
+	}
+}
+void PdfBookReader::setPositionRelativeToHere(double dX, double dY) {
+	if(myBPendingTextMatrixReset) {
+		myBPendingTextMatrixReset = false;
+		setPosition(myPendingTextMatrixH + dX, myPendingTextMatrixV + dY);
+	} else {
+		setPosition(myPositionH + dX, myPositionV + dY);
+	}
+}
+void PdfBookReader::setPosition(double horizontalPosition, double verticalPosition) {
+	double offset = verticalPosition - myPositionV;
+	double hoffset = horizontalPosition - myPositionH;
+	assert(myAscent >= 0);
+	assert(myDescent <= 0);
+	/*if(myParagraphIndentation != horizontalPosition) {
+	}*/
+	//if(offset > myAscent || offset < myDescent) { // too far, probably not a superscript/subscript.
+	/*char buffer[2000];
+	snprintf(buffer, 2000, "(%.2lf %.2lf %.2lf %.2lf)", offset, myTextHeight, myPositionV, fabs(myGraphicsState.CTMScaleV()));
+	addData(buffer);*/
+	myPositionH = horizontalPosition;
+	myPositionBeginningH = horizontalPosition;
+	double scaleV = 1.7; // FIXME don't hardcode?
+	if(offset > myTextHeight * scaleV || offset < -myTextHeight * scaleV || myIsFirstOnLine) { // too far, probably not a superscript. 
+		if(!myIsFirstOnLine)
+			addWordSpace(); // ata(" "); // make sure we finished the word, whatever it was. addData("#");
+		increaseEffectiveTextRise(-myEffectiveTextRise); /* cancel text rise */
+		myPositionV = verticalPosition;
+		// the myIsFirstOnLine check is in order to allow fraction lines.
+		if((1&&!myIsFirstOnLine) || /*offset > myTextHeight || offset < -myTextHeight || */myBForceNewLine ) { // TODO make this a setting.
+			if(myBForceNewLine || (offset <= myTextHeight * 30 && offset >= -myTextHeight * 30) || myTextHeight < EPSILON) { // avoids adding a newline in a multi-column layout which is not what you usually want.
+				myBForceNewLine = false;
+				goToNextParagraph();
+			}
+		}
+		return;
+	} else if(offset >= -myTextHeight && offset <= myTextHeight) { // probably a superscript or subscript.
+		myPositionV = verticalPosition;
+		if(increaseEffectiveTextRise(offset))
+			return;
+	} else {
+		myPositionV = verticalPosition;
+		if(offset > EPSILON || offset < -EPSILON) {
+			addWordSpace();
+			return;
+		}
+	}
+
+	if(offset < EPSILON && (hoffset > EPSILON && hoffset > 10 + myCharSpacing * 2 /* TODO allow more leeway */)) // FIXME
+		addWordSpace();
+}
+
+void PdfBookReader::setTextRise(double value) {
+	increaseEffectiveTextRise(myTextRise - value);
+	myTextRise = value;
+}
+
+bool PdfBookReader::increaseEffectiveTextRise(double offset) {
+	bool previousBoldness = myBBoldness;
+	/* returns whether we have newly entered either subscript or superscript. */
+	double value = myEffectiveTextRise + offset;
+	double minimalAD = myTextHeight / 10; // minimal ascent/descent.
+	if(minimalAD < EPSILON)
+		minimalAD = EPSILON;
+	if(fabs(offset) < EPSILON) // rounding error or dude who set the text was drunk.
+		return false; // myEffectiveTextRise <= -EPSILON || myEffectiveTextRise >= EPSILON;
+	setBoldness(false);
+	if(fabs(myEffectiveTextRise) >= EPSILON) { // get rid of previous subscript/superscript.
+		//popKind();
+		addControl(myEffectiveTextRise > 0 ? SUP : SUB, false);
+	}
+	if(value >= minimalAD) {
+		addControl(SUP, true);
+	} else if(value <= -minimalAD) {
+		addControl(SUB, true);
+	}
+	setBoldness(previousBoldness);
+	/*char tmp[2000];
+	snprintf(tmp, 2000, "(%.4f->%.4f)", myEffectiveTextRise, value);
+	addData(tmp);*/
+	bool result = (value <= -minimalAD && myEffectiveTextRise > -minimalAD) || (value >= minimalAD && myEffectiveTextRise <= minimalAD);
+	myEffectiveTextRise = value;
+	return result;
+}
+
+void PdfBookReader::goToNextLine() {
+	//setTextRise(0.0); 
+	//increaseEffectiveTextRise(-myEffectiveTextRise);
+	//setEffectiveTextRise(0.0);
+	//result = result + "\n";
+	addControl(myEffectiveTextRise > 0 ? SUP : SUB, false);
+	bool previousBBoldness = myBBoldness;
+	if(previousBBoldness)
+		setBoldness(false);
+	endParagraph();
+	beginParagraph();
+	myIsFirstOnLine = true;
+	if(fabs(myEffectiveTextRise) > EPSILON)
+		addControl(myEffectiveTextRise > 0 ? SUP : SUB, true);
+	if(previousBBoldness)
+		setBoldness(true);
+}
+
+shared_ptr<PdfFont> PdfBookReader::loadFont(shared_ptr<PdfObject> metadata, ZLInputStream &stream) {
+	assert(!metadata.isNull() && metadata->type() == PdfObject::DICTIONARY);
+	const PdfDictionaryObject& fontDictionary = (const PdfDictionaryObject&)*metadata;
+	shared_ptr<PdfObject> widths = fontDictionary["Widths"];
+	shared_ptr<PdfObject> toUnicode = fontDictionary["ToUnicode"];
+	shared_ptr<PdfObject> encoding = fontDictionary["Encoding"];
+	shared_ptr<PdfObject> fontDescriptor = fontDictionary["FontDescriptor"];
+	if(!fontDescriptor.isNull()) {
+		shared_ptr<PdfObject> fontFileRefO = ((const PdfDictionaryObject&)*fontDescriptor)["FontFile"];
+		if(!fontFileRefO.isNull() && fontFileRefO->type() == PdfObject::REFERENCE) {
+			const PdfObjectReference& fontFileRef = (const PdfObjectReference&) *fontFileRefO;
+			//std::cout << "font file ref " << fontFileRef.number() << std::endl;
+		}
+	}
+	shared_ptr<PdfObject> fontFile = fontDescriptor.isNull() ? 0 : ((const PdfDictionaryObject&)*fontDescriptor)["FontFile"];
+	shared_ptr<PdfObject> ws;
+	shared_ptr<PdfObject> resourcesObject = fontDictionary["Resources"]; // for symbol fonts.
+	PdfXObjects xObjects = prepareXObjects(resourcesObject, stream); // for symbol fonts.
+	shared_ptr<PdfObject> descendantFontsO = fontDictionary["DescendantFonts"];
+	shared_ptr<PdfObject> descendantFontO;
+	if(!descendantFontsO.isNull() && descendantFontsO->type() == PdfObject::ARRAY) {
+		PdfArrayObject& descendantFonts = ((PdfArrayObject&)*descendantFontsO);
+		if(descendantFonts.size() >= 1) { /* note: size should always be 1 according to standard. */
+			descendantFontO = descendantFonts[0];
+			if(!descendantFontO.isNull() && descendantFontO->type() == PdfObject::DICTIONARY && fontDescriptor.isNull()) { // fall back to descendant.
+				const PdfDictionaryObject& descendantFont = (const PdfDictionaryObject&)*descendantFontO;
+				/* TODO: note that this can contain "W" for the char's widths. */
+				fontDescriptor = descendantFont["FontDescriptor"];
+				ws = descendantFont["W"];
+			}
+		}
+	}
+	int widthsMissingWidth = 0;
+	int widthsFirstChar = 0;
+	if(!fontDescriptor.isNull())
+		integerFromPdfObject(((const PdfDictionaryObject&)*fontDescriptor)["MissingWidth"], widthsMissingWidth);
+	if(!integerFromPdfObject(fontDictionary["FirstChar"], widthsFirstChar))
+		widthsFirstChar = 0;
+	// TODO CharProcs
+	return new PdfFont(metadata, fontDescriptor, encoding, fontFile, toUnicode, xObjects, widths, ws, widthsMissingWidth, widthsFirstChar);
+}
+
+void PdfBookReader::loadFonts(shared_ptr<PdfObject> resourcesObject, ZLInputStream &stream) {
+	shared_ptr<PdfObject> resourceFontsObject = 0;
+	if(!resourcesObject.isNull() && resourcesObject->type() == PdfObject::DICTIONARY) {
+		const PdfDictionaryObject &resourcesDictionary = (const PdfDictionaryObject &) *resourcesObject;
+		resourceFontsObject = resourcesDictionary["Font"];
+		//if(!resourceFontsObject.isNull())
+		//	resourceFontsObject = resolveReference(resourceFontsObject, stream);
+		if(!resourceFontsObject.isNull() && resourceFontsObject->type() == PdfObject::DICTIONARY) {
+			/* /F1 ... */
+			/*for each {
+				processFont(resourceFontObject);
+			}*/
+		} else {
+			resourceFontsObject = 0;
+		}
+	}
+	if(resourceFontsObject.isNull())
+		return;
+	const PdfObject& fonts = *resourceFontsObject;
+	if(fonts.type() != PdfObject::DICTIONARY) /* WTF */
+		return;
+		
+	//std::map<shared_ptr<PdfObject>, shared_ptr<PdfToUnicodeMap> > fToUnicodeTables;
+
+	std::list<shared_ptr<PdfObject> > keys = ((PdfDictionaryObject&)fonts).keys();
+	for(std::list<shared_ptr<PdfObject> >::const_iterator iter_keys = keys.begin(); iter_keys != keys.end(); ++iter_keys) {
+		shared_ptr<PdfObject> name = *iter_keys;
+		//std::cout << "font " << ((PdfNameObject&)*name).id() << std::endl;
+		shared_ptr<PdfObject> referenceX = ((PdfDictionaryObject&)fonts)[name];
+		if(referenceX->type() != PdfObject::REFERENCE) { /* probably. */
+			// Actually, if we did that right, the same font data could be referred to by multiple names.
+			// Since here the font addresses are already resolved, not much can be done.
+			// We therefore default to the pointer address.
+			std::map<shared_ptr<PdfObject>, shared_ptr<PdfFont> >::const_iterator iter_table = fFontsByNativeAddress.find(referenceX);
+			if(iter_table == fFontsByNativeAddress.end()) {
+				fFontsByNativeAddress[referenceX] = loadFont(referenceX, stream);
+			}
+			fFontsByName[name] = fFontsByNativeAddress[referenceX];
+		} else {
+			int reference_number;
+			int reference_generation;
+			PdfObjectReference& reference = (PdfObjectReference&)*referenceX;
+			reference_number = reference.number();
+			reference_generation = reference.generation();
+			PdfToUnicodeMapAddress address(reference_number, reference_generation);
+			std::map<PdfToUnicodeMapAddress, shared_ptr<PdfFont> >::const_iterator iter_table = fFontsByAddress.find(address);
+			if(iter_table == fFontsByAddress.end()) {
+				//std::cerr << "************* loading font " << reference.number() << std::endl;
+				shared_ptr<PdfObject> metadata = resolveReferences(referenceX, stream);
+				fFontsByAddress[address] = loadFont(metadata, stream);
+				/*PdfToUnicodeMap& map = *fToUnicodeTablesByAddress[address];
+				loadFont(name, metadata, map, stream);*/
+			}
+			fFontsByName[name] = fFontsByAddress[address];
+		}
+	}
+	
+	/* /F1 ... */
+	/*for each {
+		processFont(resourceFontObject);
+	}*/
+}
+
 void PdfBookReader::processContents(shared_ptr<PdfObject> contentsObject, ZLInputStream &stream) {
-	contentsObject = resolveReference(contentsObject, stream);
+	std::list<shared_ptr<PdfObject> > contents;
+	if(contentsObject->type() == PdfObject::ARRAY) {
+		// this means that one text block can span _multiple_ of the array elements.
+		const PdfArrayObject &array = (const PdfArrayObject&)*contentsObject;
+		const size_t len = array.size();
+		for (size_t i = 0; i < len; ++i) {
+			contents.push_back(array[i]);
+		}
+	} else {
+		contents.push_back(contentsObject);
+	}
+	if(contents.size() < 1)
+		return;
+	shared_ptr<PdfContent> content = PdfContentParser::parse(contents);
+	const std::vector<shared_ptr<PdfInstruction> >& instructions = content->instructions();
+	processInstructions(instructions);
+}
+
+static bool isLineImage(const shared_ptr<PdfObject>& image) {
+	if(image->type() != PdfObject::STREAM)
+		return false;
+	PdfStreamObject& streamObject = (PdfStreamObject&)*image;
+	shared_ptr<PdfObject> dictionary1 = streamObject.dictionary();
+	PdfDictionaryObject& dictionary = (PdfDictionaryObject&)*dictionary1;
+	shared_ptr<PdfObject> type_ = dictionary["Type"];
+	if(type_.isNull() || type_->type() != PdfObject::NAME)
+		return false;
+	shared_ptr<PdfObject> subtype = dictionary["Subtype"];
+	if(subtype.isNull() || subtype->type() != PdfObject::NAME)
+		return false;
+	if(((PdfNameObject&)*type_).id() != "XObject" ||
+	   ((PdfNameObject&)*subtype).id() != "Image")
+	   	return false;
+	shared_ptr<PdfObject> widthO = dictionary["Width"];
+	shared_ptr<PdfObject> heightO = dictionary["Height"];
+	if(widthO.isNull() || heightO.isNull() || widthO->type() != PdfObject::INTEGER_NUMBER || heightO->type() != PdfObject::INTEGER_NUMBER)
+		return false;
+	int width = ((PdfIntegerObject&)*widthO).value();
+	int height = ((PdfIntegerObject&)*heightO).value();
+	if(width == 1 && height == 1)
+		return true;
+	shared_ptr<ZLInputStream> inputStreamO = streamObject.stream();
+	ZLInputStream& inputStream = *inputStreamO;
+	if(inputStream.open()) {
+		// TODO check for /Filter/CCITTFaxDecode if that even works.
+		char body[13];
+		unsigned char* x = (unsigned char*) body;
+		// TODO actually implement a CCITT T.4 decoder.
+		if(inputStream.read(body, 13) == 13) {
+			return *x++ == 0x35 &&
+			       *x++ == 0x8d && 
+			       *x++ == 0x63 && 
+			       *x++ == 0x58 && 
+			       *x++ == 0x00 && 
+			       *x++ == 0x40 && 
+			       *x++ == 0x04 && 
+			       *x++ == 0x00 && 
+			       *x++ == 0x40 &&
+			       *x++ == 0x04 && 
+			       *x++ == 0x00 && 
+			       *x++ == 0x40 && 
+			       *x++ == 0x04;
+		}
+	}
+	return false;
+}
+
+void PdfBookReader::processInstructions(const std::vector<shared_ptr<PdfInstruction> >& instructions) {
+	// this also keeps a state stack for most of the rendering parameters as per PDF standard.
+	double prevPositionV = myPositionV;
+	
+	for(std::vector<shared_ptr<PdfInstruction> >::const_iterator iter_instructions = instructions.begin(); iter_instructions != instructions.end(); ++iter_instructions) {
+		shared_ptr<PdfInstruction> instruction = *iter_instructions;
+		if(instruction->operator_() == opBeginText) {
+			const shared_ptr<PdfArrayObject>& arguments = instruction->arguments();
+			myBPendingTextMatrixReset = true;
+			myPendingTextMatrixH = myPendingTextMatrixBeginningH = myPendingTextMatrixV = 0.0;
+			int argument_count = arguments->size();
+			if(argument_count > 0) {
+				shared_ptr<PdfObject> item = (*arguments)[0];
+				if(item->type() == PdfObject::CONTENT) {
+					const std::vector<shared_ptr<PdfInstruction> >& x_instructions = ((PdfContent&)(*item)).instructions();
+					processInstructions(x_instructions);
+				}
+			}
+		} else if(instruction->operator_() == opBeginInlineImage) {
+		} else
+			processInstruction(*instruction);
+	}
+
+	//setTextRise(prevTextRise);
+	//FIXME re-add setPosition(0/*dummy*/, prevPositionV);
+}
+
+PdfXObjects PdfBookReader::prepareXObjects(shared_ptr<PdfObject> resourcesObject, ZLInputStream &stream) {
+	PdfXObjects myXObjects2; /* name -> image-data */
+	if(resourcesObject.isNull() || resourcesObject->type() != PdfObject::DICTIONARY) {
+		myXObjects2.clear();
+		return myXObjects2;
+	}
+	const PdfDictionaryObject& resourceDictionary = (const PdfDictionaryObject&)*resourcesObject;
+	if (resourceDictionary["XObject"].isNull()) {
+		myXObjects2.clear();
+	} else if(resourceDictionary["XObject"]->type() == PdfObject::DICTIONARY) {
+		shared_ptr<PdfObject> fXObjects = resourceDictionary["XObject"];
+		/* some documents use a 1x1 XObject to be able to draw a line, so remember it here: */
+		PdfDictionaryObject& xObjects = (PdfDictionaryObject&)*fXObjects;
+		std::list<shared_ptr<PdfObject> > xObjectKeys = xObjects.keys();
+		for(std::list<shared_ptr<PdfObject> >::const_iterator iter = xObjectKeys.begin(); iter != xObjectKeys.end(); ++iter) {
+			const shared_ptr<PdfObject>& key = *iter;
+			shared_ptr<PdfObject> image = xObjects[key];
+			myXObjects2[key] = image;
+			if(isLineImage(image)) {
+				myLines.insert(key);
+			}
+		}
+	} else {
+		myXObjects2.clear();
+	}
+	return myXObjects2;
 }
 
 void PdfBookReader::processPage(shared_ptr<PdfObject> pageObject, ZLInputStream &stream) {
-	pageObject = resolveReference(pageObject, stream);
+	myLeading = 0.0;
+	myTextRise = 0.0;
+	myPositionV = 0.0;
+	myEffectiveTextRise = 0.0;
+	myIsFirstOnLine = true;
+	                        
+	//pageObject = resolveReference(pageObject, stream);
 	if (pageObject.isNull() || pageObject->type() != PdfObject::DICTIONARY) {
 		return;
 	}
-	const PdfDictionaryObject &pageDictionary = (const PdfDictionaryObject&)*pageObject;
+	const PdfDictionaryObject &pageDictionary = *(const PdfDictionaryObject*)&*pageObject;
+	if (pageDictionary["Type"].isNull() || pageDictionary["Type"] != PdfNameObject::nameObject("Page")) {
+		return;
+	}
+
+	// TODO "UserUnit" for non-1/72 of an inch Tf unit.
+	//pageDictionary.dump();
+	resourcesObject = pageDictionary["Resources"];
+	//resourcesObject = resolveReferences(resourcesObject, stream);
+	loadFonts(resourcesObject, stream);
+	myXObjects2 = prepareXObjects(resourcesObject, stream);
 	shared_ptr<PdfObject> contents = pageDictionary["Contents"];
 	if (contents.isNull()) {
 		return;
 	}
+	beginParagraph();
 	switch (contents->type()) {
-		default:
-			break;
-		case PdfObject::REFERENCE:
+		case PdfObject::STREAM:
+		//case PdfObject::REFERENCE: // no.
+		case PdfObject::ARRAY:
 			processContents(contents, stream);
 			break;
-		case PdfObject::ARRAY:
+		default:
+			break;
+	}
+	endParagraph();
+	cancelSubscriptSuperscript();
+}
+
+/* precondition: prepareXObjects() was called. */
+shared_ptr<PdfObject> PdfBookReader::findXObject(const shared_ptr<PdfObject>& name) const {
+	PdfXObjects::const_iterator iter = myXObjects2.find(name);
+	if(iter != myXObjects2.end())
+		return iter->second;
+	else
+		return 0;
+}
+
+void PdfBookReader::addData(const std::string& text) {
+	myIsFirstOnLine = false;
+	BookReader::addData(text);
+	if(text.length() > 0) {
+		int count = text.length();
+		int i = count - 1;
+		unsigned char c;
+		// find the first byte of a UTF-8 sequence.
+		while(i >= 0 && ((c = (unsigned char) text[i]) >= 0x80 && c < 0xC0)) {
+			--i;
+		}
+		if(i >= 0) {
+			int j;
+			for(j = 0; j < 4 && i < count; ++j, ++i)
+				myPreviousCharacter[j] = text[i];
+			myPreviousCharacter[j] = 0;
+		} else
+			myPreviousCharacter[0] = 0;
+	}
+}
+
+void PdfBookReader::setBoldness(bool value) {
+	if(myBBoldness == value)
+		return;
+		
+	if(myBBoldness)
+		addControl(BOLD, false);
+	if(value)
+		addControl(BOLD, true);
+	myBBoldness = value;
+}
+
+void PdfBookReader::addWordSpace() {
+	if(myPreviousCharacter[0] == '^')
+		return;
+	if(myPreviousCharacter[0] == 0xCB && myPreviousCharacter[1] == 0x86 && myPreviousCharacter[2] == 0) // circumflex-2
+		return;
+	if(myPreviousCharacter[0] == 0xCB && myPreviousCharacter[1] == 0x99 && myPreviousCharacter[2] == 0) // dot above
+		return;
+	if(myPreviousCharacter[0] == 0xE2 && myPreviousCharacter[1] == 0x86 && myPreviousCharacter[2] == 0x92 && myPreviousCharacter[3] == 0) // vector arrow
+		return;
+	if(myPreviousCharacter[0] == 0xC2 && myPreviousCharacter[1] == 0xA8 && myPreviousCharacter[2] == 0) // two dots above
+		return;
+	/* wrong delta if(myPreviousCharacter[0] == 0xCE && myPreviousCharacter[1] == 0x94 && myPreviousCharacter[2] == 0) // delta.
+		return;*/
+	if(myPreviousCharacter[0] == 0xE2 && myPreviousCharacter[1] == 0x88 && myPreviousCharacter[2] == 0x86 && myPreviousCharacter[3] == 0) // delta
+		return;
+	/*if(myPreviousCharacter[0] == '(' && myPreviousCharacter[1] == 0)
+		return;*/
+	/*if(myPreviousCharacter[0] == ')' && myPreviousCharacter[1] == 0)
+		return;*/
+	if(myPreviousCharacter[0] == ',')
+		return;
+	if(myPreviousCharacter[0] == '+' || myPreviousCharacter[0] == '-') // number sign, word break dash.
+		return;
+	if(myPreviousCharacter[0] == 0xE2 && myPreviousCharacter[1] == 0x88) // partial derivation
+		return;
+	if(myPreviousCharacter[0] == 0xCB && myPreviousCharacter[1] == 0x98) // ˘
+		return;
+	addData(" ");
+}
+
+// this will resolve references IN PLACE (as a memory usage optimization). Be careful.
+shared_ptr<PdfObject> PdfBookReader::resolveReferences(shared_ptr<PdfObject> ref, ZLInputStream &stream) {
+	while(!ref.isNull() && ref->type() == PdfObject::REFERENCE)
+		ref = myParser->resolveReference(ref);
+	if(ref.isNull())
+		return(ref);
+	assert(ref->type() != PdfObject::REFERENCE);
+	switch(ref->type()) {
+	case PdfObject::ARRAY:
 		{
-			const PdfArrayObject &array = (const PdfArrayObject&)*contents;
-			const size_t len = array.size();
-			for (size_t i = 0; i < len; ++i) {
-				processContents(array[i], stream);
+			if(myResolvedTraces.find(ref) != myResolvedTraces.end())
+				return(ref);
+			myResolvedTraces.insert(ref);
+			PdfArrayObject& arr = (PdfArrayObject&) *ref;
+			for(int i = 0, size = arr.size(); i < size; ++i) {
+				arr[i] = resolveReferences(arr[i], stream);
+				assert(arr[i].isNull() || arr[i]->type() != PdfObject::REFERENCE);
 			}
-			break;
 		}
+		break;
+	case PdfObject::DICTIONARY:
+		{
+			if(myResolvedTraces.find(ref) != myResolvedTraces.end())
+				return(ref);
+			myResolvedTraces.insert(ref);
+			PdfDictionaryObject& dict = (PdfDictionaryObject&) *ref;
+			std::list<shared_ptr<PdfObject> > keys = dict.keys();
+			for(std::list<shared_ptr<PdfObject> >::const_iterator iter = keys.begin(), end_iter = keys.end(); iter != end_iter; ++iter) {
+				shared_ptr<PdfObject> key = *iter;
+				//std::cout << "key " << ((PdfNameObject&) *key).id() << std::endl;
+				shared_ptr<PdfObject> value = dict[key];
+				value = resolveReferences(value, stream);
+				assert(value.isNull() || value->type() != PdfObject::REFERENCE);
+				dict[key] = value;
+				assert(dict[key].isNull() || dict[key]->type() != PdfObject::REFERENCE);
+			}
+		}
+		break;
+	case PdfObject::STREAM:
+		{
+			if(myResolvedTraces.find(ref) != myResolvedTraces.end())
+				return(ref);
+			myResolvedTraces.insert(ref);
+			PdfStreamObject& stream2 = (PdfStreamObject&) *ref;
+			shared_ptr<PdfObject> dict = stream2.dictionary();
+			dict = resolveReferences(dict, stream);
+			stream2.setDictionary(dict);
+		}
+		break;
+	//NIL,
+	//REFERENCE done,
+	//CONTENT,
+	default:
+		return(ref);
 	}
+	return(ref);
 }
+
+void PdfBookReader::setTextScale(double h, double v) {
+	myTextScaleH = h;
+	myTextScaleV = v;
+}
+
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfBookReader.h fbreader-0.12.10/fbreader/src/formats/pdf/PdfBookReader.h
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfBookReader.h	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfBookReader.h	2011-12-29 23:38:48.805278131 +0100
@@ -21,32 +21,96 @@
 #define __PdfBOOKREADER_H__
 
 #include <map>
-
+#include <set>
+#include <stack>
 #include "../../bookmodel/BookReader.h"
+#include "PdfContent.h"
+#include "PdfToUnicodeMap.h"
+#include "PdfToUnicodeParser.h"
+#include "PdfFont.h"
+#include "PdfGraphicsState.h"
+#include "Pdf.h"
 
 class PdfObject;
 class PdfObjectReference;
 
-class PdfBookReader {
-
+class PdfBookReader : public BookReader {
 public:
 	PdfBookReader(BookModel &model);
 	~PdfBookReader();
 	bool readBook(shared_ptr<ZLInputStream> stream);
-
 private:
-	bool readReferenceTable(ZLInputStream &stream, int offset);
-	shared_ptr<PdfObject> resolveReference(shared_ptr<PdfObject> reference, ZLInputStream &stream);
-	shared_ptr<PdfObject> readObjectFromLocation(ZLInputStream &stream, const std::pair<int,int> &address);
 	void processPage(shared_ptr<PdfObject> pageObject, ZLInputStream &stream);
+	bool processPages(shared_ptr<PdfObject> pageRootNode, ZLInputStream &stream);
 	void processContents(shared_ptr<PdfObject> contentsObject, ZLInputStream &stream);
-
+	void processInstruction(const PdfInstruction& instruction_);
+	PdfXObjects prepareXObjects(shared_ptr<PdfObject> resourcesObject, ZLInputStream& stream);
+	shared_ptr<PdfObject> findXObject(const shared_ptr<PdfObject>& name) const;
+	void processXObject(shared_ptr<PdfObject> nameObject);
+	void processInstructions(const std::vector<shared_ptr<PdfInstruction> >& instructions);
+	void loadFonts(shared_ptr<PdfObject> resourcesObject, ZLInputStream &stream);
+	shared_ptr<PdfFont> loadFont(shared_ptr<PdfObject> metadata, ZLInputStream &stream);
+	void setTextRise(double value); // "Ts" command.
+	bool increaseEffectiveTextRise(double value); // real rise in FBReader, either by positioning or by "Ts" command.
+	void goToNextLine();
+	void setPosition(double horizontalPosition, double verticalPosition);
+	void setFont(const shared_ptr<PdfObject>& name, unsigned fontSize);
+	void addData(const std::string& text);
+	void addWordSpace();
+	void setBoldness(bool value);
+	std::string mangleTextPart(const std::string& part);
+	void goToNextParagraph();
+	void updateTextHeight();
+	void setTextScale(double h, double v);
+	void cancelSubscriptSuperscript();
+	void processInlineMovement(PdfStringObject* text);
+	void processInlineMovement1(int amount);
+	void setPositionRelativeToBeginning(double dX, double dY);
+	void setPositionRelativeToHere(double dX, double dY);
+protected:
+	shared_ptr<PdfObject> resolveReferences(shared_ptr<PdfObject> ref, ZLInputStream &stream);
+		
 private:
-	BookReader myModelReader;
-	std::string myBuffer;
-	std::map<std::pair<int,int>,int> myObjectLocationMap;
-	std::map<std::pair<int,int>,shared_ptr<PdfObject> > myObjectMap;
-	shared_ptr<PdfObject> myTrailer;
+	/*BookReader myModelReader;*/
+	double myBBoldness;
+	const PdfToUnicodeMap* fToUnicodeTable; /* current one, depending on font. */
+	const PdfFont* myFont;
+	std::map<shared_ptr<PdfObject>, shared_ptr<PdfFont> > fFontsByName;
+	std::map<PdfToUnicodeMapAddress, shared_ptr<PdfFont> > fFontsByAddress;
+	std::map<shared_ptr<PdfObject>, shared_ptr<PdfFont> > fFontsByNativeAddress;
+	shared_ptr<PdfObject> resourcesObject;
+	PdfXObjects myXObjects2; /* name -> image-data */
+	std::set<shared_ptr<PdfObject> > myLines; // names
+	double myLeading; // text state, not per text object.
+	double myPositionV; // text object stuff.
+	double myPositionH; // this isn't really updated correctly (yet?).
+	double myTextRise; // text state, not per text object.
+	double myEffectiveTextRise; // calculated.
+	double myDescent; // negative.
+	double myAscent;
+	double myTextSpaceFromGlyphSpaceFactor;
+	double myTextHeight; // this tries to find the maximum text height as a measure of what "big" is.
+	bool myIsFirstOnLine;
+	unsigned char myPreviousCharacter[5];
+	unsigned myImageIndex;
+	double myParagraphIndentation;
+	bool myBForceNewLine; // used in tables etc where it's important to have newlines.
+	double myPositionBeginningH;
+	unsigned myFontSize;
+	int myCharSpacing;
+	int myWordSpacing;
+	int myHorizontalScaling; /* 100 = none */
+	std::stack<PdfGraphicsState> myGraphicsStack;
+	PdfGraphicsState myGraphicsState;
+	shared_ptr<PdfParser> myParser;
+	shared_ptr<Pdf> myPDF;
+	double myTextScaleH;
+	double myTextScaleV;
+	bool myBPendingTextMatrixReset;
+	double myPendingTextMatrixBeginningH;
+	double myPendingTextMatrixH;
+	double myPendingTextMatrixV;
+	std::set<shared_ptr<PdfObject> > myResolvedTraces;
 };
 
 #endif /* __PdfBOOKREADER_H__ */
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfCffMap.cpp fbreader-0.12.10/fbreader/src/formats/pdf/PdfCffMap.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfCffMap.cpp	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfCffMap.cpp	2011-04-05 22:55:28.000000000 +0200
@@ -0,0 +1 @@
+#include "PdfCffMap.h"
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfCffMap.h fbreader-0.12.10/fbreader/src/formats/pdf/PdfCffMap.h
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfCffMap.h	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfCffMap.h	2011-04-05 22:55:28.000000000 +0200
@@ -0,0 +1,9 @@
+#ifndef __PDF_CFF_MAP_H
+#define __PDF_CFF_MAP_H
+
+/* CFF font (FontFile3) */
+
+class PdfCffMap {
+};
+
+#endif /* ndef __PDF_CFF_MAP_H */
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfCffParser.cpp fbreader-0.12.10/fbreader/src/formats/pdf/PdfCffParser.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfCffParser.cpp	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfCffParser.cpp	2011-04-05 22:55:28.000000000 +0200
@@ -0,0 +1,2 @@
+#include "PdfCffParser.h"
+
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfCffParser.h fbreader-0.12.10/fbreader/src/formats/pdf/PdfCffParser.h
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfCffParser.h	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfCffParser.h	2011-04-05 22:55:28.000000000 +0200
@@ -0,0 +1,14 @@
+#ifndef __PDF_CFF_PARSER_H
+#define __PDF_CFF_PARSER_H
+#include "PdfCffMap.h"
+#include "PdfScanner.h"
+
+/* CFF font (FontFile3) parser */
+
+class PdfCffParser : public PdfScanner {
+public:
+	PdfCffParser(shared_ptr<ZLInputStream> stream, PdfCffMap& map);
+	void parse();
+};
+
+#endif /* ndef __PDF_CFF_PARSER_H */
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfColorTable.cpp fbreader-0.12.10/fbreader/src/formats/pdf/PdfColorTable.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfColorTable.cpp	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfColorTable.cpp	2012-08-03 21:32:58.003770801 +0200
@@ -0,0 +1,34 @@
+/*PDF parser.
+Copyright (C) 2008 Danny Milosavljevic <danny_milo@yahoo.com>
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if !, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <assert.h>
+#include <string.h>
+#include "PdfColorTable.h"
+
+PdfColorTable::PdfColorTable() {
+}
+size_t PdfColorTable::size() const {
+	return(fEntries.size());
+}
+const PdfColorTableEntry PdfColorTable::operator[](int index) const {
+	return(fEntries[index]);
+}
+void PdfColorTable::set(int index, PdfColorTableEntry entry) {
+	if(index > 255) {
+		std::cerr << "warning: the PDF standard specifies a max size of 256 entries." << std::endl;
+	}
+	if(index < 0) {
+		std::cerr << "error: index into palette out of range." << std::endl;
+		return;
+	}
+	while(size() <= index)
+		fEntries.push_back(PdfColorTableEntry());
+	fEntries[index] = entry;
+}
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfColorTable.h fbreader-0.12.10/fbreader/src/formats/pdf/PdfColorTable.h
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfColorTable.h	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfColorTable.h	2012-08-03 21:20:19.927806245 +0200
@@ -0,0 +1,32 @@
+#ifndef __PDF_COLOR_TABLE_H
+#define __PDF_COLOR_TABLE_H
+#include <string>
+#include <map>
+#include <sstream>
+#include <iostream>
+#include <ZLStringUtil.h>
+#include <ZLInputStream.h>
+#include "PdfScanner.h"
+#include "PdfToUnicodeMap.h"
+#include "PdfDefaultCharMap.h"
+
+struct PdfColorTableEntry {
+	unsigned char components[4];
+	PdfColorTableEntry() {
+		components[0] = 0;
+		components[1] = 0;
+		components[2] = 0;
+		components[3] = 0;
+	}
+};
+class PdfColorTable {
+private:
+	std::vector<PdfColorTableEntry> fEntries;
+public:
+	PdfColorTable();
+	size_t size() const;
+	const PdfColorTableEntry operator[](int index) const;
+	void set(int index, PdfColorTableEntry entry);
+};
+
+#endif /* ndef __PDF_COLOR_TABLE_H */
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfColorTableParser.cpp fbreader-0.12.10/fbreader/src/formats/pdf/PdfColorTableParser.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfColorTableParser.cpp	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfColorTableParser.cpp	2012-08-03 21:59:05.847697477 +0200
@@ -0,0 +1,43 @@
+/*PDF parser.
+Copyright (C) 2008 Danny Milosavljevic <danny_milo@yahoo.com>
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if !, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <assert.h>
+#include <sstream>
+#include "PdfColorTableParser.h"
+#include "PdfColorTable.h"
+
+bool PdfColorTableParser::parse() {
+	consume();
+	if(input == EOF) {
+		return false;
+	}
+	return parse_();
+}
+bool PdfColorTableParser::parse_() {
+	int index = 0;
+	while(input != EOF) {
+		PdfColorTableEntry entry;
+		for(int j = 0; j < fComponentCount; ++j)
+			entry.components[j] = (unsigned char) consume(); /* TODO what if EOF happens in the middle? */
+		fTable.set(index, entry);
+		++index;
+	}
+	return(true);
+}
+PdfColorTableParser::PdfColorTableParser(shared_ptr<ZLInputStream> stream, int componentCount, PdfColorTable& table) : PdfScanner(stream), fComponentCount(componentCount), fTable(table) {
+	PdfColorTableEntry entry;
+	if(fComponentCount > sizeof(entry.components)/sizeof(entry.components[0]))
+		abort();
+}
+PdfColorTableParser::PdfColorTableParser(const std::string& str, int componentCount, PdfColorTable& table) : PdfScanner(new ZLStringInputStream(str)), fComponentCount(componentCount), fTable(table) {
+	PdfColorTableEntry entry;
+	if(fComponentCount > sizeof(entry.components)/sizeof(entry.components[0]))
+		abort();
+}
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfColorTableParser.h fbreader-0.12.10/fbreader/src/formats/pdf/PdfColorTableParser.h
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfColorTableParser.h	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfColorTableParser.h	2012-08-03 21:58:49.391698250 +0200
@@ -0,0 +1,25 @@
+#ifndef __PDF_COLOR_TABLE_PARSER_H
+#define __PDF_COLOR_TABLE_PARSER_H
+#include <string>
+#include <map>
+#include <sstream>
+#include <iostream>
+#include <ZLStringUtil.h>
+#include <ZLInputStream.h>
+#include "PdfScanner.h"
+#include "PdfColorTable.h"
+
+class PdfColorTableParser : public PdfScanner {
+private:
+	int fComponentCount;
+	PdfColorTable& fTable;
+protected:
+	bool parse_();
+public:
+	PdfColorTableParser(shared_ptr<ZLInputStream> stream, int componentCount, PdfColorTable& table);
+	PdfColorTableParser(const std::string& str, int componentCount, PdfColorTable& table);
+	bool parse();
+	PdfColorTable& table() const { return fTable; }
+};
+
+#endif /* ndef __PDF_COLOR_TABLE_PARSER_H */
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfContent.cpp fbreader-0.12.10/fbreader/src/formats/pdf/PdfContent.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfContent.cpp	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfContent.cpp	2011-04-05 22:55:28.000000000 +0200
@@ -0,0 +1,61 @@
+/* PDF content.
+Copyright (C) 2008 Danny Milosavljevic <danny_milo@yahoo.com>
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+#include <stdlib.h>
+#include <assert.h>
+#include "PdfContent.h"
+
+PdfContent::PdfContent()
+{
+}
+
+/* PdfInstruction */
+
+shared_ptr<PdfObject> PdfInstruction::extractFirstArgument() const {
+	const shared_ptr<PdfArrayObject>& arguments = this->arguments();
+	int argument_count = arguments->size();
+	if(argument_count == 0) /* !?!?! */
+		return shared_ptr<PdfObject>();
+	shared_ptr<PdfObject> name = (*arguments)[0];
+	return name;
+}
+
+bool PdfInstruction::extractFloatArgument(double& a) const {
+	shared_ptr<PdfObject> item = extractFirstArgument();
+	return doubleFromPdfObject(item, a);
+}
+
+std::vector<double> PdfInstruction::extractFloatArguments() const {
+	std::vector<double> result;
+	double a;
+	const shared_ptr<PdfArrayObject>& arguments = this->arguments();
+	int argument_count = arguments->size();
+	for(int i = 0; i < argument_count; ++i) {
+		shared_ptr<PdfObject> item = (*arguments)[i];
+		if(!doubleFromPdfObject(item, a))
+			return std::vector<double>();
+		result.push_back(a);
+	}
+	return result;
+}
+
+bool PdfInstruction::extractTwoFloatArguments(double& a, double& b) const {
+	const shared_ptr<PdfArrayObject>& arguments = this->arguments();
+	int argument_count = arguments->size();
+	if(argument_count == 2) {
+		shared_ptr<PdfObject> item = (*arguments)[0];
+		if(!doubleFromPdfObject(item, a))
+			return false;
+		shared_ptr<PdfObject> item_2 = (*arguments)[1];
+		if(!doubleFromPdfObject(item_2, b))
+			return false;
+		return true;
+	} else
+		return false;
+}
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfContent.h fbreader-0.12.10/fbreader/src/formats/pdf/PdfContent.h
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfContent.h	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfContent.h	2011-05-29 00:38:40.570822780 +0200
@@ -0,0 +1,141 @@
+#ifndef __PDF_CONTENT_H
+#define __PDF_CONTENT_H
+#include <iostream>
+#include <sstream>
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include <shared_ptr.h>
+/* cross dependency */
+#include "PdfObject.h"
+#include "PdfScanner.h"
+
+typedef enum {
+  // see Page 652.
+               opInvalid, 
+               opShowString /*Tj*/,
+               opNextLineShowString /*'*/,
+               opNextLineSpacedShowString /*"*/,
+               opSetWordSpacing /*Tw*/,
+               opSetCharacterSpacing /*Tc*/,
+               opSetHorizontalScaling/*Tz*/,
+               opSetFontAndSize /*Tf*/ /* second parameter: 0=auto-size */,
+               opSetTextRenderingMode /*Tr*/,
+               opSetTextRise /*Ts*/,
+               opMoveCaret /*Td*/,
+               opMoveCaretToStartOfNextLine/*T**/,
+               opMoveCaretToStartOfNextLineAndOffsetAndSetLeading/*TD*/,
+               opSetTextMatrix /*Tm*/,
+               opShowStringWithVariableSpacing /*TJ*/,
+               opSetTextLeading /*TL*/ /*for T*, ', "*/,
+               opBeginText /*BT*/,
+               opEndText /*ET*/,
+               
+               // special graphics state:
+               
+               opPushGraphicsState /*q*/,
+               opPopGraphicsState /*Q*/,
+               opTransformationMatrixAppend /*cm*/,
+
+               // drawing:
+               
+               opColorSetStrokingColorspace /*CS*/,
+               opColorSetStrokingColorLimited /*SC*/,
+               opColorSetStrokingColor /*SCN*/,
+               opColorSetStrokingGrayColor /*G*/,
+               opColorSetStrokingRGBColor /*RG*/, // colorspace := RGB, Color := <arguments>.
+               opColorSetStrokingCMYKColor /*K*/, // colorspace := CMYK, Color := <arguments>.
+               
+               opColorSetNonstrokingColorspace /*cs*/,
+               opColorSetNonstrokingColorLimited /*sc*/,
+               opColorSetNonstrokingColor /*scn*/,
+               opColorSetNonstrokingGrayColor /*g*/, // DUPE.
+               opColorSetNonstrokingRGBColor /*rg*/, // colorspace := RGB, Color := <arguments>
+               opColorSetNonstrokingCMYKColor /*k*/, // colorspace := CMYK, Color := <arguments>.
+               
+               opPathBegin /*m*/,
+               opPathAddLine /*l*/,
+               opPathAddCubicBezier123 /*c*/,
+               opPathAddCubicBezier23 /*v*/,
+               opPathAddCubicBezier13 /*y*/,
+               opPathClose /*h*/,
+               opPathRectangle /*re*/,
+
+               opPaintStroke /*S*/,
+               opPaintCloseAndStroke /*s*/, // = h S.
+               opPaintCloseAndFill /*f, F*/,
+               opPaintFillEvenOdd /*f**/,
+               opPaintFillAndStroke /*B, like construct, f, construct, S*/,
+               opPaintFillAndStrokeEvenOdd /*B**/,
+               opPaintCloseAndFillAndStroke /*b*/,
+               opPaintCloseAndFillAndStrokeEvenOdd /*b**/,
+               opPaintNoPaint /*n*/,
+               opPaintExternalObject /*Do*/,
+               
+               opClipIntersect /*W*/,
+               opClipIntersectEvenOdd /*W**/,
+               
+               // general graphics state:
+               
+               opSetLineWidth  /*w*/,
+               opSetLineCap    /*J*/,
+               opSetLineJoin   /*j*/,
+               opSetMiterLimit /*M*/,
+               opSetDashPattern/*d*/,
+               opSetColorIntent/*ri*/,
+               opFlatness      /*i*/,
+               opSetParameterValue/*gs*/,
+               
+               // marks:
+               
+               opSetMarkedContentPoint/*MP*/,
+               opSetMarkedContentPointWithAttributes/*DP*/,
+               opBeginMarkedContentBlock/*BMC*/,
+               opBeginMarkedContentBlockWithAttributes/*BDC*/,
+               opEndMarkedContentBlock/*EMC*/,
+               
+               // compat:
+               opBeginCompabilitySection/*EX*/,
+               opEndCompabilitySection/*EX*/,
+               
+               opInlineImageData/*ID*/,
+               opBeginInlineImage/*BI*/,
+               opEndInlineImage/*EI*/,
+} PdfOperator;
+
+class PdfInstruction {
+private:
+	PdfOperator myOperator_;
+	shared_ptr<PdfArrayObject> myArguments;
+public:
+	PdfInstruction() { myOperator_ = opInvalid; myArguments = new PdfArrayObject(); }
+	PdfOperator operator_() const { return myOperator_; }
+	shared_ptr<PdfArrayObject> arguments() const { return myArguments; } /* overkill. Can only contain simple types. TODO simplify. */
+	void addArgument(shared_ptr<PdfObject> argument) { myArguments->addObject(argument); }
+	void setOperator(PdfOperator value) { myOperator_ = value; }
+	void dump() const { std::cerr << "instruction " << (int) myOperator_ << std::endl; }
+	shared_ptr<PdfObject> extractFirstArgument() const;
+	bool extractFloatArgument(double& a) const;
+	std::vector<double> extractFloatArguments() const;
+	bool extractTwoFloatArguments(double& a, double& b) const;
+};
+
+class PdfContent : public PdfObject {
+private:
+	std::vector<shared_ptr<PdfInstruction> > myInstructions;
+public:
+	PdfContent();
+	virtual Type type() const { return CONTENT; }
+	std::vector<shared_ptr<PdfInstruction> > instructions() const { return myInstructions; }
+	void addInstruction(shared_ptr<PdfInstruction> item) { myInstructions.push_back(item); }
+};
+
+/*class PdfTextBlock : public PdfContent {
+};*/
+
+/* PdfInstruction helpers: */
+
+
+#endif /* ndef __PDF_CONTENT_H */
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfContentParser.cpp fbreader-0.12.10/fbreader/src/formats/pdf/PdfContentParser.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfContentParser.cpp	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfContentParser.cpp	2012-08-03 18:35:40.466949670 +0200
@@ -0,0 +1,568 @@
+/* PDF content parser.
+Copyright (C) 2008 Danny Milosavljevic <danny_milo@yahoo.com>
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+#include <stdlib.h>
+#include <assert.h>
+#include "PdfContentParser.h"
+
+// FIXME ensure args are indeed PdfStreamObjects, and not null.
+
+PdfContentParser::PdfContentParser(std::list<shared_ptr<PdfObject> >& sources, shared_ptr<PdfContent> output) : 
+	PdfScanner(""),
+	//((PdfStreamObject&)*(*sources.begin())).stream()),
+	myContent(output),
+	mySources(sources)
+{
+	mySourcesIter = mySources.begin();
+	/* debugging */
+	shared_ptr<PdfObject> item = *mySourcesIter;
+        if(item->type() != PdfObject::STREAM) {
+		std::cerr << "PdfContentParser: warning: cannot parse non-stream" << std::endl;
+	} else {
+		/*PdfStreamObject& stream = (PdfStreamObject&) *item;
+		std::cerr << "XX" << std::endl;
+		stream.dump();*/
+	}
+}
+
+
+shared_ptr<PdfInstruction> PdfContentParser::parseInstruction() {
+  shared_ptr<PdfObject> vArgument;
+  shared_ptr<PdfInstruction> result = new PdfInstruction();
+  result->setOperator(opInvalid);
+  parseOptionalWhitespace();
+  while(result->operator_() == opInvalid) {
+    if((input >= 'a' && input <= 'z') || (input >= 'A' && input <= 'Z') || input == '"' || input == '\'') { // operator.
+      result->setOperator(parseOperator());
+      if(result->operator_() == opBeginText) {
+        parseWhitespace();
+        //Result.AddTextBlock(TextBlockBodyE()); // FIXME use.
+        /*if(result->arguments()->size() != 0)
+          abort();*/
+        result->addArgument(parseTextBlockBodyE());
+        //consume('E');
+      } else if(result->operator_() == opBeginInlineImage) {
+        //parseSingleWhitespace();
+        result->addArgument(parseInlineImageBody());
+       }
+      break;
+    } else { // argument.
+      vArgument = parseValueOrBracedValueList();
+      result->addArgument(vArgument);
+    };
+    parseOptionalWhitespace(); // yeah, really optional.
+  };
+  return result;
+};
+
+PdfOperator PdfContentParser::parseOperator() {
+  // TODO: use 'switch', sort.
+
+  if(input == 'B') {
+    consume();
+    switch(input) {
+      case '*': {
+        consume();
+        return opPaintFillAndStrokeEvenOdd /*B**/;
+      };
+      case 'M': {
+       consume();
+       consume('C');
+       return opBeginMarkedContentBlock/*BMC*/;
+      };
+      case 'D': {
+        consume();
+        consume('C');
+        return opBeginMarkedContentBlockWithAttributes/*BDC*/;
+      };
+      case 'T': {
+        consume();
+        return opBeginText;
+      };
+      case 'X': {
+        consume();
+        return opBeginCompabilitySection /*BX*/;
+      };
+      case 'I': {
+        consume();
+        return opBeginInlineImage /*BI*/; /* ID will then follow */
+      }
+      default:
+        return opPaintFillAndStroke /*B, like construct, f, construct, S*/;
+       //raiseError('B[MT*]', 'B' + input);
+    };
+  } else if(input == 'C') {
+    consume();
+    consume('S');
+    return opColorSetStrokingColorspace /*CS*/;
+  } else if(input == 'D') {
+    consume();
+    switch(input) {
+      case 'o': {
+        consume();
+        return opPaintExternalObject/*Do*/;
+      };
+      case 'P': {
+        consume();
+        return opSetMarkedContentPointWithAttributes/*DP*/;
+      };
+      default:
+        raiseError("D[oP]", "D" + input);
+    };
+  } else if(input == 'E') {
+    consume();
+    switch(input) { 
+      case 'T': {
+        consume();
+        return opEndText;
+      };
+      case 'M': {
+        consume();
+        consume('C');
+        return opEndMarkedContentBlock/*EMC*/;
+      };
+      case 'X': {
+        consume();
+        return opEndCompabilitySection/*EX*/;
+      };
+      case 'I': {
+        consume();
+        return opEndInlineImage /*EI*/;
+      }
+      default:
+        raiseError("E[TM]", "E" + input);
+    };
+  } else if(input == 'M') {
+    consume();
+    switch(input) { 
+      case 'P': {
+        consume();
+        return opSetMarkedContentPoint/*MP*/;
+      };
+      default: { // 'M' alone.
+        // consume();
+        return opSetMiterLimit /*M*/;
+      };
+    };
+  } else if(input == 'T') {
+    consume();
+    if(input == 'j') {
+      consume();
+      return opShowString;
+    } else if(input == 'w') {
+      consume();
+      return opSetWordSpacing;
+    } else if(input == 'c') {
+      consume();
+      if(input == 'm') { // FIXME is that right?
+        consume();
+        return opTransformationMatrixAppend;
+      } else
+        return opSetCharacterSpacing;
+    } else if(input == 'J') {
+      consume();
+      return opShowStringWithVariableSpacing;
+    } else if(input == 'f') {
+      consume();
+      return opSetFontAndSize;
+    } else if(input == 'd') {
+      consume();
+      return opMoveCaret;
+    } else if(input == 'm') {
+      consume();
+      return opSetTextMatrix /*Tm*/;
+    } else if(input == 'L') {
+      consume();
+      return opSetTextLeading /*TL*/ /*for T*, ', "*/;
+    } else if(input == '*') {
+      consume();
+      return opMoveCaretToStartOfNextLine/*T**/;
+    } else if(input == 'r') {
+      consume();
+      return opSetTextRenderingMode/*Tr*/;
+    } else if(input == 's') {
+      consume();
+      return opSetTextRise/*Ts*/;
+    } else if(input == 'D') {
+      consume();
+      return opMoveCaretToStartOfNextLineAndOffsetAndSetLeading/*TD*/;
+    } else if(input == 'z') {
+      consume();
+      return opSetHorizontalScaling/*Tz*/; // in percent of normal width.
+    } else
+      raiseError("<text command>", "T" + input);
+  } else if(input == '\'') {
+    consume();
+    return opNextLineShowString;
+  } else if(input == '"') {
+    consume();
+    return opNextLineSpacedShowString;
+  } else if(input == 'w') {
+    consume();
+    return opSetLineWidth  /*w*/;
+  } else if(input == 'J') {
+    consume();
+    return opSetLineCap    /*J*/;
+  } else if(input == 'j') {
+    consume();
+    return opSetLineJoin   /*j*/;
+  } else if(input == 'd') {
+    consume();
+    return opSetDashPattern/*d*/;
+  } else if(input == 'i') {
+    consume();
+    return opFlatness      /*i*/;
+  } else if(input == 'g') {
+    consume();
+    if(input == 's') {
+      consume();
+      return opSetParameterValue/*gs*/;
+    } else
+      return opColorSetNonstrokingGrayColor/*g*/;
+  } else if(input == 'G') {
+    consume();
+    return opColorSetStrokingGrayColor/*G*/;
+  } else if(input == 'k') {
+    consume();
+    return opColorSetNonstrokingCMYKColor /*k*/; // colorspace = CMYK, Color = <arguments>.
+  } else if(input == 'K') {
+    consume();
+    return opColorSetStrokingCMYKColor /*K*/; // colorspace = CMYK, Color = <arguments>.
+  } else if(input == 'q') {
+    consume();
+    return opPushGraphicsState;
+  } else if(input == 'Q') {
+    consume();
+    return opPopGraphicsState;
+  } else if(input == 'm') { 
+    consume();
+    return opPathBegin;
+  } else if(input == 'l') {
+    consume();
+    return opPathAddLine;
+  } else if(input == 'c') {
+    consume();
+    if(input == 's') {
+      consume();
+      return opColorSetNonstrokingColorspace /*cs*/;
+    } else if(input == 'm') {
+      consume();
+      return opTransformationMatrixAppend /*cm*/; // FIXME remove dupe
+    } else
+      return opPathAddCubicBezier123;
+  } else if(input == 'v') {
+    consume();
+    return opPathAddCubicBezier23 /*v*/;
+  } else if(input == 'y') {
+    consume();
+    return opPathAddCubicBezier13 /*y*/;
+  } else if(input == 'h') {
+    consume();
+    return opPathClose /*h*/;
+  } else if(input == 'R') {
+    consume();
+    
+    consume('G');
+    return opColorSetStrokingRGBColor /*RG*/; // colorspace = RGB, Color = <arguments>.
+  } else if(input == 'r') {
+    consume();
+    if(input == 'i') {
+      consume();
+      return opSetColorIntent/*ri*/;
+    } else if(input =='g') {
+      consume();
+      return opColorSetNonstrokingRGBColor /*rg*/; // colorspace = RGB, Color = <arguments>
+    } else {
+      consume('e');
+      return opPathRectangle /*re*/;
+    };
+  } else if(input == 'S') {
+    consume();
+    if(input == 'C') {
+      consume();
+      if(input == 'N') {
+        consume();
+        return opColorSetStrokingColor /*SCN*/;
+      } else
+        return opColorSetStrokingColorLimited /*SC*/; // in current color space.
+    } else
+      return opPaintStroke /*S*/;
+  } else if(input == 's') {
+    consume();
+    if(input == 'c') {
+      consume();
+      if(input == 'n') {
+        consume();
+        return opColorSetNonstrokingColor /*scn*/;
+      } else {
+        return opColorSetNonstrokingColorLimited /*sc*/;
+      }
+    } else
+      return opPaintCloseAndStroke /*s*/; // == h S.
+  } else if(input == 'f' || input == 'F') {
+    if(consume() == 'f') {
+      if(input == '*') {
+        consume();
+        return opPaintFillEvenOdd /*f**/;
+      } else
+        return opPaintCloseAndFill /*f, F*/;
+    } else
+        return opPaintCloseAndFill /*f, F*/;
+  } else if(input == 'b') {
+    consume();
+    if(input == '*') { 
+      consume();
+      return opPaintCloseAndFillAndStrokeEvenOdd /*b**/;
+    } else
+      return opPaintCloseAndFillAndStroke /*b*/;
+  } else if(input == 'n') {
+    consume();
+    return opPaintNoPaint /*n*/;
+  } else if(input == 'W') {
+    consume();
+    if(input == '*') {
+      consume();
+      return opClipIntersectEvenOdd /*W**/;
+    } else
+      return opClipIntersect /*W*/;
+  } else if(input == 'I') {
+      consume();
+      switch(input) {
+        case 'D': {
+          consume();
+          return opInlineImageData /*ID*/;
+        } 
+        default:
+          raiseError("<command>");
+      }
+  } else
+    raiseError("<command>");
+  return opInvalid;
+};
+
+shared_ptr<PdfObject> PdfContentParser::parseInlineImageBody() {
+  parseWhitespace();
+  parseAttributesBody(false, 'I'); // TODO process
+  /* TODO parse stupid attribute name abbreviations:
+     BPC BitsPerComponent
+     CS ColorSpace
+     D  Decode
+     DP DecodeParams
+     F  Filter
+     H  Height
+     IM ImageMask
+     Intent Intent
+     I Interpolate
+     W Width
+     G DeviceGray
+     RGB DeviceRGB
+     CMYK DeviceCMYK
+     I Indexed
+     AHx ASCIIHexDecode
+     A85 ASCII85Decode
+     LZW LZWDecode
+     Fl FlateDecode
+     RL RunLengthDecode
+     CCF CCITTFaxDecode
+     DCT DCTDecode
+  */
+  consume('I');
+  consume('D');
+  parseSingleWhitespace();
+  while(input != EOF) {
+    if(input == 'E') {
+      consume();
+      if(input == 'I') { // FIXME make this nicer
+        consume();
+        break;
+      }
+    } else
+      consume();
+  }
+  //if(parseOperator() != opEndInlineImage)
+  //  raiseError("<end-of-inline-image>");
+  // FIXME create PdfImage (if applicable)
+  return shared_ptr<PdfObject>();
+}
+shared_ptr<PdfObject> PdfContentParser::parseTextBlockBodyE() { /* actually returns PdfContentParser */
+  PdfOperator vOperator;
+  shared_ptr<PdfInstruction> vInstruction;
+  PdfContent* result = new PdfContent();
+  vOperator = opInvalid;
+  while (vOperator != opEndText && input != EOF) {
+    vInstruction = parseInstruction();
+    vOperator = vInstruction->operator_();
+    myContent->addInstruction(vInstruction);
+  };
+  return result;
+  /*} catch(...) {
+    delete result;
+    throw;
+  }*/
+};
+
+
+shared_ptr<PdfContent> PdfContentParser::parse(std::list<shared_ptr<PdfObject> >& sources) {
+  shared_ptr<PdfContent> result = new PdfContent();
+  shared_ptr<PdfContentParser> parser = new PdfContentParser(sources, result);
+  parser->consume();
+  while(parser->input != EOF) {
+    shared_ptr<PdfInstruction> vInstruction = parser->parseInstruction(); /* can recurse using opBeginText */
+    result->addInstruction(vInstruction);
+    parser->parseOptionalWhitespace();
+  };
+  return result;
+};
+
+/* BEGIN: really basic stuff */
+
+shared_ptr<PdfObject> PdfContentParser::parseValue() {
+  // FIXME other values.
+  
+  if(input == 't' ) {
+    consume("true");
+    return PdfBooleanObject::TRUE();
+  } else if(input == 'f' ) {
+    consume("false");
+    return PdfBooleanObject::FALSE();
+  } else if(input == 'n' ) {
+    consume("null");
+    return 0;
+  } else {
+    int result = (input != '.') ? parseInteger() : 0;
+    if(input == '.' ) // floating-point, ! integer.
+      return PdfRealObject::realObject(result + parseFloatingFraction() * ((result > 0) ? 1 : -1)); // converts to Double, I hope.
+    return PdfIntegerObject::integerObject(result);
+  };
+};
+
+
+// [1 2 3]
+shared_ptr<PdfObject> PdfContentParser::parseSquareBracedValueList() { /* actually returns PdfArrayObject */
+  int i = 0;
+
+  PdfArrayObject* result = new PdfArrayObject();
+  /* TODO try catch to delete */
+  consume('[');
+  parseOptionalWhitespace();
+
+  while(input != ']' && input != EOF) {
+    // /ID [<DEC7FD857A7F7236327743F487C9FBC7> <DEC7FD857A7F7236327743F487C9FBC7>] >>
+
+    if(input == 'R' ) {
+      //Grow(i + 1);
+      raiseError("<not-object_reference>");
+#if 0
+      consume('R');
+      assert(i >= 2);
+      result[i - 2] = parseObjectReference(result[i - 2], result[i - 1]);
+      result[i - 1] = variants.Null;
+      //result[i] = variants.Null;
+      Dec(i, 1);
+#endif
+    } else {
+      result->addObject(parseValueOrBracedValueList()); // Value();
+      ++i;
+    };
+
+    if(input == 10 || input == 13)
+      parseNewline();
+    else if(input == ']' )
+      ;
+    else
+      parseOptionalWhitespace(); // aaargh! '(In)26(tro)-26(duction)-302(to)-302(tensors)]TJ'. you can't be serious.
+    /*else if(input != ']' )
+      Break; some PDFs have: [15/foo] */
+  };
+
+  parseOptionalWhitespace();
+  consume(']');
+  //OptionalWhitespace();
+  return result;
+};
+
+shared_ptr<PdfObject> PdfContentParser::parseValueOrBracedValueList() {
+  if(input == '[' )
+    return parseSquareBracedValueList();
+  else if(input == '/' )
+    return PdfNameObject::nameObject(parseAttributeName()); // FIXME SymbolReference(AttributeName())
+  else if(input == '<' ) {
+    consume();
+    if(input == '<' ) {
+      consume('<');
+      parseAttributesBody(true, '>'); /* note: ignored */
+      consume(">>");
+      return new PdfStringObject("");
+    } else {
+      std::string result = parseHexadecimalStringBody();
+      consume('>');
+      return new PdfStringObject(result);
+    };
+  } else if(input == '(' )
+    return new PdfStringObject(parseBracedString());
+  else
+    return parseValue();
+};
+
+/* END: really basic stuff */
+
+shared_ptr<ZLInputStream> PdfContentParser::goToNextStream() {
+	//std::cerr << "PdfContentParser:: going to next stream" << std::endl;
+	if(mySourcesIter == mySources.end())
+		return shared_ptr<ZLInputStream>();
+	shared_ptr<PdfObject> item = *mySourcesIter;
+	++mySourcesIter;
+	if(item->type() != PdfObject::STREAM)
+		return shared_ptr<ZLInputStream>();
+	return ((PdfStreamObject&)*item).stream();
+}
+
+shared_ptr<PdfObject> PdfContentParser::parseAttributesBody(bool BAllowObjectReferences, int delimiter) {
+  // TODO actually store stuff somewhere.
+  parseOptionalWhitespace();
+  while(input && input != delimiter) {
+    std::string key;
+    parseAttribute(BAllowObjectReferences, key);
+    //Result.Add(key, value);
+    parseOptionalWhitespace();
+  }
+  return shared_ptr<PdfObject>();
+}
+
+shared_ptr<PdfObject> PdfContentParser::parseAttribute(bool BAllowObjectReferences, std::string& key) {
+  shared_ptr<PdfObject> result;
+  unsigned version;
+  unsigned ID;
+  key = parseAttributeName();
+  parseWhitespace(); 
+  // /Contents 3 0 R
+  result = parseValueOrBracedValueList();
+  //OptionalWhitespace();
+  // FIXME allow references?
+#if 0
+  if(input == ' ') {
+    parseWhitespace(); // OptionalSpaces();
+    if Input in ['0'..'9'] then begin
+      vVersion := parsePositiveInteger();
+      parseWhitespace();
+      consume('R');
+      if(BAllowObjectReferences/*avoid reference cycles*/) {
+        ID = atoi(result.c_str());
+        Result := parseObjectReference(result, version);
+        if(!result.isNull())
+          IPDFObject(result).SetID(ID);
+      } else
+        result set null; // useful for Trailer parsing...
+    }
+  }
+#endif
+  parseOptionalWhitespace();
+  return result;
+}
+
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfContentParser.h fbreader-0.12.10/fbreader/src/formats/pdf/PdfContentParser.h
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfContentParser.h	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfContentParser.h	2011-05-29 00:39:57.130822753 +0200
@@ -0,0 +1,29 @@
+#ifndef __PDF_CONTENT_PARSER_H
+#define __PDF_CONTENT_PARSER_H
+#include <list>
+#include "PdfObject.h"
+#include "PdfScanner.h"
+#include "PdfContent.h"
+
+class PdfContentParser : public PdfScanner {
+private:
+	shared_ptr<PdfContent> myContent;
+	std::list<shared_ptr<PdfObject> > mySources;
+	std::list<shared_ptr<PdfObject> >::const_iterator mySourcesIter;
+protected /* parser */:
+	shared_ptr<PdfInstruction> parseInstruction();
+	PdfOperator parseOperator();
+	shared_ptr<PdfObject> parseTextBlockBodyE(); /* actually returns PdfContent */
+	shared_ptr<PdfObject> parseInlineImageBody();
+	shared_ptr<PdfObject> parseValueOrBracedValueList();
+	shared_ptr<PdfObject> parseValue();
+	shared_ptr<PdfObject> parseSquareBracedValueList(); /* actually returns PdfArrayObject */
+	virtual shared_ptr<ZLInputStream> goToNextStream();
+	PdfContentParser(std::list<shared_ptr<PdfObject> >& sources, shared_ptr<PdfContent> output);
+	shared_ptr<PdfObject> parseAttributesBody(bool BAllowObjectReferences = true, int delimiter = '>');
+	shared_ptr<PdfObject> parseAttribute(bool BAllowObjectReferences, std::string& key);
+public:
+	static shared_ptr<PdfContent> parse(std::list<shared_ptr<PdfObject> >& sources);
+};
+
+#endif /* ndef __PDF_CONTENT_PARSER_H */
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/Pdf.cpp fbreader-0.12.10/fbreader/src/formats/pdf/Pdf.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/Pdf.cpp	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/Pdf.cpp	2011-04-05 22:55:28.000000000 +0200
@@ -0,0 +1,23 @@
+#include <iostream>
+#include "Pdf.h"
+
+shared_ptr<PdfObject> Pdf::findObject(const std::pair<int,int> address) {
+	std::map<std::pair<int,int>,shared_ptr<PdfObject> >::iterator iter = myObjectMap.find(address);
+	if(iter != myObjectMap.end())
+		return iter->second;
+	else
+		return shared_ptr<PdfObject>();
+}
+
+void Pdf::addObject(const std::pair<int,int> address, shared_ptr<PdfObject> object) {
+	if(!findObject(address).isNull()) {
+		std::cerr << "error: duplicate object data for object (" << address.first << "," << address.second << ")!" << std::endl;
+	}
+	myObjectMap.insert(std::pair<std::pair<int,int>,shared_ptr<PdfObject> >(address, object));
+}
+
+void Pdf::ensureTrailer(shared_ptr<PdfObject> trailer) {
+	if (myTrailer.isNull()) {
+		myTrailer = trailer;
+	}
+}
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfDefaultCharMap.cpp fbreader-0.12.10/fbreader/src/formats/pdf/PdfDefaultCharMap.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfDefaultCharMap.cpp	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfDefaultCharMap.cpp	2011-04-05 22:55:28.000000000 +0200
@@ -0,0 +1,27 @@
+#include <string>
+#include <map>
+#include <iostream>
+#include <sstream>
+#include "PdfDefaultCharMap.h"
+#include "parseDefaultCharName.h"
+
+/** \return cNilCodepoint if not found. */
+unsigned int getUnicodeFromDefaultCharMap(const std::string& key) {
+	const char* x_name = key.c_str();
+	unsigned int unicode = parseDefaultCharName(x_name);
+	if(unicode)
+		return unicode;
+	else {
+		/* note: it seems that with Type 3 symbol "fonts" (which uses Pdf XObjects as glyphs), the names are dummy names that are to map directly to their own code. 
+		   Since this is not unicode, we don't do it anyway. */
+		std::string readableKey = key;
+		if(readableKey.length() == 1 && readableKey[0] < 32) {
+			std::stringstream x;
+			x << "(code " << (unsigned int) (unsigned char) readableKey[0] << ")";
+			readableKey = x.str();
+		}
+		std::cerr << "PdfDefaultCharMap: entry not found: " << readableKey << std::endl;
+		return cNilCodepoint;
+	}
+}
+
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfDefaultCharMap.h fbreader-0.12.10/fbreader/src/formats/pdf/PdfDefaultCharMap.h
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfDefaultCharMap.h	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfDefaultCharMap.h	2011-04-05 22:55:28.000000000 +0200
@@ -0,0 +1,8 @@
+#ifndef __PDF_DEFAULT_CHAR_MAP_H
+#define __PDF_DEFAULT_CHAR_MAP_H
+#include <string>
+
+#define cNilCodepoint 0xFFFD
+unsigned int getUnicodeFromDefaultCharMap(const std::string& key);
+
+#endif /* ndef __PDF_DEFAULT_CHAR_MAP_H */
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfDefaultCharMapMap.cpp fbreader-0.12.10/fbreader/src/formats/pdf/PdfDefaultCharMapMap.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfDefaultCharMapMap.cpp	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfDefaultCharMapMap.cpp	2011-05-29 12:03:11.980808465 +0200
@@ -0,0 +1,4468 @@
+#include <string>
+#include <map>
+#include <iostream>
+#include "PdfDefaultCharMap.h"
+
+// please don't use C comments in this file (only C++ comments), because generate-state-table's mind is too small to understand them.
+#if 0
+// causes GCC in scratchbox Fremantle to endless loop and use up 1GB RAM until it is killed by the kernel. Very funny.
+#pragma optimize("", off)
+#pragma GCC optimization_level 0
+static std::map<std::string, unsigned int> createCharMap() {
+	std::map<std::string, unsigned int> chars;
+	chars["A"] = 0x0041;
+	chars["a"] = 0x0061;
+	chars["aabengali"] = 0x0986;
+	chars["Aacute"] = 0x00C1;
+	chars["aacute"] = 0x00E1;
+	chars["Aacutesmall"] = 0xF7E1;
+	chars["aadeva"] = 0x0906;
+	chars["aagujarati"] = 0x0A86;
+	chars["aagurmukhi"] = 0x0A06;
+	chars["aamatragurmukhi"] = 0x0A3E;
+	chars["aarusquare"] = 0x3303;
+	chars["aavowelsignbengali"] = 0x09BE;
+	chars["aavowelsigndeva"] = 0x093E;
+	chars["aavowelsigngujarati"] = 0x0ABE;
+	chars["abbreviationmarkarmenian"] = 0x055F;
+	chars["abbreviationsigndeva"] = 0x0970;
+	chars["abengali"] = 0x0985;
+	chars["abopomofo"] = 0x311A;
+	chars["Abreve"] = 0x0102;
+	chars["abreve"] = 0x0103;
+	chars["Abreveacute"] = 0x1EAE;
+	chars["abreveacute"] = 0x1EAF;
+	chars["Abrevecyrillic"] = 0x04D0;
+	chars["abrevecyrillic"] = 0x04D1;
+	chars["Abrevedotbelow"] = 0x1EB6;
+	chars["abrevedotbelow"] = 0x1EB7;
+	chars["Abrevegrave"] = 0x1EB0;
+	chars["abrevegrave"] = 0x1EB1;
+	chars["Abrevehookabove"] = 0x1EB2;
+	chars["abrevehookabove"] = 0x1EB3;
+	chars["Abrevetilde"] = 0x1EB4;
+	chars["abrevetilde"] = 0x1EB5;
+	chars["Acaron"] = 0x01CD;
+	chars["acaron"] = 0x01CE;
+	chars["Acircle"] = 0x24B6;
+	chars["acircle"] = 0x24D0;
+	chars["Acircumflex"] = 0x00C2;
+	chars["acircumflex"] = 0x00E2;
+	chars["Acircumflexacute"] = 0x1EA4;
+	chars["acircumflexacute"] = 0x1EA5;
+	chars["Acircumflexdotbelow"] = 0x1EAC;
+	chars["acircumflexdotbelow"] = 0x1EAD;
+	chars["Acircumflexgrave"] = 0x1EA6;
+	chars["acircumflexgrave"] = 0x1EA7;
+	chars["Acircumflexhookabove"] = 0x1EA8;
+	chars["acircumflexhookabove"] = 0x1EA9;
+	chars["Acircumflexsmall"] = 0xF7E2;
+	chars["Acircumflextilde"] = 0x1EAA;
+	chars["acircumflextilde"] = 0x1EAB;
+	chars["acute"] = 0x00B4;
+	chars["Acute"] = 0xF6C9;
+	chars["acutebelowcmb"] = 0x0317;
+	chars["acutecmb"] = 0x0301;
+	chars["acutecomb"] = 0x0301;
+	chars["acutedeva"] = 0x0954;
+	chars["acutelowmod"] = 0x02CF;
+	chars["Acutesmall"] = 0xF7B4;
+	chars["acutetonecmb"] = 0x0341;
+	chars["Acyrillic"] = 0x0410;
+	chars["acyrillic"] = 0x0430;
+	chars["Adblgrave"] = 0x0200;
+	chars["adblgrave"] = 0x0201;
+	chars["addakgurmukhi"] = 0x0A71;
+	chars["adeva"] = 0x0905;
+	chars["Adieresis"] = 0x00C4;
+	chars["adieresis"] = 0x00E4;
+	chars["Adieresiscyrillic"] = 0x04D2;
+	chars["adieresiscyrillic"] = 0x04D3;
+	chars["Adieresismacron"] = 0x01DE;
+	chars["adieresismacron"] = 0x01DF;
+	chars["Adieresissmall"] = 0xF7E4;
+	chars["Adotbelow"] = 0x1EA0;
+	chars["adotbelow"] = 0x1EA1;
+	chars["Adotmacron"] = 0x01E0;
+	chars["adotmacron"] = 0x01E1;
+	chars["AE"] = 0x00C6;
+	chars["ae"] = 0x00E6;
+	chars["AEacute"] = 0x01FC;
+	chars["aeacute"] = 0x01FD;
+	chars["aekorean"] = 0x3150;
+	chars["AEmacron"] = 0x01E2;
+	chars["aemacron"] = 0x01E3;
+	chars["AEsmall"] = 0xF7E6;
+	chars["afii00208"] = 0x2015;
+	chars["afii08941"] = 0x20A4;
+	chars["afii10017"] = 0x0410;
+	chars["afii10018"] = 0x0411;
+	chars["afii10019"] = 0x0412;
+	chars["afii10020"] = 0x0413;
+	chars["afii10021"] = 0x0414;
+	chars["afii10022"] = 0x0415;
+	chars["afii10023"] = 0x0401;
+	chars["afii10024"] = 0x0416;
+	chars["afii10025"] = 0x0417;
+	chars["afii10026"] = 0x0418;
+	chars["afii10027"] = 0x0419;
+	chars["afii10028"] = 0x041A;
+	chars["afii10029"] = 0x041B;
+	chars["afii10030"] = 0x041C;
+	chars["afii10031"] = 0x041D;
+	chars["afii10032"] = 0x041E;
+	chars["afii10033"] = 0x041F;
+	chars["afii10034"] = 0x0420;
+	chars["afii10035"] = 0x0421;
+	chars["afii10036"] = 0x0422;
+	chars["afii10037"] = 0x0423;
+	chars["afii10038"] = 0x0424;
+	chars["afii10039"] = 0x0425;
+	chars["afii10040"] = 0x0426;
+	chars["afii10041"] = 0x0427;
+	chars["afii10042"] = 0x0428;
+	chars["afii10043"] = 0x0429;
+	chars["afii10044"] = 0x042A;
+	chars["afii10045"] = 0x042B;
+	chars["afii10046"] = 0x042C;
+	chars["afii10047"] = 0x042D;
+	chars["afii10048"] = 0x042E;
+	chars["afii10049"] = 0x042F;
+	chars["afii10050"] = 0x0490;
+	chars["afii10051"] = 0x0402;
+	chars["afii10052"] = 0x0403;
+	chars["afii10053"] = 0x0404;
+	chars["afii10054"] = 0x0405;
+	chars["afii10055"] = 0x0406;
+	chars["afii10056"] = 0x0407;
+	chars["afii10057"] = 0x0408;
+	chars["afii10058"] = 0x0409;
+	chars["afii10059"] = 0x040A;
+	chars["afii10060"] = 0x040B;
+	chars["afii10061"] = 0x040C;
+	chars["afii10062"] = 0x040E;
+	chars["afii10063"] = 0xF6C4;
+	chars["afii10064"] = 0xF6C5;
+	chars["afii10065"] = 0x0430;
+	chars["afii10066"] = 0x0431;
+	chars["afii10067"] = 0x0432;
+	chars["afii10068"] = 0x0433;
+	chars["afii10069"] = 0x0434;
+	chars["afii10070"] = 0x0435;
+	chars["afii10071"] = 0x0451;
+	chars["afii10072"] = 0x0436;
+	chars["afii10073"] = 0x0437;
+	chars["afii10074"] = 0x0438;
+	chars["afii10075"] = 0x0439;
+	chars["afii10076"] = 0x043A;
+	chars["afii10077"] = 0x043B;
+	chars["afii10078"] = 0x043C;
+	chars["afii10079"] = 0x043D;
+	chars["afii10080"] = 0x043E;
+	chars["afii10081"] = 0x043F;
+	chars["afii10082"] = 0x0440;
+	chars["afii10083"] = 0x0441;
+	chars["afii10084"] = 0x0442;
+	chars["afii10085"] = 0x0443;
+	chars["afii10086"] = 0x0444;
+	chars["afii10087"] = 0x0445;
+	chars["afii10088"] = 0x0446;
+	chars["afii10089"] = 0x0447;
+	chars["afii10090"] = 0x0448;
+	chars["afii10091"] = 0x0449;
+	chars["afii10092"] = 0x044A;
+	chars["afii10093"] = 0x044B;
+	chars["afii10094"] = 0x044C;
+	chars["afii10095"] = 0x044D;
+	chars["afii10096"] = 0x044E;
+	chars["afii10097"] = 0x044F;
+	chars["afii10098"] = 0x0491;
+	chars["afii10099"] = 0x0452;
+	chars["afii10100"] = 0x0453;
+	chars["afii10101"] = 0x0454;
+	chars["afii10102"] = 0x0455;
+	chars["afii10103"] = 0x0456;
+	chars["afii10104"] = 0x0457;
+	chars["afii10105"] = 0x0458;
+	chars["afii10106"] = 0x0459;
+	chars["afii10107"] = 0x045A;
+	chars["afii10108"] = 0x045B;
+	chars["afii10109"] = 0x045C;
+	chars["afii10110"] = 0x045E;
+	chars["afii10145"] = 0x040F;
+	chars["afii10146"] = 0x0462;
+	chars["afii10147"] = 0x0472;
+	chars["afii10148"] = 0x0474;
+	chars["afii10192"] = 0xF6C6;
+	chars["afii10193"] = 0x045F;
+	chars["afii10194"] = 0x0463;
+	chars["afii10195"] = 0x0473;
+	chars["afii10196"] = 0x0475;
+	chars["afii10831"] = 0xF6C7;
+	chars["afii10832"] = 0xF6C8;
+	chars["afii10846"] = 0x04D9;
+	chars["afii299"] = 0x200E;
+	chars["afii300"] = 0x200F;
+	chars["afii301"] = 0x200D;
+	chars["afii57381"] = 0x066A;
+	chars["afii57388"] = 0x060C;
+	chars["afii57392"] = 0x0660;
+	chars["afii57393"] = 0x0661;
+	chars["afii57394"] = 0x0662;
+	chars["afii57395"] = 0x0663;
+	chars["afii57396"] = 0x0664;
+	chars["afii57397"] = 0x0665;
+	chars["afii57398"] = 0x0666;
+	chars["afii57399"] = 0x0667;
+	chars["afii57400"] = 0x0668;
+	chars["afii57401"] = 0x0669;
+	chars["afii57403"] = 0x061B;
+	chars["afii57407"] = 0x061F;
+	chars["afii57409"] = 0x0621;
+	chars["afii57410"] = 0x0622;
+	chars["afii57411"] = 0x0623;
+	chars["afii57412"] = 0x0624;
+	chars["afii57413"] = 0x0625;
+	chars["afii57414"] = 0x0626;
+	chars["afii57415"] = 0x0627;
+	chars["afii57416"] = 0x0628;
+	chars["afii57417"] = 0x0629;
+	chars["afii57418"] = 0x062A;
+	chars["afii57419"] = 0x062B;
+	chars["afii57420"] = 0x062C;
+	chars["afii57421"] = 0x062D;
+	chars["afii57422"] = 0x062E;
+	chars["afii57423"] = 0x062F;
+	chars["afii57424"] = 0x0630;
+	chars["afii57425"] = 0x0631;
+	chars["afii57426"] = 0x0632;
+	chars["afii57427"] = 0x0633;
+	chars["afii57428"] = 0x0634;
+	chars["afii57429"] = 0x0635;
+	chars["afii57430"] = 0x0636;
+	chars["afii57431"] = 0x0637;
+	chars["afii57432"] = 0x0638;
+	chars["afii57433"] = 0x0639;
+	chars["afii57434"] = 0x063A;
+	chars["afii57440"] = 0x0640;
+	chars["afii57441"] = 0x0641;
+	chars["afii57442"] = 0x0642;
+	chars["afii57443"] = 0x0643;
+	chars["afii57444"] = 0x0644;
+	chars["afii57445"] = 0x0645;
+	chars["afii57446"] = 0x0646;
+	chars["afii57448"] = 0x0648;
+	chars["afii57449"] = 0x0649;
+	chars["afii57450"] = 0x064A;
+	chars["afii57451"] = 0x064B;
+	chars["afii57452"] = 0x064C;
+	chars["afii57453"] = 0x064D;
+	chars["afii57454"] = 0x064E;
+	chars["afii57455"] = 0x064F;
+	chars["afii57456"] = 0x0650;
+	chars["afii57457"] = 0x0651;
+	chars["afii57458"] = 0x0652;
+	chars["afii57470"] = 0x0647;
+	chars["afii57505"] = 0x06A4;
+	chars["afii57506"] = 0x067E;
+	chars["afii57507"] = 0x0686;
+	chars["afii57508"] = 0x0698;
+	chars["afii57509"] = 0x06AF;
+	chars["afii57511"] = 0x0679;
+	chars["afii57512"] = 0x0688;
+	chars["afii57513"] = 0x0691;
+	chars["afii57514"] = 0x06BA;
+	chars["afii57519"] = 0x06D2;
+	chars["afii57534"] = 0x06D5;
+	chars["afii57636"] = 0x20AA;
+	chars["afii57645"] = 0x05BE;
+	chars["afii57658"] = 0x05C3;
+	chars["afii57664"] = 0x05D0;
+	chars["afii57665"] = 0x05D1;
+	chars["afii57666"] = 0x05D2;
+	chars["afii57667"] = 0x05D3;
+	chars["afii57668"] = 0x05D4;
+	chars["afii57669"] = 0x05D5;
+	chars["afii57670"] = 0x05D6;
+	chars["afii57671"] = 0x05D7;
+	chars["afii57672"] = 0x05D8;
+	chars["afii57673"] = 0x05D9;
+	chars["afii57674"] = 0x05DA;
+	chars["afii57675"] = 0x05DB;
+	chars["afii57676"] = 0x05DC;
+	chars["afii57677"] = 0x05DD;
+	chars["afii57678"] = 0x05DE;
+	chars["afii57679"] = 0x05DF;
+	chars["afii57680"] = 0x05E0;
+	chars["afii57681"] = 0x05E1;
+	chars["afii57682"] = 0x05E2;
+	chars["afii57683"] = 0x05E3;
+	chars["afii57684"] = 0x05E4;
+	chars["afii57685"] = 0x05E5;
+	chars["afii57686"] = 0x05E6;
+	chars["afii57687"] = 0x05E7;
+	chars["afii57688"] = 0x05E8;
+	chars["afii57689"] = 0x05E9;
+	chars["afii57690"] = 0x05EA;
+	chars["afii57694"] = 0xFB2A;
+	chars["afii57695"] = 0xFB2B;
+	chars["afii57700"] = 0xFB4B;
+	chars["afii57705"] = 0xFB1F;
+	chars["afii57716"] = 0x05F0;
+	chars["afii57717"] = 0x05F1;
+	chars["afii57718"] = 0x05F2;
+	chars["afii57723"] = 0xFB35;
+	chars["afii57793"] = 0x05B4;
+	chars["afii57794"] = 0x05B5;
+	chars["afii57795"] = 0x05B6;
+	chars["afii57796"] = 0x05BB;
+	chars["afii57797"] = 0x05B8;
+	chars["afii57798"] = 0x05B7;
+	chars["afii57799"] = 0x05B0;
+	chars["afii57800"] = 0x05B2;
+	chars["afii57801"] = 0x05B1;
+	chars["afii57802"] = 0x05B3;
+	chars["afii57803"] = 0x05C2;
+	chars["afii57804"] = 0x05C1;
+	chars["afii57806"] = 0x05B9;
+	chars["afii57807"] = 0x05BC;
+	chars["afii57839"] = 0x05BD;
+	chars["afii57841"] = 0x05BF;
+	chars["afii57842"] = 0x05C0;
+	chars["afii57929"] = 0x02BC;
+	chars["afii61248"] = 0x2105;
+	chars["afii61289"] = 0x2113;
+	chars["afii61352"] = 0x2116;
+	chars["afii61573"] = 0x202C;
+	chars["afii61574"] = 0x202D;
+	chars["afii61575"] = 0x202E;
+	chars["afii61664"] = 0x200C;
+	chars["afii63167"] = 0x066D;
+	chars["afii64937"] = 0x02BD;
+	chars["Agrave"] = 0x00C0;
+	chars["agrave"] = 0x00E0;
+	chars["Agravesmall"] = 0xF7E0;
+	chars["agujarati"] = 0x0A85;
+	chars["agurmukhi"] = 0x0A05;
+	chars["ahiragana"] = 0x3042;
+	chars["Ahookabove"] = 0x1EA2;
+	chars["ahookabove"] = 0x1EA3;
+	chars["aibengali"] = 0x0990;
+	chars["aibopomofo"] = 0x311E;
+	chars["aideva"] = 0x0910;
+	chars["Aiecyrillic"] = 0x04D4;
+	chars["aiecyrillic"] = 0x04D5;
+	chars["aigujarati"] = 0x0A90;
+	chars["aigurmukhi"] = 0x0A10;
+	chars["aimatragurmukhi"] = 0x0A48;
+	chars["ainarabic"] = 0x0639;
+	chars["ainfinalarabic"] = 0xFECA;
+	chars["aininitialarabic"] = 0xFECB;
+	chars["ainmedialarabic"] = 0xFECC;
+	chars["Ainvertedbreve"] = 0x0202;
+	chars["ainvertedbreve"] = 0x0203;
+	chars["aivowelsignbengali"] = 0x09C8;
+	chars["aivowelsigndeva"] = 0x0948;
+	chars["aivowelsigngujarati"] = 0x0AC8;
+	chars["akatakana"] = 0x30A2;
+	chars["akatakanahalfwidth"] = 0xFF71;
+	chars["akorean"] = 0x314F;
+	chars["alef"] = 0x05D0;
+	chars["alefarabic"] = 0x0627;
+	chars["alefdageshhebrew"] = 0xFB30;
+	chars["aleffinalarabic"] = 0xFE8E;
+	chars["alefhamzaabovearabic"] = 0x0623;
+	chars["alefhamzaabovefinalarabic"] = 0xFE84;
+	chars["alefhamzabelowarabic"] = 0x0625;
+	chars["alefhamzabelowfinalarabic"] = 0xFE88;
+	chars["alefhebrew"] = 0x05D0;
+	chars["aleflamedhebrew"] = 0xFB4F;
+	chars["alefmaddaabovearabic"] = 0x0622;
+	chars["alefmaddaabovefinalarabic"] = 0xFE82;
+	chars["alefmaksuraarabic"] = 0x0649;
+	chars["alefmaksurafinalarabic"] = 0xFEF0;
+	chars["alefmaksurainitialarabic"] = 0xFEF3;
+	chars["alefmaksuramedialarabic"] = 0xFEF4;
+	chars["alefpatahhebrew"] = 0xFB2E;
+	chars["alefqamatshebrew"] = 0xFB2F;
+	chars["aleph"] = 0x2135;
+	chars["allequal"] = 0x224C;
+	chars["Alpha"] = 0x0391;
+	chars["alpha"] = 0x03B1;
+	chars["Alphatonos"] = 0x0386;
+	chars["alphatonos"] = 0x03AC;
+	chars["Amacron"] = 0x0100;
+	chars["amacron"] = 0x0101;
+	chars["Amonospace"] = 0xFF21;
+	chars["amonospace"] = 0xFF41;
+	chars["ampersand"] = 0x0026;
+	chars["ampersandmonospace"] = 0xFF06;
+	chars["ampersandsmall"] = 0xF726;
+	chars["amsquare"] = 0x33C2;
+	chars["anbopomofo"] = 0x3122;
+	chars["angbopomofo"] = 0x3124;
+	chars["angkhankhuthai"] = 0x0E5A;
+	chars["angle"] = 0x2220;
+	chars["anglebracketleft"] = 0x3008;
+	chars["anglebracketleftvertical"] = 0xFE3F;
+	chars["anglebracketright"] = 0x3009;
+	chars["anglebracketrightvertical"] = 0xFE40;
+	chars["angleleft"] = 0x2329;
+	chars["angleright"] = 0x232A;
+	chars["angstrom"] = 0x212B;
+	chars["anoteleia"] = 0x0387;
+	chars["anudattadeva"] = 0x0952;
+	chars["anusvarabengali"] = 0x0982;
+	chars["anusvaradeva"] = 0x0902;
+	chars["anusvaragujarati"] = 0x0A82;
+	chars["Aogonek"] = 0x0104;
+	chars["aogonek"] = 0x0105;
+	chars["apaatosquare"] = 0x3300;
+	chars["aparen"] = 0x249C;
+	chars["apostrophearmenian"] = 0x055A;
+	chars["apostrophemod"] = 0x02BC;
+	chars["apple"] = 0xF8FF;
+	chars["approaches"] = 0x2250;
+	chars["approxequal"] = 0x2248;
+	chars["approxequalorimage"] = 0x2252;
+	chars["approximatelyequal"] = 0x2245;
+	chars["araeaekorean"] = 0x318E;
+	chars["araeakorean"] = 0x318D;
+	chars["arc"] = 0x2312;
+	chars["arighthalfring"] = 0x1E9A;
+	chars["Aring"] = 0x00C5;
+	chars["aring"] = 0x00E5;
+	chars["Aringacute"] = 0x01FA;
+	chars["aringacute"] = 0x01FB;
+	chars["Aringbelow"] = 0x1E00;
+	chars["aringbelow"] = 0x1E01;
+	chars["Aringsmall"] = 0xF7E5;
+	chars["arrowbarright"] = 0x21A6;
+	chars["arrowboth"] = 0x2194;
+	chars["arrowdashdown"] = 0x21E3;
+	chars["arrowdashleft"] = 0x21E0;
+	chars["arrowdashright"] = 0x21E2;
+	chars["arrowdashup"] = 0x21E1;
+	chars["arrowdblboth"] = 0x21D4;
+	chars["arrowdbldown"] = 0x21D3;
+	chars["arrowdblleft"] = 0x21D0;
+	chars["arrowdblright"] = 0x21D2;
+	chars["arrowdblup"] = 0x21D1;
+	chars["arrowdown"] = 0x2193;
+	chars["arrowdownleft"] = 0x2199;
+	chars["arrowdownright"] = 0x2198;
+	chars["arrowdownwhite"] = 0x21E9;
+	chars["arrowheaddownmod"] = 0x02C5;
+	chars["arrowheadleftmod"] = 0x02C2;
+	chars["arrowheadrightmod"] = 0x02C3;
+	chars["arrowheadupmod"] = 0x02C4;
+	chars["arrowhorizex"] = 0xF8E7;
+	chars["arrowleft"] = 0x2190;
+	chars["arrowleftdbl"] = 0x21D0;
+	chars["arrowleftdblstroke"] = 0x21CD;
+	chars["arrowleftoverright"] = 0x21C6;
+	chars["arrowleftwhite"] = 0x21E6;
+	chars["arrowright"] = 0x2192;
+	chars["arrowrightdblstroke"] = 0x21CF;
+	chars["arrowrightheavy"] = 0x279E;
+	chars["arrowrightoverleft"] = 0x21C4;
+	chars["arrowrightwhite"] = 0x21E8;
+	chars["arrowtableft"] = 0x21E4;
+	chars["arrowtabright"] = 0x21E5;
+	chars["arrowup"] = 0x2191;
+	chars["arrowupdn"] = 0x2195;
+	chars["arrowupdnbse"] = 0x21A8;
+	chars["arrowupdownbase"] = 0x21A8;
+	chars["arrowupleft"] = 0x2196;
+	chars["arrowupleftofdown"] = 0x21C5;
+	chars["arrowupright"] = 0x2197;
+	chars["arrowupwhite"] = 0x21E7;
+	chars["arrowvertex"] = 0xF8E6;
+	chars["asciicircum"] = 0x005E;
+	chars["asciicircummonospace"] = 0xFF3E;
+	chars["asciitilde"] = 0x007E;
+	chars["asciitildemonospace"] = 0xFF5E;
+	chars["ascript"] = 0x0251;
+	chars["ascriptturned"] = 0x0252;
+	chars["Asmall"] = 0xF761;
+	chars["asmallhiragana"] = 0x3041;
+	chars["asmallkatakana"] = 0x30A1;
+	chars["asmallkatakanahalfwidth"] = 0xFF67;
+	chars["asterisk"] = 0x002A;
+	chars["asteriskaltonearabic"] = 0x066D;
+	chars["asteriskarabic"] = 0x066D;
+	chars["asteriskmath"] = 0x2217;
+	chars["asteriskmonospace"] = 0xFF0A;
+	chars["asterisksmall"] = 0xFE61;
+	chars["asterism"] = 0x2042;
+	chars["asuperior"] = 0xF6E9;
+	chars["asymptoticallyequal"] = 0x2243;
+	chars["at"] = 0x0040;
+	chars["Atilde"] = 0x00C3;
+	chars["atilde"] = 0x00E3;
+	chars["Atildesmall"] = 0xF7E3;
+	chars["atmonospace"] = 0xFF20;
+	chars["atsmall"] = 0xFE6B;
+	chars["aturned"] = 0x0250;
+	chars["aubengali"] = 0x0994;
+	chars["aubopomofo"] = 0x3120;
+	chars["audeva"] = 0x0914;
+	chars["augujarati"] = 0x0A94;
+	chars["augurmukhi"] = 0x0A14;
+	chars["aulengthmarkbengali"] = 0x09D7;
+	chars["aumatragurmukhi"] = 0x0A4C;
+	chars["auvowelsignbengali"] = 0x09CC;
+	chars["auvowelsigndeva"] = 0x094C;
+	chars["auvowelsigngujarati"] = 0x0ACC;
+	chars["avagrahadeva"] = 0x093D;
+	chars["Aybarmenian"] = 0x0531;
+	chars["aybarmenian"] = 0x0561;
+	chars["ayin"] = 0x05E2;
+	chars["ayinaltonehebrew"] = 0xFB20;
+	chars["ayinhebrew"] = 0x05E2;
+	chars["B"] = 0x0042;
+	chars["b"] = 0x0062;
+	chars["babengali"] = 0x09AC;
+	chars["backslash"] = 0x005C;
+	chars["backslashmonospace"] = 0xFF3C;
+	chars["badeva"] = 0x092C;
+	chars["bagujarati"] = 0x0AAC;
+	chars["bagurmukhi"] = 0x0A2C;
+	chars["bahiragana"] = 0x3070;
+	chars["bahtthai"] = 0x0E3F;
+	chars["bakatakana"] = 0x30D0;
+	chars["bar"] = 0x007C;
+	chars["barmonospace"] = 0xFF5C;
+	chars["bbopomofo"] = 0x3105;
+	chars["Bcircle"] = 0x24B7;
+	chars["bcircle"] = 0x24D1;
+	chars["Bdotaccent"] = 0x1E02;
+	chars["bdotaccent"] = 0x1E03;
+	chars["Bdotbelow"] = 0x1E04;
+	chars["bdotbelow"] = 0x1E05;
+	chars["beamedsixteenthnotes"] = 0x266C;
+	chars["because"] = 0x2235;
+	chars["Becyrillic"] = 0x0411;
+	chars["becyrillic"] = 0x0431;
+	chars["beharabic"] = 0x0628;
+	chars["behfinalarabic"] = 0xFE90;
+	chars["behinitialarabic"] = 0xFE91;
+	chars["behiragana"] = 0x3079;
+	chars["behmedialarabic"] = 0xFE92;
+	chars["behmeeminitialarabic"] = 0xFC9F;
+	chars["behmeemisolatedarabic"] = 0xFC08;
+	chars["behnoonfinalarabic"] = 0xFC6D;
+	chars["bekatakana"] = 0x30D9;
+	chars["Benarmenian"] = 0x0532;
+	chars["benarmenian"] = 0x0562;
+	chars["bet"] = 0x05D1;
+	chars["Beta"] = 0x0392;
+	chars["beta"] = 0x03B2;
+	chars["betasymbolgreek"] = 0x03D0;
+	chars["betdagesh"] = 0xFB31;
+	chars["betdageshhebrew"] = 0xFB31;
+	chars["bethebrew"] = 0x05D1;
+	chars["betrafehebrew"] = 0xFB4C;
+	chars["bhabengali"] = 0x09AD;
+	chars["bhadeva"] = 0x092D;
+	chars["bhagujarati"] = 0x0AAD;
+	chars["bhagurmukhi"] = 0x0A2D;
+	chars["Bhook"] = 0x0181;
+	chars["bhook"] = 0x0253;
+	chars["bihiragana"] = 0x3073;
+	chars["bikatakana"] = 0x30D3;
+	chars["bilabialclick"] = 0x0298;
+	chars["bindigurmukhi"] = 0x0A02;
+	chars["birusquare"] = 0x3331;
+	chars["blackcircle"] = 0x25CF;
+	chars["blackdiamond"] = 0x25C6;
+	chars["blackdownpointingtriangle"] = 0x25BC;
+	chars["blackleftpointingpointer"] = 0x25C4;
+	chars["blackleftpointingtriangle"] = 0x25C0;
+	chars["blacklenticularbracketleft"] = 0x3010;
+	chars["blacklenticularbracketleftvertical"] = 0xFE3B;
+	chars["blacklenticularbracketright"] = 0x3011;
+	chars["blacklenticularbracketrightvertical"] = 0xFE3C;
+	chars["blacklowerlefttriangle"] = 0x25E3;
+	chars["blacklowerrighttriangle"] = 0x25E2;
+	chars["blackrectangle"] = 0x25AC;
+	chars["blackrightpointingpointer"] = 0x25BA;
+	chars["blackrightpointingtriangle"] = 0x25B6;
+	chars["blacksmallsquare"] = 0x25AA;
+	chars["blacksmilingface"] = 0x263B;
+	chars["blacksquare"] = 0x25A0;
+	chars["blackstar"] = 0x2605;
+	chars["blackupperlefttriangle"] = 0x25E4;
+	chars["blackupperrighttriangle"] = 0x25E5;
+	chars["blackuppointingsmalltriangle"] = 0x25B4;
+	chars["blackuppointingtriangle"] = 0x25B2;
+	chars["blank"] = 0x2423;
+	chars["Blinebelow"] = 0x1E06;
+	chars["blinebelow"] = 0x1E07;
+	chars["block"] = 0x2588;
+	chars["Bmonospace"] = 0xFF22;
+	chars["bmonospace"] = 0xFF42;
+	chars["bobaimaithai"] = 0x0E1A;
+	chars["bohiragana"] = 0x307C;
+	chars["bokatakana"] = 0x30DC;
+	chars["bparen"] = 0x249D;
+	chars["bqsquare"] = 0x33C3;
+	chars["braceex"] = 0x23AA;
+	chars["braceleft"] = 0x007B;
+	chars["braceleftbt"] = 0x23A9;
+	chars["braceleftmid"] = 0x23A8;
+	chars["braceleftmonospace"] = 0xFF5B;
+	chars["braceleftsmall"] = 0xFE5B;
+	chars["bracelefttp"] = 0x23A7;
+	chars["braceleftvertical"] = 0xFE37;
+	chars["braceright"] = 0x007D;
+	chars["bracerightbt"] = 0x23AD;
+	chars["bracerightmid"] = 0x23AC;
+	chars["bracerightmonospace"] = 0xFF5D;
+	chars["bracerightsmall"] = 0xFE5C;
+	chars["bracerighttp"] = 0x23AB;
+	chars["bracerightvertical"] = 0xFE38;
+	chars["bracketleft"] = 0x005B;
+	chars["bracketleftbt"] = 0x23A3;
+	chars["bracketleftex"] = 0x23a2;
+	chars["bracketleftmonospace"] = 0xFF3B;
+	chars["bracketlefttp"] = 0x23A1;
+	chars["bracketright"] = 0x005D;
+	chars["bracketrightbt"] = 0x23A6;
+	chars["bracketrightex"] = 0x23A5;
+	chars["bracketrightmonospace"] = 0xFF3D;
+	chars["bracketrighttp"] = 0x23A4;
+	chars["breve"] = 0x02D8;
+	chars["brevebelowcmb"] = 0x032E;
+	chars["brevecmb"] = 0x0306;
+	chars["breveinvertedbelowcmb"] = 0x032F;
+	chars["breveinvertedcmb"] = 0x0311;
+	chars["breveinverteddoublecmb"] = 0x0361;
+	chars["Brevesmall"] = 0xF6F4;
+	chars["bridgebelowcmb"] = 0x032A;
+	chars["bridgeinvertedbelowcmb"] = 0x033A;
+	chars["brokenbar"] = 0x00A6;
+	chars["Bsmall"] = 0xF762;
+	chars["bstroke"] = 0x0180;
+	chars["bsuperior"] = 0xF6EA;
+	chars["Btopbar"] = 0x0182;
+	chars["btopbar"] = 0x0183;
+	chars["buhiragana"] = 0x3076;
+	chars["bukatakana"] = 0x30D6;
+	chars["bullet"] = 0x2022;
+	chars["bulletinverse"] = 0x25D8;
+	chars["bulletoperator"] = 0x2219;
+	chars["bullseye"] = 0x25CE;
+	chars["C"] = 0x0043;
+	chars["c"] = 0x0063;
+	chars["Caarmenian"] = 0x053E;
+	chars["caarmenian"] = 0x056E;
+	chars["cabengali"] = 0x099A;
+	chars["Cacute"] = 0x0106;
+	chars["cacute"] = 0x0107;
+	chars["cadeva"] = 0x091A;
+	chars["cagujarati"] = 0x0A9A;
+	chars["cagurmukhi"] = 0x0A1A;
+	chars["calsquare"] = 0x3388;
+	chars["candrabindubengali"] = 0x0981;
+	chars["candrabinducmb"] = 0x0310;
+	chars["candrabindudeva"] = 0x0901;
+	chars["candrabindugujarati"] = 0x0A81;
+	chars["capslock"] = 0x21EA;
+	chars["careof"] = 0x2105;
+	chars["caron"] = 0x02C7;
+	chars["Caron"] = 0xF6CA;
+	chars["caronbelowcmb"] = 0x032C;
+	chars["caroncmb"] = 0x030C;
+	chars["Caronsmall"] = 0xF6F5;
+	chars["carriagereturn"] = 0x21B5;
+	chars["cbopomofo"] = 0x3118;
+	chars["Ccaron"] = 0x010C;
+	chars["ccaron"] = 0x010D;
+	chars["Ccedilla"] = 0x00C7;
+	chars["ccedilla"] = 0x00E7;
+	chars["Ccedillaacute"] = 0x1E08;
+	chars["ccedillaacute"] = 0x1E09;
+	chars["Ccedillasmall"] = 0xF7E7;
+	chars["Ccircle"] = 0x24B8;
+	chars["ccircle"] = 0x24D2;
+	chars["Ccircumflex"] = 0x0108;
+	chars["ccircumflex"] = 0x0109;
+	chars["ccurl"] = 0x0255;
+	chars["Cdot"] = 0x010A;
+	chars["cdot"] = 0x010B;
+	chars["Cdotaccent"] = 0x010A;
+	chars["cdotaccent"] = 0x010B;
+	chars["cdsquare"] = 0x33C5;
+	chars["cedilla"] = 0x00B8;
+	chars["cedillacmb"] = 0x0327;
+	chars["Cedillasmall"] = 0xF7B8;
+	chars["cent"] = 0x00A2;
+	chars["centigrade"] = 0x2103;
+	chars["centinferior"] = 0xF6DF;
+	chars["centmonospace"] = 0xFFE0;
+	chars["centoldstyle"] = 0xF7A2;
+	chars["centsuperior"] = 0xF6E0;
+	chars["Chaarmenian"] = 0x0549;
+	chars["chaarmenian"] = 0x0579;
+	chars["chabengali"] = 0x099B;
+	chars["chadeva"] = 0x091B;
+	chars["chagujarati"] = 0x0A9B;
+	chars["chagurmukhi"] = 0x0A1B;
+	chars["chbopomofo"] = 0x3114;
+	chars["Cheabkhasiancyrillic"] = 0x04BC;
+	chars["cheabkhasiancyrillic"] = 0x04BD;
+	chars["checkmark"] = 0x2713;
+	chars["Checyrillic"] = 0x0427;
+	chars["checyrillic"] = 0x0447;
+	chars["Chedescenderabkhasiancyrillic"] = 0x04BE;
+	chars["chedescenderabkhasiancyrillic"] = 0x04BF;
+	chars["Chedescendercyrillic"] = 0x04B6;
+	chars["chedescendercyrillic"] = 0x04B7;
+	chars["Chedieresiscyrillic"] = 0x04F4;
+	chars["chedieresiscyrillic"] = 0x04F5;
+	chars["Cheharmenian"] = 0x0543;
+	chars["cheharmenian"] = 0x0573;
+	chars["Chekhakassiancyrillic"] = 0x04CB;
+	chars["chekhakassiancyrillic"] = 0x04CC;
+	chars["Cheverticalstrokecyrillic"] = 0x04B8;
+	chars["cheverticalstrokecyrillic"] = 0x04B9;
+	chars["Chi"] = 0x03A7;
+	chars["chi"] = 0x03C7;
+	chars["chieuchacirclekorean"] = 0x3277;
+	chars["chieuchaparenkorean"] = 0x3217;
+	chars["chieuchcirclekorean"] = 0x3269;
+	chars["chieuchkorean"] = 0x314A;
+	chars["chieuchparenkorean"] = 0x3209;
+	chars["chochangthai"] = 0x0E0A;
+	chars["chochanthai"] = 0x0E08;
+	chars["chochingthai"] = 0x0E09;
+	chars["chochoethai"] = 0x0E0C;
+	chars["Chook"] = 0x0187;
+	chars["chook"] = 0x0188;
+	chars["cieucacirclekorean"] = 0x3276;
+	chars["cieucaparenkorean"] = 0x3216;
+	chars["cieuccirclekorean"] = 0x3268;
+	chars["cieuckorean"] = 0x3148;
+	chars["cieucparenkorean"] = 0x3208;
+	chars["cieucuparenkorean"] = 0x321C;
+	chars["circle"] = 0x25CB;
+	chars["circledot"] = 0x2299;
+	chars["circlemultiply"] = 0x2297;
+	chars["circleot"] = 0x2299;
+	chars["circleminus"] = 0x2296;
+	chars["circleplus"] = 0x2295;
+	chars["circlepostalmark"] = 0x3036;
+	chars["circlewithlefthalfblack"] = 0x25D0;
+	chars["circlewithrighthalfblack"] = 0x25D1;
+	chars["circumflex"] = 0x02C6;
+	chars["circumflexbelowcmb"] = 0x032D;
+	chars["circumflexcmb"] = 0x0302;
+	chars["Circumflexsmall"] = 0xF6F6;
+	chars["clear"] = 0x2327;
+	chars["clickalveolar"] = 0x01C2;
+	chars["clickdental"] = 0x01C0;
+	chars["clicklateral"] = 0x01C1;
+	chars["clickretroflex"] = 0x01C3;
+	chars["club"] = 0x2663;
+	chars["clubsuitblack"] = 0x2663;
+	chars["clubsuitwhite"] = 0x2667;
+	chars["cmcubedsquare"] = 0x33A4;
+	chars["Cmonospace"] = 0xFF23;
+	chars["cmonospace"] = 0xFF43;
+	chars["cmsquaredsquare"] = 0x33A0;
+	chars["Coarmenian"] = 0x0551;
+	chars["coarmenian"] = 0x0581;
+	chars["colon"] = 0x003A;
+	chars["colonmonetary"] = 0x20A1;
+	chars["colonmonospace"] = 0xFF1A;
+	chars["colonsign"] = 0x20A1;
+	chars["colonsmall"] = 0xFE55;
+	chars["colontriangularhalfmod"] = 0x02D1;
+	chars["colontriangularmod"] = 0x02D0;
+	chars["comma"] = 0x002C;
+	chars["commaabovecmb"] = 0x0313;
+	chars["commaaboverightcmb"] = 0x0315;
+	chars["commaaccent"] = 0xF6C3;
+	chars["commaarabic"] = 0x060C;
+	chars["commaarmenian"] = 0x055D;
+	chars["commainferior"] = 0xF6E1;
+	chars["commamonospace"] = 0xFF0C;
+	chars["commareversedabovecmb"] = 0x0314;
+	chars["commareversedmod"] = 0x02BD;
+	chars["commasmall"] = 0xFE50;
+	chars["commasuperior"] = 0xF6E2;
+	chars["commaturnedabovecmb"] = 0x0312;
+	chars["commaturnedmod"] = 0x02BB;
+	chars["compass"] = 0x263C;
+	chars["congruent"] = 0x2245;
+	chars["contourintegral"] = 0x222E;
+	chars["control"] = 0x2303;
+	chars["controlACK"] = 0x0006;
+	chars["controlBEL"] = 0x0007;
+	chars["controlBS"] = 0x0008;
+	chars["controlCAN"] = 0x0018;
+	chars["controlCR"] = 0x000D;
+	chars["controlDC1"] = 0x0011;
+	chars["controlDC2"] = 0x0012;
+	chars["controlDC3"] = 0x0013;
+	chars["controlDC4"] = 0x0014;
+	chars["controlDEL"] = 0x007F;
+	chars["controlDLE"] = 0x0010;
+	chars["controlEM"] = 0x0019;
+	chars["controlENQ"] = 0x0005;
+	chars["controlEOT"] = 0x0004;
+	chars["controlESC"] = 0x001B;
+	chars["controlETB"] = 0x0017;
+	chars["controlETX"] = 0x0003;
+	chars["controlFF"] = 0x000C;
+	chars["controlFS"] = 0x001C;
+	chars["controlGS"] = 0x001D;
+	chars["controlHT"] = 0x0009;
+	chars["controlLF"] = 0x000A;
+	chars["controlNAK"] = 0x0015;
+	chars["controlRS"] = 0x001E;
+	chars["controlSI"] = 0x000F;
+	chars["controlSO"] = 0x000E;
+	chars["controlSOT"] = 0x0002;
+	chars["controlSTX"] = 0x0001;
+	chars["controlSUB"] = 0x001A;
+	chars["controlSYN"] = 0x0016;
+	chars["controlUS"] = 0x001F;
+	chars["controlVT"] = 0x000B;
+	chars["copyright"] = 0x00A9;
+	chars["copyrightsans"] = 0xF8E9;
+	chars["copyrightserif"] = 0xF6D9;
+	chars["cornerbracketleft"] = 0x300C;
+	chars["cornerbracketlefthalfwidth"] = 0xFF62;
+	chars["cornerbracketleftvertical"] = 0xFE41;
+	chars["cornerbracketright"] = 0x300D;
+	chars["cornerbracketrighthalfwidth"] = 0xFF63;
+	chars["cornerbracketrightvertical"] = 0xFE42;
+	chars["corporationsquare"] = 0x337F;
+	chars["cosquare"] = 0x33C7;
+	chars["coverkgsquare"] = 0x33C6;
+	chars["cparen"] = 0x249E;
+	chars["cruzeiro"] = 0x20A2;
+	chars["Csmall"] = 0xF763;
+	chars["cstretched"] = 0x0297;
+	chars["curlyand"] = 0x22CF;
+	chars["curlyor"] = 0x22CE;
+	chars["currency"] = 0x00A4;
+	chars["cyrBreve"] = 0xF6D1;
+	chars["cyrbreve"] = 0xF6D4;
+	chars["cyrFlex"] = 0xF6D2;
+	chars["cyrflex"] = 0xF6D5;
+	chars["D"] = 0x0044;
+	chars["d"] = 0x0064;
+	chars["Daarmenian"] = 0x0534;
+	chars["daarmenian"] = 0x0564;
+	chars["dabengali"] = 0x09A6;
+	chars["dadarabic"] = 0x0636;
+	chars["dadeva"] = 0x0926;
+	chars["dadfinalarabic"] = 0xFEBE;
+	chars["dadinitialarabic"] = 0xFEBF;
+	chars["dadmedialarabic"] = 0xFEC0;
+	chars["Dafrican"] = 0x0189;
+	chars["dagesh"] = 0x05BC;
+	chars["dageshhebrew"] = 0x05BC;
+	chars["dagger"] = 0x2020;
+	chars["daggerdbl"] = 0x2021;
+	chars["dagujarati"] = 0x0AA6;
+	chars["dagurmukhi"] = 0x0A26;
+	chars["dahiragana"] = 0x3060;
+	chars["dakatakana"] = 0x30C0;
+	chars["dalarabic"] = 0x062F;
+	chars["dalet"] = 0x05D3;
+	chars["daletdagesh"] = 0xFB33;
+	chars["daletdageshhebrew"] = 0xFB33;
+	//chars["dalethatafpatah"] = 0x05D3 05B2;
+	//chars["dalethatafpatahhebrew"] = 0x05D3 05B2;
+	//chars["dalethatafsegol"] = 0x05D3 05B1;
+	//chars["dalethatafsegolhebrew"] = 0x05D3 05B1;
+	//chars["dalethebrew"] = 0x05D3;
+	//chars["dalethiriq"] = 0x05D3 05B4;
+	//chars["dalethiriqhebrew"] = 0x05D3 05B4;
+	//chars["daletholam"] = 0x05D3 05B9;
+	//chars["daletholamhebrew"] = 0x05D3 05B9;
+	//chars["daletpatah"] = 0x05D3 05B7;
+	//chars["daletpatahhebrew"] = 0x05D3 05B7;
+	//chars["daletqamats"] = 0x05D3 05B8;
+	//chars["daletqamatshebrew"] = 0x05D3 05B8;
+	//chars["daletqubuts"] = 0x05D3 05BB;
+	//chars["daletqubutshebrew"] = 0x05D3 05BB;
+	//chars["daletsegol"] = 0x05D3 05B6;
+	//chars["daletsegolhebrew"] = 0x05D3 05B6;
+	//chars["daletsheva"] = 0x05D3 05B0;
+	//chars["daletshevahebrew"] = 0x05D3 05B0;
+	//chars["dalettsere"] = 0x05D3 05B5;
+	//chars["dalettserehebrew"] = 0x05D3 05B5;
+	chars["dalfinalarabic"] = 0xFEAA;
+	chars["dammaarabic"] = 0x064F;
+	chars["dammalowarabic"] = 0x064F;
+	chars["dammatanaltonearabic"] = 0x064C;
+	chars["dammatanarabic"] = 0x064C;
+	chars["danda"] = 0x0964;
+	chars["dargahebrew"] = 0x05A7;
+	chars["dargalefthebrew"] = 0x05A7;
+	chars["dasiapneumatacyrilliccmb"] = 0x0485;
+	chars["dblanglebracketleft"] = 0x300A;
+	chars["dblanglebracketleftvertical"] = 0xFE3D;
+	chars["dblanglebracketright"] = 0x300B;
+	chars["dblanglebracketrightvertical"] = 0xFE3E;
+	chars["dblarchinvertedbelowcmb"] = 0x032B;
+	chars["dblarrowleft"] = 0x21D4;
+	chars["dblarrowright"] = 0x21D2;
+	chars["dbldanda"] = 0x0965;
+	chars["dblGrave"] = 0xF6D3;
+	chars["dblgrave"] = 0xF6D6;
+	chars["dblgravecmb"] = 0x030F;
+	chars["dblintegral"] = 0x222C;
+	chars["dbllowline"] = 0x2017;
+	chars["dbllowlinecmb"] = 0x0333;
+	chars["dbloverlinecmb"] = 0x033F;
+	chars["dblprimemod"] = 0x02BA;
+	chars["dblverticalbar"] = 0x2016;
+	chars["dblverticallineabovecmb"] = 0x030E;
+	chars["dbopomofo"] = 0x3109;
+	chars["dbsquare"] = 0x33C8;
+	chars["Dcaron"] = 0x010E;
+	chars["dcaron"] = 0x010F;
+	chars["Dcedilla"] = 0x1E10;
+	chars["dcedilla"] = 0x1E11;
+	chars["Dcircle"] = 0x24B9;
+	chars["dcircle"] = 0x24D3;
+	chars["Dcircumflexbelow"] = 0x1E12;
+	chars["dcircumflexbelow"] = 0x1E13;
+	chars["Dcroat"] = 0x0110;
+	chars["dcroat"] = 0x0111;
+	chars["ddabengali"] = 0x09A1;
+	chars["ddadeva"] = 0x0921;
+	chars["ddagujarati"] = 0x0AA1;
+	chars["ddagurmukhi"] = 0x0A21;
+	chars["ddalarabic"] = 0x0688;
+	chars["ddalfinalarabic"] = 0xFB89;
+	chars["dddhadeva"] = 0x095C;
+	chars["ddhabengali"] = 0x09A2;
+	chars["ddhadeva"] = 0x0922;
+	chars["ddhagujarati"] = 0x0AA2;
+	chars["ddhagurmukhi"] = 0x0A22;
+	chars["Ddotaccent"] = 0x1E0A;
+	chars["ddotaccent"] = 0x1E0B;
+	chars["Ddotbelow"] = 0x1E0C;
+	chars["ddotbelow"] = 0x1E0D;
+	chars["decimalseparatorarabic"] = 0x066B;
+	chars["decimalseparatorpersian"] = 0x066B;
+	chars["Decyrillic"] = 0x0414;
+	chars["decyrillic"] = 0x0434;
+	chars["degree"] = 0x00B0;
+	chars["dehihebrew"] = 0x05AD;
+	chars["dehiragana"] = 0x3067;
+	chars["Deicoptic"] = 0x03EE;
+	chars["deicoptic"] = 0x03EF;
+	chars["dekatakana"] = 0x30C7;
+	chars["deleteleft"] = 0x232B;
+	chars["deleteright"] = 0x2326;
+	chars["delta"] = 0x03B4;
+	chars["Delta"] = 0x2206;
+	chars["Deltagreek"] = 0x0394;
+	chars["deltaturned"] = 0x018D;
+	chars["denominatorminusonenumeratorbengali"] = 0x09F8;
+	chars["dezh"] = 0x02A4;
+	chars["dhabengali"] = 0x09A7;
+	chars["dhadeva"] = 0x0927;
+	chars["dhagujarati"] = 0x0AA7;
+	chars["dhagurmukhi"] = 0x0A27;
+	chars["Dhook"] = 0x018A;
+	chars["dhook"] = 0x0257;
+	chars["dialytikatonos"] = 0x0385;
+	chars["dialytikatonoscmb"] = 0x0344;
+	chars["diamond"] = 0x2666;
+	chars["diamondsuitwhite"] = 0x2662;
+	chars["dieresis"] = 0x00A8;
+	chars["Dieresis"] = 0xF6CB;
+	chars["DieresisAcute"] = 0xF6CC;
+	chars["dieresisacute"] = 0xF6D7;
+	chars["dieresisbelowcmb"] = 0x0324;
+	chars["dieresiscmb"] = 0x0308;
+	chars["DieresisGrave"] = 0xF6CD;
+	chars["dieresisgrave"] = 0xF6D8;
+	chars["Dieresissmall"] = 0xF7A8;
+	chars["dieresistonos"] = 0x0385;
+	chars["Digammagreek"] = 0x03DC;
+	chars["dihiragana"] = 0x3062;
+	chars["dikatakana"] = 0x30C2;
+	chars["dittomark"] = 0x3003;
+	chars["divide"] = 0x00F7;
+	chars["divides"] = 0x2223;
+	chars["divisionslash"] = 0x2215;
+	chars["Djecyrillic"] = 0x0402;
+	chars["djecyrillic"] = 0x0452;
+	chars["dkshade"] = 0x2593;
+	chars["Dlinebelow"] = 0x1E0E;
+	chars["dlinebelow"] = 0x1E0F;
+	chars["dlsquare"] = 0x3397;
+	chars["dmacron"] = 0x0111;
+	chars["Dmonospace"] = 0xFF24;
+	chars["dmonospace"] = 0xFF44;
+	chars["dnblock"] = 0x2584;
+	chars["dochadathai"] = 0x0E0E;
+	chars["dodekthai"] = 0x0E14;
+	chars["dohiragana"] = 0x3069;
+	chars["dokatakana"] = 0x30C9;
+	chars["dollar"] = 0x0024;
+	chars["dollarinferior"] = 0xF6E3;
+	chars["dollarmonospace"] = 0xFF04;
+	chars["dollaroldstyle"] = 0xF724;
+	chars["dollarsmall"] = 0xFE69;
+	chars["dollarsuperior"] = 0xF6E4;
+	chars["dong"] = 0x20AB;
+	chars["dorusquare"] = 0x3326;
+	chars["dotaccent"] = 0x02D9;
+	chars["dotaccentcmb"] = 0x0307;
+	chars["Dotaccentsmall"] = 0xF6F7;
+	chars["dotbelowcmb"] = 0x0323;
+	chars["dotbelowcomb"] = 0x0323;
+	chars["dotkatakana"] = 0x30FB;
+	chars["dotlessi"] = 0x0131;
+	chars["dotlessj"] = 0xF6BE;
+	chars["dotlessjstrokehook"] = 0x0284;
+	chars["dotmath"] = 0x22C5;
+	chars["dottedcircle"] = 0x25CC;
+	chars["doubleyodpatah"] = 0xFB1F;
+	chars["doubleyodpatahhebrew"] = 0xFB1F;
+	chars["downtackbelowcmb"] = 0x031E;
+	chars["downtackmod"] = 0x02D5;
+	chars["dparen"] = 0x249F;
+	chars["Dslash"] = 0x0110;
+	chars["Dsmall"] = 0xF764;
+	chars["dsuperior"] = 0xF6EB;
+	chars["dtail"] = 0x0256;
+	chars["Dtopbar"] = 0x018B;
+	chars["dtopbar"] = 0x018C;
+	chars["duhiragana"] = 0x3065;
+	chars["dukatakana"] = 0x30C5;
+	chars["DZ"] = 0x01F1;
+	chars["Dz"] = 0x01F2;
+	chars["dz"] = 0x01F3;
+	chars["dzaltone"] = 0x02A3;
+	chars["DZcaron"] = 0x01C4;
+	chars["Dzcaron"] = 0x01C5;
+	chars["dzcaron"] = 0x01C6;
+	chars["dzcurl"] = 0x02A5;
+	chars["Dzeabkhasiancyrillic"] = 0x04E0;
+	chars["dzeabkhasiancyrillic"] = 0x04E1;
+	chars["Dzecyrillic"] = 0x0405;
+	chars["dzecyrillic"] = 0x0455;
+	chars["Dzhecyrillic"] = 0x040F;
+	chars["dzhecyrillic"] = 0x045F;
+	chars["E"] = 0x0045;
+	chars["e"] = 0x0065;
+	chars["Eacute"] = 0x00C9;
+	chars["eacute"] = 0x00E9;
+	chars["Eacutesmall"] = 0xF7E9;
+	chars["earth"] = 0x2641;
+	chars["ebengali"] = 0x098F;
+	chars["ebopomofo"] = 0x311C;
+	chars["Ebreve"] = 0x0114;
+	chars["ebreve"] = 0x0115;
+	chars["ecandradeva"] = 0x090D;
+	chars["ecandragujarati"] = 0x0A8D;
+	chars["ecandravowelsigndeva"] = 0x0945;
+	chars["ecandravowelsigngujarati"] = 0x0AC5;
+	chars["Ecaron"] = 0x011A;
+	chars["ecaron"] = 0x011B;
+	chars["Ecedillabreve"] = 0x1E1C;
+	chars["ecedillabreve"] = 0x1E1D;
+	chars["Echarmenian"] = 0x0535;
+	chars["echarmenian"] = 0x0565;
+	chars["echyiwnarmenian"] = 0x0587;
+	chars["Ecircle"] = 0x24BA;
+	chars["ecircle"] = 0x24D4;
+	chars["Ecircumflex"] = 0x00CA;
+	chars["ecircumflex"] = 0x00EA;
+	chars["Ecircumflexacute"] = 0x1EBE;
+	chars["ecircumflexacute"] = 0x1EBF;
+	chars["Ecircumflexbelow"] = 0x1E18;
+	chars["ecircumflexbelow"] = 0x1E19;
+	chars["Ecircumflexdotbelow"] = 0x1EC6;
+	chars["ecircumflexdotbelow"] = 0x1EC7;
+	chars["Ecircumflexgrave"] = 0x1EC0;
+	chars["ecircumflexgrave"] = 0x1EC1;
+	chars["Ecircumflexhookabove"] = 0x1EC2;
+	chars["ecircumflexhookabove"] = 0x1EC3;
+	chars["Ecircumflexsmall"] = 0xF7EA;
+	chars["Ecircumflextilde"] = 0x1EC4;
+	chars["ecircumflextilde"] = 0x1EC5;
+	chars["Ecyrillic"] = 0x0404;
+	chars["ecyrillic"] = 0x0454;
+	chars["Edblgrave"] = 0x0204;
+	chars["edblgrave"] = 0x0205;
+	chars["edeva"] = 0x090F;
+	chars["Edieresis"] = 0x00CB;
+	chars["edieresis"] = 0x00EB;
+	chars["Edieresissmall"] = 0xF7EB;
+	chars["Edot"] = 0x0116;
+	chars["edot"] = 0x0117;
+	chars["Edotaccent"] = 0x0116;
+	chars["edotaccent"] = 0x0117;
+	chars["Edotbelow"] = 0x1EB8;
+	chars["edotbelow"] = 0x1EB9;
+	chars["eegurmukhi"] = 0x0A0F;
+	chars["eematragurmukhi"] = 0x0A47;
+	chars["Efcyrillic"] = 0x0424;
+	chars["efcyrillic"] = 0x0444;
+	chars["Egrave"] = 0x00C8;
+	chars["egrave"] = 0x00E8;
+	chars["Egravesmall"] = 0xF7E8;
+	chars["egujarati"] = 0x0A8F;
+	chars["Eharmenian"] = 0x0537;
+	chars["eharmenian"] = 0x0567;
+	chars["ehbopomofo"] = 0x311D;
+	chars["ehiragana"] = 0x3048;
+	chars["Ehookabove"] = 0x1EBA;
+	chars["ehookabove"] = 0x1EBB;
+	chars["eibopomofo"] = 0x311F;
+	chars["eight"] = 0x0038;
+	chars["eightarabic"] = 0x0668;
+	chars["eightbengali"] = 0x09EE;
+	chars["eightcircle"] = 0x2467;
+	chars["eightcircleinversesansserif"] = 0x2791;
+	chars["eightdeva"] = 0x096E;
+	chars["eighteencircle"] = 0x2471;
+	chars["eighteenparen"] = 0x2485;
+	chars["eighteenperiod"] = 0x2499;
+	chars["eightgujarati"] = 0x0AEE;
+	chars["eightgurmukhi"] = 0x0A6E;
+	chars["eighthackarabic"] = 0x0668;
+	chars["eighthangzhou"] = 0x3028;
+	chars["eighthnotebeamed"] = 0x266B;
+	chars["eightideographicparen"] = 0x3227;
+	chars["eightinferior"] = 0x2088;
+	chars["eightmonospace"] = 0xFF18;
+	chars["eightoldstyle"] = 0xF738;
+	chars["eightparen"] = 0x247B;
+	chars["eightperiod"] = 0x248F;
+	chars["eightpersian"] = 0x06F8;
+	chars["Eightroman"] = 0x2167;
+	chars["eightroman"] = 0x2177;
+	chars["eightsuperior"] = 0x2078;
+	chars["eightthai"] = 0x0E58;
+	chars["Einvertedbreve"] = 0x0206;
+	chars["einvertedbreve"] = 0x0207;
+	chars["Eiotifiedcyrillic"] = 0x0464;
+	chars["eiotifiedcyrillic"] = 0x0465;
+	chars["ekatakana"] = 0x30A8;
+	chars["ekatakanahalfwidth"] = 0xFF74;
+	chars["ekonkargurmukhi"] = 0x0A74;
+	chars["ekorean"] = 0x3154;
+	chars["Elcyrillic"] = 0x041B;
+	chars["elcyrillic"] = 0x043B;
+	chars["element"] = 0x2208;
+	chars["elevencircle"] = 0x246A;
+	chars["elevenparen"] = 0x247E;
+	chars["elevenperiod"] = 0x2492;
+	chars["Elevenroman"] = 0x216A;
+	chars["elevenroman"] = 0x217A;
+	chars["ellipsis"] = 0x2026;
+	chars["ellipsisvertical"] = 0x22EE;
+	chars["Emacron"] = 0x0112;
+	chars["emacron"] = 0x0113;
+	chars["Emacronacute"] = 0x1E16;
+	chars["emacronacute"] = 0x1E17;
+	chars["Emacrongrave"] = 0x1E14;
+	chars["emacrongrave"] = 0x1E15;
+	chars["Emcyrillic"] = 0x041C;
+	chars["emcyrillic"] = 0x043C;
+	chars["emdash"] = 0x2014;
+	chars["emdashvertical"] = 0xFE31;
+	chars["Emonospace"] = 0xFF25;
+	chars["emonospace"] = 0xFF45;
+	chars["emphasismarkarmenian"] = 0x055B;
+	chars["emptyset"] = 0x2205;
+	chars["enbopomofo"] = 0x3123;
+	chars["Encyrillic"] = 0x041D;
+	chars["encyrillic"] = 0x043D;
+	chars["endash"] = 0x2013;
+	chars["endashvertical"] = 0xFE32;
+	chars["Endescendercyrillic"] = 0x04A2;
+	chars["endescendercyrillic"] = 0x04A3;
+	chars["Eng"] = 0x014A;
+	chars["eng"] = 0x014B;
+	chars["engbopomofo"] = 0x3125;
+	chars["Enghecyrillic"] = 0x04A4;
+	chars["enghecyrillic"] = 0x04A5;
+	chars["Enhookcyrillic"] = 0x04C7;
+	chars["enhookcyrillic"] = 0x04C8;
+	chars["enspace"] = 0x2002;
+	chars["Eogonek"] = 0x0118;
+	chars["eogonek"] = 0x0119;
+	chars["eokorean"] = 0x3153;
+	chars["Eopen"] = 0x0190;
+	chars["eopen"] = 0x025B;
+	chars["eopenclosed"] = 0x029A;
+	chars["eopenreversed"] = 0x025C;
+	chars["eopenreversedclosed"] = 0x025E;
+	chars["eopenreversedhook"] = 0x025D;
+	chars["eparen"] = 0x24A0;
+	chars["Epsilon"] = 0x0395;
+	chars["epsilon"] = 0x03B5;
+	chars["epsilon1"] = 0x0190;
+	chars["Epsilontonos"] = 0x0388;
+	chars["epsilontonos"] = 0x03AD;
+	chars["equal"] = 0x003D;
+	chars["equalmonospace"] = 0xFF1D;
+	chars["equalsmall"] = 0xFE66;
+	chars["equalsuperior"] = 0x207C;
+	chars["equivalence"] = 0x2261;
+	chars["erbopomofo"] = 0x3126;
+	chars["Ercyrillic"] = 0x0420;
+	chars["ercyrillic"] = 0x0440;
+	chars["Ereversed"] = 0x018E;
+	chars["ereversed"] = 0x0258;
+	chars["Ereversedcyrillic"] = 0x042D;
+	chars["ereversedcyrillic"] = 0x044D;
+	chars["Escyrillic"] = 0x0421;
+	chars["escyrillic"] = 0x0441;
+	chars["Esdescendercyrillic"] = 0x04AA;
+	chars["esdescendercyrillic"] = 0x04AB;
+	chars["Esh"] = 0x01A9;
+	chars["esh"] = 0x0283;
+	chars["eshcurl"] = 0x0286;
+	chars["eshortdeva"] = 0x090E;
+	chars["eshortvowelsigndeva"] = 0x0946;
+	chars["eshreversedloop"] = 0x01AA;
+	chars["eshsquatreversed"] = 0x0285;
+	chars["Esmall"] = 0xF765;
+	chars["esmallhiragana"] = 0x3047;
+	chars["esmallkatakana"] = 0x30A7;
+	chars["esmallkatakanahalfwidth"] = 0xFF6A;
+	chars["estimated"] = 0x212E;
+	chars["esuperior"] = 0xF6EC;
+	chars["Eta"] = 0x0397;
+	chars["eta"] = 0x03B7;
+	chars["Etarmenian"] = 0x0538;
+	chars["etarmenian"] = 0x0568;
+	chars["Etatonos"] = 0x0389;
+	chars["etatonos"] = 0x03AE;
+	chars["Eth"] = 0x00D0;
+	chars["eth"] = 0x00F0;
+	chars["Ethsmall"] = 0xF7F0;
+	chars["Etilde"] = 0x1EBC;
+	chars["etilde"] = 0x1EBD;
+	chars["Etildebelow"] = 0x1E1A;
+	chars["etildebelow"] = 0x1E1B;
+	chars["etnahtafoukhhebrew"] = 0x0591;
+	chars["etnahtafoukhlefthebrew"] = 0x0591;
+	chars["etnahtahebrew"] = 0x0591;
+	chars["etnahtalefthebrew"] = 0x0591;
+	chars["eturned"] = 0x01DD;
+	chars["eukorean"] = 0x3161;
+	chars["euro"] = 0x20AC;
+	chars["Euro"] = 0x20AC;
+	chars["evowelsignbengali"] = 0x09C7;
+	chars["evowelsigndeva"] = 0x0947;
+	chars["evowelsigngujarati"] = 0x0AC7;
+	chars["exclam"] = 0x0021;
+	chars["exclamarmenian"] = 0x055C;
+	chars["exclamdbl"] = 0x203C;
+	chars["exclamdown"] = 0x00A1;
+	chars["exclamdownsmall"] = 0xF7A1;
+	chars["exclammonospace"] = 0xFF01;
+	chars["exclamsmall"] = 0xF721;
+	chars["existential"] = 0x2203;
+	chars["Ezh"] = 0x01B7;
+	chars["ezh"] = 0x0292;
+	chars["Ezhcaron"] = 0x01EE;
+	chars["ezhcaron"] = 0x01EF;
+	chars["ezhcurl"] = 0x0293;
+	chars["Ezhreversed"] = 0x01B8;
+	chars["ezhreversed"] = 0x01B9;
+	chars["ezhtail"] = 0x01BA;
+	chars["F"] = 0x0046;
+	chars["f"] = 0x0066;
+	chars["fadeva"] = 0x095E;
+	chars["fagurmukhi"] = 0x0A5E;
+	chars["fahrenheit"] = 0x2109;
+	chars["fathaarabic"] = 0x064E;
+	chars["fathalowarabic"] = 0x064E;
+	chars["fathatanarabic"] = 0x064B;
+	chars["fbopomofo"] = 0x3108;
+	chars["Fcircle"] = 0x24BB;
+	chars["fcircle"] = 0x24D5;
+	chars["Fdotaccent"] = 0x1E1E;
+	chars["fdotaccent"] = 0x1E1F;
+	chars["feharabic"] = 0x0641;
+	chars["Feharmenian"] = 0x0556;
+	chars["feharmenian"] = 0x0586;
+	chars["fehfinalarabic"] = 0xFED2;
+	chars["fehinitialarabic"] = 0xFED3;
+	chars["fehmedialarabic"] = 0xFED4;
+	chars["Feicoptic"] = 0x03E4;
+	chars["feicoptic"] = 0x03E5;
+	chars["female"] = 0x2640;
+	chars["ff"] = 0xFB00;
+	chars["ffi"] = 0xFB03;
+	chars["ffl"] = 0xFB04;
+	chars["Fhook"] = 0x0191;
+	chars["fi"] = 0xFB01;
+	chars["fifteencircle"] = 0x246E;
+	chars["fifteenparen"] = 0x2482;
+	chars["fifteenperiod"] = 0x2496;
+	chars["figuredash"] = 0x2012;
+	chars["filledbox"] = 0x25A0;
+	chars["filledrect"] = 0x25AC;
+	chars["finalkaf"] = 0x05DA;
+	//chars["finalkafdagesh"] = 0xFB3A;
+	//chars["finalkafdageshhebrew"] = 0xFB3A;
+	//chars["finalkafhebrew"] = 0x05DA;
+	//chars["finalkafqamats"] = 0x05DA 05B8;
+	//chars["finalkafqamatshebrew"] = 0x05DA 05B8;
+	//chars["finalkafsheva"] = 0x05DA 05B0;
+	//chars["finalkafshevahebrew"] = 0x05DA 05B0;
+	chars["finalmem"] = 0x05DD;
+	chars["finalmemhebrew"] = 0x05DD;
+	chars["finalnun"] = 0x05DF;
+	chars["finalnunhebrew"] = 0x05DF;
+	chars["finalpe"] = 0x05E3;
+	chars["finalpehebrew"] = 0x05E3;
+	chars["finaltsadi"] = 0x05E5;
+	chars["finaltsadihebrew"] = 0x05E5;
+	chars["firsttonechinese"] = 0x02C9;
+	chars["fisheye"] = 0x25C9;
+	chars["Fitacyrillic"] = 0x0472;
+	chars["fitacyrillic"] = 0x0473;
+	chars["five"] = 0x0035;
+	chars["fivearabic"] = 0x0665;
+	chars["fivebengali"] = 0x09EB;
+	chars["fivecircle"] = 0x2464;
+	chars["fivecircleinversesansserif"] = 0x278E;
+	chars["fivedeva"] = 0x096B;
+	chars["fiveeighths"] = 0x215D;
+	chars["fivegujarati"] = 0x0AEB;
+	chars["fivegurmukhi"] = 0x0A6B;
+	chars["fivehackarabic"] = 0x0665;
+	chars["fivehangzhou"] = 0x3025;
+	chars["fiveideographicparen"] = 0x3224;
+	chars["fiveinferior"] = 0x2085;
+	chars["fivemonospace"] = 0xFF15;
+	chars["fiveoldstyle"] = 0xF735;
+	chars["fiveparen"] = 0x2478;
+	chars["fiveperiod"] = 0x248C;
+	chars["fivepersian"] = 0x06F5;
+	chars["Fiveroman"] = 0x2164;
+	chars["fiveroman"] = 0x2174;
+	chars["fivesuperior"] = 0x2075;
+	chars["fivethai"] = 0x0E55;
+	chars["fl"] = 0xFB02;
+	chars["florin"] = 0x0192;
+	chars["Fmonospace"] = 0xFF26;
+	chars["fmonospace"] = 0xFF46;
+	chars["fmsquare"] = 0x3399;
+	chars["fofanthai"] = 0x0E1F;
+	chars["fofathai"] = 0x0E1D;
+	chars["fongmanthai"] = 0x0E4F;
+	chars["forall"] = 0x2200;
+	chars["four"] = 0x0034;
+	chars["fourarabic"] = 0x0664;
+	chars["fourbengali"] = 0x09EA;
+	chars["fourcircle"] = 0x2463;
+	chars["fourcircleinversesansserif"] = 0x278D;
+	chars["fourdeva"] = 0x096A;
+	chars["fourgujarati"] = 0x0AEA;
+	chars["fourgurmukhi"] = 0x0A6A;
+	chars["fourhackarabic"] = 0x0664;
+	chars["fourhangzhou"] = 0x3024;
+	chars["fourideographicparen"] = 0x3223;
+	chars["fourinferior"] = 0x2084;
+	chars["fourmonospace"] = 0xFF14;
+	chars["fournumeratorbengali"] = 0x09F7;
+	chars["fouroldstyle"] = 0xF734;
+	chars["fourparen"] = 0x2477;
+	chars["fourperiod"] = 0x248B;
+	chars["fourpersian"] = 0x06F4;
+	chars["Fourroman"] = 0x2163;
+	chars["fourroman"] = 0x2173;
+	chars["foursuperior"] = 0x2074;
+	chars["fourteencircle"] = 0x246D;
+	chars["fourteenparen"] = 0x2481;
+	chars["fourteenperiod"] = 0x2495;
+	chars["fourthai"] = 0x0E54;
+	chars["fourthtonechinese"] = 0x02CB;
+	chars["fparen"] = 0x24A1;
+	chars["fraction"] = 0x2044;
+	chars["franc"] = 0x20A3;
+	chars["Fsmall"] = 0xF766;
+	chars["G"] = 0x0047;
+	chars["g"] = 0x0067;
+	chars["gabengali"] = 0x0997;
+	chars["Gacute"] = 0x01F4;
+	chars["gacute"] = 0x01F5;
+	chars["gadeva"] = 0x0917;
+	chars["gafarabic"] = 0x06AF;
+	chars["gaffinalarabic"] = 0xFB93;
+	chars["gafinitialarabic"] = 0xFB94;
+	chars["gafmedialarabic"] = 0xFB95;
+	chars["gagujarati"] = 0x0A97;
+	chars["gagurmukhi"] = 0x0A17;
+	chars["gahiragana"] = 0x304C;
+	chars["gakatakana"] = 0x30AC;
+	chars["Gamma"] = 0x0393;
+	chars["gamma"] = 0x03B3;
+	chars["Gammaafrican"] = 0x0194;
+	chars["gammalatinsmall"] = 0x0263;
+	chars["gammasuperior"] = 0x02E0;
+	chars["Gangiacoptic"] = 0x03EA;
+	chars["gangiacoptic"] = 0x03EB;
+	chars["gbopomofo"] = 0x310D;
+	chars["Gbreve"] = 0x011E;
+	chars["gbreve"] = 0x011F;
+	chars["GBsquare"] = 0x3387;
+	chars["Gcaron"] = 0x01E6;
+	chars["gcaron"] = 0x01E7;
+	chars["Gcedilla"] = 0x0122;
+	chars["gcedilla"] = 0x0123;
+	chars["Gcircle"] = 0x24BC;
+	chars["gcircle"] = 0x24D6;
+	chars["Gcircumflex"] = 0x011C;
+	chars["gcircumflex"] = 0x011D;
+	chars["Gcommaaccent"] = 0x0122;
+	chars["gcommaaccent"] = 0x0123;
+	chars["Gdot"] = 0x0120;
+	chars["gdot"] = 0x0121;
+	chars["Gdotaccent"] = 0x0120;
+	chars["gdotaccent"] = 0x0121;
+	chars["Gecyrillic"] = 0x0413;
+	chars["gecyrillic"] = 0x0433;
+	chars["gehiragana"] = 0x3052;
+	chars["gekatakana"] = 0x30B2;
+	chars["geometricallyequal"] = 0x2251;
+	chars["gereshaccenthebrew"] = 0x059C;
+	chars["gereshhebrew"] = 0x05F3;
+	chars["gereshmuqdamhebrew"] = 0x059D;
+	chars["germandbls"] = 0x00DF;
+	chars["gershayimaccenthebrew"] = 0x059E;
+	chars["gershayimhebrew"] = 0x05F4;
+	chars["getamark"] = 0x3013;
+	chars["ghabengali"] = 0x0998;
+	chars["Ghadarmenian"] = 0x0542;
+	chars["ghadarmenian"] = 0x0572;
+	chars["ghadeva"] = 0x0918;
+	chars["ghagujarati"] = 0x0A98;
+	chars["ghagurmukhi"] = 0x0A18;
+	chars["ghainarabic"] = 0x063A;
+	chars["ghainfinalarabic"] = 0xFECE;
+	chars["ghaininitialarabic"] = 0xFECF;
+	chars["ghainmedialarabic"] = 0xFED0;
+	chars["Ghemiddlehookcyrillic"] = 0x0494;
+	chars["ghemiddlehookcyrillic"] = 0x0495;
+	chars["Ghestrokecyrillic"] = 0x0492;
+	chars["ghestrokecyrillic"] = 0x0493;
+	chars["Gheupturncyrillic"] = 0x0490;
+	chars["gheupturncyrillic"] = 0x0491;
+	chars["ghhadeva"] = 0x095A;
+	chars["ghhagurmukhi"] = 0x0A5A;
+	chars["Ghook"] = 0x0193;
+	chars["ghook"] = 0x0260;
+	chars["ghzsquare"] = 0x3393;
+	chars["gihiragana"] = 0x304E;
+	chars["gikatakana"] = 0x30AE;
+	chars["Gimarmenian"] = 0x0533;
+	chars["gimarmenian"] = 0x0563;
+	chars["gimel"] = 0x05D2;
+	chars["gimeldagesh"] = 0xFB32;
+	chars["gimeldageshhebrew"] = 0xFB32;
+	chars["gimelhebrew"] = 0x05D2;
+	chars["Gjecyrillic"] = 0x0403;
+	chars["gjecyrillic"] = 0x0453;
+	chars["glottalinvertedstroke"] = 0x01BE;
+	chars["glottalstop"] = 0x0294;
+	chars["glottalstopinverted"] = 0x0296;
+	chars["glottalstopmod"] = 0x02C0;
+	chars["glottalstopreversed"] = 0x0295;
+	chars["glottalstopreversedmod"] = 0x02C1;
+	chars["glottalstopreversedsuperior"] = 0x02E4;
+	chars["glottalstopstroke"] = 0x02A1;
+	chars["glottalstopstrokereversed"] = 0x02A2;
+	chars["Gmacron"] = 0x1E20;
+	chars["gmacron"] = 0x1E21;
+	chars["Gmonospace"] = 0xFF27;
+	chars["gmonospace"] = 0xFF47;
+	chars["gohiragana"] = 0x3054;
+	chars["gokatakana"] = 0x30B4;
+	chars["gparen"] = 0x24A2;
+	chars["gpasquare"] = 0x33AC;
+	chars["gradient"] = 0x2207;
+	chars["grave"] = 0x0060;
+	chars["Grave"] = 0xF6CE;
+	chars["gravebelowcmb"] = 0x0316;
+	chars["gravecmb"] = 0x0300;
+	chars["gravecomb"] = 0x0300;
+	chars["gravedeva"] = 0x0953;
+	chars["gravelowmod"] = 0x02CE;
+	chars["gravemonospace"] = 0xFF40;
+	chars["Gravesmall"] = 0xF760;
+	chars["gravetonecmb"] = 0x0340;
+	chars["greater"] = 0x003E;
+	chars["greaterdblequal"] = 0x2267;
+	chars["greaterequal"] = 0x2265;
+	chars["greaterequalorless"] = 0x22DB;
+	chars["greaterlessequal"] = 0x22DB;
+	chars["greatermonospace"] = 0xFF1E;
+	chars["greatermuch"] = 0x22D9;
+	chars["greaterorapproxeql"] = 0x2A86;
+	chars["greaterorequivalent"] = 0x2273;
+	chars["greaterorless"] = 0x2277;
+	chars["greaterorsimilar"] = 0x2273;
+	chars["greateroverequal"] = 0x2267;
+	chars["greatersmall"] = 0xFE65;
+	chars["gscript"] = 0x0261;
+	chars["Gsmall"] = 0xF767;
+	chars["Gsmallhook"] = 0x029B;
+	chars["Gstroke"] = 0x01E4;
+	chars["gstroke"] = 0x01E5;
+	chars["guhiragana"] = 0x3050;
+	chars["guillemotleft"] = 0x00AB;
+	chars["guillemotright"] = 0x00BB;
+	chars["guilsinglleft"] = 0x2039;
+	chars["guilsinglright"] = 0x203A;
+	chars["gukatakana"] = 0x30B0;
+	chars["guramusquare"] = 0x3318;
+	chars["gysquare"] = 0x33C9;
+	chars["H"] = 0x0048;
+	chars["h"] = 0x0068;
+	chars["H18533"] = 0x25CF;
+	chars["H18543"] = 0x25AA;
+	chars["H18551"] = 0x25AB;
+	chars["H22073"] = 0x25A1;
+	chars["Haabkhasiancyrillic"] = 0x04A8;
+	chars["haabkhasiancyrillic"] = 0x04A9;
+	chars["haaltonearabic"] = 0x06C1;
+	chars["habengali"] = 0x09B9;
+	chars["Hadescendercyrillic"] = 0x04B2;
+	chars["hadescendercyrillic"] = 0x04B3;
+	chars["hadeva"] = 0x0939;
+	chars["hagujarati"] = 0x0AB9;
+	chars["hagurmukhi"] = 0x0A39;
+	chars["haharabic"] = 0x062D;
+	chars["hahfinalarabic"] = 0xFEA2;
+	chars["hahinitialarabic"] = 0xFEA3;
+	chars["hahiragana"] = 0x306F;
+	chars["hahmedialarabic"] = 0xFEA4;
+	chars["haitusquare"] = 0x332A;
+	chars["hakatakana"] = 0x30CF;
+	chars["hakatakanahalfwidth"] = 0xFF8A;
+	chars["halantgurmukhi"] = 0x0A4D;
+	chars["hamzaarabic"] = 0x0621;
+	//chars["hamzadammaarabic"] = 0x0621 064F;
+	//chars["hamzadammatanarabic"] = 0x0621 064C;
+	//chars["hamzafathaarabic"] = 0x0621 064E;
+	//chars["hamzafathatanarabic"] = 0x0621 064B;
+	//chars["hamzalowarabic"] = 0x0621;
+	//chars["hamzalowkasraarabic"] = 0x0621 0650;
+	//chars["hamzalowkasratanarabic"] = 0x0621 064D;
+	//chars["hamzasukunarabic"] = 0x0621 0652;
+	chars["hangulfiller"] = 0x3164;
+	chars["Hardsigncyrillic"] = 0x042A;
+	chars["hardsigncyrillic"] = 0x044A;
+	chars["harpoonleftbarbup"] = 0x21BC;
+	chars["harpoonrightbarbup"] = 0x21C0;
+	chars["hasquare"] = 0x33CA;
+	chars["hatafpatah"] = 0x05B2;
+	chars["hatafpatah16"] = 0x05B2;
+	chars["hatafpatah23"] = 0x05B2;
+	chars["hatafpatah2f"] = 0x05B2;
+	chars["hatafpatahhebrew"] = 0x05B2;
+	chars["hatafpatahnarrowhebrew"] = 0x05B2;
+	chars["hatafpatahquarterhebrew"] = 0x05B2;
+	chars["hatafpatahwidehebrew"] = 0x05B2;
+	chars["hatafqamats"] = 0x05B3;
+	chars["hatafqamats1b"] = 0x05B3;
+	chars["hatafqamats28"] = 0x05B3;
+	chars["hatafqamats34"] = 0x05B3;
+	chars["hatafqamatshebrew"] = 0x05B3;
+	chars["hatafqamatsnarrowhebrew"] = 0x05B3;
+	chars["hatafqamatsquarterhebrew"] = 0x05B3;
+	chars["hatafqamatswidehebrew"] = 0x05B3;
+	chars["hatafsegol"] = 0x05B1;
+	chars["hatafsegol17"] = 0x05B1;
+	chars["hatafsegol24"] = 0x05B1;
+	chars["hatafsegol30"] = 0x05B1;
+	chars["hatafsegolhebrew"] = 0x05B1;
+	chars["hatafsegolnarrowhebrew"] = 0x05B1;
+	chars["hatafsegolquarterhebrew"] = 0x05B1;
+	chars["hatafsegolwidehebrew"] = 0x05B1;
+	chars["Hbar"] = 0x0126;
+	chars["hbar"] = 0x0127;
+	chars["hbopomofo"] = 0x310F;
+	chars["Hbrevebelow"] = 0x1E2A;
+	chars["hbrevebelow"] = 0x1E2B;
+	chars["Hcedilla"] = 0x1E28;
+	chars["hcedilla"] = 0x1E29;
+	chars["Hcircle"] = 0x24BD;
+	chars["hcircle"] = 0x24D7;
+	chars["Hcircumflex"] = 0x0124;
+	chars["hcircumflex"] = 0x0125;
+	chars["Hdieresis"] = 0x1E26;
+	chars["hdieresis"] = 0x1E27;
+	chars["Hdotaccent"] = 0x1E22;
+	chars["hdotaccent"] = 0x1E23;
+	chars["Hdotbelow"] = 0x1E24;
+	chars["hdotbelow"] = 0x1E25;
+	chars["he"] = 0x05D4;
+	chars["heart"] = 0x2665;
+	chars["heartsuitblack"] = 0x2665;
+	chars["heartsuitwhite"] = 0x2661;
+	chars["hedagesh"] = 0xFB34;
+	chars["hedageshhebrew"] = 0xFB34;
+	chars["hehaltonearabic"] = 0x06C1;
+	chars["heharabic"] = 0x0647;
+	chars["hehebrew"] = 0x05D4;
+	chars["hehfinalaltonearabic"] = 0xFBA7;
+	chars["hehfinalalttwoarabic"] = 0xFEEA;
+	chars["hehfinalarabic"] = 0xFEEA;
+	chars["hehhamzaabovefinalarabic"] = 0xFBA5;
+	chars["hehhamzaaboveisolatedarabic"] = 0xFBA4;
+	chars["hehinitialaltonearabic"] = 0xFBA8;
+	chars["hehinitialarabic"] = 0xFEEB;
+	chars["hehiragana"] = 0x3078;
+	chars["hehmedialaltonearabic"] = 0xFBA9;
+	chars["hehmedialarabic"] = 0xFEEC;
+	chars["heiseierasquare"] = 0x337B;
+	chars["hekatakana"] = 0x30D8;
+	chars["hekatakanahalfwidth"] = 0xFF8D;
+	chars["hekutaarusquare"] = 0x3336;
+	chars["henghook"] = 0x0267;
+	chars["herutusquare"] = 0x3339;
+	chars["het"] = 0x05D7;
+	chars["hethebrew"] = 0x05D7;
+	chars["hhook"] = 0x0266;
+	chars["hhooksuperior"] = 0x02B1;
+	chars["hieuhacirclekorean"] = 0x327B;
+	chars["hieuhaparenkorean"] = 0x321B;
+	chars["hieuhcirclekorean"] = 0x326D;
+	chars["hieuhkorean"] = 0x314E;
+	chars["hieuhparenkorean"] = 0x320D;
+	chars["hihiragana"] = 0x3072;
+	chars["hikatakana"] = 0x30D2;
+	chars["hikatakanahalfwidth"] = 0xFF8B;
+	chars["hiriq"] = 0x05B4;
+	chars["hiriq14"] = 0x05B4;
+	chars["hiriq21"] = 0x05B4;
+	chars["hiriq2d"] = 0x05B4;
+	chars["hiriqhebrew"] = 0x05B4;
+	chars["hiriqnarrowhebrew"] = 0x05B4;
+	chars["hiriqquarterhebrew"] = 0x05B4;
+	chars["hiriqwidehebrew"] = 0x05B4;
+	chars["hlinebelow"] = 0x1E96;
+	chars["Hmonospace"] = 0xFF28;
+	chars["hmonospace"] = 0xFF48;
+	chars["Hoarmenian"] = 0x0540;
+	chars["hoarmenian"] = 0x0570;
+	chars["hohipthai"] = 0x0E2B;
+	chars["hohiragana"] = 0x307B;
+	chars["hokatakana"] = 0x30DB;
+	chars["hokatakanahalfwidth"] = 0xFF8E;
+	chars["holam"] = 0x05B9;
+	chars["holam19"] = 0x05B9;
+	chars["holam26"] = 0x05B9;
+	chars["holam32"] = 0x05B9;
+	chars["holamhebrew"] = 0x05B9;
+	chars["holamnarrowhebrew"] = 0x05B9;
+	chars["holamquarterhebrew"] = 0x05B9;
+	chars["holamwidehebrew"] = 0x05B9;
+	chars["honokhukthai"] = 0x0E2E;
+	chars["hookabovecomb"] = 0x0309;
+	chars["hookcmb"] = 0x0309;
+	chars["hookpalatalizedbelowcmb"] = 0x0321;
+	chars["hookretroflexbelowcmb"] = 0x0322;
+	chars["hoonsquare"] = 0x3342;
+	chars["Horicoptic"] = 0x03E8;
+	chars["horicoptic"] = 0x03E9;
+	chars["horizontalbar"] = 0x2015;
+	chars["horncmb"] = 0x031B;
+	chars["hotsprings"] = 0x2668;
+	chars["house"] = 0x2302;
+	chars["hparen"] = 0x24A3;
+	chars["HPsquare"] = 0x33CB;
+	chars["Hsmall"] = 0xF768;
+	chars["hsuperior"] = 0x02B0;
+	chars["hturned"] = 0x0265;
+	chars["huhiragana"] = 0x3075;
+	chars["huiitosquare"] = 0x3333;
+	chars["hukatakana"] = 0x30D5;
+	chars["hukatakanahalfwidth"] = 0xFF8C;
+	chars["hungarumlaut"] = 0x02DD;
+	chars["Hungarumlaut"] = 0xF6CF;
+	chars["hungarumlautcmb"] = 0x030B;
+	chars["Hungarumlautsmall"] = 0xF6F8;
+	chars["hv"] = 0x0195;
+	chars["hyphen"] = 0x002D;
+	chars["hypheninferior"] = 0xF6E5;
+	chars["hyphenmonospace"] = 0xFF0D;
+	chars["hyphensmall"] = 0xFE63;
+	chars["hyphensuperior"] = 0xF6E6;
+	chars["hyphentwo"] = 0x2010;
+	chars["Hzsquare"] = 0x3390;
+	chars["I"] = 0x0049;
+	chars["i"] = 0x0069;
+	chars["Iacute"] = 0x00CD;
+	chars["iacute"] = 0x00ED;
+	chars["Iacutesmall"] = 0xF7ED;
+	chars["IAcyrillic"] = 0x042F;
+	chars["iacyrillic"] = 0x044F;
+	chars["ibengali"] = 0x0987;
+	chars["ibopomofo"] = 0x3127;
+	chars["Ibreve"] = 0x012C;
+	chars["ibreve"] = 0x012D;
+	chars["Icaron"] = 0x01CF;
+	chars["icaron"] = 0x01D0;
+	chars["Icircle"] = 0x24BE;
+	chars["icircle"] = 0x24D8;
+	chars["Icircumflex"] = 0x00CE;
+	chars["icircumflex"] = 0x00EE;
+	chars["Icircumflexsmall"] = 0xF7EE;
+	chars["Icyrillic"] = 0x0406;
+	chars["icyrillic"] = 0x0456;
+	chars["Idblgrave"] = 0x0208;
+	chars["idblgrave"] = 0x0209;
+	chars["ideographearthcircle"] = 0x328F;
+	chars["ideographfirecircle"] = 0x328B;
+	chars["ideographicallianceparen"] = 0x323F;
+	chars["ideographiccallparen"] = 0x323A;
+	chars["ideographiccentrecircle"] = 0x32A5;
+	chars["ideographicclose"] = 0x3006;
+	chars["ideographiccomma"] = 0x3001;
+	chars["ideographiccommaleft"] = 0xFF64;
+	chars["ideographiccongratulationparen"] = 0x3237;
+	chars["ideographiccorrectcircle"] = 0x32A3;
+	chars["ideographicearthparen"] = 0x322F;
+	chars["ideographicenterpriseparen"] = 0x323D;
+	chars["ideographicexcellentcircle"] = 0x329D;
+	chars["ideographicfestivalparen"] = 0x3240;
+	chars["ideographicfinancialcircle"] = 0x3296;
+	chars["ideographicfinancialparen"] = 0x3236;
+	chars["ideographicfireparen"] = 0x322B;
+	chars["ideographichaveparen"] = 0x3232;
+	chars["ideographichighcircle"] = 0x32A4;
+	chars["ideographiciterationmark"] = 0x3005;
+	chars["ideographiclaborcircle"] = 0x3298;
+	chars["ideographiclaborparen"] = 0x3238;
+	chars["ideographicleftcircle"] = 0x32A7;
+	chars["ideographiclowcircle"] = 0x32A6;
+	chars["ideographicmedicinecircle"] = 0x32A9;
+	chars["ideographicmetalparen"] = 0x322E;
+	chars["ideographicmoonparen"] = 0x322A;
+	chars["ideographicnameparen"] = 0x3234;
+	chars["ideographicperiod"] = 0x3002;
+	chars["ideographicprintcircle"] = 0x329E;
+	chars["ideographicreachparen"] = 0x3243;
+	chars["ideographicrepresentparen"] = 0x3239;
+	chars["ideographicresourceparen"] = 0x323E;
+	chars["ideographicrightcircle"] = 0x32A8;
+	chars["ideographicsecretcircle"] = 0x3299;
+	chars["ideographicselfparen"] = 0x3242;
+	chars["ideographicsocietyparen"] = 0x3233;
+	chars["ideographicspace"] = 0x3000;
+	chars["ideographicspecialparen"] = 0x3235;
+	chars["ideographicstockparen"] = 0x3231;
+	chars["ideographicstudyparen"] = 0x323B;
+	chars["ideographicsunparen"] = 0x3230;
+	chars["ideographicsuperviseparen"] = 0x323C;
+	chars["ideographicwaterparen"] = 0x322C;
+	chars["ideographicwoodparen"] = 0x322D;
+	chars["ideographiczero"] = 0x3007;
+	chars["ideographmetalcircle"] = 0x328E;
+	chars["ideographmooncircle"] = 0x328A;
+	chars["ideographnamecircle"] = 0x3294;
+	chars["ideographsuncircle"] = 0x3290;
+	chars["ideographwatercircle"] = 0x328C;
+	chars["ideographwoodcircle"] = 0x328D;
+	chars["ideva"] = 0x0907;
+	chars["Idieresis"] = 0x00CF;
+	chars["idieresis"] = 0x00EF;
+	chars["Idieresisacute"] = 0x1E2E;
+	chars["idieresisacute"] = 0x1E2F;
+	chars["Idieresiscyrillic"] = 0x04E4;
+	chars["idieresiscyrillic"] = 0x04E5;
+	chars["Idieresissmall"] = 0xF7EF;
+	chars["Idot"] = 0x0130;
+	chars["Idotaccent"] = 0x0130;
+	chars["Idotbelow"] = 0x1ECA;
+	chars["idotbelow"] = 0x1ECB;
+	chars["Iebrevecyrillic"] = 0x04D6;
+	chars["iebrevecyrillic"] = 0x04D7;
+	chars["Iecyrillic"] = 0x0415;
+	chars["iecyrillic"] = 0x0435;
+	chars["ieungacirclekorean"] = 0x3275;
+	chars["ieungaparenkorean"] = 0x3215;
+	chars["ieungcirclekorean"] = 0x3267;
+	chars["ieungkorean"] = 0x3147;
+	chars["ieungparenkorean"] = 0x3207;
+	chars["Ifraktur"] = 0x2111;
+	chars["Igrave"] = 0x00CC;
+	chars["igrave"] = 0x00EC;
+	chars["Igravesmall"] = 0xF7EC;
+	chars["igujarati"] = 0x0A87;
+	chars["igurmukhi"] = 0x0A07;
+	chars["ihiragana"] = 0x3044;
+	chars["Ihookabove"] = 0x1EC8;
+	chars["ihookabove"] = 0x1EC9;
+	chars["iibengali"] = 0x0988;
+	chars["Iicyrillic"] = 0x0418;
+	chars["iicyrillic"] = 0x0438;
+	chars["iideva"] = 0x0908;
+	chars["iigujarati"] = 0x0A88;
+	chars["iigurmukhi"] = 0x0A08;
+	chars["iimatragurmukhi"] = 0x0A40;
+	chars["Iinvertedbreve"] = 0x020A;
+	chars["iinvertedbreve"] = 0x020B;
+	chars["Iishortcyrillic"] = 0x0419;
+	chars["iishortcyrillic"] = 0x0439;
+	chars["iivowelsignbengali"] = 0x09C0;
+	chars["iivowelsigndeva"] = 0x0940;
+	chars["iivowelsigngujarati"] = 0x0AC0;
+	chars["IJ"] = 0x0132;
+	chars["ij"] = 0x0133;
+	chars["ikatakana"] = 0x30A4;
+	chars["ikatakanahalfwidth"] = 0xFF72;
+	chars["ikorean"] = 0x3163;
+	chars["ilde"] = 0x02DC;
+	chars["iluyhebrew"] = 0x05AC;
+	chars["Imacron"] = 0x012A;
+	chars["imacron"] = 0x012B;
+	chars["Imacroncyrillic"] = 0x04E2;
+	chars["imacroncyrillic"] = 0x04E3;
+	chars["imageorapproximatelyequal"] = 0x2253;
+	chars["imatragurmukhi"] = 0x0A3F;
+	chars["Imonospace"] = 0xFF29;
+	chars["imonospace"] = 0xFF49;
+	chars["increment"] = 0x2206;
+	chars["infinity"] = 0x221E;
+	chars["Iniarmenian"] = 0x053B;
+	chars["iniarmenian"] = 0x056B;
+	chars["integral"] = 0x222B;
+	chars["integralbottom"] = 0x2321;
+	chars["integralbt"] = 0x2321;
+	chars["integralex"] = 0xF8F5;
+	chars["integraltop"] = 0x2320;
+	chars["integraltp"] = 0x2320;
+	chars["intersection"] = 0x2229;
+	chars["intisquare"] = 0x3305;
+	chars["invbullet"] = 0x25D8;
+	chars["invcircle"] = 0x25D9;
+	chars["invsmileface"] = 0x263B;
+	chars["Iocyrillic"] = 0x0401;
+	chars["iocyrillic"] = 0x0451;
+	chars["Iogonek"] = 0x012E;
+	chars["iogonek"] = 0x012F;
+	chars["Iota"] = 0x0399;
+	chars["iota"] = 0x03B9;
+	chars["Iotaafrican"] = 0x0196;
+	chars["Iotadieresis"] = 0x03AA;
+	chars["iotadieresis"] = 0x03CA;
+	chars["iotadieresistonos"] = 0x0390;
+	chars["iotalatin"] = 0x0269;
+	chars["Iotatonos"] = 0x038A;
+	chars["iotatonos"] = 0x03AF;
+	chars["iparen"] = 0x24A4;
+	chars["irigurmukhi"] = 0x0A72;
+	chars["Ismall"] = 0xF769;
+	chars["ismallhiragana"] = 0x3043;
+	chars["ismallkatakana"] = 0x30A3;
+	chars["ismallkatakanahalfwidth"] = 0xFF68;
+	chars["issharbengali"] = 0x09FA;
+	chars["Istroke"] = 0x0197;
+	chars["istroke"] = 0x0268;
+	chars["isuperior"] = 0xF6ED;
+	chars["iterationhiragana"] = 0x309D;
+	chars["iterationkatakana"] = 0x30FD;
+	chars["Itilde"] = 0x0128;
+	chars["itilde"] = 0x0129;
+	chars["Itildebelow"] = 0x1E2C;
+	chars["itildebelow"] = 0x1E2D;
+	chars["iubopomofo"] = 0x3129;
+	chars["IUcyrillic"] = 0x042E;
+	chars["iucyrillic"] = 0x044E;
+	chars["ivowelsignbengali"] = 0x09BF;
+	chars["ivowelsigndeva"] = 0x093F;
+	chars["ivowelsigngujarati"] = 0x0ABF;
+	chars["Izhitsacyrillic"] = 0x0474;
+	chars["izhitsacyrillic"] = 0x0475;
+	chars["Izhitsadblgravecyrillic"] = 0x0476;
+	chars["izhitsadblgravecyrillic"] = 0x0477;
+	chars["J"] = 0x004A;
+	chars["j"] = 0x006A;
+	chars["Jaarmenian"] = 0x0541;
+	chars["jaarmenian"] = 0x0571;
+	chars["jabengali"] = 0x099C;
+	chars["jadeva"] = 0x091C;
+	chars["jagujarati"] = 0x0A9C;
+	chars["jagurmukhi"] = 0x0A1C;
+	chars["jbopomofo"] = 0x3110;
+	chars["jcaron"] = 0x01F0;
+	chars["Jcircle"] = 0x24BF;
+	chars["jcircle"] = 0x24D9;
+	chars["Jcircumflex"] = 0x0134;
+	chars["jcircumflex"] = 0x0135;
+	chars["jcrossedtail"] = 0x029D;
+	chars["jdotlessstroke"] = 0x025F;
+	chars["Jecyrillic"] = 0x0408;
+	chars["jecyrillic"] = 0x0458;
+	chars["jeemarabic"] = 0x062C;
+	chars["jeemfinalarabic"] = 0xFE9E;
+	chars["jeeminitialarabic"] = 0xFE9F;
+	chars["jeemmedialarabic"] = 0xFEA0;
+	chars["jeharabic"] = 0x0698;
+	chars["jehfinalarabic"] = 0xFB8B;
+	chars["jhabengali"] = 0x099D;
+	chars["jhadeva"] = 0x091D;
+	chars["jhagujarati"] = 0x0A9D;
+	chars["jhagurmukhi"] = 0x0A1D;
+	chars["Jheharmenian"] = 0x054B;
+	chars["jheharmenian"] = 0x057B;
+	chars["jis"] = 0x3004;
+	chars["Jmonospace"] = 0xFF2A;
+	chars["jmonospace"] = 0xFF4A;
+	chars["jparen"] = 0x24A5;
+	chars["Jsmall"] = 0xF76A;
+	chars["jsuperior"] = 0x02B2;
+	chars["K"] = 0x004B;
+	chars["k"] = 0x006B;
+	chars["Kabashkircyrillic"] = 0x04A0;
+	chars["kabashkircyrillic"] = 0x04A1;
+	chars["kabengali"] = 0x0995;
+	chars["Kacute"] = 0x1E30;
+	chars["kacute"] = 0x1E31;
+	chars["Kacyrillic"] = 0x041A;
+	chars["kacyrillic"] = 0x043A;
+	chars["Kadescendercyrillic"] = 0x049A;
+	chars["kadescendercyrillic"] = 0x049B;
+	chars["kadeva"] = 0x0915;
+	chars["kaf"] = 0x05DB;
+	chars["kafarabic"] = 0x0643;
+	chars["kafdagesh"] = 0xFB3B;
+	chars["kafdageshhebrew"] = 0xFB3B;
+	chars["kaffinalarabic"] = 0xFEDA;
+	chars["kafhebrew"] = 0x05DB;
+	chars["kafinitialarabic"] = 0xFEDB;
+	chars["kafmedialarabic"] = 0xFEDC;
+	chars["kafrafehebrew"] = 0xFB4D;
+	chars["kagujarati"] = 0x0A95;
+	chars["kagurmukhi"] = 0x0A15;
+	chars["kahiragana"] = 0x304B;
+	chars["Kahookcyrillic"] = 0x04C3;
+	chars["kahookcyrillic"] = 0x04C4;
+	chars["kakatakana"] = 0x30AB;
+	chars["kakatakanahalfwidth"] = 0xFF76;
+	chars["Kappa"] = 0x039A;
+	chars["kappa"] = 0x03BA;
+	chars["kappasymbolgreek"] = 0x03F0;
+	chars["kapyeounmieumkorean"] = 0x3171;
+	chars["kapyeounphieuphkorean"] = 0x3184;
+	chars["kapyeounpieupkorean"] = 0x3178;
+	chars["kapyeounssangpieupkorean"] = 0x3179;
+	chars["karoriisquare"] = 0x330D;
+	chars["kashidaautoarabic"] = 0x0640;
+	chars["kashidaautonosidebearingarabic"] = 0x0640;
+	chars["kasmallkatakana"] = 0x30F5;
+	chars["kasquare"] = 0x3384;
+	chars["kasraarabic"] = 0x0650;
+	chars["kasratanarabic"] = 0x064D;
+	chars["Kastrokecyrillic"] = 0x049E;
+	chars["kastrokecyrillic"] = 0x049F;
+	chars["katahiraprolongmarkhalfwidth"] = 0xFF70;
+	chars["Kaverticalstrokecyrillic"] = 0x049C;
+	chars["kaverticalstrokecyrillic"] = 0x049D;
+	chars["kbopomofo"] = 0x310E;
+	chars["KBsquare"] = 0x3385;
+	chars["kcalsquare"] = 0x3389;
+	chars["Kcaron"] = 0x01E8;
+	chars["kcaron"] = 0x01E9;
+	chars["Kcedilla"] = 0x0136;
+	chars["kcedilla"] = 0x0137;
+	chars["Kcircle"] = 0x24C0;
+	chars["kcircle"] = 0x24DA;
+	chars["Kcommaaccent"] = 0x0136;
+	chars["kcommaaccent"] = 0x0137;
+	chars["Kdotbelow"] = 0x1E32;
+	chars["kdotbelow"] = 0x1E33;
+	chars["Keharmenian"] = 0x0554;
+	chars["keharmenian"] = 0x0584;
+	chars["kehiragana"] = 0x3051;
+	chars["kekatakana"] = 0x30B1;
+	chars["kekatakanahalfwidth"] = 0xFF79;
+	chars["Kenarmenian"] = 0x053F;
+	chars["kenarmenian"] = 0x056F;
+	chars["kesmallkatakana"] = 0x30F6;
+	chars["kgreenlandic"] = 0x0138;
+	chars["khabengali"] = 0x0996;
+	chars["Khacyrillic"] = 0x0425;
+	chars["khacyrillic"] = 0x0445;
+	chars["khadeva"] = 0x0916;
+	chars["khagujarati"] = 0x0A96;
+	chars["khagurmukhi"] = 0x0A16;
+	chars["khaharabic"] = 0x062E;
+	chars["khahfinalarabic"] = 0xFEA6;
+	chars["khahinitialarabic"] = 0xFEA7;
+	chars["khahmedialarabic"] = 0xFEA8;
+	chars["Kheicoptic"] = 0x03E6;
+	chars["kheicoptic"] = 0x03E7;
+	chars["khhadeva"] = 0x0959;
+	chars["khhagurmukhi"] = 0x0A59;
+	chars["khieukhacirclekorean"] = 0x3278;
+	chars["khieukhaparenkorean"] = 0x3218;
+	chars["khieukhcirclekorean"] = 0x326A;
+	chars["khieukhkorean"] = 0x314B;
+	chars["khieukhparenkorean"] = 0x320A;
+	chars["khokhaithai"] = 0x0E02;
+	chars["khokhonthai"] = 0x0E05;
+	chars["khokhuatthai"] = 0x0E03;
+	chars["khokhwaithai"] = 0x0E04;
+	chars["khomutthai"] = 0x0E5B;
+	chars["Khook"] = 0x0198;
+	chars["khook"] = 0x0199;
+	chars["khorakhangthai"] = 0x0E06;
+	chars["khzsquare"] = 0x3391;
+	chars["kihiragana"] = 0x304D;
+	chars["kikatakana"] = 0x30AD;
+	chars["kikatakanahalfwidth"] = 0xFF77;
+	chars["kiroguramusquare"] = 0x3315;
+	chars["kiromeetorusquare"] = 0x3316;
+	chars["kirosquare"] = 0x3314;
+	chars["kiyeokacirclekorean"] = 0x326E;
+	chars["kiyeokaparenkorean"] = 0x320E;
+	chars["kiyeokcirclekorean"] = 0x3260;
+	chars["kiyeokkorean"] = 0x3131;
+	chars["kiyeokparenkorean"] = 0x3200;
+	chars["kiyeoksioskorean"] = 0x3133;
+	chars["Kjecyrillic"] = 0x040C;
+	chars["kjecyrillic"] = 0x045C;
+	chars["KKsquare"] = 0x33CD;
+	chars["Klinebelow"] = 0x1E34;
+	chars["klinebelow"] = 0x1E35;
+	chars["klsquare"] = 0x3398;
+	chars["kmcubedsquare"] = 0x33A6;
+	chars["Kmonospace"] = 0xFF2B;
+	chars["kmonospace"] = 0xFF4B;
+	chars["kmsquaredsquare"] = 0x33A2;
+	chars["kohiragana"] = 0x3053;
+	chars["kohmsquare"] = 0x33C0;
+	chars["kokaithai"] = 0x0E01;
+	chars["kokatakana"] = 0x30B3;
+	chars["kokatakanahalfwidth"] = 0xFF7A;
+	chars["kooposquare"] = 0x331E;
+	chars["Koppacyrillic"] = 0x0480;
+	chars["koppacyrillic"] = 0x0481;
+	chars["Koppagreek"] = 0x03DE;
+	chars["koreanstandardsymbol"] = 0x327F;
+	chars["koroniscmb"] = 0x0343;
+	chars["kparen"] = 0x24A6;
+	chars["kpasquare"] = 0x33AA;
+	chars["Ksicyrillic"] = 0x046E;
+	chars["ksicyrillic"] = 0x046F;
+	chars["Ksmall"] = 0xF76B;
+	chars["ktsquare"] = 0x33CF;
+	chars["kturned"] = 0x029E;
+	chars["kuhiragana"] = 0x304F;
+	chars["kukatakana"] = 0x30AF;
+	chars["kukatakanahalfwidth"] = 0xFF78;
+	chars["kvsquare"] = 0x33B8;
+	chars["kwsquare"] = 0x33BE;
+	chars["L"] = 0x004C;
+	chars["l"] = 0x006C;
+	chars["labengali"] = 0x09B2;
+	chars["Lacute"] = 0x0139;
+	chars["lacute"] = 0x013A;
+	chars["ladeva"] = 0x0932;
+	chars["lagujarati"] = 0x0AB2;
+	chars["lagurmukhi"] = 0x0A32;
+	chars["lakkhangyaothai"] = 0x0E45;
+	chars["lamaleffinalarabic"] = 0xFEFC;
+	chars["lamalefhamzaabovefinalarabic"] = 0xFEF8;
+	chars["lamalefhamzaaboveisolatedarabic"] = 0xFEF7;
+	chars["lamalefhamzabelowfinalarabic"] = 0xFEFA;
+	chars["lamalefhamzabelowisolatedarabic"] = 0xFEF9;
+	chars["lamalefisolatedarabic"] = 0xFEFB;
+	chars["lamalefmaddaabovefinalarabic"] = 0xFEF6;
+	chars["lamalefmaddaaboveisolatedarabic"] = 0xFEF5;
+	chars["lamarabic"] = 0x0644;
+	chars["Lambda"] = 0x039B;
+	chars["lambda"] = 0x03BB;
+	chars["lambdastroke"] = 0x019B;
+	chars["lamed"] = 0x05DC;
+	chars["lameddagesh"] = 0xFB3C;
+	chars["lameddageshhebrew"] = 0xFB3C;
+	//chars["lamedhebrew"] = 0x05DC;
+	//chars["lamedholam"] = 0x05DC 05B9;
+	//chars["lamedholamdagesh"] = 0x05DC 05B9 05BC;
+	//chars["lamedholamdageshhebrew"] = 0x05DC 05B9 05BC;
+	//chars["lamedholamhebrew"] = 0x05DC 05B9;
+	//chars["lamfinalarabic"] = 0xFEDE;
+	//chars["lamhahinitialarabic"] = 0xFCCA;
+	//chars["laminitialarabic"] = 0xFEDF;
+	//chars["lamjeeminitialarabic"] = 0xFCC9;
+	//chars["lamkhahinitialarabic"] = 0xFCCB;
+	//chars["lamlamhehisolatedarabic"] = 0xFDF2;
+	//chars["lammedialarabic"] = 0xFEE0;
+	//chars["lammeemhahinitialarabic"] = 0xFD88;
+	//chars["lammeeminitialarabic"] = 0xFCCC;
+	//chars["lammeemjeeminitialarabic"] = 0xFEDF FEE4 FEA0;
+	//chars["lammeemkhahinitialarabic"] = 0xFEDF FEE4 FEA8;
+	chars["largecircle"] = 0x25EF;
+	chars["lbar"] = 0x019A;
+	chars["lbelt"] = 0x026C;
+	chars["lbopomofo"] = 0x310C;
+	chars["Lcaron"] = 0x013D;
+	chars["lcaron"] = 0x013E;
+	chars["Lcedilla"] = 0x013B;
+	chars["lcedilla"] = 0x013C;
+	chars["Lcircle"] = 0x24C1;
+	chars["lcircle"] = 0x24DB;
+	chars["Lcircumflexbelow"] = 0x1E3C;
+	chars["lcircumflexbelow"] = 0x1E3D;
+	chars["Lcommaaccent"] = 0x013B;
+	chars["lcommaaccent"] = 0x013C;
+	chars["Ldot"] = 0x013F;
+	chars["ldot"] = 0x0140;
+	chars["Ldotaccent"] = 0x013F;
+	chars["ldotaccent"] = 0x0140;
+	chars["Ldotbelow"] = 0x1E36;
+	chars["ldotbelow"] = 0x1E37;
+	chars["Ldotbelowmacron"] = 0x1E38;
+	chars["ldotbelowmacron"] = 0x1E39;
+	chars["leftangleabovecmb"] = 0x031A;
+	chars["lefttackbelowcmb"] = 0x0318;
+	chars["less"] = 0x003C;
+	chars["lessdblequal"] = 0x2266;
+	chars["lessequal"] = 0x2264;
+	chars["lessequalorgreater"] = 0x22DA;
+	chars["lessmonospace"] = 0xFF1C;
+	chars["lessmuch"] = 0x22D8;
+	chars["lessorequivalent"] = 0x2272;
+	chars["lessorgreater"] = 0x2276;
+	chars["lessorsimilar"] = 0x2272;
+	chars["lessoverequal"] = 0x2266;
+	chars["lesssmall"] = 0xFE64;
+	chars["lezh"] = 0x026E;
+	chars["lfblock"] = 0x258C;
+	chars["lhookretroflex"] = 0x026D;
+	chars["lira"] = 0x20A4;
+	chars["Liwnarmenian"] = 0x053C;
+	chars["liwnarmenian"] = 0x056C;
+	chars["LJ"] = 0x01C7;
+	chars["Lj"] = 0x01C8;
+	chars["lj"] = 0x01C9;
+	chars["Ljecyrillic"] = 0x0409;
+	chars["ljecyrillic"] = 0x0459;
+	chars["LL"] = 0xF6BF;
+	chars["ll"] = 0xF6C0;
+	chars["lladeva"] = 0x0933;
+	chars["llagujarati"] = 0x0AB3;
+	chars["Llinebelow"] = 0x1E3A;
+	chars["llinebelow"] = 0x1E3B;
+	chars["llladeva"] = 0x0934;
+	chars["llvocalicbengali"] = 0x09E1;
+	chars["llvocalicdeva"] = 0x0961;
+	chars["llvocalicvowelsignbengali"] = 0x09E3;
+	chars["llvocalicvowelsigndeva"] = 0x0963;
+	chars["lmiddletilde"] = 0x026B;
+	chars["Lmonospace"] = 0xFF2C;
+	chars["lmonospace"] = 0xFF4C;
+	chars["lmsquare"] = 0x33D0;
+	chars["lochulathai"] = 0x0E2C;
+	chars["logicaland"] = 0x2227;
+	chars["logicalnot"] = 0x00AC;
+	chars["logicalnotreversed"] = 0x2310;
+	chars["logicalor"] = 0x2228;
+	chars["lolingthai"] = 0x0E25;
+	chars["longs"] = 0x017F;
+	chars["lowlinecenterline"] = 0xFE4E;
+	chars["lowlinecmb"] = 0x0332;
+	chars["lowlinedashed"] = 0xFE4D;
+	chars["lozenge"] = 0x25CA;
+	chars["lparen"] = 0x24A7;
+	chars["Lslash"] = 0x0141;
+	chars["lslash"] = 0x0142;
+	chars["Lslashsmall"] = 0xF6F9;
+	chars["Lsmall"] = 0xF76C;
+	chars["lsquare"] = 0x2113;
+	chars["lsuperior"] = 0xF6EE;
+	chars["ltshade"] = 0x2591;
+	chars["luthai"] = 0x0E26;
+	chars["lvocalicbengali"] = 0x098C;
+	chars["lvocalicdeva"] = 0x090C;
+	chars["lvocalicvowelsignbengali"] = 0x09E2;
+	chars["lvocalicvowelsigndeva"] = 0x0962;
+	chars["lxsquare"] = 0x33D3;
+	chars["M"] = 0x004D;
+	chars["m"] = 0x006D;
+	chars["mabengali"] = 0x09AE;
+	chars["macron"] = 0x00AF;
+	chars["Macron"] = 0xF6D0;
+	chars["macronbelowcmb"] = 0x0331;
+	chars["macroncmb"] = 0x0304;
+	chars["macronlowmod"] = 0x02CD;
+	chars["macronmonospace"] = 0xFFE3;
+	chars["Macronsmall"] = 0xF7AF;
+	chars["Macute"] = 0x1E3E;
+	chars["macute"] = 0x1E3F;
+	chars["madeva"] = 0x092E;
+	chars["magujarati"] = 0x0AAE;
+	chars["magurmukhi"] = 0x0A2E;
+	chars["mahapakhhebrew"] = 0x05A4;
+	chars["mahapakhlefthebrew"] = 0x05A4;
+	chars["mahiragana"] = 0x307E;
+	chars["maichattawalowleftthai"] = 0xF895;
+	chars["maichattawalowrightthai"] = 0xF894;
+	chars["maichattawathai"] = 0x0E4B;
+	chars["maichattawaupperleftthai"] = 0xF893;
+	chars["maieklowleftthai"] = 0xF88C;
+	chars["maieklowrightthai"] = 0xF88B;
+	chars["maiekthai"] = 0x0E48;
+	chars["maiekupperleftthai"] = 0xF88A;
+	chars["maihanakatleftthai"] = 0xF884;
+	chars["maihanakatthai"] = 0x0E31;
+	chars["maitaikhuleftthai"] = 0xF889;
+	chars["maitaikhuthai"] = 0x0E47;
+	chars["maitholowleftthai"] = 0xF88F;
+	chars["maitholowrightthai"] = 0xF88E;
+	chars["maithothai"] = 0x0E49;
+	chars["maithoupperleftthai"] = 0xF88D;
+	chars["maitrilowleftthai"] = 0xF892;
+	chars["maitrilowrightthai"] = 0xF891;
+	chars["maitrithai"] = 0x0E4A;
+	chars["maitriupperleftthai"] = 0xF890;
+	chars["maiyamokthai"] = 0x0E46;
+	chars["makatakana"] = 0x30DE;
+	chars["makatakanahalfwidth"] = 0xFF8F;
+	chars["male"] = 0x2642;
+	chars["mapsto"] = 0x21A6;
+	chars["mansyonsquare"] = 0x3347;
+	chars["maqafhebrew"] = 0x05BE;
+	chars["mars"] = 0x2642;
+	chars["masoracirclehebrew"] = 0x05AF;
+	chars["masquare"] = 0x3383;
+	chars["mbopomofo"] = 0x3107;
+	chars["MBsquare"] = 0x3386;
+	chars["mbsquare"] = 0x33D4;
+	chars["Mcircle"] = 0x24C2;
+	chars["mcircle"] = 0x24DC;
+	chars["mcubedsquare"] = 0x33A5;
+	chars["Mdotaccent"] = 0x1E40;
+	chars["mdotaccent"] = 0x1E41;
+	chars["Mdotbelow"] = 0x1E42;
+	chars["mdotbelow"] = 0x1E43;
+	chars["meemarabic"] = 0x0645;
+	chars["meemfinalarabic"] = 0xFEE2;
+	chars["meeminitialarabic"] = 0xFEE3;
+	chars["meemmedialarabic"] = 0xFEE4;
+	chars["meemmeeminitialarabic"] = 0xFCD1;
+	chars["meemmeemisolatedarabic"] = 0xFC48;
+	chars["meetorusquare"] = 0x334D;
+	chars["mehiragana"] = 0x3081;
+	chars["meizierasquare"] = 0x337E;
+	chars["mekatakana"] = 0x30E1;
+	chars["mekatakanahalfwidth"] = 0xFF92;
+	chars["mem"] = 0x05DE;
+	chars["memdagesh"] = 0xFB3E;
+	chars["memdageshhebrew"] = 0xFB3E;
+	chars["memhebrew"] = 0x05DE;
+	chars["Menarmenian"] = 0x0544;
+	chars["menarmenian"] = 0x0574;
+	chars["merkhahebrew"] = 0x05A5;
+	chars["merkhakefulahebrew"] = 0x05A6;
+	chars["merkhakefulalefthebrew"] = 0x05A6;
+	chars["merkhalefthebrew"] = 0x05A5;
+	chars["mhook"] = 0x0271;
+	chars["mhzsquare"] = 0x3392;
+	chars["middledotkatakanahalfwidth"] = 0xFF65;
+	chars["middot"] = 0x00B7;
+	chars["mieumacirclekorean"] = 0x3272;
+	chars["mieumaparenkorean"] = 0x3212;
+	chars["mieumcirclekorean"] = 0x3264;
+	chars["mieumkorean"] = 0x3141;
+	chars["mieumpansioskorean"] = 0x3170;
+	chars["mieumparenkorean"] = 0x3204;
+	chars["mieumpieupkorean"] = 0x316E;
+	chars["mieumsioskorean"] = 0x316F;
+	chars["mihiragana"] = 0x307F;
+	chars["mikatakana"] = 0x30DF;
+	chars["mikatakanahalfwidth"] = 0xFF90;
+	chars["minus"] = 0x2212;
+	chars["minusbelowcmb"] = 0x0320;
+	chars["minuscircle"] = 0x2296;
+	chars["minusmod"] = 0x02D7;
+	chars["minusplus"] = 0x2213;
+	chars["minute"] = 0x2032;
+	chars["miribaarusquare"] = 0x334A;
+	chars["mirisquare"] = 0x3349;
+	chars["mlonglegturned"] = 0x0270;
+	chars["mlsquare"] = 0x3396;
+	chars["mmcubedsquare"] = 0x33A3;
+	chars["Mmonospace"] = 0xFF2D;
+	chars["mmonospace"] = 0xFF4D;
+	chars["mmsquaredsquare"] = 0x339F;
+	chars["mohiragana"] = 0x3082;
+	chars["mohmsquare"] = 0x33C1;
+	chars["mokatakana"] = 0x30E2;
+	chars["mokatakanahalfwidth"] = 0xFF93;
+	chars["molsquare"] = 0x33D6;
+	chars["momathai"] = 0x0E21;
+	chars["moverssquare"] = 0x33A7;
+	chars["moverssquaredsquare"] = 0x33A8;
+	chars["mparen"] = 0x24A8;
+	chars["mpasquare"] = 0x33AB;
+	chars["Msmall"] = 0xF76D;
+	chars["mssquare"] = 0x33B3;
+	chars["msuperior"] = 0xF6EF;
+	chars["Mturned"] = 0x019C;
+	chars["mturned"] = 0x026F;
+	chars["mu"] = 0x00B5;
+	chars["Mu"] = 0x039C;
+	chars["mu1"] = 0x00B5;
+	chars["muasquare"] = 0x3382;
+	chars["muchgreater"] = 0x226B;
+	chars["muchless"] = 0x226A;
+	chars["mufsquare"] = 0x338C;
+	chars["mugreek"] = 0x03BC;
+	chars["mugsquare"] = 0x338D;
+	chars["muhiragana"] = 0x3080;
+	chars["mukatakana"] = 0x30E0;
+	chars["mukatakanahalfwidth"] = 0xFF91;
+	chars["mulsquare"] = 0x3395;
+	chars["multiply"] = 0x00D7;
+	chars["mumsquare"] = 0x339B;
+	chars["munahhebrew"] = 0x05A3;
+	chars["munahlefthebrew"] = 0x05A3;
+	chars["musicalnote"] = 0x266A;
+	chars["musicalnotedbl"] = 0x266B;
+	chars["musicflatsign"] = 0x266D;
+	chars["musicsharpsign"] = 0x266F;
+	chars["mussquare"] = 0x33B2;
+	chars["muvsquare"] = 0x33B6;
+	chars["muwsquare"] = 0x33BC;
+	chars["mvmegasquare"] = 0x33B9;
+	chars["mvsquare"] = 0x33B7;
+	chars["mwmegasquare"] = 0x33BF;
+	chars["mwsquare"] = 0x33BD;
+	chars["N"] = 0x004E;
+	chars["n"] = 0x006E;
+	chars["nabengali"] = 0x09A8;
+	chars["nabla"] = 0x2207;
+	chars["Nacute"] = 0x0143;
+	chars["nacute"] = 0x0144;
+	chars["nadeva"] = 0x0928;
+	chars["nagujarati"] = 0x0AA8;
+	chars["nagurmukhi"] = 0x0A28;
+	chars["nahiragana"] = 0x306A;
+	chars["nakatakana"] = 0x30CA;
+	chars["nakatakanahalfwidth"] = 0xFF85;
+	chars["napostrophe"] = 0x0149;
+	chars["nasquare"] = 0x3381;
+	chars["nbopomofo"] = 0x310B;
+	chars["nbspace"] = 0x00A0;
+	chars["Ncaron"] = 0x0147;
+	chars["ncaron"] = 0x0148;
+	chars["Ncedilla"] = 0x0145;
+	chars["ncedilla"] = 0x0146;
+	chars["Ncircle"] = 0x24C3;
+	chars["ncircle"] = 0x24DD;
+	chars["Ncircumflexbelow"] = 0x1E4A;
+	chars["ncircumflexbelow"] = 0x1E4B;
+	chars["Ncommaaccent"] = 0x0145;
+	chars["ncommaaccent"] = 0x0146;
+	chars["Ndotaccent"] = 0x1E44;
+	chars["ndotaccent"] = 0x1E45;
+	chars["Ndotbelow"] = 0x1E46;
+	chars["ndotbelow"] = 0x1E47;
+	chars["negationslash"] = 0x2AEE;
+	chars["nehiragana"] = 0x306D;
+	chars["nekatakana"] = 0x30CD;
+	chars["nekatakanahalfwidth"] = 0xFF88;
+	chars["newsheqelsign"] = 0x20AA;
+	chars["nfsquare"] = 0x338B;
+	chars["ngabengali"] = 0x0999;
+	chars["ngadeva"] = 0x0919;
+	chars["ngagujarati"] = 0x0A99;
+	chars["ngagurmukhi"] = 0x0A19;
+	chars["ngonguthai"] = 0x0E07;
+	chars["nhiragana"] = 0x3093;
+	chars["Nhookleft"] = 0x019D;
+	chars["nhookleft"] = 0x0272;
+	chars["nhookretroflex"] = 0x0273;
+	chars["nieunacirclekorean"] = 0x326F;
+	chars["nieunaparenkorean"] = 0x320F;
+	chars["nieuncieuckorean"] = 0x3135;
+	chars["nieuncirclekorean"] = 0x3261;
+	chars["nieunhieuhkorean"] = 0x3136;
+	chars["nieunkorean"] = 0x3134;
+	chars["nieunpansioskorean"] = 0x3168;
+	chars["nieunparenkorean"] = 0x3201;
+	chars["nieunsioskorean"] = 0x3167;
+	chars["nieuntikeutkorean"] = 0x3166;
+	chars["nihiragana"] = 0x306B;
+	chars["nikatakana"] = 0x30CB;
+	chars["nikatakanahalfwidth"] = 0xFF86;
+	chars["nikhahitleftthai"] = 0xF899;
+	chars["nikhahitthai"] = 0x0E4D;
+	chars["nine"] = 0x0039;
+	chars["ninearabic"] = 0x0669;
+	chars["ninebengali"] = 0x09EF;
+	chars["ninecircle"] = 0x2468;
+	chars["ninecircleinversesansserif"] = 0x2792;
+	chars["ninedeva"] = 0x096F;
+	chars["ninegujarati"] = 0x0AEF;
+	chars["ninegurmukhi"] = 0x0A6F;
+	chars["ninehackarabic"] = 0x0669;
+	chars["ninehangzhou"] = 0x3029;
+	chars["nineideographicparen"] = 0x3228;
+	chars["nineinferior"] = 0x2089;
+	chars["ninemonospace"] = 0xFF19;
+	chars["nineoldstyle"] = 0xF739;
+	chars["nineparen"] = 0x247C;
+	chars["nineperiod"] = 0x2490;
+	chars["ninepersian"] = 0x06F9;
+	chars["Nineroman"] = 0x2168;
+	chars["nineroman"] = 0x2178;
+	chars["ninesuperior"] = 0x2079;
+	chars["nineteencircle"] = 0x2472;
+	chars["nineteenparen"] = 0x2486;
+	chars["nineteenperiod"] = 0x249A;
+	chars["ninethai"] = 0x0E59;
+	chars["NJ"] = 0x01CA;
+	chars["Nj"] = 0x01CB;
+	chars["nj"] = 0x01CC;
+	chars["Njecyrillic"] = 0x040A;
+	chars["njecyrillic"] = 0x045A;
+	chars["nkatakana"] = 0x30F3;
+	chars["nkatakanahalfwidth"] = 0xFF9D;
+	chars["nlegrightlong"] = 0x019E;
+	chars["Nlinebelow"] = 0x1E48;
+	chars["nlinebelow"] = 0x1E49;
+	chars["Nmonospace"] = 0xFF2E;
+	chars["nmonospace"] = 0xFF4E;
+	chars["nmsquare"] = 0x339A;
+	chars["nnabengali"] = 0x09A3;
+	chars["nnadeva"] = 0x0923;
+	chars["nnagujarati"] = 0x0AA3;
+	chars["nnagurmukhi"] = 0x0A23;
+	chars["nnnadeva"] = 0x0929;
+	chars["nohiragana"] = 0x306E;
+	chars["nokatakana"] = 0x30CE;
+	chars["nokatakanahalfwidth"] = 0xFF89;
+	chars["nonbreakingspace"] = 0x00A0;
+	chars["nonenthai"] = 0x0E13;
+	chars["nonuthai"] = 0x0E19;
+	chars["noonarabic"] = 0x0646;
+	chars["noonfinalarabic"] = 0xFEE6;
+	chars["noonghunnaarabic"] = 0x06BA;
+	chars["noonghunnafinalarabic"] = 0xFB9F;
+	//chars["noonhehinitialarabic"] = 0xFEE7 FEEC;
+	//chars["nooninitialarabic"] = 0xFEE7;
+	//chars["noonjeeminitialarabic"] = 0xFCD2;
+	//chars["noonjeemisolatedarabic"] = 0xFC4B;
+	//chars["noonmedialarabic"] = 0xFEE8;
+	//chars["noonmeeminitialarabic"] = 0xFCD5;
+	//chars["noonmeemisolatedarabic"] = 0xFC4E;
+	//chars["noonnoonfinalarabic"] = 0xFC8D;
+	chars["notcontains"] = 0x220C;
+	chars["notelement"] = 0x2209;
+	chars["notelementof"] = 0x2209;
+	chars["notequal"] = 0x2260;
+	chars["notgreater"] = 0x226F;
+	chars["notgreaternorequal"] = 0x2271;
+	chars["notgreaternorless"] = 0x2279;
+	chars["notidentical"] = 0x2262;
+	chars["notless"] = 0x226E;
+	chars["notlessnorequal"] = 0x2270;
+	chars["notparallel"] = 0x2226;
+	chars["notprecedes"] = 0x2280;
+	chars["notsubset"] = 0x2284;
+	chars["notsucceeds"] = 0x2281;
+	chars["notsuperset"] = 0x2285;
+	chars["Nowarmenian"] = 0x0546;
+	chars["nowarmenian"] = 0x0576;
+	chars["nparen"] = 0x24A9;
+	chars["Nsmall"] = 0xF76E;
+	chars["nssquare"] = 0x33B1;
+	chars["nsuperior"] = 0x207F;
+	chars["Ntilde"] = 0x00D1;
+	chars["ntilde"] = 0x00F1;
+	chars["Ntildesmall"] = 0xF7F1;
+	chars["Nu"] = 0x039D;
+	chars["nu"] = 0x03BD;
+	chars["nuhiragana"] = 0x306C;
+	chars["nukatakana"] = 0x30CC;
+	chars["nukatakanahalfwidth"] = 0xFF87;
+	chars["nuktabengali"] = 0x09BC;
+	chars["nuktadeva"] = 0x093C;
+	chars["nuktagujarati"] = 0x0ABC;
+	chars["nuktagurmukhi"] = 0x0A3C;
+	chars["numbersign"] = 0x0023;
+	chars["numbersignmonospace"] = 0xFF03;
+	chars["numbersignsmall"] = 0xFE5F;
+	chars["numeralsigngreek"] = 0x0374;
+	chars["numeralsignlowergreek"] = 0x0375;
+	chars["numero"] = 0x2116;
+	chars["nun"] = 0x05E0;
+	chars["nundagesh"] = 0xFB40;
+	chars["nundageshhebrew"] = 0xFB40;
+	chars["nunhebrew"] = 0x05E0;
+	chars["nvsquare"] = 0x33B5;
+	chars["nwsquare"] = 0x33BB;
+	chars["nyabengali"] = 0x099E;
+	chars["nyadeva"] = 0x091E;
+	chars["nyagujarati"] = 0x0A9E;
+	chars["nyagurmukhi"] = 0x0A1E;
+	chars["O"] = 0x004F;
+	chars["o"] = 0x006F;
+	chars["Oacute"] = 0x00D3;
+	chars["oacute"] = 0x00F3;
+	chars["Oacutesmall"] = 0xF7F3;
+	chars["oangthai"] = 0x0E2D;
+	chars["obarred"] = 0x0275;
+	chars["Obarredcyrillic"] = 0x04E8;
+	chars["obarredcyrillic"] = 0x04E9;
+	chars["Obarreddieresiscyrillic"] = 0x04EA;
+	chars["obarreddieresiscyrillic"] = 0x04EB;
+	chars["obengali"] = 0x0993;
+	chars["obopomofo"] = 0x311B;
+	chars["Obreve"] = 0x014E;
+	chars["obreve"] = 0x014F;
+	chars["ocandradeva"] = 0x0911;
+	chars["ocandragujarati"] = 0x0A91;
+	chars["ocandravowelsigndeva"] = 0x0949;
+	chars["ocandravowelsigngujarati"] = 0x0AC9;
+	chars["Ocaron"] = 0x01D1;
+	chars["ocaron"] = 0x01D2;
+	chars["Ocenteredtilde"] = 0x019F;
+	chars["Ocircle"] = 0x24C4;
+	chars["ocircle"] = 0x24DE;
+	chars["Ocircumflex"] = 0x00D4;
+	chars["ocircumflex"] = 0x00F4;
+	chars["Ocircumflexacute"] = 0x1ED0;
+	chars["ocircumflexacute"] = 0x1ED1;
+	chars["Ocircumflexdotbelow"] = 0x1ED8;
+	chars["ocircumflexdotbelow"] = 0x1ED9;
+	chars["Ocircumflexgrave"] = 0x1ED2;
+	chars["ocircumflexgrave"] = 0x1ED3;
+	chars["Ocircumflexhookabove"] = 0x1ED4;
+	chars["ocircumflexhookabove"] = 0x1ED5;
+	chars["Ocircumflexsmall"] = 0xF7F4;
+	chars["Ocircumflextilde"] = 0x1ED6;
+	chars["ocircumflextilde"] = 0x1ED7;
+	chars["Ocyrillic"] = 0x041E;
+	chars["ocyrillic"] = 0x043E;
+	chars["Odblacute"] = 0x0150;
+	chars["odblacute"] = 0x0151;
+	chars["Odblgrave"] = 0x020C;
+	chars["odblgrave"] = 0x020D;
+	chars["odeva"] = 0x0913;
+	chars["Odieresis"] = 0x00D6;
+	chars["odieresis"] = 0x00F6;
+	chars["Odieresiscyrillic"] = 0x04E6;
+	chars["odieresiscyrillic"] = 0x04E7;
+	chars["Odieresissmall"] = 0xF7F6;
+	chars["Odotbelow"] = 0x1ECC;
+	chars["odotbelow"] = 0x1ECD;
+	chars["OE"] = 0x0152;
+	chars["oe"] = 0x0153;
+	chars["oekorean"] = 0x315A;
+	chars["OEsmall"] = 0xF6FA;
+	chars["ogonek"] = 0x02DB;
+	chars["ogonekcmb"] = 0x0328;
+	chars["Ogoneksmall"] = 0xF6FB;
+	chars["Ograve"] = 0x00D2;
+	chars["ograve"] = 0x00F2;
+	chars["Ogravesmall"] = 0xF7F2;
+	chars["ogujarati"] = 0x0A93;
+	chars["Oharmenian"] = 0x0555;
+	chars["oharmenian"] = 0x0585;
+	chars["ohiragana"] = 0x304A;
+	chars["Ohm"] = 0x2126;
+	chars["Ohookabove"] = 0x1ECE;
+	chars["ohookabove"] = 0x1ECF;
+	chars["Ohorn"] = 0x01A0;
+	chars["ohorn"] = 0x01A1;
+	chars["Ohornacute"] = 0x1EDA;
+	chars["ohornacute"] = 0x1EDB;
+	chars["Ohorndotbelow"] = 0x1EE2;
+	chars["ohorndotbelow"] = 0x1EE3;
+	chars["Ohorngrave"] = 0x1EDC;
+	chars["ohorngrave"] = 0x1EDD;
+	chars["Ohornhookabove"] = 0x1EDE;
+	chars["ohornhookabove"] = 0x1EDF;
+	chars["Ohorntilde"] = 0x1EE0;
+	chars["ohorntilde"] = 0x1EE1;
+	chars["Ohungarumlaut"] = 0x0150;
+	chars["ohungarumlaut"] = 0x0151;
+	chars["Oi"] = 0x01A2;
+	chars["oi"] = 0x01A3;
+	chars["Oinvertedbreve"] = 0x020E;
+	chars["oinvertedbreve"] = 0x020F;
+	chars["okatakana"] = 0x30AA;
+	chars["okatakanahalfwidth"] = 0xFF75;
+	chars["okorean"] = 0x3157;
+	chars["olehebrew"] = 0x05AB;
+	chars["Omacron"] = 0x014C;
+	chars["omacron"] = 0x014D;
+	chars["Omacronacute"] = 0x1E52;
+	chars["omacronacute"] = 0x1E53;
+	chars["Omacrongrave"] = 0x1E50;
+	chars["omacrongrave"] = 0x1E51;
+	chars["omdeva"] = 0x0950;
+	chars["omega"] = 0x03C9;
+	chars["Omega"] = 0x2126;
+	chars["omega1"] = 0x03D6;
+	chars["Omegacyrillic"] = 0x0460;
+	chars["omegacyrillic"] = 0x0461;
+	chars["Omegagreek"] = 0x03A9;
+	chars["omegalatinclosed"] = 0x0277;
+	chars["Omegaroundcyrillic"] = 0x047A;
+	chars["omegaroundcyrillic"] = 0x047B;
+	chars["Omegatitlocyrillic"] = 0x047C;
+	chars["omegatitlocyrillic"] = 0x047D;
+	chars["Omegatonos"] = 0x038F;
+	chars["omegatonos"] = 0x03CE;
+	chars["omgujarati"] = 0x0AD0;
+	chars["Omicron"] = 0x039F;
+	chars["omicron"] = 0x03BF;
+	chars["Omicrontonos"] = 0x038C;
+	chars["omicrontonos"] = 0x03CC;
+	chars["Omonospace"] = 0xFF2F;
+	chars["omonospace"] = 0xFF4F;
+	chars["one"] = 0x0031;
+	chars["onearabic"] = 0x0661;
+	chars["onebengali"] = 0x09E7;
+	chars["onecircle"] = 0x2460;
+	chars["onecircleinversesansserif"] = 0x278A;
+	chars["onedeva"] = 0x0967;
+	chars["onedotenleader"] = 0x2024;
+	chars["oneeighth"] = 0x215B;
+	chars["onefitted"] = 0xF6DC;
+	chars["onegujarati"] = 0x0AE7;
+	chars["onegurmukhi"] = 0x0A67;
+	chars["onehackarabic"] = 0x0661;
+	chars["onehalf"] = 0x00BD;
+	chars["onehangzhou"] = 0x3021;
+	chars["oneideographicparen"] = 0x3220;
+	chars["oneinferior"] = 0x2081;
+	chars["onemonospace"] = 0xFF11;
+	chars["onenumeratorbengali"] = 0x09F4;
+	chars["oneoldstyle"] = 0xF731;
+	chars["oneparen"] = 0x2474;
+	chars["oneperiod"] = 0x2488;
+	chars["onepersian"] = 0x06F1;
+	chars["onequarter"] = 0x00BC;
+	chars["Oneroman"] = 0x2160;
+	chars["oneroman"] = 0x2170;
+	chars["onesuperior"] = 0x00B9;
+	chars["onethai"] = 0x0E51;
+	chars["onethird"] = 0x2153;
+	chars["Oogonek"] = 0x01EA;
+	chars["oogonek"] = 0x01EB;
+	chars["Oogonekmacron"] = 0x01EC;
+	chars["oogonekmacron"] = 0x01ED;
+	chars["oogurmukhi"] = 0x0A13;
+	chars["oomatragurmukhi"] = 0x0A4B;
+	chars["Oopen"] = 0x0186;
+	chars["oopen"] = 0x0254;
+	chars["oparen"] = 0x24AA;
+	chars["openbullet"] = 0x25E6;
+	chars["option"] = 0x2325;
+	chars["ordfeminine"] = 0x00AA;
+	chars["ordmasculine"] = 0x00BA;
+	chars["orthogonal"] = 0x221F;
+	chars["oshortdeva"] = 0x0912;
+	chars["oshortvowelsigndeva"] = 0x094A;
+	chars["Oslash"] = 0x00D8;
+	chars["oslash"] = 0x00F8;
+	chars["Oslashacute"] = 0x01FE;
+	chars["oslashacute"] = 0x01FF;
+	chars["Oslashsmall"] = 0xF7F8;
+	chars["Osmall"] = 0xF76F;
+	chars["osmallhiragana"] = 0x3049;
+	chars["osmallkatakana"] = 0x30A9;
+	chars["osmallkatakanahalfwidth"] = 0xFF6B;
+	chars["Ostrokeacute"] = 0x01FE;
+	chars["ostrokeacute"] = 0x01FF;
+	chars["osuperior"] = 0xF6F0;
+	chars["Otcyrillic"] = 0x047E;
+	chars["otcyrillic"] = 0x047F;
+	chars["Otilde"] = 0x00D5;
+	chars["otilde"] = 0x00F5;
+	chars["Otildeacute"] = 0x1E4C;
+	chars["otildeacute"] = 0x1E4D;
+	chars["Otildedieresis"] = 0x1E4E;
+	chars["otildedieresis"] = 0x1E4F;
+	chars["Otildesmall"] = 0xF7F5;
+	chars["oubopomofo"] = 0x3121;
+	chars["overline"] = 0x203E;
+	chars["overlinecenterline"] = 0xFE4A;
+	chars["overlinecmb"] = 0x0305;
+	chars["overlinedashed"] = 0xFE49;
+	chars["overlinedblwavy"] = 0xFE4C;
+	chars["overlinewavy"] = 0xFE4B;
+	chars["overscore"] = 0x00AF;
+	chars["ovowelsignbengali"] = 0x09CB;
+	chars["ovowelsigndeva"] = 0x094B;
+	chars["ovowelsigngujarati"] = 0x0ACB;
+	chars["P"] = 0x0050;
+	chars["p"] = 0x0070;
+	chars["paampssquare"] = 0x3380;
+	chars["paasentosquare"] = 0x332B;
+	chars["pabengali"] = 0x09AA;
+	chars["Pacute"] = 0x1E54;
+	chars["pacute"] = 0x1E55;
+	chars["padeva"] = 0x092A;
+	chars["pagedown"] = 0x21DF;
+	chars["pageup"] = 0x21DE;
+	chars["pagujarati"] = 0x0AAA;
+	chars["pagurmukhi"] = 0x0A2A;
+	chars["pahiragana"] = 0x3071;
+	chars["paiyannoithai"] = 0x0E2F;
+	chars["pakatakana"] = 0x30D1;
+	chars["palatalizationcyrilliccmb"] = 0x0484;
+	chars["palochkacyrillic"] = 0x04C0;
+	chars["pansioskorean"] = 0x317F;
+	chars["paragraph"] = 0x00B6;
+	chars["parallel"] = 0x2225;
+	chars["parenleft"] = 0x0028;
+	chars["parenleftaltonearabic"] = 0xFD3E;
+	chars["parenleftbt"] = 0x239D;
+	chars["parenleftex"] = 0x239C;
+	chars["parenleftinferior"] = 0x208D;
+	chars["parenleftmonospace"] = 0xFF08;
+	chars["parenleftsmall"] = 0xFE59;
+	chars["parenleftsuperior"] = 0x207D;
+	chars["parenlefttp"] = 0x239B;
+	chars["parenleftvertical"] = 0xFE35;
+	chars["parenright"] = 0x0029;
+	chars["parenrightaltonearabic"] = 0xFD3F;
+	chars["parenrightbt"] = 0x23A0;
+	chars["parenrightex"] = 0x239F;
+	chars["parenrightinferior"] = 0x208E;
+	chars["parenrightmonospace"] = 0xFF09;
+	chars["parenrightsmall"] = 0xFE5A;
+	chars["parenrightsuperior"] = 0x207E;
+	chars["parenrighttp"] = 0x239e;
+	chars["parenrightvertical"] = 0xFE36;
+	chars["partialdiff"] = 0x2202;
+	chars["paseqhebrew"] = 0x05C0;
+	chars["pashtahebrew"] = 0x0599;
+	chars["pasquare"] = 0x33A9;
+	chars["patah"] = 0x05B7;
+	chars["patah11"] = 0x05B7;
+	chars["patah1d"] = 0x05B7;
+	chars["patah2a"] = 0x05B7;
+	chars["patahhebrew"] = 0x05B7;
+	chars["patahnarrowhebrew"] = 0x05B7;
+	chars["patahquarterhebrew"] = 0x05B7;
+	chars["patahwidehebrew"] = 0x05B7;
+	chars["pazerhebrew"] = 0x05A1;
+	chars["pbopomofo"] = 0x3106;
+	chars["Pcircle"] = 0x24C5;
+	chars["pcircle"] = 0x24DF;
+	chars["Pdotaccent"] = 0x1E56;
+	chars["pdotaccent"] = 0x1E57;
+	chars["pe"] = 0x05E4;
+	chars["Pecyrillic"] = 0x041F;
+	chars["pecyrillic"] = 0x043F;
+	chars["pedagesh"] = 0xFB44;
+	chars["pedageshhebrew"] = 0xFB44;
+	chars["peezisquare"] = 0x333B;
+	chars["pefinaldageshhebrew"] = 0xFB43;
+	chars["peharabic"] = 0x067E;
+	chars["Peharmenian"] = 0x054A;
+	chars["peharmenian"] = 0x057A;
+	chars["pehebrew"] = 0x05E4;
+	chars["pehfinalarabic"] = 0xFB57;
+	chars["pehinitialarabic"] = 0xFB58;
+	chars["pehiragana"] = 0x307A;
+	chars["pehmedialarabic"] = 0xFB59;
+	chars["pekatakana"] = 0x30DA;
+	chars["Pemiddlehookcyrillic"] = 0x04A6;
+	chars["pemiddlehookcyrillic"] = 0x04A7;
+	chars["perafehebrew"] = 0xFB4E;
+	chars["percent"] = 0x0025;
+	chars["percentarabic"] = 0x066A;
+	chars["percentmonospace"] = 0xFF05;
+	chars["percentsmall"] = 0xFE6A;
+	chars["period"] = 0x002E;
+	chars["periodarmenian"] = 0x0589;
+	chars["periodcentered"] = 0x00B7;
+	chars["periodhalfwidth"] = 0xFF61;
+	chars["periodinferior"] = 0xF6E7;
+	chars["periodmonospace"] = 0xFF0E;
+	chars["periodsmall"] = 0xFE52;
+	chars["periodsuperior"] = 0xF6E8;
+	chars["perispomenigreekcmb"] = 0x0342;
+	chars["perpendicular"] = 0x22A5;
+	chars["perthousand"] = 0x2030;
+	chars["peseta"] = 0x20A7;
+	chars["pfsquare"] = 0x338A;
+	chars["phabengali"] = 0x09AB;
+	chars["phadeva"] = 0x092B;
+	chars["phagujarati"] = 0x0AAB;
+	chars["phagurmukhi"] = 0x0A2B;
+	chars["Phi"] = 0x03A6;
+	chars["phi"] = 0x03C6;
+	chars["phi1"] = 0x03D5;
+	chars["phieuphacirclekorean"] = 0x327A;
+	chars["phieuphaparenkorean"] = 0x321A;
+	chars["phieuphcirclekorean"] = 0x326C;
+	chars["phieuphkorean"] = 0x314D;
+	chars["phieuphparenkorean"] = 0x320C;
+	chars["philatin"] = 0x0278;
+	chars["phinthuthai"] = 0x0E3A;
+	chars["phisymbolgreek"] = 0x03D5;
+	chars["Phook"] = 0x01A4;
+	chars["phook"] = 0x01A5;
+	chars["phophanthai"] = 0x0E1E;
+	chars["phophungthai"] = 0x0E1C;
+	chars["phosamphaothai"] = 0x0E20;
+	chars["Pi"] = 0x03A0;
+	chars["pi"] = 0x03C0;
+	chars["pieupacirclekorean"] = 0x3273;
+	chars["pieupaparenkorean"] = 0x3213;
+	chars["pieupcieuckorean"] = 0x3176;
+	chars["pieupcirclekorean"] = 0x3265;
+	chars["pieupkiyeokkorean"] = 0x3172;
+	chars["pieupkorean"] = 0x3142;
+	chars["pieupparenkorean"] = 0x3205;
+	chars["pieupsioskiyeokkorean"] = 0x3174;
+	chars["pieupsioskorean"] = 0x3144;
+	chars["pieupsiostikeutkorean"] = 0x3175;
+	chars["pieupthieuthkorean"] = 0x3177;
+	chars["pieuptikeutkorean"] = 0x3173;
+	chars["pihiragana"] = 0x3074;
+	chars["pikatakana"] = 0x30D4;
+	chars["pisymbolgreek"] = 0x03D6;
+	chars["Piwrarmenian"] = 0x0553;
+	chars["piwrarmenian"] = 0x0583;
+	chars["planckover2pi"] = 0x210F; // slanted bar.
+	chars["planckover2pi1"] = 0x210F; // straight bar.
+	chars["plus"] = 0x002B;
+	chars["plusbelowcmb"] = 0x031F;
+	chars["pluscircle"] = 0x2295;
+	chars["plusminus"] = 0x00B1;
+	chars["plusmod"] = 0x02D6;
+	chars["plusmonospace"] = 0xFF0B;
+	chars["plussmall"] = 0xFE62;
+	chars["plussuperior"] = 0x207A;
+	chars["Pmonospace"] = 0xFF30;
+	chars["pmonospace"] = 0xFF50;
+	chars["pmsquare"] = 0x33D8;
+	chars["pohiragana"] = 0x307D;
+	chars["pointingindexdownwhite"] = 0x261F;
+	chars["pointingindexleftwhite"] = 0x261C;
+	chars["pointingindexrightwhite"] = 0x261E;
+	chars["pointingindexupwhite"] = 0x261D;
+	chars["pokatakana"] = 0x30DD;
+	chars["poplathai"] = 0x0E1B;
+	chars["postalmark"] = 0x3012;
+	chars["postalmarkface"] = 0x3020;
+	chars["pparen"] = 0x24AB;
+	chars["precedes"] = 0x227A;
+	chars["prescription"] = 0x211E;
+	chars["primemod"] = 0x02B9;
+	chars["primereversed"] = 0x2035;
+	chars["product"] = 0x220F;
+	chars["producttext"] = 0x220F; // ?
+	chars["projective"] = 0x2305;
+	chars["prolongedkana"] = 0x30FC;
+	chars["propellor"] = 0x2318;
+	chars["propersubset"] = 0x2282;
+	chars["propersuperset"] = 0x2283;
+	chars["proportion"] = 0x2237;
+	chars["proportional"] = 0x221D;
+	chars["Psi"] = 0x03A8;
+	chars["psi"] = 0x03C8;
+	chars["Psicyrillic"] = 0x0470;
+	chars["psicyrillic"] = 0x0471;
+	chars["psilipneumatacyrilliccmb"] = 0x0486;
+	chars["Psmall"] = 0xF770;
+	chars["pssquare"] = 0x33B0;
+	chars["puhiragana"] = 0x3077;
+	chars["pukatakana"] = 0x30D7;
+	chars["pvsquare"] = 0x33B4;
+	chars["pwsquare"] = 0x33BA;
+	chars["Q"] = 0x0051;
+	chars["q"] = 0x0071;
+	chars["qadeva"] = 0x0958;
+	chars["qadmahebrew"] = 0x05A8;
+	chars["qafarabic"] = 0x0642;
+	chars["qaffinalarabic"] = 0xFED6;
+	chars["qafinitialarabic"] = 0xFED7;
+	chars["qafmedialarabic"] = 0xFED8;
+	chars["qamats"] = 0x05B8;
+	chars["qamats10"] = 0x05B8;
+	chars["qamats1a"] = 0x05B8;
+	chars["qamats1c"] = 0x05B8;
+	chars["qamats27"] = 0x05B8;
+	chars["qamats29"] = 0x05B8;
+	chars["qamats33"] = 0x05B8;
+	chars["qamatsde"] = 0x05B8;
+	chars["qamatshebrew"] = 0x05B8;
+	chars["qamatsnarrowhebrew"] = 0x05B8;
+	chars["qamatsqatanhebrew"] = 0x05B8;
+	chars["qamatsqatannarrowhebrew"] = 0x05B8;
+	chars["qamatsqatanquarterhebrew"] = 0x05B8;
+	chars["qamatsqatanwidehebrew"] = 0x05B8;
+	chars["qamatsquarterhebrew"] = 0x05B8;
+	chars["qamatswidehebrew"] = 0x05B8;
+	chars["qarneyparahebrew"] = 0x059F;
+	chars["qbopomofo"] = 0x3111;
+	chars["Qcircle"] = 0x24C6;
+	chars["qcircle"] = 0x24E0;
+	chars["qhook"] = 0x02A0;
+	chars["Qmonospace"] = 0xFF31;
+	chars["qmonospace"] = 0xFF51;
+	chars["qof"] = 0x05E7;
+	//chars["qofdagesh"] = 0xFB47;
+	//chars["qofdageshhebrew"] = 0xFB47;
+	//chars["qofhatafpatah"] = 0x05E7 05B2;
+	//chars["qofhatafpatahhebrew"] = 0x05E7 05B2;
+	//chars["qofhatafsegol"] = 0x05E7 05B1;
+	//chars["qofhatafsegolhebrew"] = 0x05E7 05B1;
+	//chars["qofhebrew"] = 0x05E7;
+	//chars["qofhiriq"] = 0x05E7 05B4;
+	//chars["qofhiriqhebrew"] = 0x05E7 05B4;
+	//chars["qofholam"] = 0x05E7 05B9;
+	//chars["qofholamhebrew"] = 0x05E7 05B9;
+	//chars["qofpatah"] = 0x05E7 05B7;
+	//chars["qofpatahhebrew"] = 0x05E7 05B7;
+	//chars["qofqamats"] = 0x05E7 05B8;
+	//chars["qofqamatshebrew"] = 0x05E7 05B8;
+	//chars["qofqubuts"] = 0x05E7 05BB;
+	//chars["qofqubutshebrew"] = 0x05E7 05BB;
+	//chars["qofsegol"] = 0x05E7 05B6;
+	//chars["qofsegolhebrew"] = 0x05E7 05B6;
+	//chars["qofsheva"] = 0x05E7 05B0;
+	//chars["qofshevahebrew"] = 0x05E7 05B0;
+	//chars["qoftsere"] = 0x05E7 05B5;
+	//chars["qoftserehebrew"] = 0x05E7 05B5;
+	chars["qparen"] = 0x24AC;
+	chars["Qsmall"] = 0xF771;
+	chars["quarternote"] = 0x2669;
+	chars["qubuts"] = 0x05BB;
+	chars["qubuts18"] = 0x05BB;
+	chars["qubuts25"] = 0x05BB;
+	chars["qubuts31"] = 0x05BB;
+	chars["qubutshebrew"] = 0x05BB;
+	chars["qubutsnarrowhebrew"] = 0x05BB;
+	chars["qubutsquarterhebrew"] = 0x05BB;
+	chars["qubutswidehebrew"] = 0x05BB;
+	chars["question"] = 0x003F;
+	chars["questionarabic"] = 0x061F;
+	chars["questionarmenian"] = 0x055E;
+	chars["questiondown"] = 0x00BF;
+	chars["questiondownsmall"] = 0xF7BF;
+	chars["questiongreek"] = 0x037E;
+	chars["questionmonospace"] = 0xFF1F;
+	chars["questionsmall"] = 0xF73F;
+	chars["quotedbl"] = 0x0022;
+	chars["quotedblbase"] = 0x201E;
+	chars["quotedblleft"] = 0x201C;
+	chars["quotedblmonospace"] = 0xFF02;
+	chars["quotedblprime"] = 0x301E;
+	chars["quotedblprimereversed"] = 0x301D;
+	chars["quotedblright"] = 0x201D;
+	chars["quoteleft"] = 0x2018;
+	chars["quoteleftreversed"] = 0x201B;
+	chars["quotereversed"] = 0x201B;
+	chars["quoteright"] = 0x2019;
+	chars["quoterightn"] = 0x0149;
+	chars["quotesinglbase"] = 0x201A;
+	chars["quotesingle"] = 0x0027;
+	chars["quotesinglemonospace"] = 0xFF07;
+	chars["R"] = 0x0052;
+	chars["r"] = 0x0072;
+	chars["Raarmenian"] = 0x054C;
+	chars["raarmenian"] = 0x057C;
+	chars["rabengali"] = 0x09B0;
+	chars["Racute"] = 0x0154;
+	chars["racute"] = 0x0155;
+	chars["radeva"] = 0x0930;
+	chars["radical"] = 0x221A;
+	chars["radicalex"] = 0xF8E5;
+	chars["radoverssquare"] = 0x33AE;
+	chars["radoverssquaredsquare"] = 0x33AF;
+	chars["radsquare"] = 0x33AD;
+	chars["rafe"] = 0x05BF;
+	chars["rafehebrew"] = 0x05BF;
+	chars["ragujarati"] = 0x0AB0;
+	chars["ragurmukhi"] = 0x0A30;
+	chars["rahiragana"] = 0x3089;
+	chars["rakatakana"] = 0x30E9;
+	chars["rakatakanahalfwidth"] = 0xFF97;
+	chars["ralowerdiagonalbengali"] = 0x09F1;
+	chars["ramiddlediagonalbengali"] = 0x09F0;
+	chars["ramshorn"] = 0x0264;
+	chars["ratio"] = 0x2236;
+	chars["rbopomofo"] = 0x3116;
+	chars["Rcaron"] = 0x0158;
+	chars["rcaron"] = 0x0159;
+	chars["Rcedilla"] = 0x0156;
+	chars["rcedilla"] = 0x0157;
+	chars["Rcircle"] = 0x24C7;
+	chars["rcircle"] = 0x24E1;
+	chars["Rcommaaccent"] = 0x0156;
+	chars["rcommaaccent"] = 0x0157;
+	chars["Rdblgrave"] = 0x0210;
+	chars["rdblgrave"] = 0x0211;
+	chars["Rdotaccent"] = 0x1E58;
+	chars["rdotaccent"] = 0x1E59;
+	chars["Rdotbelow"] = 0x1E5A;
+	chars["rdotbelow"] = 0x1E5B;
+	chars["Rdotbelowmacron"] = 0x1E5C;
+	chars["rdotbelowmacron"] = 0x1E5D;
+	chars["referencemark"] = 0x203B;
+	chars["reflexsubset"] = 0x2286;
+	chars["reflexsuperset"] = 0x2287;
+	chars["registered"] = 0x00AE;
+	chars["registersans"] = 0xF8E8;
+	chars["registerserif"] = 0xF6DA;
+	chars["reharabic"] = 0x0631;
+	chars["Reharmenian"] = 0x0550;
+	chars["reharmenian"] = 0x0580;
+	chars["rehfinalarabic"] = 0xFEAE;
+	chars["rehiragana"] = 0x308C;
+	// chars["rehyehaleflamarabic"] = 0x0631 FEF3 FE8E 0644;
+	chars["rekatakana"] = 0x30EC;
+	chars["rekatakanahalfwidth"] = 0xFF9A;
+	chars["resh"] = 0x05E8;
+	//chars["reshdageshhebrew"] = 0xFB48;
+	//chars["reshhatafpatah"] = 0x05E8 05B2;
+	//chars["reshhatafpatahhebrew"] = 0x05E8 05B2;
+	//chars["reshhatafsegol"] = 0x05E8 05B1;
+	//chars["reshhatafsegolhebrew"] = 0x05E8 05B1;
+	//chars["reshhebrew"] = 0x05E8;
+	//chars["reshhiriq"] = 0x05E8 05B4;
+	//chars["reshhiriqhebrew"] = 0x05E8 05B4;
+	//chars["reshholam"] = 0x05E8 05B9;
+	//chars["reshholamhebrew"] = 0x05E8 05B9;
+	//chars["reshpatah"] = 0x05E8 05B7;
+	//chars["reshpatahhebrew"] = 0x05E8 05B7;
+	//chars["reshqamats"] = 0x05E8 05B8;
+	//chars["reshqamatshebrew"] = 0x05E8 05B8;
+	//chars["reshqubuts"] = 0x05E8 05BB;
+	//chars["reshqubutshebrew"] = 0x05E8 05BB;
+	//chars["reshsegol"] = 0x05E8 05B6;
+	//chars["reshsegolhebrew"] = 0x05E8 05B6;
+	//chars["reshsheva"] = 0x05E8 05B0;
+	//chars["reshshevahebrew"] = 0x05E8 05B0;
+	//chars["reshtsere"] = 0x05E8 05B5;
+	//chars["reshtserehebrew"] = 0x05E8 05B5;
+	chars["reviahebrew"] = 0x0597;
+	chars["reviamugrashhebrew"] = 0x0597;
+	chars["reversedtilde"] = 0x223D;
+	chars["revlogicalnot"] = 0x2310;
+	chars["rfishhook"] = 0x027E;
+	chars["rfishhookreversed"] = 0x027F;
+	chars["Rfraktur"] = 0x211C;
+	chars["rhabengali"] = 0x09DD;
+	chars["rhadeva"] = 0x095D;
+	chars["Rho"] = 0x03A1;
+	chars["rho"] = 0x03C1;
+	chars["rhook"] = 0x027D;
+	chars["rhookturned"] = 0x027B;
+	chars["rhookturnedsuperior"] = 0x02B5;
+	chars["rhosymbolgreek"] = 0x03F1;
+	chars["rhotichookmod"] = 0x02DE;
+	chars["rieulacirclekorean"] = 0x3271;
+	chars["rieulaparenkorean"] = 0x3211;
+	chars["rieulcirclekorean"] = 0x3263;
+	chars["rieulhieuhkorean"] = 0x3140;
+	chars["rieulkiyeokkorean"] = 0x313A;
+	chars["rieulkiyeoksioskorean"] = 0x3169;
+	chars["rieulkorean"] = 0x3139;
+	chars["rieulmieumkorean"] = 0x313B;
+	chars["rieulpansioskorean"] = 0x316C;
+	chars["rieulparenkorean"] = 0x3203;
+	chars["rieulphieuphkorean"] = 0x313F;
+	chars["rieulpieupkorean"] = 0x313C;
+	chars["rieulpieupsioskorean"] = 0x316B;
+	chars["rieulsioskorean"] = 0x313D;
+	chars["rieulthieuthkorean"] = 0x313E;
+	chars["rieultikeutkorean"] = 0x316A;
+	chars["rieulyeorinhieuhkorean"] = 0x316D;
+	chars["rightangle"] = 0x221F;
+	chars["righttackbelowcmb"] = 0x0319;
+	chars["righttriangle"] = 0x22BF;
+	chars["rihiragana"] = 0x308A;
+	chars["rikatakana"] = 0x30EA;
+	chars["rikatakanahalfwidth"] = 0xFF98;
+	chars["ring"] = 0x02DA;
+	chars["ringbelowcmb"] = 0x0325;
+	chars["ringcmb"] = 0x030A;
+	chars["ringhalfleft"] = 0x02BF;
+	chars["ringhalfleftarmenian"] = 0x0559;
+	chars["ringhalfleftbelowcmb"] = 0x031C;
+	chars["ringhalfleftcentered"] = 0x02D3;
+	chars["ringhalfright"] = 0x02BE;
+	chars["ringhalfrightbelowcmb"] = 0x0339;
+	chars["ringhalfrightcentered"] = 0x02D2;
+	chars["Ringsmall"] = 0xF6FC;
+	chars["Rinvertedbreve"] = 0x0212;
+	chars["rinvertedbreve"] = 0x0213;
+	chars["rittorusquare"] = 0x3351;
+	chars["Rlinebelow"] = 0x1E5E;
+	chars["rlinebelow"] = 0x1E5F;
+	chars["rlongleg"] = 0x027C;
+	chars["rlonglegturned"] = 0x027A;
+	chars["Rmonospace"] = 0xFF32;
+	chars["rmonospace"] = 0xFF52;
+	chars["rohiragana"] = 0x308D;
+	chars["rokatakana"] = 0x30ED;
+	chars["rokatakanahalfwidth"] = 0xFF9B;
+	chars["roruathai"] = 0x0E23;
+	chars["rparen"] = 0x24AD;
+	chars["rrabengali"] = 0x09DC;
+	chars["rradeva"] = 0x0931;
+	chars["rragurmukhi"] = 0x0A5C;
+	chars["rreharabic"] = 0x0691;
+	chars["rrehfinalarabic"] = 0xFB8D;
+	chars["rrvocalicbengali"] = 0x09E0;
+	chars["rrvocalicdeva"] = 0x0960;
+	chars["rrvocalicgujarati"] = 0x0AE0;
+	chars["rrvocalicvowelsignbengali"] = 0x09C4;
+	chars["rrvocalicvowelsigndeva"] = 0x0944;
+	chars["rrvocalicvowelsigngujarati"] = 0x0AC4;
+	chars["Rsmall"] = 0xF772;
+	chars["Rsmallinverted"] = 0x0281;
+	chars["Rsmallinvertedsuperior"] = 0x02B6;
+	chars["rsuperior"] = 0xF6F1;
+	chars["rtblock"] = 0x2590;
+	chars["rturned"] = 0x0279;
+	chars["rturnedsuperior"] = 0x02B4;
+	chars["ruhiragana"] = 0x308B;
+	chars["rukatakana"] = 0x30EB;
+	chars["rukatakanahalfwidth"] = 0xFF99;
+	chars["rupeemarkbengali"] = 0x09F2;
+	chars["rupeesignbengali"] = 0x09F3;
+	chars["rupiah"] = 0xF6DD;
+	chars["ruthai"] = 0x0E24;
+	chars["rvocalicbengali"] = 0x098B;
+	chars["rvocalicdeva"] = 0x090B;
+	chars["rvocalicgujarati"] = 0x0A8B;
+	chars["rvocalicvowelsignbengali"] = 0x09C3;
+	chars["rvocalicvowelsigndeva"] = 0x0943;
+	chars["rvocalicvowelsigngujarati"] = 0x0AC3;
+	chars["S"] = 0x0053;
+	chars["s"] = 0x0073;
+	chars["sabengali"] = 0x09B8;
+	chars["Sacute"] = 0x015A;
+	chars["sacute"] = 0x015B;
+	chars["Sacutedotaccent"] = 0x1E64;
+	chars["sacutedotaccent"] = 0x1E65;
+	chars["sadarabic"] = 0x0635;
+	chars["sadeva"] = 0x0938;
+	chars["sadfinalarabic"] = 0xFEBA;
+	chars["sadinitialarabic"] = 0xFEBB;
+	chars["sadmedialarabic"] = 0xFEBC;
+	chars["sagujarati"] = 0x0AB8;
+	chars["sagurmukhi"] = 0x0A38;
+	chars["sahiragana"] = 0x3055;
+	chars["sakatakana"] = 0x30B5;
+	chars["sakatakanahalfwidth"] = 0xFF7B;
+	chars["sallallahoualayhewasallamarabic"] = 0xFDFA;
+	chars["samekh"] = 0x05E1;
+	chars["samekhdagesh"] = 0xFB41;
+	chars["samekhdageshhebrew"] = 0xFB41;
+	chars["samekhhebrew"] = 0x05E1;
+	chars["Sampigreek"] = 0x03E0;
+	chars["saraaathai"] = 0x0E32;
+	chars["saraaethai"] = 0x0E41;
+	chars["saraaimaimalaithai"] = 0x0E44;
+	chars["saraaimaimuanthai"] = 0x0E43;
+	chars["saraamthai"] = 0x0E33;
+	chars["saraathai"] = 0x0E30;
+	chars["saraethai"] = 0x0E40;
+	chars["saraiileftthai"] = 0xF886;
+	chars["saraiithai"] = 0x0E35;
+	chars["saraileftthai"] = 0xF885;
+	chars["saraithai"] = 0x0E34;
+	chars["saraothai"] = 0x0E42;
+	chars["saraueeleftthai"] = 0xF888;
+	chars["saraueethai"] = 0x0E37;
+	chars["saraueleftthai"] = 0xF887;
+	chars["sarauethai"] = 0x0E36;
+	chars["sarauthai"] = 0x0E38;
+	chars["sarauuthai"] = 0x0E39;
+	chars["sbopomofo"] = 0x3119;
+	chars["Scaron"] = 0x0160;
+	chars["scaron"] = 0x0161;
+	chars["Scarondotaccent"] = 0x1E66;
+	chars["scarondotaccent"] = 0x1E67;
+	chars["Scaronsmall"] = 0xF6FD;
+	chars["Scedilla"] = 0x015E;
+	chars["scedilla"] = 0x015F;
+	chars["Schwa"] = 0x018F;
+	chars["schwa"] = 0x0259;
+	chars["Schwacyrillic"] = 0x04D8;
+	chars["schwacyrillic"] = 0x04D9;
+	chars["Schwadieresiscyrillic"] = 0x04DA;
+	chars["schwadieresiscyrillic"] = 0x04DB;
+	chars["schwahook"] = 0x025A;
+	chars["Scircle"] = 0x24C8;
+	chars["scircle"] = 0x24E2;
+	chars["Scircumflex"] = 0x015C;
+	chars["scircumflex"] = 0x015D;
+	chars["Scommaaccent"] = 0x0218;
+	chars["scommaaccent"] = 0x0219;
+	chars["Sdotaccent"] = 0x1E60;
+	chars["sdotaccent"] = 0x1E61;
+	chars["Sdotbelow"] = 0x1E62;
+	chars["sdotbelow"] = 0x1E63;
+	chars["Sdotbelowdotaccent"] = 0x1E68;
+	chars["sdotbelowdotaccent"] = 0x1E69;
+	chars["seagullbelowcmb"] = 0x033C;
+	chars["second"] = 0x2033;
+	chars["secondtonechinese"] = 0x02CA;
+	chars["section"] = 0x00A7;
+	chars["seenarabic"] = 0x0633;
+	chars["seenfinalarabic"] = 0xFEB2;
+	chars["seeninitialarabic"] = 0xFEB3;
+	chars["seenmedialarabic"] = 0xFEB4;
+	chars["segol"] = 0x05B6;
+	chars["segol13"] = 0x05B6;
+	chars["segol1f"] = 0x05B6;
+	chars["segol2c"] = 0x05B6;
+	chars["segolhebrew"] = 0x05B6;
+	chars["segolnarrowhebrew"] = 0x05B6;
+	chars["segolquarterhebrew"] = 0x05B6;
+	chars["segoltahebrew"] = 0x0592;
+	chars["segolwidehebrew"] = 0x05B6;
+	chars["Seharmenian"] = 0x054D;
+	chars["seharmenian"] = 0x057D;
+	chars["sehiragana"] = 0x305B;
+	chars["sekatakana"] = 0x30BB;
+	chars["sekatakanahalfwidth"] = 0xFF7E;
+	chars["semicolon"] = 0x003B;
+	chars["semicolonarabic"] = 0x061B;
+	chars["semicolonmonospace"] = 0xFF1B;
+	chars["semicolonsmall"] = 0xFE54;
+	chars["semivoicedmarkkana"] = 0x309C;
+	chars["semivoicedmarkkanahalfwidth"] = 0xFF9F;
+	chars["sentisquare"] = 0x3322;
+	chars["sentosquare"] = 0x3323;
+	chars["seven"] = 0x0037;
+	chars["sevenarabic"] = 0x0667;
+	chars["sevenbengali"] = 0x09ED;
+	chars["sevencircle"] = 0x2466;
+	chars["sevencircleinversesansserif"] = 0x2790;
+	chars["sevendeva"] = 0x096D;
+	chars["seveneighths"] = 0x215E;
+	chars["sevengujarati"] = 0x0AED;
+	chars["sevengurmukhi"] = 0x0A6D;
+	chars["sevenhackarabic"] = 0x0667;
+	chars["sevenhangzhou"] = 0x3027;
+	chars["sevenideographicparen"] = 0x3226;
+	chars["seveninferior"] = 0x2087;
+	chars["sevenmonospace"] = 0xFF17;
+	chars["sevenoldstyle"] = 0xF737;
+	chars["sevenparen"] = 0x247A;
+	chars["sevenperiod"] = 0x248E;
+	chars["sevenpersian"] = 0x06F7;
+	chars["Sevenroman"] = 0x2166;
+	chars["sevenroman"] = 0x2176;
+	chars["sevensuperior"] = 0x2077;
+	chars["seventeencircle"] = 0x2470;
+	chars["seventeenparen"] = 0x2484;
+	chars["seventeenperiod"] = 0x2498;
+	chars["seventhai"] = 0x0E57;
+	chars["SF010000"] = 0x250C;
+	chars["SF020000"] = 0x2514;
+	chars["SF030000"] = 0x2510;
+	chars["SF040000"] = 0x2518;
+	chars["SF050000"] = 0x253C;
+	chars["SF060000"] = 0x252C;
+	chars["SF070000"] = 0x2534;
+	chars["SF080000"] = 0x251C;
+	chars["SF090000"] = 0x2524;
+	chars["SF100000"] = 0x2500;
+	chars["SF110000"] = 0x2502;
+	chars["SF190000"] = 0x2561;
+	chars["SF200000"] = 0x2562;
+	chars["SF210000"] = 0x2556;
+	chars["SF220000"] = 0x2555;
+	chars["SF230000"] = 0x2563;
+	chars["SF240000"] = 0x2551;
+	chars["SF250000"] = 0x2557;
+	chars["SF260000"] = 0x255D;
+	chars["SF270000"] = 0x255C;
+	chars["SF280000"] = 0x255B;
+	chars["SF360000"] = 0x255E;
+	chars["SF370000"] = 0x255F;
+	chars["SF380000"] = 0x255A;
+	chars["SF390000"] = 0x2554;
+	chars["SF400000"] = 0x2569;
+	chars["SF410000"] = 0x2566;
+	chars["SF420000"] = 0x2560;
+	chars["SF430000"] = 0x2550;
+	chars["SF440000"] = 0x256C;
+	chars["SF450000"] = 0x2567;
+	chars["SF460000"] = 0x2568;
+	chars["SF470000"] = 0x2564;
+	chars["SF480000"] = 0x2565;
+	chars["SF490000"] = 0x2559;
+	chars["SF500000"] = 0x2558;
+	chars["SF510000"] = 0x2552;
+	chars["SF520000"] = 0x2553;
+	chars["SF530000"] = 0x256B;
+	chars["SF540000"] = 0x256A;
+	chars["sfthyphen"] = 0x00AD;
+	chars["Shaarmenian"] = 0x0547;
+	chars["shaarmenian"] = 0x0577;
+	chars["shabengali"] = 0x09B6;
+	chars["Shacyrillic"] = 0x0428;
+	chars["shacyrillic"] = 0x0448;
+	chars["shaddaarabic"] = 0x0651;
+	//chars["shaddadammaarabic"] = 0xFC61;
+	//chars["shaddadammatanarabic"] = 0xFC5E;
+	//chars["shaddafathaarabic"] = 0xFC60;
+	//chars["shaddafathatanarabic"] = 0x0651 064B;
+	//chars["shaddakasraarabic"] = 0xFC62;
+	//chars["shaddakasratanarabic"] = 0xFC5F;
+	chars["shade"] = 0x2592;
+	chars["shadedark"] = 0x2593;
+	chars["shadelight"] = 0x2591;
+	chars["shademedium"] = 0x2592;
+	chars["shadeva"] = 0x0936;
+	chars["shagujarati"] = 0x0AB6;
+	chars["shagurmukhi"] = 0x0A36;
+	chars["shalshelethebrew"] = 0x0593;
+	chars["shbopomofo"] = 0x3115;
+	chars["Shchacyrillic"] = 0x0429;
+	chars["shchacyrillic"] = 0x0449;
+	chars["sheenarabic"] = 0x0634;
+	chars["sheenfinalarabic"] = 0xFEB6;
+	chars["sheeninitialarabic"] = 0xFEB7;
+	chars["sheenmedialarabic"] = 0xFEB8;
+	chars["Sheicoptic"] = 0x03E2;
+	chars["sheicoptic"] = 0x03E3;
+	chars["sheqel"] = 0x20AA;
+	chars["sheqelhebrew"] = 0x20AA;
+	chars["sheva"] = 0x05B0;
+	chars["sheva115"] = 0x05B0;
+	chars["sheva15"] = 0x05B0;
+	chars["sheva22"] = 0x05B0;
+	chars["sheva2e"] = 0x05B0;
+	chars["shevahebrew"] = 0x05B0;
+	chars["shevanarrowhebrew"] = 0x05B0;
+	chars["shevaquarterhebrew"] = 0x05B0;
+	chars["shevawidehebrew"] = 0x05B0;
+	chars["Shhacyrillic"] = 0x04BA;
+	chars["shhacyrillic"] = 0x04BB;
+	chars["Shimacoptic"] = 0x03EC;
+	chars["shimacoptic"] = 0x03ED;
+	chars["shin"] = 0x05E9;
+	chars["shindagesh"] = 0xFB49;
+	chars["shindageshhebrew"] = 0xFB49;
+	chars["shindageshshindot"] = 0xFB2C;
+	chars["shindageshshindothebrew"] = 0xFB2C;
+	chars["shindageshsindot"] = 0xFB2D;
+	chars["shindageshsindothebrew"] = 0xFB2D;
+	chars["shindothebrew"] = 0x05C1;
+	chars["shinhebrew"] = 0x05E9;
+	chars["shinshindot"] = 0xFB2A;
+	chars["shinshindothebrew"] = 0xFB2A;
+	chars["shinsindot"] = 0xFB2B;
+	chars["shinsindothebrew"] = 0xFB2B;
+	chars["shook"] = 0x0282;
+	chars["Sigma"] = 0x03A3;
+	chars["sigma"] = 0x03C3;
+	chars["sigma1"] = 0x03C2;
+	chars["sigmafinal"] = 0x03C2;
+	chars["sigmalunatesymbolgreek"] = 0x03F2;
+	chars["sihiragana"] = 0x3057;
+	chars["sikatakana"] = 0x30B7;
+	chars["sikatakanahalfwidth"] = 0xFF7C;
+	chars["siluqhebrew"] = 0x05BD;
+	chars["siluqlefthebrew"] = 0x05BD;
+	chars["similar"] = 0x223C;
+	chars["similarequal"] = 0x2243;
+	chars["sindothebrew"] = 0x05C2;
+	chars["siosacirclekorean"] = 0x3274;
+	chars["siosaparenkorean"] = 0x3214;
+	chars["sioscieuckorean"] = 0x317E;
+	chars["sioscirclekorean"] = 0x3266;
+	chars["sioskiyeokkorean"] = 0x317A;
+	chars["sioskorean"] = 0x3145;
+	chars["siosnieunkorean"] = 0x317B;
+	chars["siosparenkorean"] = 0x3206;
+	chars["siospieupkorean"] = 0x317D;
+	chars["siostikeutkorean"] = 0x317C;
+	chars["six"] = 0x0036;
+	chars["sixarabic"] = 0x0666;
+	chars["sixbengali"] = 0x09EC;
+	chars["sixcircle"] = 0x2465;
+	chars["sixcircleinversesansserif"] = 0x278F;
+	chars["sixdeva"] = 0x096C;
+	chars["sixgujarati"] = 0x0AEC;
+	chars["sixgurmukhi"] = 0x0A6C;
+	chars["sixhackarabic"] = 0x0666;
+	chars["sixhangzhou"] = 0x3026;
+	chars["sixideographicparen"] = 0x3225;
+	chars["sixinferior"] = 0x2086;
+	chars["sixmonospace"] = 0xFF16;
+	chars["sixoldstyle"] = 0xF736;
+	chars["sixparen"] = 0x2479;
+	chars["sixperiod"] = 0x248D;
+	chars["sixpersian"] = 0x06F6;
+	chars["Sixroman"] = 0x2165;
+	chars["sixroman"] = 0x2175;
+	chars["sixsuperior"] = 0x2076;
+	chars["sixteencircle"] = 0x246F;
+	chars["sixteencurrencydenominatorbengali"] = 0x09F9;
+	chars["sixteenparen"] = 0x2483;
+	chars["sixteenperiod"] = 0x2497;
+	chars["sixthai"] = 0x0E56;
+	chars["slash"] = 0x002F;
+	chars["slashmonospace"] = 0xFF0F;
+	chars["slong"] = 0x017F;
+	chars["slongdotaccent"] = 0x1E9B;
+	chars["smileface"] = 0x263A;
+	chars["Smonospace"] = 0xFF33;
+	chars["smonospace"] = 0xFF53;
+	chars["sofpasuqhebrew"] = 0x05C3;
+	chars["softhyphen"] = 0x00AD;
+	chars["Softsigncyrillic"] = 0x042C;
+	chars["softsigncyrillic"] = 0x044C;
+	chars["sohiragana"] = 0x305D;
+	chars["sokatakana"] = 0x30BD;
+	chars["sokatakanahalfwidth"] = 0xFF7F;
+	chars["soliduslongoverlaycmb"] = 0x0338;
+	chars["solidusshortoverlaycmb"] = 0x0337;
+	chars["sorusithai"] = 0x0E29;
+	chars["sosalathai"] = 0x0E28;
+	chars["sosothai"] = 0x0E0B;
+	chars["sosuathai"] = 0x0E2A;
+	chars["space"] = 0x0020;
+	chars["spacehackarabic"] = 0x0020;
+	chars["spade"] = 0x2660;
+	chars["spadesuitblack"] = 0x2660;
+	chars["spadesuitwhite"] = 0x2664;
+	chars["sparen"] = 0x24AE;
+	chars["sphericalangle"] = 0x2222;
+	chars["squarebelowcmb"] = 0x033B;
+	chars["squarecc"] = 0x33C4;
+	chars["squarecm"] = 0x339D;
+	chars["squarediagonalcrosshatchfill"] = 0x25A9;
+	chars["squarehorizontalfill"] = 0x25A4;
+	chars["squarekg"] = 0x338F;
+	chars["squarekm"] = 0x339E;
+	chars["squarekmcapital"] = 0x33CE;
+	chars["squareln"] = 0x33D1;
+	chars["squarelog"] = 0x33D2;
+	chars["squaremg"] = 0x338E;
+	chars["squaremil"] = 0x33D5;
+	chars["squaremm"] = 0x339C;
+	chars["squaremsquared"] = 0x33A1;
+	chars["squareorthogonalcrosshatchfill"] = 0x25A6;
+	chars["squareupperlefttolowerrightfill"] = 0x25A7;
+	chars["squareupperrighttolowerleftfill"] = 0x25A8;
+	chars["squareverticalfill"] = 0x25A5;
+	chars["squarewhitewithsmallblack"] = 0x25A3;
+	chars["srsquare"] = 0x33DB;
+	chars["ssabengali"] = 0x09B7;
+	chars["ssadeva"] = 0x0937;
+	chars["ssagujarati"] = 0x0AB7;
+	chars["ssangcieuckorean"] = 0x3149;
+	chars["ssanghieuhkorean"] = 0x3185;
+	chars["ssangieungkorean"] = 0x3180;
+	chars["ssangkiyeokkorean"] = 0x3132;
+	chars["ssangnieunkorean"] = 0x3165;
+	chars["ssangpieupkorean"] = 0x3143;
+	chars["ssangsioskorean"] = 0x3146;
+	chars["ssangtikeutkorean"] = 0x3138;
+	chars["Ssmall"] = 0xF773;
+	chars["ssuperior"] = 0xF6F2;
+	chars["star"] = 0x22C6;
+	chars["sterling"] = 0x00A3;
+	chars["sterlingmonospace"] = 0xFFE1;
+	chars["Stigmagreek"] = 0x03DA;
+	chars["strokelongoverlaycmb"] = 0x0336;
+	chars["strokeshortoverlaycmb"] = 0x0335;
+	chars["subset"] = 0x2282;
+	chars["subsetnotequal"] = 0x228A;
+	chars["subsetorequal"] = 0x2286;
+	chars["succeeds"] = 0x227B;
+	chars["suchthat"] = 0x220B;
+	chars["suhiragana"] = 0x3059;
+	chars["sukatakana"] = 0x30B9;
+	chars["sukatakanahalfwidth"] = 0xFF7D;
+	chars["sukunarabic"] = 0x0652;
+	chars["summation"] = 0x2211;
+	chars["sun"] = 0x263C;
+	chars["superset"] = 0x2283;
+	chars["supersetnotequal"] = 0x228B;
+	chars["supersetorequal"] = 0x2287;
+	chars["svsquare"] = 0x33DC;
+	chars["syouwaerasquare"] = 0x337C;
+	chars["T"] = 0x0054;
+	chars["t"] = 0x0074;
+	chars["tabengali"] = 0x09A4;
+	chars["tackdown"] = 0x22A4;
+	chars["tackleft"] = 0x22A3;
+	chars["tadeva"] = 0x0924;
+	chars["tagujarati"] = 0x0AA4;
+	chars["tagurmukhi"] = 0x0A24;
+	chars["taharabic"] = 0x0637;
+	chars["tahfinalarabic"] = 0xFEC2;
+	chars["tahinitialarabic"] = 0xFEC3;
+	chars["tahiragana"] = 0x305F;
+	chars["tahmedialarabic"] = 0xFEC4;
+	chars["taisyouerasquare"] = 0x337D;
+	chars["takatakana"] = 0x30BF;
+	chars["takatakanahalfwidth"] = 0xFF80;
+	chars["tatweelarabic"] = 0x0640;
+	chars["Tau"] = 0x03A4;
+	chars["tau"] = 0x03C4;
+	chars["tav"] = 0x05EA;
+	chars["tavdages"] = 0xFB4A;
+	chars["tavdagesh"] = 0xFB4A;
+	chars["tavdageshhebrew"] = 0xFB4A;
+	chars["tavhebrew"] = 0x05EA;
+	chars["Tbar"] = 0x0166;
+	chars["tbar"] = 0x0167;
+	chars["tbopomofo"] = 0x310A;
+	chars["Tcaron"] = 0x0164;
+	chars["tcaron"] = 0x0165;
+	chars["tccurl"] = 0x02A8;
+	chars["Tcedilla"] = 0x0162;
+	chars["tcedilla"] = 0x0163;
+	chars["tcheharabic"] = 0x0686;
+	//chars["tchehfinalarabic"] = 0xFB7B;
+	//chars["tchehinitialarabic"] = 0xFB7C;
+	//chars["tchehmedialarabic"] = 0xFB7D;
+	//chars["tchehmeeminitialarabic"] = 0xFB7C FEE4;
+	chars["Tcircle"] = 0x24C9;
+	chars["tcircle"] = 0x24E3;
+	chars["Tcircumflexbelow"] = 0x1E70;
+	chars["tcircumflexbelow"] = 0x1E71;
+	chars["Tcommaaccent"] = 0x0162;
+	chars["tcommaaccent"] = 0x0163;
+	chars["tdieresis"] = 0x1E97;
+	chars["Tdotaccent"] = 0x1E6A;
+	chars["tdotaccent"] = 0x1E6B;
+	chars["Tdotbelow"] = 0x1E6C;
+	chars["tdotbelow"] = 0x1E6D;
+	chars["Tecyrillic"] = 0x0422;
+	chars["tecyrillic"] = 0x0442;
+	chars["Tedescendercyrillic"] = 0x04AC;
+	chars["tedescendercyrillic"] = 0x04AD;
+	chars["teharabic"] = 0x062A;
+	chars["tehfinalarabic"] = 0xFE96;
+	chars["tehhahinitialarabic"] = 0xFCA2;
+	chars["tehhahisolatedarabic"] = 0xFC0C;
+	chars["tehinitialarabic"] = 0xFE97;
+	chars["tehiragana"] = 0x3066;
+	chars["tehjeeminitialarabic"] = 0xFCA1;
+	chars["tehjeemisolatedarabic"] = 0xFC0B;
+	chars["tehmarbutaarabic"] = 0x0629;
+	chars["tehmarbutafinalarabic"] = 0xFE94;
+	chars["tehmedialarabic"] = 0xFE98;
+	chars["tehmeeminitialarabic"] = 0xFCA4;
+	chars["tehmeemisolatedarabic"] = 0xFC0E;
+	chars["tehnoonfinalarabic"] = 0xFC73;
+	chars["tekatakana"] = 0x30C6;
+	chars["tekatakanahalfwidth"] = 0xFF83;
+	chars["telephone"] = 0x2121;
+	chars["telephoneblack"] = 0x260E;
+	chars["telishagedolahebrew"] = 0x05A0;
+	chars["telishaqetanahebrew"] = 0x05A9;
+	chars["tencircle"] = 0x2469;
+	chars["tenideographicparen"] = 0x3229;
+	chars["tenparen"] = 0x247D;
+	chars["tenperiod"] = 0x2491;
+	chars["Tenroman"] = 0x2169;
+	chars["tenroman"] = 0x2179;
+	chars["tesh"] = 0x02A7;
+	chars["tet"] = 0x05D8;
+	chars["tetdagesh"] = 0xFB38;
+	chars["tetdageshhebrew"] = 0xFB38;
+	chars["tethebrew"] = 0x05D8;
+	chars["Tetsecyrillic"] = 0x04B4;
+	chars["tetsecyrillic"] = 0x04B5;
+	chars["tevirhebrew"] = 0x059B;
+	chars["tevirlefthebrew"] = 0x059B;
+	chars["thabengali"] = 0x09A5;
+	chars["thadeva"] = 0x0925;
+	chars["thagujarati"] = 0x0AA5;
+	chars["thagurmukhi"] = 0x0A25;
+	chars["thalarabic"] = 0x0630;
+	chars["thalfinalarabic"] = 0xFEAC;
+	chars["thanthakhatlowleftthai"] = 0xF898;
+	chars["thanthakhatlowrightthai"] = 0xF897;
+	chars["thanthakhatthai"] = 0x0E4C;
+	chars["thanthakhatupperleftthai"] = 0xF896;
+	chars["theharabic"] = 0x062B;
+	chars["thehfinalarabic"] = 0xFE9A;
+	chars["thehinitialarabic"] = 0xFE9B;
+	chars["thehmedialarabic"] = 0xFE9C;
+	chars["thereexists"] = 0x2203;
+	chars["therefore"] = 0x2234;
+	chars["Theta"] = 0x0398;
+	chars["theta"] = 0x03B8;
+	chars["theta1"] = 0x03D1;
+	chars["thetasymbolgreek"] = 0x03D1;
+	chars["thieuthacirclekorean"] = 0x3279;
+	chars["thieuthaparenkorean"] = 0x3219;
+	chars["thieuthcirclekorean"] = 0x326B;
+	chars["thieuthkorean"] = 0x314C;
+	chars["thieuthparenkorean"] = 0x320B;
+	chars["thirteencircle"] = 0x246C;
+	chars["thirteenparen"] = 0x2480;
+	chars["thirteenperiod"] = 0x2494;
+	chars["thonangmonthothai"] = 0x0E11;
+	chars["Thook"] = 0x01AC;
+	chars["thook"] = 0x01AD;
+	chars["thophuthaothai"] = 0x0E12;
+	chars["Thorn"] = 0x00DE;
+	chars["thorn"] = 0x00FE;
+	chars["Thornsmall"] = 0xF7FE;
+	chars["thothahanthai"] = 0x0E17;
+	chars["thothanthai"] = 0x0E10;
+	chars["thothongthai"] = 0x0E18;
+	chars["thothungthai"] = 0x0E16;
+	chars["thousandcyrillic"] = 0x0482;
+	chars["thousandsseparatorarabic"] = 0x066C;
+	chars["thousandsseparatorpersian"] = 0x066C;
+	chars["three"] = 0x0033;
+	chars["threearabic"] = 0x0663;
+	chars["threebengali"] = 0x09E9;
+	chars["threecircle"] = 0x2462;
+	chars["threecircleinversesansserif"] = 0x278C;
+	chars["threedeva"] = 0x0969;
+	chars["threeeighths"] = 0x215C;
+	chars["threegujarati"] = 0x0AE9;
+	chars["threegurmukhi"] = 0x0A69;
+	chars["threehackarabic"] = 0x0663;
+	chars["threehangzhou"] = 0x3023;
+	chars["threeideographicparen"] = 0x3222;
+	chars["threeinferior"] = 0x2083;
+	chars["threemonospace"] = 0xFF13;
+	chars["threenumeratorbengali"] = 0x09F6;
+	chars["threeoldstyle"] = 0xF733;
+	chars["threeparen"] = 0x2476;
+	chars["threeperiod"] = 0x248A;
+	chars["threepersian"] = 0x06F3;
+	chars["threequarters"] = 0x00BE;
+	chars["threequartersemdash"] = 0xF6DE;
+	chars["Threeroman"] = 0x2162;
+	chars["threeroman"] = 0x2172;
+	chars["threesuperior"] = 0x00B3;
+	chars["threethai"] = 0x0E53;
+	chars["thzsquare"] = 0x3394;
+	chars["tihiragana"] = 0x3061;
+	chars["tikatakana"] = 0x30C1;
+	chars["tikatakanahalfwidth"] = 0xFF81;
+	chars["tikeutacirclekorean"] = 0x3270;
+	chars["tikeutaparenkorean"] = 0x3210;
+	chars["tikeutcirclekorean"] = 0x3262;
+	chars["tikeutkorean"] = 0x3137;
+	chars["tikeutparenkorean"] = 0x3202;
+	chars["tilde"] = 0x02DC;
+	chars["tildebelowcmb"] = 0x0330;
+	chars["tildecmb"] = 0x0303;
+	chars["tildecomb"] = 0x0303;
+	chars["tildedoublecmb"] = 0x0360;
+	chars["tildeoperator"] = 0x223C;
+	chars["tildeoverlaycmb"] = 0x0334;
+	chars["Tildesmall"] = 0xF6FE;
+	chars["tildeverticalcmb"] = 0x033E;
+	chars["timescircle"] = 0x2297;
+	chars["tipehahebrew"] = 0x0596;
+	chars["tipehalefthebrew"] = 0x0596;
+	chars["tippigurmukhi"] = 0x0A70;
+	chars["titlocyrilliccmb"] = 0x0483;
+	chars["Tiwnarmenian"] = 0x054F;
+	chars["tiwnarmenian"] = 0x057F;
+	chars["Tlinebelow"] = 0x1E6E;
+	chars["tlinebelow"] = 0x1E6F;
+	chars["Tmonospace"] = 0xFF34;
+	chars["tmonospace"] = 0xFF54;
+	chars["Toarmenian"] = 0x0539;
+	chars["toarmenian"] = 0x0569;
+	chars["tohiragana"] = 0x3068;
+	chars["tokatakana"] = 0x30C8;
+	chars["tokatakanahalfwidth"] = 0xFF84;
+	chars["tonebarextrahighmod"] = 0x02E5;
+	chars["tonebarextralowmod"] = 0x02E9;
+	chars["tonebarhighmod"] = 0x02E6;
+	chars["tonebarlowmod"] = 0x02E8;
+	chars["tonebarmidmod"] = 0x02E7;
+	chars["Tonefive"] = 0x01BC;
+	chars["tonefive"] = 0x01BD;
+	chars["Tonesix"] = 0x0184;
+	chars["tonesix"] = 0x0185;
+	chars["Tonetwo"] = 0x01A7;
+	chars["tonetwo"] = 0x01A8;
+	chars["tonos"] = 0x0384;
+	chars["tonsquare"] = 0x3327;
+	chars["topatakthai"] = 0x0E0F;
+	chars["tortoiseshellbracketleft"] = 0x3014;
+	chars["tortoiseshellbracketleftsmall"] = 0xFE5D;
+	chars["tortoiseshellbracketleftvertical"] = 0xFE39;
+	chars["tortoiseshellbracketright"] = 0x3015;
+	chars["tortoiseshellbracketrightsmall"] = 0xFE5E;
+	chars["tortoiseshellbracketrightvertical"] = 0xFE3A;
+	chars["totaothai"] = 0x0E15;
+	chars["tpalatalhook"] = 0x01AB;
+	chars["tparen"] = 0x24AF;
+	chars["trademark"] = 0x2122;
+	chars["trademarksans"] = 0xF8EA;
+	chars["trademarkserif"] = 0xF6DB;
+	chars["Tretroflexhook"] = 0x01AE;
+	chars["tretroflexhook"] = 0x0288;
+	chars["triagdn"] = 0x25BC;
+	chars["triaglf"] = 0x25C4;
+	chars["triagrt"] = 0x25BA;
+	chars["triagup"] = 0x25B2;
+	chars["triangle"] = 0x25B5;
+	chars["trianglerightsld"] = 0x25B6;
+	chars["ts"] = 0x02A6;
+	chars["tsadi"] = 0x05E6;
+	chars["tsadidagesh"] = 0xFB46;
+	chars["tsadidageshhebrew"] = 0xFB46;
+	chars["tsadihebrew"] = 0x05E6;
+	chars["Tsecyrillic"] = 0x0426;
+	chars["tsecyrillic"] = 0x0446;
+	chars["tsere"] = 0x05B5;
+	chars["tsere12"] = 0x05B5;
+	chars["tsere1e"] = 0x05B5;
+	chars["tsere2b"] = 0x05B5;
+	chars["tserehebrew"] = 0x05B5;
+	chars["tserenarrowhebrew"] = 0x05B5;
+	chars["tserequarterhebrew"] = 0x05B5;
+	chars["tserewidehebrew"] = 0x05B5;
+	chars["Tshecyrillic"] = 0x040B;
+	chars["tshecyrillic"] = 0x045B;
+	chars["Tsmall"] = 0xF774;
+	chars["tsuperior"] = 0xF6F3;
+	chars["ttabengali"] = 0x099F;
+	chars["ttadeva"] = 0x091F;
+	chars["ttagujarati"] = 0x0A9F;
+	chars["ttagurmukhi"] = 0x0A1F;
+	chars["tteharabic"] = 0x0679;
+	chars["ttehfinalarabic"] = 0xFB67;
+	chars["ttehinitialarabic"] = 0xFB68;
+	chars["ttehmedialarabic"] = 0xFB69;
+	chars["tthabengali"] = 0x09A0;
+	chars["tthadeva"] = 0x0920;
+	chars["tthagujarati"] = 0x0AA0;
+	chars["tthagurmukhi"] = 0x0A20;
+	chars["tturned"] = 0x0287;
+	chars["tuhiragana"] = 0x3064;
+	chars["tukatakana"] = 0x30C4;
+	chars["tukatakanahalfwidth"] = 0xFF82;
+	chars["tusmallhiragana"] = 0x3063;
+	chars["tusmallkatakana"] = 0x30C3;
+	chars["tusmallkatakanahalfwidth"] = 0xFF6F;
+	chars["twelvecircle"] = 0x246B;
+	chars["twelveparen"] = 0x247F;
+	chars["twelveperiod"] = 0x2493;
+	chars["Twelveroman"] = 0x216B;
+	chars["twelveroman"] = 0x217B;
+	chars["twentycircle"] = 0x2473;
+	chars["twentyhangzhou"] = 0x5344;
+	chars["twentyparen"] = 0x2487;
+	chars["twentyperiod"] = 0x249B;
+	chars["two"] = 0x0032;
+	chars["twoarabic"] = 0x0662;
+	chars["twobengali"] = 0x09E8;
+	chars["twocircle"] = 0x2461;
+	chars["twocircleinversesansserif"] = 0x278B;
+	chars["twodeva"] = 0x0968;
+	chars["twodotenleader"] = 0x2025;
+	chars["twodotleader"] = 0x2025;
+	chars["twodotleadervertical"] = 0xFE30;
+	chars["twogujarati"] = 0x0AE8;
+	chars["twogurmukhi"] = 0x0A68;
+	chars["twohackarabic"] = 0x0662;
+	chars["twohangzhou"] = 0x3022;
+	chars["twoideographicparen"] = 0x3221;
+	chars["twoinferior"] = 0x2082;
+	chars["twomonospace"] = 0xFF12;
+	chars["twonumeratorbengali"] = 0x09F5;
+	chars["twooldstyle"] = 0xF732;
+	chars["twoparen"] = 0x2475;
+	chars["twoperiod"] = 0x2489;
+	chars["twopersian"] = 0x06F2;
+	chars["Tworoman"] = 0x2161;
+	chars["tworoman"] = 0x2171;
+	chars["twostroke"] = 0x01BB;
+	chars["twosuperior"] = 0x00B2;
+	chars["twothai"] = 0x0E52;
+	chars["twothirds"] = 0x2154;
+	chars["U"] = 0x0055;
+	chars["u"] = 0x0075;
+	chars["Uacute"] = 0x00DA;
+	chars["uacute"] = 0x00FA;
+	chars["Uacutesmall"] = 0xF7FA;
+	chars["ubar"] = 0x0289;
+	chars["ubengali"] = 0x0989;
+	chars["ubopomofo"] = 0x3128;
+	chars["Ubreve"] = 0x016C;
+	chars["ubreve"] = 0x016D;
+	chars["Ucaron"] = 0x01D3;
+	chars["ucaron"] = 0x01D4;
+	chars["Ucircle"] = 0x24CA;
+	chars["ucircle"] = 0x24E4;
+	chars["Ucircumflex"] = 0x00DB;
+	chars["ucircumflex"] = 0x00FB;
+	chars["Ucircumflexbelow"] = 0x1E76;
+	chars["ucircumflexbelow"] = 0x1E77;
+	chars["Ucircumflexsmall"] = 0xF7FB;
+	chars["Ucyrillic"] = 0x0423;
+	chars["ucyrillic"] = 0x0443;
+	chars["udattadeva"] = 0x0951;
+	chars["Udblacute"] = 0x0170;
+	chars["udblacute"] = 0x0171;
+	chars["Udblgrave"] = 0x0214;
+	chars["udblgrave"] = 0x0215;
+	chars["udeva"] = 0x0909;
+	chars["Udieresis"] = 0x00DC;
+	chars["udieresis"] = 0x00FC;
+	chars["Udieresisacute"] = 0x01D7;
+	chars["udieresisacute"] = 0x01D8;
+	chars["Udieresisbelow"] = 0x1E72;
+	chars["udieresisbelow"] = 0x1E73;
+	chars["Udieresiscaron"] = 0x01D9;
+	chars["udieresiscaron"] = 0x01DA;
+	chars["Udieresiscyrillic"] = 0x04F0;
+	chars["udieresiscyrillic"] = 0x04F1;
+	chars["Udieresisgrave"] = 0x01DB;
+	chars["udieresisgrave"] = 0x01DC;
+	chars["Udieresismacron"] = 0x01D5;
+	chars["udieresismacron"] = 0x01D6;
+	chars["Udieresissmall"] = 0xF7FC;
+	chars["Udotbelow"] = 0x1EE4;
+	chars["udotbelow"] = 0x1EE5;
+	chars["Ugrave"] = 0x00D9;
+	chars["ugrave"] = 0x00F9;
+	chars["Ugravesmall"] = 0xF7F9;
+	chars["ugujarati"] = 0x0A89;
+	chars["ugurmukhi"] = 0x0A09;
+	chars["uhiragana"] = 0x3046;
+	chars["Uhookabove"] = 0x1EE6;
+	chars["uhookabove"] = 0x1EE7;
+	chars["Uhorn"] = 0x01AF;
+	chars["uhorn"] = 0x01B0;
+	chars["Uhornacute"] = 0x1EE8;
+	chars["uhornacute"] = 0x1EE9;
+	chars["Uhorndotbelow"] = 0x1EF0;
+	chars["uhorndotbelow"] = 0x1EF1;
+	chars["Uhorngrave"] = 0x1EEA;
+	chars["uhorngrave"] = 0x1EEB;
+	chars["Uhornhookabove"] = 0x1EEC;
+	chars["uhornhookabove"] = 0x1EED;
+	chars["Uhorntilde"] = 0x1EEE;
+	chars["uhorntilde"] = 0x1EEF;
+	chars["Uhungarumlaut"] = 0x0170;
+	chars["uhungarumlaut"] = 0x0171;
+	chars["Uhungarumlautcyrillic"] = 0x04F2;
+	chars["uhungarumlautcyrillic"] = 0x04F3;
+	chars["Uinvertedbreve"] = 0x0216;
+	chars["uinvertedbreve"] = 0x0217;
+	chars["ukatakana"] = 0x30A6;
+	chars["ukatakanahalfwidth"] = 0xFF73;
+	chars["Ukcyrillic"] = 0x0478;
+	chars["ukcyrillic"] = 0x0479;
+	chars["ukorean"] = 0x315C;
+	chars["Umacron"] = 0x016A;
+	chars["umacron"] = 0x016B;
+	chars["Umacroncyrillic"] = 0x04EE;
+	chars["umacroncyrillic"] = 0x04EF;
+	chars["Umacrondieresis"] = 0x1E7A;
+	chars["umacrondieresis"] = 0x1E7B;
+	chars["umatragurmukhi"] = 0x0A41;
+	chars["Umonospace"] = 0xFF35;
+	chars["umonospace"] = 0xFF55;
+	chars["underscore"] = 0x005F;
+	chars["underscoredbl"] = 0x2017;
+	chars["underscoremonospace"] = 0xFF3F;
+	chars["underscorevertical"] = 0xFE33;
+	chars["underscorewavy"] = 0xFE4F;
+	chars["union"] = 0x222A;
+	chars["universal"] = 0x2200;
+	chars["Uogonek"] = 0x0172;
+	chars["uogonek"] = 0x0173;
+	chars["uparen"] = 0x24B0;
+	chars["upblock"] = 0x2580;
+	chars["upperdothebrew"] = 0x05C4;
+	chars["Upsilon"] = 0x03A5;
+	chars["upsilon"] = 0x03C5;
+	chars["Upsilon1"] = 0x03D2;
+	chars["Upsilonacutehooksymbolgreek"] = 0x03D3;
+	chars["Upsilonafrican"] = 0x01B1;
+	chars["Upsilondieresis"] = 0x03AB;
+	chars["upsilondieresis"] = 0x03CB;
+	chars["Upsilondieresishooksymbolgreek"] = 0x03D4;
+	chars["upsilondieresistonos"] = 0x03B0;
+	chars["Upsilonhooksymbol"] = 0x03D2;
+	chars["upsilonlatin"] = 0x028A;
+	chars["Upsilontonos"] = 0x038E;
+	chars["upsilontonos"] = 0x03CD;
+	chars["uptackbelowcmb"] = 0x031D;
+	chars["uptackmod"] = 0x02D4;
+	chars["uragurmukhi"] = 0x0A73;
+	chars["Uring"] = 0x016E;
+	chars["uring"] = 0x016F;
+	chars["Ushortcyrillic"] = 0x040E;
+	chars["ushortcyrillic"] = 0x045E;
+	chars["Usmall"] = 0xF775;
+	chars["usmallhiragana"] = 0x3045;
+	chars["usmallkatakana"] = 0x30A5;
+	chars["usmallkatakanahalfwidth"] = 0xFF69;
+	chars["Ustraightcyrillic"] = 0x04AE;
+	chars["ustraightcyrillic"] = 0x04AF;
+	chars["Ustraightstrokecyrillic"] = 0x04B0;
+	chars["ustraightstrokecyrillic"] = 0x04B1;
+	chars["Utilde"] = 0x0168;
+	chars["utilde"] = 0x0169;
+	chars["Utildeacute"] = 0x1E78;
+	chars["utildeacute"] = 0x1E79;
+	chars["Utildebelow"] = 0x1E74;
+	chars["utildebelow"] = 0x1E75;
+	chars["uubengali"] = 0x098A;
+	chars["uudeva"] = 0x090A;
+	chars["uugujarati"] = 0x0A8A;
+	chars["uugurmukhi"] = 0x0A0A;
+	chars["uumatragurmukhi"] = 0x0A42;
+	chars["uuvowelsignbengali"] = 0x09C2;
+	chars["uuvowelsigndeva"] = 0x0942;
+	chars["uuvowelsigngujarati"] = 0x0AC2;
+	chars["uvowelsignbengali"] = 0x09C1;
+	chars["uvowelsigndeva"] = 0x0941;
+	chars["uvowelsigngujarati"] = 0x0AC1;
+	chars["V"] = 0x0056;
+	chars["v"] = 0x0076;
+	chars["vadeva"] = 0x0935;
+	chars["vagujarati"] = 0x0AB5;
+	chars["vagurmukhi"] = 0x0A35;
+	chars["vakatakana"] = 0x30F7;
+	chars["vav"] = 0x05D5;
+	chars["vavdagesh"] = 0xFB35;
+	chars["vavdagesh65"] = 0xFB35;
+	chars["vavdageshhebrew"] = 0xFB35;
+	chars["vavhebrew"] = 0x05D5;
+	chars["vavholam"] = 0xFB4B;
+	chars["vavholamhebrew"] = 0xFB4B;
+	chars["vavvavhebrew"] = 0x05F0;
+	chars["vavyodhebrew"] = 0x05F1;
+	chars["Vcircle"] = 0x24CB;
+	chars["vcircle"] = 0x24E5;
+	chars["Vdotbelow"] = 0x1E7E;
+	chars["vdotbelow"] = 0x1E7F;
+	chars["Vecyrillic"] = 0x0412;
+	chars["vecyrillic"] = 0x0432;
+	chars["veharabic"] = 0x06A4;
+	chars["vehfinalarabic"] = 0xFB6B;
+	chars["vehinitialarabic"] = 0xFB6C;
+	chars["vehmedialarabic"] = 0xFB6D;
+	chars["vekatakana"] = 0x30F9;
+	chars["venus"] = 0x2640;
+	chars["verticalbar"] = 0x007C;
+	chars["verticallineabovecmb"] = 0x030D;
+	chars["verticallinebelowcmb"] = 0x0329;
+	chars["verticallinelowmod"] = 0x02CC;
+	chars["verticallinemod"] = 0x02C8;
+	chars["Vewarmenian"] = 0x054E;
+	chars["vewarmenian"] = 0x057E;
+	chars["Vhook"] = 0x01B2;
+	chars["vhook"] = 0x028B;
+	chars["vikatakana"] = 0x30F8;
+	chars["viramabengali"] = 0x09CD;
+	chars["viramadeva"] = 0x094D;
+	chars["viramagujarati"] = 0x0ACD;
+	chars["visargabengali"] = 0x0983;
+	chars["visargadeva"] = 0x0903;
+	chars["visargagujarati"] = 0x0A83;
+	chars["Vmonospace"] = 0xFF36;
+	chars["vmonospace"] = 0xFF56;
+	chars["Voarmenian"] = 0x0548;
+	chars["voarmenian"] = 0x0578;
+	chars["voicediterationhiragana"] = 0x309E;
+	chars["voicediterationkatakana"] = 0x30FE;
+	chars["voicedmarkkana"] = 0x309B;
+	chars["voicedmarkkanahalfwidth"] = 0xFF9E;
+	chars["vokatakana"] = 0x30FA;
+	chars["vparen"] = 0x24B1;
+	chars["Vsmall"] = 0xF776;
+	chars["Vtilde"] = 0x1E7C;
+	chars["vtilde"] = 0x1E7D;
+	chars["vturned"] = 0x028C;
+	chars["vuhiragana"] = 0x3094;
+	chars["vukatakana"] = 0x30F4;
+	chars["W"] = 0x0057;
+	chars["w"] = 0x0077;
+	chars["Wacute"] = 0x1E82;
+	chars["wacute"] = 0x1E83;
+	chars["waekorean"] = 0x3159;
+	chars["wahiragana"] = 0x308F;
+	chars["wakatakana"] = 0x30EF;
+	chars["wakatakanahalfwidth"] = 0xFF9C;
+	chars["wakorean"] = 0x3158;
+	chars["wasmallhiragana"] = 0x308E;
+	chars["wasmallkatakana"] = 0x30EE;
+	chars["wattosquare"] = 0x3357;
+	chars["wavedash"] = 0x301C;
+	chars["wavyunderscorevertical"] = 0xFE34;
+	chars["wawarabic"] = 0x0648;
+	chars["wawfinalarabic"] = 0xFEEE;
+	chars["wawhamzaabovearabic"] = 0x0624;
+	chars["wawhamzaabovefinalarabic"] = 0xFE86;
+	chars["wbsquare"] = 0x33DD;
+	chars["Wcircle"] = 0x24CC;
+	chars["wcircle"] = 0x24E6;
+	chars["Wcircumflex"] = 0x0174;
+	chars["wcircumflex"] = 0x0175;
+	chars["Wdieresis"] = 0x1E84;
+	chars["wdieresis"] = 0x1E85;
+	chars["Wdotaccent"] = 0x1E86;
+	chars["wdotaccent"] = 0x1E87;
+	chars["Wdotbelow"] = 0x1E88;
+	chars["wdotbelow"] = 0x1E89;
+	chars["wehiragana"] = 0x3091;
+	chars["weierstrass"] = 0x2118;
+	chars["wekatakana"] = 0x30F1;
+	chars["wekorean"] = 0x315E;
+	chars["weokorean"] = 0x315D;
+	chars["Wgrave"] = 0x1E80;
+	chars["wgrave"] = 0x1E81;
+	chars["whitebullet"] = 0x25E6;
+	chars["whitecircle"] = 0x25CB;
+	chars["whitecircleinverse"] = 0x25D9;
+	chars["whitecornerbracketleft"] = 0x300E;
+	chars["whitecornerbracketleftvertical"] = 0xFE43;
+	chars["whitecornerbracketright"] = 0x300F;
+	chars["whitecornerbracketrightvertical"] = 0xFE44;
+	chars["whitediamond"] = 0x25C7;
+	chars["whitediamondcontainingblacksmalldiamond"] = 0x25C8;
+	chars["whitedownpointingsmalltriangle"] = 0x25BF;
+	chars["whitedownpointingtriangle"] = 0x25BD;
+	chars["whiteleftpointingsmalltriangle"] = 0x25C3;
+	chars["whiteleftpointingtriangle"] = 0x25C1;
+	chars["whitelenticularbracketleft"] = 0x3016;
+	chars["whitelenticularbracketright"] = 0x3017;
+	chars["whiterightpointingsmalltriangle"] = 0x25B9;
+	chars["whiterightpointingtriangle"] = 0x25B7;
+	chars["whitesmallsquare"] = 0x25AB;
+	chars["whitesmilingface"] = 0x263A;
+	chars["whitesquare"] = 0x25A1;
+	chars["whitestar"] = 0x2606;
+	chars["whitetelephone"] = 0x260F;
+	chars["whitetortoiseshellbracketleft"] = 0x3018;
+	chars["whitetortoiseshellbracketright"] = 0x3019;
+	chars["whiteuppointingsmalltriangle"] = 0x25B5;
+	chars["whiteuppointingtriangle"] = 0x25B3;
+	chars["wihiragana"] = 0x3090;
+	chars["wikatakana"] = 0x30F0;
+	chars["wikorean"] = 0x315F;
+	chars["Wmonospace"] = 0xFF37;
+	chars["wmonospace"] = 0xFF57;
+	chars["wohiragana"] = 0x3092;
+	chars["wokatakana"] = 0x30F2;
+	chars["wokatakanahalfwidth"] = 0xFF66;
+	chars["won"] = 0x20A9;
+	chars["wonmonospace"] = 0xFFE6;
+	chars["wowaenthai"] = 0x0E27;
+	chars["wparen"] = 0x24B2;
+	chars["wring"] = 0x1E98;
+	chars["Wsmall"] = 0xF777;
+	chars["wsuperior"] = 0x02B7;
+	chars["wturned"] = 0x028D;
+	chars["wynn"] = 0x01BF;
+	chars["X"] = 0x0058;
+	chars["x"] = 0x0078;
+	chars["xabovecmb"] = 0x033D;
+	chars["xbopomofo"] = 0x3112;
+	chars["Xcircle"] = 0x24CD;
+	chars["xcircle"] = 0x24E7;
+	chars["Xdieresis"] = 0x1E8C;
+	chars["xdieresis"] = 0x1E8D;
+	chars["Xdotaccent"] = 0x1E8A;
+	chars["xdotaccent"] = 0x1E8B;
+	chars["Xeharmenian"] = 0x053D;
+	chars["xeharmenian"] = 0x056D;
+	chars["Xi"] = 0x039E;
+	chars["xi"] = 0x03BE;
+	chars["Xmonospace"] = 0xFF38;
+	chars["xmonospace"] = 0xFF58;
+	chars["xparen"] = 0x24B3;
+	chars["Xsmall"] = 0xF778;
+	chars["xsuperior"] = 0x02E3;
+	chars["Y"] = 0x0059;
+	chars["y"] = 0x0079;
+	chars["yaadosquare"] = 0x334E;
+	chars["yabengali"] = 0x09AF;
+	chars["Yacute"] = 0x00DD;
+	chars["yacute"] = 0x00FD;
+	chars["Yacutesmall"] = 0xF7FD;
+	chars["yadeva"] = 0x092F;
+	chars["yaekorean"] = 0x3152;
+	chars["yagujarati"] = 0x0AAF;
+	chars["yagurmukhi"] = 0x0A2F;
+	chars["yahiragana"] = 0x3084;
+	chars["yakatakana"] = 0x30E4;
+	chars["yakatakanahalfwidth"] = 0xFF94;
+	chars["yakorean"] = 0x3151;
+	chars["yamakkanthai"] = 0x0E4E;
+	chars["yasmallhiragana"] = 0x3083;
+	chars["yasmallkatakana"] = 0x30E3;
+	chars["yasmallkatakanahalfwidth"] = 0xFF6C;
+	chars["Yatcyrillic"] = 0x0462;
+	chars["yatcyrillic"] = 0x0463;
+	chars["Ycircle"] = 0x24CE;
+	chars["ycircle"] = 0x24E8;
+	chars["Ycircumflex"] = 0x0176;
+	chars["ycircumflex"] = 0x0177;
+	chars["ydieresis"] = 0x00FF;
+	chars["Ydieresis"] = 0x0178;
+	chars["Ydieresissmall"] = 0xF7FF;
+	chars["Ydotaccent"] = 0x1E8E;
+	chars["ydotaccent"] = 0x1E8F;
+	chars["Ydotbelow"] = 0x1EF4;
+	chars["ydotbelow"] = 0x1EF5;
+	chars["yeharabic"] = 0x064A;
+	chars["yehbarreearabic"] = 0x06D2;
+	chars["yehbarreefinalarabic"] = 0xFBAF;
+	chars["yehfinalarabic"] = 0xFEF2;
+	chars["yehhamzaabovearabic"] = 0x0626;
+	chars["yehhamzaabovefinalarabic"] = 0xFE8A;
+	chars["yehhamzaaboveinitialarabic"] = 0xFE8B;
+	chars["yehhamzaabovemedialarabic"] = 0xFE8C;
+	chars["yehinitialarabic"] = 0xFEF3;
+	chars["yehmedialarabic"] = 0xFEF4;
+	chars["yehmeeminitialarabic"] = 0xFCDD;
+	chars["yehmeemisolatedarabic"] = 0xFC58;
+	chars["yehnoonfinalarabic"] = 0xFC94;
+	chars["yehthreedotsbelowarabic"] = 0x06D1;
+	chars["yekorean"] = 0x3156;
+	chars["yen"] = 0x00A5;
+	chars["yenmonospace"] = 0xFFE5;
+	chars["yeokorean"] = 0x3155;
+	chars["yeorinhieuhkorean"] = 0x3186;
+	chars["yerahbenyomohebrew"] = 0x05AA;
+	chars["yerahbenyomolefthebrew"] = 0x05AA;
+	chars["Yericyrillic"] = 0x042B;
+	chars["yericyrillic"] = 0x044B;
+	chars["Yerudieresiscyrillic"] = 0x04F8;
+	chars["yerudieresiscyrillic"] = 0x04F9;
+	chars["yesieungkorean"] = 0x3181;
+	chars["yesieungpansioskorean"] = 0x3183;
+	chars["yesieungsioskorean"] = 0x3182;
+	chars["yetivhebrew"] = 0x059A;
+	chars["Ygrave"] = 0x1EF2;
+	chars["ygrave"] = 0x1EF3;
+	chars["Yhook"] = 0x01B3;
+	chars["yhook"] = 0x01B4;
+	chars["Yhookabove"] = 0x1EF6;
+	chars["yhookabove"] = 0x1EF7;
+	chars["Yiarmenian"] = 0x0545;
+	chars["yiarmenian"] = 0x0575;
+	chars["Yicyrillic"] = 0x0407;
+	chars["yicyrillic"] = 0x0457;
+	chars["yikorean"] = 0x3162;
+	chars["yinyang"] = 0x262F;
+	chars["Yiwnarmenian"] = 0x0552;
+	chars["yiwnarmenian"] = 0x0582;
+	chars["Ymonospace"] = 0xFF39;
+	chars["ymonospace"] = 0xFF59;
+	chars["yod"] = 0x05D9;
+	chars["yoddagesh"] = 0xFB39;
+	chars["yoddageshhebrew"] = 0xFB39;
+	chars["yodhebrew"] = 0x05D9;
+	chars["yodyodhebrew"] = 0x05F2;
+	chars["yodyodpatahhebrew"] = 0xFB1F;
+	chars["yohiragana"] = 0x3088;
+	chars["yoikorean"] = 0x3189;
+	chars["yokatakana"] = 0x30E8;
+	chars["yokatakanahalfwidth"] = 0xFF96;
+	chars["yokorean"] = 0x315B;
+	chars["yosmallhiragana"] = 0x3087;
+	chars["yosmallkatakana"] = 0x30E7;
+	chars["yosmallkatakanahalfwidth"] = 0xFF6E;
+	chars["yotgreek"] = 0x03F3;
+	chars["yoyaekorean"] = 0x3188;
+	chars["yoyakorean"] = 0x3187;
+	chars["yoyakthai"] = 0x0E22;
+	chars["yoyingthai"] = 0x0E0D;
+	chars["yparen"] = 0x24B4;
+	chars["ypogegrammeni"] = 0x037A;
+	chars["ypogegrammenigreekcmb"] = 0x0345;
+	chars["yr"] = 0x01A6;
+	chars["yring"] = 0x1E99;
+	chars["Ysmall"] = 0xF779;
+	chars["ysuperior"] = 0x02B8;
+	chars["Ytilde"] = 0x1EF8;
+	chars["ytilde"] = 0x1EF9;
+	chars["yturned"] = 0x028E;
+	chars["yuhiragana"] = 0x3086;
+	chars["yuikorean"] = 0x318C;
+	chars["yukatakana"] = 0x30E6;
+	chars["yukatakanahalfwidth"] = 0xFF95;
+	chars["yukorean"] = 0x3160;
+	chars["Yusbigcyrillic"] = 0x046A;
+	chars["yusbigcyrillic"] = 0x046B;
+	chars["Yusbigiotifiedcyrillic"] = 0x046C;
+	chars["yusbigiotifiedcyrillic"] = 0x046D;
+	chars["Yuslittlecyrillic"] = 0x0466;
+	chars["yuslittlecyrillic"] = 0x0467;
+	chars["Yuslittleiotifiedcyrillic"] = 0x0468;
+	chars["yuslittleiotifiedcyrillic"] = 0x0469;
+	chars["yusmallhiragana"] = 0x3085;
+	chars["yusmallkatakana"] = 0x30E5;
+	chars["yusmallkatakanahalfwidth"] = 0xFF6D;
+	chars["yuyekorean"] = 0x318B;
+	chars["yuyeokorean"] = 0x318A;
+	chars["yyabengali"] = 0x09DF;
+	chars["yyadeva"] = 0x095F;
+	chars["Z"] = 0x005A;
+	chars["z"] = 0x007A;
+	chars["Zaarmenian"] = 0x0536;
+	chars["zaarmenian"] = 0x0566;
+	chars["Zacute"] = 0x0179;
+	chars["zacute"] = 0x017A;
+	chars["zadeva"] = 0x095B;
+	chars["zagurmukhi"] = 0x0A5B;
+	chars["zaharabic"] = 0x0638;
+	chars["zahfinalarabic"] = 0xFEC6;
+	chars["zahinitialarabic"] = 0xFEC7;
+	chars["zahiragana"] = 0x3056;
+	chars["zahmedialarabic"] = 0xFEC8;
+	chars["zainarabic"] = 0x0632;
+	chars["zainfinalarabic"] = 0xFEB0;
+	chars["zakatakana"] = 0x30B6;
+	chars["zaqefgadolhebrew"] = 0x0595;
+	chars["zaqefqatanhebrew"] = 0x0594;
+	chars["zarqahebrew"] = 0x0598;
+	chars["zayin"] = 0x05D6;
+	chars["zayindagesh"] = 0xFB36;
+	chars["zayindageshhebrew"] = 0xFB36;
+	chars["zayinhebrew"] = 0x05D6;
+	chars["zbopomofo"] = 0x3117;
+	chars["Zcaron"] = 0x017D;
+	chars["zcaron"] = 0x017E;
+	chars["Zcaronsmall"] = 0xF6FF;
+	chars["Zcircle"] = 0x24CF;
+	chars["zcircle"] = 0x24E9;
+	chars["Zcircumflex"] = 0x1E90;
+	chars["zcircumflex"] = 0x1E91;
+	chars["zcurl"] = 0x0291;
+	chars["Zdot"] = 0x017B;
+	chars["zdot"] = 0x017C;
+	chars["Zdotaccent"] = 0x017B;
+	chars["zdotaccent"] = 0x017C;
+	chars["Zdotbelow"] = 0x1E92;
+	chars["zdotbelow"] = 0x1E93;
+	chars["Zecyrillic"] = 0x0417;
+	chars["zecyrillic"] = 0x0437;
+	chars["Zedescendercyrillic"] = 0x0498;
+	chars["zedescendercyrillic"] = 0x0499;
+	chars["Zedieresiscyrillic"] = 0x04DE;
+	chars["zedieresiscyrillic"] = 0x04DF;
+	chars["zehiragana"] = 0x305C;
+	chars["zekatakana"] = 0x30BC;
+	chars["zero"] = 0x0030;
+	chars["zeroarabic"] = 0x0660;
+	chars["zerobengali"] = 0x09E6;
+	chars["zerodeva"] = 0x0966;
+	chars["zerogujarati"] = 0x0AE6;
+	chars["zerogurmukhi"] = 0x0A66;
+	chars["zerohackarabic"] = 0x0660;
+	chars["zeroinferior"] = 0x2080;
+	chars["zeromonospace"] = 0xFF10;
+	chars["zerooldstyle"] = 0xF730;
+	chars["zeropersian"] = 0x06F0;
+	chars["zerosuperior"] = 0x2070;
+	chars["zerothai"] = 0x0E50;
+	chars["zerowidthjoiner"] = 0xFEFF;
+	chars["zerowidthnonjoiner"] = 0x200C;
+	chars["zerowidthspace"] = 0x200B;
+	chars["Zeta"] = 0x0396;
+	chars["zeta"] = 0x03B6;
+	chars["zhbopomofo"] = 0x3113;
+	chars["Zhearmenian"] = 0x053A;
+	chars["zhearmenian"] = 0x056A;
+	chars["Zhebrevecyrillic"] = 0x04C1;
+	chars["zhebrevecyrillic"] = 0x04C2;
+	chars["Zhecyrillic"] = 0x0416;
+	chars["zhecyrillic"] = 0x0436;
+	chars["Zhedescendercyrillic"] = 0x0496;
+	chars["zhedescendercyrillic"] = 0x0497;
+	chars["Zhedieresiscyrillic"] = 0x04DC;
+	chars["zhedieresiscyrillic"] = 0x04DD;
+	chars["zihiragana"] = 0x3058;
+	chars["zikatakana"] = 0x30B8;
+	chars["zinorhebrew"] = 0x05AE;
+	chars["Zlinebelow"] = 0x1E94;
+	chars["zlinebelow"] = 0x1E95;
+	chars["Zmonospace"] = 0xFF3A;
+	chars["zmonospace"] = 0xFF5A;
+	chars["zohiragana"] = 0x305E;
+	chars["zokatakana"] = 0x30BE;
+	chars["zparen"] = 0x24B5;
+	chars["zretroflexhook"] = 0x0290;
+	chars["Zsmall"] = 0xF77A;
+	chars["Zstroke"] = 0x01B5;
+	chars["zstroke"] = 0x01B6;
+	chars["zuhiragana"] = 0x305A;
+	chars["zukatakana"] = 0x30BA;
+	// unsorted:
+	chars["angbracketleft"] = 0x3008;
+	chars["angbracketright"] = 0x3009;
+	chars["circlecopyrt"] = 0x00A9;
+	chars["angbracketleftbig"] = 0x2329;
+	chars["angbracketleftBig"] = 0x2329;
+	chars["angbracketleftbigg"] = 0x2329;
+	chars["angbracketleftBigg"] = 0x2329;
+	chars["angbracketrightBig"] = 0x232A;
+	chars["angbracketrightbig"] = 0x232A;
+	chars["angbracketrightBigg"] = 0x232A;
+	chars["angbracketrightbigg"] = 0x232A;
+	chars["arrowhookleft"] = 0x21AA;
+	chars["arrowhookright"] = 0x21A9;
+	chars["arrowlefttophalf"] = 0x21BC;
+	chars["arrowleftbothalf"] = 0x21BD;
+	chars["arrownortheast"] = 0x2197;
+	chars["arrownorthwest"] = 0x2196;
+	chars["arrowrighttophalf"] = 0x21C0;
+	chars["arrowrightbothalf"] = 0x21C1;
+	chars["arrowsoutheast"] = 0x2198;
+	chars["arrowsouthwest"] = 0x2199;
+	chars["backslashbig"] = 0x2216;
+	chars["backslashBig"] = 0x2216;
+	chars["backslashBigg"] = 0x2216;
+	chars["backslashbigg"] = 0x2216;
+	chars["bardbl"] = 0x2016;
+	chars["bracehtipdownleft"] = 0xFE37;
+	chars["bracehtipdownright"] = 0xFE37;
+	chars["bracehtipupleft"] = 0xFE38;
+	chars["bracehtipupright"] = 0xFE38;
+	chars["braceleftBig"] = 0x007B;
+	chars["braceleftbig"] = 0x007B;
+	chars["braceleftbigg"] = 0x007B;
+	chars["braceleftBigg"] = 0x007B;
+	chars["bracerightBig"] = 0x007D;
+	chars["bracerightbig"] = 0x007D;
+	chars["bracerightbigg"] = 0x007D;
+	chars["bracerightBigg"] = 0x007D;
+	chars["bracketleftbig"] = 0x005B;
+	chars["bracketleftBig"] = 0x005B;
+	chars["bracketleftbigg"] = 0x005B;
+	chars["bracketleftBigg"] = 0x005B;
+	chars["bracketrightBig"] = 0x005D;
+	chars["bracketrightbig"] = 0x005D;
+	chars["bracketrightbigg"] = 0x005D;
+	chars["bracketrightBigg"] = 0x005D;
+	chars["ceilingleftbig"] = 0x2308;
+	chars["ceilingleftBig"] = 0x2308;
+	chars["ceilingleftBigg"] = 0x2308;
+	chars["ceilingleftbigg"] = 0x2308;
+	chars["ceilingrightbig"] = 0x2309;
+	chars["ceilingrightBig"] = 0x2309;
+	chars["ceilingrightbigg"] = 0x2309;
+	chars["ceilingrightBigg"] = 0x2309;
+	chars["circledotdisplay"] = 0x2299;
+	chars["circledottext"] = 0x2299;
+	chars["circlemultiplydisplay"] = 0x2297;
+	chars["circlemultiplytext"] = 0x2297;
+	chars["circleplusdisplay"] = 0x2295;
+	chars["circleplustext"] = 0x2295;
+	chars["contintegraldisplay"] = 0x222E;
+	chars["contintegraltext"] = 0x222E;
+	chars["coproductdisplay"] = 0x2210;
+	chars["coproducttext"] = 0x2210;
+	chars["floorleftBig"] = 0x230A;
+	chars["floorleftbig"] = 0x230A;
+	chars["floorleftbigg"] = 0x230A;
+	chars["floorleftBigg"] = 0x230A;
+	chars["floorrightbig"] = 0x230B;
+	chars["floorrightBig"] = 0x230B;
+	chars["floorrightBigg"] = 0x230B;
+	chars["floorrightbigg"] = 0x230B;
+	chars["hatwide"] = 0x0302;
+	chars["hatwider"] = 0x0302;
+	chars["hatwidest"] = 0x0302;
+	chars["intercal"] = 0x1D40;
+	chars["integraldisplay"] = 0x222B;
+	chars["integraltext"] = 0x222B;
+	chars["intersectiondisplay"] = 0x22C2;
+	chars["intersectiontext"] = 0x22C2;
+	chars["logicalanddisplay"] = 0x2227;
+	chars["logicalandtext"] = 0x2227;
+	chars["logicalordisplay"] = 0x2228;
+	chars["logicalortext"] = 0x2228;
+	chars["parenleftBig"] = 0x0028;
+	chars["parenleftbig"] = 0x0028;
+	chars["parenleftBigg"] = 0x0028;
+	chars["parenleftbigg"] = 0x0028;
+	chars["parenrightBig"] = 0x0029;
+	chars["parenrightbig"] = 0x0029;
+	chars["parenrightBigg"] = 0x0029;
+	chars["parenrightbigg"] = 0x0029;
+	chars["prime"] = 0x2032;
+	chars["productdisplay"] = 0x220F;
+	chars["producttext"] = 0x220F;
+	chars["radicalbig"] = 0x221A;
+	chars["radicalBig"] = 0x221A;
+	chars["radicalBigg"] = 0x221A;
+	chars["radicalbigg"] = 0x221A;
+	chars["radicalbt"] = 0x221A;
+	chars["radicaltp"] = 0x221A;
+	chars["radicalvertex"] = 0x221A;
+	chars["slashbig"] = 0x002F;
+	chars["slashBig"] = 0x002F;
+	chars["slashBigg"] = 0x002F;
+	chars["slashbigg"] = 0x002F;
+	chars["summationdisplay"] = 0x2211;
+	chars["summationtext"] = 0x2211;
+	chars["tildewide"] = 0x02DC;
+	chars["tildewider"] = 0x02DC;
+	chars["tildewidest"] = 0x02DC;
+	chars["uniondisplay"] = 0x22C3;
+	chars["unionmultidisplay"] = 0x228E;
+	chars["unionmultitext"] = 0x228E;
+	chars["unionsqdisplay"] = 0x2294;
+	chars["unionsqtext"] = 0x2294;
+	chars["uniontext"] = 0x22C3;
+	chars["vextenddouble"] = 0x2225;
+	chars["vextendsingle"] = 0x2223;
+	chars["x1b"] = 0xFB00;
+	chars["x1c"] = 0xFB01;
+	chars["x1d"] = 0xFB02;
+	chars["x1e"] = 0xFB03;
+	chars["x8a"] = 0x0141;
+	chars["xff"] = 0x00DF;
+	chars["a27"] = 0xFB00;
+	chars["a28"] = 0xFB01;
+	chars["a29"] = 0xFB02;
+	chars["a30"] = 0xFB03;
+	chars["a138"] = 0x0141;
+	chars["a255"] = 0x00DF;
+	chars["lscript"] = 0x006C; // TODO U1D4C1;
+	chars["rho1"] = 0x03A1;  // what's special with this rho?
+	chars["slurabove"] = 0x2322;
+	chars["slurbelow"] = 0x2323;
+	return chars;
+}
+
+static std::map<std::string, unsigned int> charMap = createCharMap();
+
+/// \return cNilCodepoint if not found.
+unsigned int getUnicodeFromDefaultCharMap(const std::string& key) {
+	std::map<std::string, unsigned int>::const_iterator iter = charMap.find(key);
+	if(iter != charMap.end())
+		return iter->second;
+	else {
+		std::cerr << "PdfDefaultCharMap: entry not found: " << key << std::endl;
+		return cNilCodepoint;
+	}
+}
+
+#endif
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfDepredictor.cpp fbreader-0.12.10/fbreader/src/formats/pdf/PdfDepredictor.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfDepredictor.cpp	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfDepredictor.cpp	2011-04-05 22:55:28.000000000 +0200
@@ -0,0 +1,107 @@
+#include <iostream>
+#include <string>
+#include <string.h>
+#include <vector>
+#include "PdfDepredictor.h"
+
+/* this is used for the funniest things in PDF in the wild, even for the Trailer (which isn't a picture :P) */
+
+	unsigned int abs42(int a) {
+		return(a > 0) ? a : -a;
+	}
+	
+/* this could actually be converted into a fully-fledged InputStream if it just buffered two "lines". */
+	/* in-place depredictor */
+	int PNG_depredict(int columns, unsigned char* data, int data_len) {
+		unsigned char* row_data;
+		unsigned char* original_row_data;
+		unsigned char* original_data;
+		int original_data_len;
+		int scanline_length = columns + 1;
+		int paeth = 0;
+		int pa = 0;
+		int index;
+		int pb = 0;
+		int pc = 0;
+		original_data = data;
+		original_data_len = data_len;
+		for(int row = 0; row_data = data, data_len >= scanline_length; ++row, data += scanline_length, data_len -= scanline_length) {
+			int filter = *row_data;
+			++row_data;
+			original_row_data = row_data;
+			if(filter == 0) {
+				/* none */
+			} else if(filter == 1) { /* Sub */
+				for(index = 0; index < scanline_length - 1; ++index, ++row_data) {
+					unsigned char left = (index < 1) ? 0 : *(row_data - 1);
+					*row_data += left;
+					/* prediction [pixel, left, row_data[index]] */
+				}
+			} else if(filter == 2) { /* Up */
+				for(index = 0; index < scanline_length - 1; ++index, ++row_data) {
+					unsigned char upper = (row == 0) ? 0 : *(row_data - scanline_length);
+					*row_data += upper;
+				}
+			} else if(filter == 3) { /* Average */
+				unsigned char pixel;
+				for(index = 0; pixel = row_data[index], index < scanline_length - 1; ++index, ++row_data) {
+					unsigned char upper = (row == 0) ? 0 : *(row_data - scanline_length);
+					unsigned char left = (index < 1) ? 0 : *(row_data - 1);
+					*row_data = (unsigned int) (pixel + (unsigned int)((left + upper)/2));
+				}
+			} else if(filter == 4) { /* Paeth */
+				/* TODO test */
+				unsigned char pixel;
+				unsigned char left = 0;
+				unsigned char upper = 0;
+				unsigned char upper_left = 0;
+				for(index = 0; pixel = *row_data, index < scanline_length - 1; ++index) {
+					left = (index < 1) ? 0 : *(row_data - 1);
+					if(row == 0) {
+						upper = 0;
+						upper_left = 0;
+					} else {
+						upper = *(row_data - scanline_length);
+						upper_left = (index == 0) ? 0 : *(row_data - scanline_length - 1);
+					}
+					int p = (int) left + (int) upper - (int) upper_left;
+					pa = abs42(p - left);
+					pb = abs42(p - upper);
+					pc = abs42(p - upper_left);
+					paeth = (pa <= pb && pa <= pc) ? left :
+					        (pb <= pc) ? upper : 
+					        upper_left;
+					*row_data = (pixel + paeth);
+				}
+			} else {
+				std::cerr << "invalid filter " << filter << std::endl;
+				/*raise DepredictionError("invalid filter %r" % filter)*/
+			}
+		}
+		{ /* remove the filters.
+		     Memory layout is:
+		        <filter> <data> <data> <data> [...]
+		        <filter> <data> <data> <data> [...]
+		        ...
+		     remove the <filter> by scrolling over it. */
+			int shortened_count = 0;
+			int i;
+			for(i = 0; i < original_data_len; i += scanline_length, ++shortened_count) {
+				memcpy(&original_data[i - shortened_count], &original_data[i + 1], scanline_length - 1);
+			}
+			return shortened_count;
+		}
+	}
+	int depredict(int columns, int predictor, unsigned char* data, int data_len) {
+		if(predictor == 0 || predictor == 1)
+			return 0;
+		else if(predictor == 2) /* TIFF */ {
+			std::cerr << "error: TIFF predictor not supported yet." << std::endl;
+			return 0;
+		} else if(predictor == 10 || predictor == 11 || predictor == 12 || predictor == 13 || predictor == 14 || predictor == 15)
+			return PNG_depredict(columns, data, data_len);
+		else {
+			std::cerr << "error: ignored unknown predictor " << predictor << std::endl;
+			return 0;
+		}
+	}
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfDepredictor.h fbreader-0.12.10/fbreader/src/formats/pdf/PdfDepredictor.h
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfDepredictor.h	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfDepredictor.h	2011-04-05 22:55:28.000000000 +0200
@@ -0,0 +1,6 @@
+#ifndef __PDF_DEPREDICTOR_H
+#define __PDF_DEPREDICTOR_H
+
+int depredict(int columns, int predictor, unsigned char* data, int data_len);
+
+#endif /* __PDF_DEPREDICTOR_H */
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfFont.cpp fbreader-0.12.10/fbreader/src/formats/pdf/PdfFont.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfFont.cpp	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfFont.cpp	2012-08-03 18:39:21.390943304 +0200
@@ -0,0 +1,434 @@
+/*PDF parser.
+Copyright (C) 2008 Danny Milosavljevic <danny_milo@yahoo.com>
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if !, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+#include <assert.h>
+#include <math.h>
+#include "PdfFont.h"
+#include "PdfToUnicodeParser.h"
+#include "PdfType1FontFileParser.h"
+#include "PdfDefaultCharMap.h"
+
+/* TODO have one place to define this */
+#define EPSILON 0.0002           
+
+/* widths is an array of:
+   number [array]
+Widths are in font coordinates.
+ */
+PdfFont::PdfFont(shared_ptr<PdfObject> metadata, 
+                 shared_ptr<PdfObject> fontDescriptor, 
+                 shared_ptr<PdfObject> encoding, 
+                 shared_ptr<PdfObject> fontFile, 
+                 shared_ptr<PdfObject> toUnicode, 
+                 PdfXObjects resources, 
+                 shared_ptr<PdfObject> widths, 
+                 shared_ptr<PdfObject> ws,
+                 int widthsMissingWidth,
+                 int widthsFirstChar) : 
+                 myResources(resources), 
+                 myWidths(widths), 
+                 myWs(ws), 
+                 myWidthsMissingWidth(widthsMissingWidth),
+                 myWidthsFirstChar(widthsFirstChar) {
+	if(metadata->type() != PdfObject::DICTIONARY)
+		return;
+	PdfDictionaryObject& fontDictionary = (PdfDictionaryObject&)*metadata;
+	if(fontDictionary["Type"].isNull() || fontDictionary["Type"] != PdfNameObject::nameObject("Font"))
+		return;
+	if(containsUnicode()) {
+		parseEncoding(encoding);
+		if(!parseToUnicodeTable(toUnicode)) {
+			parseFontFile(fontFile);
+		}
+	}
+
+	myScale = 0.001; // default as per spec.
+	myBBoldness = false;
+	std::string fontName = "?";
+	if(!fontDescriptor.isNull()) {
+		const PdfDictionaryObject& fontDescriptorDictionary = (const PdfDictionaryObject&)*fontDescriptor;
+		doubleFromPdfObject(fontDescriptorDictionary["Descent"], myDescent);
+		doubleFromPdfObject(fontDescriptorDictionary["Ascent"], myAscent);
+		shared_ptr<PdfObject> fontNameX = fontDescriptorDictionary["FontName"];
+		if(!fontNameX.isNull() && fontNameX->type() == PdfObject::NAME) {
+			fontName = ((PdfNameObject&)*fontNameX).id();
+			myBBoldness = fontName.find("Bold") != std::string::npos;
+		}
+		int flags;
+		if(integerFromPdfObject(fontDescriptorDictionary["Flags"], flags)) {
+			if(flags & (1 << 18)) { // force bold.
+				myBBoldness = true;
+			}
+		}
+		shared_ptr<PdfObject> fontBBoxX = fontDescriptorDictionary["FontBBox"];
+		if(!fontBBoxX.isNull() && fontBBoxX->type() == PdfObject::ARRAY) {
+			const PdfArrayObject& fontBBox = (const PdfArrayObject&)*fontBBoxX;
+			double topBBox, bottomBBox;
+			if(fontBBox.size() >= 4 && doubleFromPdfObject(fontBBox[1], topBBox) && doubleFromPdfObject(fontBBox[3], bottomBBox)) {
+				if(myAscent < EPSILON && myDescent > -EPSILON) {
+					myDescent = topBBox;
+					myAscent = bottomBBox;
+				}
+#if 0
+				myScale = fabs(bottomBBox - topBBox);
+				if(myScale > EPSILON)
+						myScale = 1/myScale;
+				else {
+					std::cerr << "warning: BBox of font \"" << fontName << "\" is invalid. Ignoring." << std::endl;
+					myScale = 0.001;
+				}
+#endif
+			}
+		}
+	} else {
+		myDescent = myAscent = 0.0;
+		std::cerr << "warning: no ascent/descent information for font." << std::endl;
+	}
+	
+	
+	shared_ptr<PdfObject> fontMatrixX = fontDictionary["FontMatrix"];
+	if(!fontMatrixX.isNull() && fontMatrixX->type() == PdfObject::ARRAY) {
+		const PdfArrayObject& fontMatrix = (const PdfArrayObject&)*fontMatrixX;
+		if(fontMatrix.size() >= 1) {
+			if(doubleFromPdfObject(fontMatrix[0], myScale)) {
+			}
+		}
+		// 6 values. default: [0.001 0 0 0.001 0 0] for the default 1000 units glyph space = 1 unit text space.
+	}
+
+	if(myToUnicodeMap.size() == 0 && containsUnicode()) { 
+		std::cerr << "warning: font \"" << fontName << "\" has no known unicode codepoints, although it should." << std::endl;
+	}
+	//std::cout << "font attrs: " << fontName << ": ascent " << myAscent << ", descent " << myDescent << std::endl;
+	prepare();
+}
+
+static unsigned unicodeFromAnsiTableHigh[32] = {
+	0x20AC, /* 128 */
+	0x81, /* 129 */
+	0x201A, /* 130 */
+	0x192, /* 131 */
+	0x201E, /* 132 */
+	0x2026, /* 133 */
+	0x2020, /* 134 */
+	0x2021, /* 135 */
+	0x2C6, /* 136 */
+	0x2030, /* 137 */
+	0x160, /* 138 */
+	0x2039, /* 139 */
+	0x152, /* 140 */
+	0x8D, /* 141 */
+	0x17D, /* 142 */
+	0x8F, /* 143 */
+	0x90, /* 144 */
+	0x2018, /* 145 */
+	0x2019, /* 146 */
+	0x201C, /* 147 */
+	0x201D, /* 148 */
+	0x2022, /* 149 */
+	0x2013, /* 150 */
+	0x2014, /* 151 */
+	0x2DC, /* 152 */
+	0x2122, /* 153 */
+	0x161, /* 154 */
+	0x203A, /* 155 */
+	0x153, /* 156 */
+	0x9D, /* 157 */
+	0x17E, /* 158 */
+	0x178, /* 159 */
+};
+
+static unsigned unicodeFromMacRomanTableHigh[] = {
+	0x00C4, /* 128 */
+	0x00C5, /* 129 */
+	0x00C7, /* 130 */
+	0x00C9, /* 131 */
+	0x00D1, /* 132 */
+	0x00D6, /* 133 */
+	0x00DC, /* 134 */
+	0x00E1, /* 135 */
+	0x00E0, /* 136 */
+	0x00E2, /* 137 */
+	0x00E4, /* 138 */
+	0x00E3, /* 139 */
+	0x00E5, /* 140 */
+	0x00E7, /* 141 */
+	0x00E9, /* 142 */
+	0x00E8, /* 143 */
+	0x00EA, /* 144 */
+	0x00EB, /* 145 */
+	0x00ED, /* 146 */
+	0x00EC, /* 147 */
+	0x00EE, /* 148 */
+	0x00EF, /* 149 */
+	0x00F1, /* 150 */
+	0x00F3, /* 151 */
+	0x00F2, /* 152 */
+	0x00F4, /* 153 */
+	0x00F6, /* 154 */
+	0x00F5, /* 155 */
+	0x00FA, /* 156 */
+	0x00F9, /* 157 */
+	0x00FB, /* 158 */
+	0x00FC, /* 159 */
+	0x2020, /* 160 */
+	0x00B0, /* 161 */
+	0x00A2, /* 162 */
+	0x00A3, /* 163 */
+	0x00A7, /* 164 */
+	0x2022, /* 165 */
+	0x00B6, /* 166 */
+	0x00DF, /* 167 */
+	0x00AE, /* 168 */
+	0x00A9, /* 169 */
+	0x2122, /* 170 */
+	0x00B4, /* 171 */
+	0x00A8, /* 172 */
+	0x2260, /* 173 */
+	0x00C6, /* 174 */
+	0x00D8, /* 175 */
+	0x221E, /* 176 */
+	0x00B1, /* 177 */
+	0x2264, /* 178 */
+	0x2265, /* 179 */
+	0x00A5, /* 180 */
+	0x00B5, /* 181 */
+	0x2202, /* 182 */
+	0x2211, /* 183 */
+	0x220F, /* 184 */
+	0x03C0, /* 185 */
+	0x222B, /* 186 */
+	0x00AA, /* 187 */
+	0x00BA, /* 188 */
+	0x03A9, /* 189 */
+	0x00E6, /* 190 */
+	0x00F8, /* 191 */
+	0x00BF, /* 192 */
+	0x00A1, /* 193 */
+	0x00AC, /* 194 */
+	0x221A, /* 195 */
+	0x0192, /* 196 */
+	0x2248, /* 197 */
+	0x2206, /* 198 */
+	0x00AB, /* 199 */
+	0x00BB, /* 200 */
+	0x2026, /* 201 */
+	0x00A0, /* 202 */
+	0x00C0, /* 203 */
+	0x00C3, /* 204 */
+	0x00D5, /* 205 */
+	0x0152, /* 206 */
+	0x0153, /* 207 */
+	0x2013, /* 208 */
+	0x2014, /* 209 */
+	0x201C, /* 210 */
+	0x201D, /* 211 */
+	0x2018, /* 212 */
+	0x2019, /* 213 */
+	0x00F7, /* 214 */
+	0x25CA, /* 215 */
+	0x00FF, /* 216 */
+	0x0178, /* 217 */
+	0x2044, /* 218 */
+	0x20AC, /* 219 */
+	0x2039, /* 220 */
+	0x203A, /* 221 */
+	0xFB01, /* 222 */
+	0xFB02, /* 223 */
+	0x2021, /* 224 */
+	0x00B7, /* 225 */
+	0x201A, /* 226 */
+	0x201E, /* 227 */
+	0x2030, /* 228 */
+	0x00C2, /* 229 */
+	0x00CA, /* 230 */
+	0x00C1, /* 231 */
+	0x00CB, /* 232 */
+	0x00C8, /* 233 */
+	0x00CD, /* 234 */
+	0x00CE, /* 235 */
+	0x00CF, /* 236 */
+	0x00CC, /* 237 */
+	0x00D3, /* 238 */
+	0x00D4, /* 239 */
+	0xF8FF, /* 240 */
+	0x00D2, /* 241 */
+	0x00DA, /* 242 */
+	0x00DB, /* 243 */
+	0x00D9, /* 244 */
+	0x0131, /* 245 */
+	0x02C6, /* 246 */
+	0x02DC, /* 247 */
+	0x00AF, /* 248 */
+	0x02D8, /* 249 */
+	0x02D9, /* 250 */
+	0x02DA, /* 251 */
+	0x00B8, /* 252 */
+	0x02DD, /* 253 */
+	0x02DB, /* 254 */
+	0x02C7, /* 255 */
+};
+
+static std::vector<unsigned int> vec(unsigned int i) {
+	std::vector<unsigned int> result;
+	result.push_back(i);
+	return(result);
+}
+
+
+void PdfFont::parseDefaultEncoding(shared_ptr<PdfObject> encoding) {
+	if(encoding.isNull() || encoding->type() != PdfObject::NAME)
+		return;
+	if(encoding == PdfNameObject::nameObject("WinAnsiEncoding")) {
+		// XXX FIXME provide actual conversion table.
+		assert(myToUnicodeMap.size() == 0);
+		char s[2] = {0, 0};
+		char t[2] = {0, 0};
+		s[0] = 1;
+		t[0] = 127;
+		myToUnicodeMap.addRange(s, t, vec(1));
+		for(int i = 128; i < 160; ++i) {
+			s[0] = i;
+			myToUnicodeMap.addRange(s, s, vec(unicodeFromAnsiTableHigh[i - 128]));
+		}
+		for(int i = 160; i < 256; ++i) {
+			s[0] = i;
+			myToUnicodeMap.addRange(s, s, vec(i));
+		}
+	} else if(encoding == PdfNameObject::nameObject("MacRomanEncoding")) {
+		char s[2] = {0, 0};
+		char t[2] = {0, 0};
+		s[0] = 1;
+		t[0] = 127;
+		myToUnicodeMap.addRange(s, t, vec(1));
+		for(int i = 128; i < 256; ++i) {
+			s[0] = i;
+			myToUnicodeMap.addRange(s, s, vec(unicodeFromMacRomanTableHigh[i - 128]));
+		}
+	}
+}
+
+void PdfFont::parseEncoding(shared_ptr<PdfObject> encoding) {
+	if(encoding.isNull())
+		return;
+	if(encoding->type() != PdfObject::DICTIONARY)
+		return parseDefaultEncoding(encoding);
+	unsigned int unicode;
+	unsigned int nativeCode = 1;
+	const PdfDictionaryObject& encodingDictionary = (const PdfDictionaryObject&)*encoding;
+	shared_ptr<PdfObject> actual_data = encodingDictionary["Differences"];
+	if(actual_data.isNull() || actual_data->type() != PdfObject::ARRAY)
+		return;
+	const PdfArrayObject& items = (const PdfArrayObject&)*actual_data;
+	
+	int count = items.size();	
+	for(int i = 0; i < count; ++i) {
+		shared_ptr<PdfObject> item = items[i];
+		PdfObject& xitem = *item;
+		if(xitem.type() == PdfObject::NAME) {
+			PdfNameObject& name = (PdfNameObject&) xitem;
+			std::string name_id = name.id();
+			unicode = getUnicodeFromDefaultCharMap(name_id);
+			if(unicode == cNilCodepoint && name_id.length() == 1) { // fallback for graphical fonts. These want you to leave the code alone.
+				unicode = name_id[0];
+				assert(unicode < 256);
+			}
+			if(unicode == cNilCodepoint) {
+	                        std::cerr << "unknown encoding entry: /" << name_id << std::endl;
+			} /*else FIXME*/ {
+				std::string s2;
+				s2.append(1, nativeCode);
+				assert(s2.length() == 1);
+				myToUnicodeMap.addRange(s2, s2, vec(unicode));
+			}
+			++nativeCode;
+		} else if(xitem.type() == PdfObject::INTEGER_NUMBER) {
+			PdfIntegerObject& number = (PdfIntegerObject&) xitem;
+			nativeCode = number.value();
+		} else {
+			std::cerr << "warning: PdfFont: Encoding parser: ignored unknown PdfObject." << std::endl;
+		}
+	}
+}
+
+void PdfFont::parseFontFile(shared_ptr<PdfObject> actual_data) {
+	// TODO it is possible for the FontDescriptor entry to be missing and an Resources entry to be there instead. Then, the Resources entry's value points to an XObject which contains an array of images that are the glyphs for the font. Handle these.
+	// fall back to FontDescriptor, resolve, DICT, /Encoding|/FontFile.
+	//dictionary.dump();
+	if(!actual_data.isNull() && actual_data->type() == PdfObject::STREAM) {
+		((PdfStreamObject&)*actual_data).dump(); /* FIXME remove */
+		shared_ptr<ZLInputStream> actual_stream = ((PdfStreamObject&)*actual_data).stream();
+		PdfType1FontFileParser parser(actual_stream, myToUnicodeMap);
+		parser.parse();
+	}
+}
+
+bool PdfFont::parseToUnicodeTable(shared_ptr<PdfObject> actual_data) {
+	if(!actual_data.isNull()) {
+		if(!actual_data.isNull() && actual_data->type() == PdfObject::STREAM) {
+			shared_ptr<ZLInputStream> actual_stream = ((PdfStreamObject&)*actual_data).stream();
+			PdfToUnicodeParser parser(actual_stream, myToUnicodeMap);
+			parser.parse();
+		}
+		return true;
+	} else 
+		return false;
+}
+
+void PdfFont::prepare() {
+	/* TODO non-integer widths? */
+	int i;
+	/* TODO prepare width cache for the usual characters */
+	for(i = 0; i < 256; ++i)
+		myCachedWidths[i] = -1;
+	if(!myWidths.isNull() && myWidths->type() == PdfObject::ARRAY) {
+		PdfArrayObject& items = (PdfArrayObject&) *myWidths;
+		int size = items.size();
+		for(i = 0; i < size; ++i) {
+			int o = myWidthsFirstChar + i;
+			if(o >= 0 && o < 256) {
+				integerFromPdfObject(items[i], myCachedWidths[o]);
+			}
+		}
+	}
+	if(!myWs.isNull() && myWs->type() == PdfObject::ARRAY) {
+		PdfArrayObject& items = (PdfArrayObject&) *myWs;
+		int size = items.size();
+		int width;
+		int x_code = 0;
+		for(i = 0; i < size; ++i) {
+			shared_ptr<PdfObject> item = items[i];
+			if(!item.isNull() && item->type() == PdfObject::INTEGER_NUMBER) {
+				if(!integerFromPdfObject(item, x_code))
+					return;
+			} else { /* sub-array */
+				PdfArrayObject& x_items = (PdfArrayObject&) *item;
+				int x_size = x_items.size();
+				for(int j = 0; j < x_size; ++j) {
+					if(!integerFromPdfObject(x_items[j], width))
+						width = -1;
+					int o = x_code + j;
+					if(o >= 0 && o < 256)
+						myCachedWidths[o] = width;
+				}
+			}
+		}
+	}
+	/*std::cerr << "cached widths: ";
+	for(i = 0; i < 256; ++i) 
+		if(myCachedWidths[i] != -1)
+			std::cerr << myCachedWidths[i] << " *** ";
+	std::cerr << std::endl;*/
+}
+int PdfFont::width(int code) const {
+	if(code >= 0 && code < 256)
+		return(myCachedWidths[code]);
+	else
+		return(-1); /* TODO traverse manually */
+}
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfFont.h fbreader-0.12.10/fbreader/src/formats/pdf/PdfFont.h
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfFont.h	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfFont.h	2011-04-05 22:55:28.000000000 +0200
@@ -0,0 +1,50 @@
+#ifndef __PDF_FONT_H
+#define __PDF_FONT_H
+/*PDF parser.
+Copyright (C) 2008 Danny Milosavljevic <danny_milo@yahoo.com>
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if !, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+#include "PdfObject.h"
+#include "PdfToUnicodeMap.h"
+#include <ZLInputStream.h>
+
+typedef std::map<shared_ptr<PdfObject>, shared_ptr<PdfObject> > PdfXObjects; /* name -> image-data */
+
+class PdfFont {
+private:
+	shared_ptr<PdfObject> myMetadata;
+	shared_ptr<PdfObject> myFontDescriptor;
+	PdfXObjects myResources; // for symbol font.
+	shared_ptr<PdfObject> myWidths;
+	shared_ptr<PdfObject> myWs;
+	int myWidthsMissingWidth;
+	int myWidthsFirstChar;
+	bool myBBoldness;
+	PdfToUnicodeMap myToUnicodeMap;
+	double myScale;
+	double myDescent;
+	double myAscent;
+	int myCachedWidths[256]; /* -1 = unknown */
+public:
+	PdfFont(shared_ptr<PdfObject> metadata, shared_ptr<PdfObject> fontDescriptor, shared_ptr<PdfObject> encoding, shared_ptr<PdfObject> fontFile, shared_ptr<PdfObject> toUnicode, PdfXObjects resources, shared_ptr<PdfObject> widths, shared_ptr<PdfObject> ws, int widthsMissingWidth, int widthsFirstChar);
+	double textSpaceFromGlyphSpaceFactor() const { return myScale; }
+	double descent() const { return myDescent; }
+	double ascent() const { return myAscent; }
+	bool boldness() const { return myBBoldness; }
+	const PdfToUnicodeMap* toUnicodeTable() const { return &myToUnicodeMap; }
+	bool containsUnicode() const { return myResources.size() == 0; }
+	int width(int code) const;
+protected:
+	void prepare();
+	void parseEncoding(shared_ptr<PdfObject> encoding);
+	void parseDefaultEncoding(shared_ptr<PdfObject> encoding);
+	void parseFontFile(shared_ptr<PdfObject> fontFile);
+	bool parseToUnicodeTable(shared_ptr<PdfObject> toUnicode);
+};
+	
+#endif /* ndef __PDF_FONT_H */
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfGraphicsState.cpp fbreader-0.12.10/fbreader/src/formats/pdf/PdfGraphicsState.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfGraphicsState.cpp	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfGraphicsState.cpp	2011-04-05 22:55:28.000000000 +0200
@@ -0,0 +1,26 @@
+/*PDF parser.
+Copyright (C) 2008 Danny Milosavljevic <danny_milo@yahoo.com>
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if !, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+#include "PdfGraphicsState.h"
+
+PdfGraphicsState::PdfGraphicsState(double aCTMScaleH, double aCTMScaleV) {
+	setCTMScale(aCTMScaleH, aCTMScaleV);
+}
+
+void PdfGraphicsState::setCTMScale(double aCTMScaleH, double aCTMScaleV) {
+	myCTMScaleH = aCTMScaleH;
+	myCTMScaleV = aCTMScaleV;
+}
+
+PdfGraphicsState::PdfGraphicsState(const PdfGraphicsState& source) :
+	myCTMScaleH(source.myCTMScaleH),
+	myCTMScaleV(source.myCTMScaleV) 
+{
+}
+
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfGraphicsState.h fbreader-0.12.10/fbreader/src/formats/pdf/PdfGraphicsState.h
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfGraphicsState.h	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfGraphicsState.h	2011-04-05 22:55:28.000000000 +0200
@@ -0,0 +1,29 @@
+#ifndef __PDF_GRAPHICS_STATE_H
+#define __PDF_GRAPHICS_STATE_H
+/*PDF parser.
+Copyright (C) 2008 Danny Milosavljevic <danny_milo@yahoo.com>
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if !, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+class PdfGraphicsState {
+private:
+	double myCTMScaleH;
+	double myCTMScaleV;
+public:
+	PdfGraphicsState(double aCTMScaleH, double aCTMScaleV);
+	PdfGraphicsState(const PdfGraphicsState& source);
+	void setCTMScale(double aCTMScaleH, double aCTMScaleV);
+	double CTMScaleH() const {
+		return myCTMScaleH;
+	}
+	double CTMScaleV() const {
+		return myCTMScaleV;
+	}
+};
+
+#endif /* ndef __PDF_GRAPHICS_STATE_H */
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/Pdf.h fbreader-0.12.10/fbreader/src/formats/pdf/Pdf.h
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/Pdf.h	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/Pdf.h	2011-04-05 22:55:28.000000000 +0200
@@ -0,0 +1,20 @@
+#ifndef __PDF_H
+#define __PDF_H
+#include <map>
+#include <shared_ptr.h>
+#include "PdfObject.h"
+
+// main data class for the PDF file.
+class Pdf {
+private:
+	shared_ptr<PdfObject> myTrailer;
+	std::map<std::pair<int,int>,shared_ptr<PdfObject> > myObjectMap;
+public:
+	shared_ptr<PdfObject> trailer() const {
+		return myTrailer;
+	}
+	shared_ptr<PdfObject> findObject(const std::pair<int,int> address);
+	void addObject(const std::pair<int,int> address, shared_ptr<PdfObject> object);
+	void ensureTrailer(shared_ptr<PdfObject> trailer);
+};
+#endif /* ndef __PDF_H */
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfImage.cpp fbreader-0.12.10/fbreader/src/formats/pdf/PdfImage.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfImage.cpp	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfImage.cpp	2012-08-03 22:52:24.568950904 +0200
@@ -0,0 +1,293 @@
+#include <assert.h>
+#include <stdint.h>
+#include <iostream>
+#include <algorithm>
+#include <iterator>
+#include <sstream>
+#include <fstream> /* for debugging */
+#include <ZLInputStream.h>
+#include "PdfImage.h"
+#include "PdfObject.h"
+#include "PdfTiffWriter.h"
+#include "PdfColorTable.h"
+#include "PdfColorTableParser.h"
+
+struct BMPMagic {
+	unsigned char magic[2];// 0x42 0x4D (BM)
+};
+
+struct BMPFileHeader {
+	uint32_t   size; /* of the entire file, in Bytes. */
+	uint16_t   __reserved_1;
+	uint16_t   __reserved_2;
+	uint32_t   data_offset;
+}; // total size = 14 bytes.
+
+static void convertToLittleEndian(uint16_t& value) {
+	// FIXME
+}
+
+static void convertToLittleEndian(uint32_t& value) {
+	// FIXME
+}
+
+static void prepareStorage(struct BMPFileHeader& header) {
+	assert(sizeof(header) == 12);
+	convertToLittleEndian(header.size);
+	convertToLittleEndian(header.__reserved_1);
+	convertToLittleEndian(header.__reserved_2);
+	convertToLittleEndian(header.data_offset);
+}
+
+#if 0
+struct BMPDIBHeader {
+	uint32_t header_size;
+	uint32_t width;
+	uint32_t height;
+	uint16_t plane_count;
+	uint16_t bits_per_pixel;
+	uint32_t compression_type; // 0
+	uint32_t data_size;
+	uint32_t horizontal_resolution; // pixel per meter.
+	uint32_t vertical_resolution; // pixel per meter.
+	uint32_t palette_count;
+	uint32_t palette_important_count;
+};
+#endif
+
+struct BMPOS2Header {
+	// header size (4 byte)
+	uint16_t width;
+	uint16_t height;
+	uint16_t plane_count; // 1
+	uint16_t bits_per_pixel; // 24. 32 doesn't work.
+}; // total size = 12.
+
+static void prepareStorage(struct BMPOS2Header& header) {
+	assert(sizeof(header) == 8);
+	convertToLittleEndian(header.width);
+	convertToLittleEndian(header.height);
+	convertToLittleEndian(header.plane_count);
+	convertToLittleEndian(header.bits_per_pixel);
+}
+
+static void wrapBMP(int width, int height, int componentSize, int componentCount, size_t dataSize, std::ostream& destination) {
+	// magic:
+	destination << (char) 0x42 << (char) 0x4D;
+	struct BMPFileHeader mainHeader;
+	mainHeader.__reserved_1 = 1;
+	mainHeader.__reserved_2 = 2;
+	mainHeader.data_offset = 2+12+12;
+	mainHeader.size = dataSize + mainHeader.data_offset;
+	prepareStorage(mainHeader);
+	destination.write((const char*) &mainHeader, sizeof(mainHeader));
+	struct BMPOS2Header imageHeader;
+	uint32_t os2Size = 12;
+	convertToLittleEndian(os2Size);
+	destination.write((const char*) &os2Size, sizeof(os2Size));
+	imageHeader.width = width;
+	imageHeader.height = height;
+	imageHeader.plane_count = 1;
+	imageHeader.bits_per_pixel = componentSize * componentCount;
+	destination.write((const char*) &imageHeader, sizeof(imageHeader));
+	prepareStorage(imageHeader);
+}
+
+struct TGAHeader {
+   char  idlength; // str length.
+   char  colourmaptype; // 0
+   char  datatypecode; // 2=RGB
+   short int colourmaporigin; // 0
+   short int colourmaplength; // 0
+   char  colourmapdepth; // 0
+   short int x_origin; // 0
+   short int y_origin; // 0
+   short width;
+   short height;
+   char  bitsperpixel;
+   char  imagedescriptor; // 0
+};
+
+void wrapTGA(int width, int height, int componentSize, int componentCount, std::ostream& destination, shared_ptr<PdfColorTable> colorTableO) {
+	// TODO http://local.wasp.uwa.edu.au/~pbourke/dataformats/tga/
+	int paletteEntryCount = 0;
+	if(!colorTableO.isNull()) {
+		PdfColorTable& colorTable = (PdfColorTable& ) *colorTableO;
+		paletteEntryCount = colorTable.size();
+	}
+	destination << '\3'; /* length of image ID */
+	destination << (colorTableO.isNull() ? '\0' : '\1'); /* palette flag */
+	destination << (colorTableO.isNull() ? '\2' : '\1'); /* image type */
+	destination << '\0' << '\0'; /* first palette index */
+	destination << (unsigned char) (paletteEntryCount & 0xFF)  << (unsigned char) ((paletteEntryCount >> 8) & 0xFF);
+	destination << '\0' << '\0'<< '\0'<< '\0'<< '\40';
+	destination << (char) (width & 0x00FF) << (char) ((width & 0xFF00) >>8);
+	destination << (char) (height & 0x00FF) << (char) ((height & 0xFF00) >>8);
+	destination << (char) (componentSize * componentCount); // bits per pixel.
+	destination << (char) 0;
+	destination << "TGA"; /* image ID */
+	if(!colorTableO.isNull()) {
+		PdfColorTable& colorTable = (PdfColorTable& ) *colorTableO;
+		for(int i = 0; i < paletteEntryCount; ++i) {
+			PdfColorTableEntry entry = colorTable[i];
+			destination << (unsigned char) entry.components[2];
+			destination << (unsigned char) entry.components[1];
+			destination << (unsigned char) entry.components[0];
+		}
+	}
+}
+void wrapTIFF(int width, int height, int componentSize, int size, int k, bool blackis1, std::ostream& destination) {
+	destination << PdfTiffWriter(k, width, height, blackis1, size).str();
+}
+
+static std::string getMimeType(const shared_ptr<PdfObject>& xObject) {
+	return "image/auto";
+#if 0
+	PdfStreamObject& stream1 = (PdfStreamObject&) *xObject;
+	shared_ptr<ZLInputStream> stream = stream1.stream();
+	if(stream.isNull())
+		return "application/octet-stream";
+	char magic[4096];
+	size_t count = stream->read(magic, 4096);
+	if(count >= 3 && memcmp(magic, "\377\330\377" /* \341 or \356 */, 3) == 0)
+		return "image/jpeg";
+	else if(count >= 6 && memcmp(magic, "GIF89a", 6) == 0)
+		return "image/gif";
+	else if(count >= 6 && memcmp(magic, "\211PNG\r\n", 6) == 0)
+		return "image/png";
+	// } else if (substr($first_line, 0, 2) == "BM" && unpack_I4(substr($first_line, 2, 4)) == filesize($path)) return "image/x-ms-bmp"
+	return "application/octet-stream";
+#endif
+}
+
+static int getComponentCount(PdfNameObject& colorSpace) {
+	/* FIXME */
+	std::cerr << "warning: PdfImage: getComponentCount: unknown ColorSpace " << colorSpace.id() << std::endl;
+	return(3);
+}
+static shared_ptr<PdfColorTable> buildColorTable(const PdfDictionaryObject& dict) {
+	shared_ptr<PdfObject> a = dict[PdfNameObject::nameObject("ColorSpace")];
+	if(!a.isNull() && a->type() == PdfObject::ARRAY) {
+		PdfArrayObject& arr = (PdfArrayObject&) *a;
+		if(arr.size() >= 4) {
+			shared_ptr<PdfObject> colorSpace = arr[0];
+			shared_ptr<PdfObject> baseColorSpaceO = arr[1];
+			shared_ptr<PdfObject> hivalO = arr[2];
+			shared_ptr<PdfObject> paletteO = arr[3]; // image.dict[ColorSpace];
+			if(!colorSpace.isNull() && !baseColorSpaceO.isNull() && !hivalO.isNull() && !paletteO.isNull() &&
+			   colorSpace->type() == PdfObject::NAME && baseColorSpaceO->type() == PdfObject::NAME &&
+			   hivalO->type() == PdfObject::INTEGER_NUMBER) {
+				int hival = 0;
+				if(colorSpace == PdfNameObject::nameObject("Indexed") && integerFromPdfObject(hivalO, hival) && hival < 256) {
+					PdfNameObject& baseColorSpace = (PdfNameObject&) *baseColorSpaceO;
+					int componentCount = getComponentCount(baseColorSpace);
+					int count = hival + 1;
+					shared_ptr<PdfColorTable> result(new PdfColorTable());
+					if(paletteO->type() == PdfObject::STREAM) {
+						PdfStreamObject& palette = (PdfStreamObject&) *paletteO;
+						PdfColorTableParser parser(palette.stream(), componentCount, *result);
+					} else if(paletteO->type() == PdfObject::STRING) {
+						PdfStringObject& palette = (PdfStringObject&) *paletteO;
+						PdfColorTableParser parser(palette.value(), componentCount, *result);
+					}
+					if(count == result->size()) {
+						return(result);
+					}
+				}
+			}
+		}
+	}
+	return shared_ptr<PdfColorTable>();
+}
+
+PdfImage::PdfImage(shared_ptr<PdfObject> xObject) : ZLSingleImage(getMimeType(xObject)), myXObject(xObject) {
+	assert(!myXObject.isNull() && myXObject->type() == PdfObject::STREAM);
+}
+
+const shared_ptr<std::string> PdfImage::stringData() const {
+	PdfStreamObject& stream1 = (PdfStreamObject&) *myXObject;
+	shared_ptr<ZLInputStream> stream = stream1.stream();
+	std::stringstream result(std::ios_base::out | std::ios_base::binary);
+#if 0
+	/* doesn't work. */
+	std::copy(std::istream_iterator<char>(*stream), std::istream_iterator<char>(), std::ostream_iterator<char>(result));
+#endif
+	ZLInputStream& inputStream = *stream;
+
+	char buffer[4096];
+	size_t count;
+	while((count = inputStream.read(buffer, 4096)) > 0) {
+		result.write(buffer, count);
+	}
+	std::string body = result.str();
+
+	int myWidth;
+	int myHeight;
+	int myBitsPerComponent;
+	int mySize;
+
+	shared_ptr<PdfObject> imageDictionaryX = stream1.dictionary();
+	if(!imageDictionaryX.isNull() && imageDictionaryX->type() == PdfObject::DICTIONARY) {
+		const PdfDictionaryObject& imageDictionary = (const PdfDictionaryObject&) *imageDictionaryX;
+		if(integerFromPdfObject(imageDictionary["Width"], myWidth) &&
+		   integerFromPdfObject(imageDictionary["Height"], myHeight) &&
+		   integerFromPdfObject(imageDictionary["BitsPerComponent"], myBitsPerComponent)
+		 ) {
+			result.str("");
+			if(!imageDictionary["Filter"].isNull() &&
+			    imageDictionary["Filter"]->type() == PdfObject::NAME) {
+				if(imageDictionary["Filter"] == PdfNameObject::nameObject("DCTDecode") && !imageDictionary["ColorSpace"].isNull() && imageDictionary["ColorSpace"] == PdfNameObject::nameObject("DeviceRGB")) {
+					/* JPEG */
+					/*std::ofstream f("/tmp/image", std::ios_base::out | std::ios_base::binary);
+					f << result.str() << body;*/
+				} else if(imageDictionary["Filter"] == PdfNameObject::nameObject("CCITTFaxDecode") &&
+				        integerFromPdfObject(imageDictionary["Length"], mySize)) {
+					bool blackis1 = false; // FIXME
+					shared_ptr<PdfObject> DecodeParms = imageDictionary["DecodeParms"];
+					// find the one with the columns...
+					shared_ptr<PdfObject> x = DecodeParms;
+					if(!DecodeParms.isNull() && DecodeParms->type() == PdfObject::ARRAY) {
+						const PdfArrayObject& DecodeParmsArray = (const PdfArrayObject&) *DecodeParms;
+						for(int i = 0, count = DecodeParmsArray.size(); i < count; ++i) {
+							shared_ptr<PdfObject> c = DecodeParmsArray[i];
+							if(!c.isNull() && c->type() == PdfObject::DICTIONARY) {
+								const PdfDictionaryObject& cDictionary = (const PdfDictionaryObject&) *c;
+								if(!cDictionary["Columns"].isNull()) {
+									// FIXME what legitimate purpose does "null" have in this context?
+									x = c;
+									break;
+								}
+							}
+						}
+					}
+					DecodeParms = x;
+					int cols = 1728;
+					int rows = 0;
+					int k = 0;
+					if(!DecodeParms.isNull() && DecodeParms->type() == PdfObject::DICTIONARY) {
+						const PdfDictionaryObject& DecodeParmsDictionary = (const PdfDictionaryObject&) *DecodeParms;
+						if(!integerFromPdfObject(DecodeParmsDictionary["Columns"], cols))
+							cols = myWidth;
+						if(!integerFromPdfObject(DecodeParmsDictionary["Rows"], rows))
+							rows = myHeight;
+						if(DecodeParmsDictionary["BlackIs1"] == PdfBooleanObject::TRUE())
+							blackis1 = true;
+						if(!integerFromPdfObject(DecodeParmsDictionary["K"], k))
+							k = 0;
+					} else
+						k = 0;
+					wrapTIFF(cols, rows, myBitsPerComponent, mySize, k, blackis1, result);
+				} else if(!imageDictionary["ColorSpace"].isNull() && imageDictionary["ColorSpace"] == PdfNameObject::nameObject("DeviceRGB")) { /* fallback (especially Flate and LZW) */
+					shared_ptr<PdfColorTable> colorTable = buildColorTable(imageDictionary);
+					wrapTGA(myWidth, myHeight, myBitsPerComponent, 3, /*body.length(),*/ result, colorTable);
+				}
+			} else {
+				wrapTGA(myWidth, myHeight, myBitsPerComponent, 3, /*body.length(),*/ result, shared_ptr<PdfColorTable>());
+			}
+			return new std::string(result.str() + body);
+		}
+	}
+	
+	return new std::string(body);
+}
+
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfImage.h fbreader-0.12.10/fbreader/src/formats/pdf/PdfImage.h
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfImage.h	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfImage.h	2012-08-03 21:11:03.479832275 +0200
@@ -0,0 +1,18 @@
+#ifndef __PDF_IMAGE_H
+#define __PDF_IMAGE_H
+#include <vector>
+#include <iostream>
+#include <ZLImage.h>
+#include "PdfObject.h"
+
+class PdfImage : public ZLSingleImage {
+public:
+	PdfImage(shared_ptr<PdfObject> xObject);
+	virtual /* override */ const shared_ptr<std::string> stringData() const;
+private:
+	shared_ptr<PdfObject> myXObject;
+};
+
+//void wrapTGA(int width, int height, int componentSize, int componentCount, std::ostream& destination);
+
+#endif /* __PDF_IMAGE_H */
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfImageRasterizer.cpp fbreader-0.12.10/fbreader/src/formats/pdf/PdfImageRasterizer.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfImageRasterizer.cpp	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfImageRasterizer.cpp	2011-04-05 22:55:28.000000000 +0200
@@ -0,0 +1,245 @@
+#include <vector>
+#include "PdfObject.h"
+#include "PdfImageRasterizer.h"
+#include "PdfImage.h"
+
+#ifdef USE_CAIRO
+#include <cairo.h>
+
+PdfImageRasterizer::PdfImageRasterizer(std::map<shared_ptr<PdfObject>, shared_ptr<PdfFont> >& fontsByName) :
+	ZLSingleImage("image/auto"),
+	myToUnicodeTable(NULL),
+	myFontsByName(fontsByName)
+{
+	// TODO draw into a SVG surface or cairo_recording_surface_create (1.9.4), then find out the extremes and scale down to howevermuch space we really need.
+	int width = 400; // FIXME
+	int height = 300; // FIXME
+	mySurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
+	myContext = cairo_create(mySurface);
+	/*
+	cairo_translate
+	cairo_rotate
+	cairo_scale
+	cairo_transform
+	cairo_set_matrix
+	cairo_get_matrix
+	cairo_identity_matrix
+	cairo_device_to_user
+	cairo_user_to_device
+	*/
+}
+
+void PdfImageRasterizer::transform(double x, double y, double& tx, double& ty) {
+	// FIXME scale down to surface extents.
+	tx = x;
+	ty = y;
+}
+
+void PdfImageRasterizer::setNonstrokingColor(std::vector<double> color) {
+	if(color.size() == 3) {
+		// FIXME distinguish from the stroking color?
+		cairo_set_source_rgb(myContext, color[0], color[1], color[2]);
+	} else {
+		std::cerr << "warning: opColorSetNonstrokingRGBColor: did not get 3 arguments." << std::endl;
+	}
+}
+
+void PdfImageRasterizer::processInstruction(const PdfInstruction& instruction) {
+	PdfOperator operator_ = instruction.operator_();
+	switch(operator_) {
+	case opColorSetNonstrokingRGBColor:
+		setNonstrokingColor(instruction.extractFloatArguments());
+		break;
+	case opClipIntersect:
+		cairo_clip(myContext);
+		break;
+	case opPaintNoPaint:
+		// FIXME cairo_close_path???(myContext);
+		break;
+	case opPathBegin:
+		cairo_new_path(myContext);
+		if(instruction.extractTwoFloatArguments(x, y)) {
+			transform(x, y, tx, ty);
+			cairo_move_to(myContext, tx, ty);
+		}
+		break;
+	case opPathAddLine:
+		if(instruction.extractTwoFloatArguments(x, y)) {
+			transform(x, y, tx, ty);
+			cairo_line_to(myContext, tx, ty);
+		}
+		break;
+	case opPaintFillEvenOdd:
+		cairo_set_fill_rule(myContext, CAIRO_FILL_RULE_EVEN_ODD);
+		cairo_fill(myContext);
+		break;
+	case opTransformationMatrixAppend:
+		appendTransformationMatrix(instruction.extractFloatArguments());
+		break;
+	case opPushGraphicsState:
+		cairo_save(myContext);
+		break;
+	case opPopGraphicsState:
+		cairo_restore(myContext);
+		break;
+	case opSetTextMatrix:
+	case opSetTextLeading: // FIXME can also be outside
+	case opSetFontAndSize: // FIXME can also be outside
+	case opShowStringWithVariableSpacing:
+	case opSetWordSpacing: // FIXME can also be outside
+	case opSetCharacterSpacing: // FIXME can also be outside
+	case opMoveCaret:
+	case opMoveCaretToStartOfNextLine:
+	case opMoveCaretToStartOfNextLineAndOffsetAndSetLeading:
+		std::cerr << "warning: ignored text instruction in non-text block." << std::endl;
+		break;
+	case opInvalid:
+	default:
+		std::cerr << "warning: ignored unknown operator." << std::endl;
+	}
+}
+
+void PdfImageRasterizer::appendTransformationMatrix(std::vector<double> components) {
+	if(components.size() == 6) {
+		cairo_matrix_t matrix;
+		cairo_matrix_init(&matrix, components[0], components[1], components[2], components[3], components[4], components[5]);
+		cairo_transform(myContext, &matrix);
+		// TODO make this pushable.
+	} else {
+		std::cerr << "warning: ignored invalid transformation matrix." << std::endl;
+	}
+}
+
+void PdfImageRasterizer::processInstructions(const std::vector<shared_ptr<PdfInstruction> >& instructions) {
+	for(std::vector<shared_ptr<PdfInstruction> >::const_iterator iter_instructions = instructions.begin(); iter_instructions != instructions.end(); ++iter_instructions) {
+		shared_ptr<PdfInstruction> instruction = *iter_instructions;
+		if(instruction->operator_() == opBeginText) {
+			const shared_ptr<PdfArrayObject>& arguments = instruction->arguments();
+			int argument_count = arguments->size();
+			if(argument_count > 0) {
+				shared_ptr<PdfObject> item = (*arguments)[0];
+				if(item->type() == PdfObject::CONTENT) {
+					const std::vector<shared_ptr<PdfInstruction> >& x_instructions = ((PdfContent&)(*item)).instructions();
+					processTextInstructions(x_instructions);
+				}
+			}
+		} else
+			processInstruction(*instruction);
+	}
+}
+
+const shared_ptr<std::string> PdfImageRasterizer::stringData() const {
+	std::stringstream result(std::ios_base::out | std::ios_base::binary);
+	int width = cairo_image_surface_get_width(mySurface);
+	int height = cairo_image_surface_get_height(mySurface);
+	cairo_format_t format = cairo_image_surface_get_format(mySurface);
+	wrapTGA(width, height, 8, (format == CAIRO_FORMAT_ARGB32 || format == CAIRO_FORMAT_RGB24) ? 4 : 1, result);
+	result << cairo_image_surface_get_data(mySurface);
+	return new std::string(result.str());
+}
+
+void PdfImageRasterizer::processTextInstructions(const std::vector<shared_ptr<PdfInstruction> >& instructions) {
+	// TODO: its own mini-world.
+	for(std::vector<shared_ptr<PdfInstruction> >::const_iterator iter_instructions = instructions.begin(); iter_instructions != instructions.end(); ++iter_instructions) {
+		shared_ptr<PdfInstruction> instruction = *iter_instructions;
+		processTextInstruction(*instruction);
+	}
+}
+
+void PdfImageRasterizer::processTextInstruction(const PdfInstruction& instruction) {
+	// TODO.
+	PdfOperator operator_ = instruction.operator_();
+	switch(operator_) {
+	case opSetTextMatrix:
+		break;
+	case opSetTextLeading:
+		break;
+	case opSetFontAndSize:
+		break;
+	case opSetWordSpacing:
+		break;
+	case opSetCharacterSpacing:
+		break;
+	case opMoveCaret:
+		break;
+	case opMoveCaretToStartOfNextLine:
+		break;
+	case opMoveCaretToStartOfNextLineAndOffsetAndSetLeading:
+		break;
+	case opShowStringWithVariableSpacing:
+	case opShowString:
+	case opNextLineShowString:
+	case opNextLineSpacedShowString:
+		showString(instruction.extractFirstArgument());
+		break;
+	case opPathBegin:
+	case opPathAddLine:
+	case opPathAddCubicBezier123:
+	case opPathAddCubicBezier23:
+	case opPathAddCubicBezier13:
+	case opPathClose:
+	case opPathRectangle:
+	case opPaintStroke:
+	case opPaintCloseAndStroke:
+	case opPaintCloseAndFill:
+	case opPaintFillEvenOdd:
+	case opPaintFillAndStroke:
+	case opPaintFillAndStrokeEvenOdd:
+	case opPaintCloseAndFillAndStroke:
+	case opPaintCloseAndFillAndStrokeEvenOdd:
+	case opPaintNoPaint:
+	case opPaintExternalObject:
+	case opClipIntersect:
+	case opClipIntersectEvenOdd:
+	case opSetLineWidth:
+	case opSetLineCap:
+	case opSetLineJoin:
+	case opSetMiterLimit:
+	case opSetDashPattern:
+	case opSetColorIntent:
+	case opFlatness:
+	case opSetParameterValue:
+	case opSetMarkedContentPoint:
+	case opSetMarkedContentPointWithAttributes:
+	case opInvalid: /*?*/
+		std::cerr << "warning: ignored non-text operator in text block." << std::endl;
+		break;
+	}
+}
+
+static std::string mangleTextPart(const std::string& value) {
+	return value;
+}
+
+void PdfImageRasterizer::showString(shared_ptr<PdfObject> item) {
+	std::string result;
+	if(item->type() == PdfObject::ARRAY) {
+		PdfArrayObject* xarray = (PdfArrayObject*)&*item;
+		int argument_count = xarray->size();
+		for(int i = 0; i < argument_count; ++i) {
+			shared_ptr<PdfObject> xitem = (*xarray)[i];
+			if(xitem->type() == PdfObject::STRING) { // esp. ! number
+				PdfStringObject* stringObject = (PdfStringObject*)&*xitem;
+				result = result + mangleTextPart(myToUnicodeTable->convertStringToUnicode(stringObject->value()));
+				//result = result + ' ';
+			} else if(xitem->type() == PdfObject::INTEGER_NUMBER) {
+				PdfIntegerObject* integerObject = (PdfIntegerObject*)&*xitem;
+				if(integerObject->value() < -57) // TODO these are textspace/1000.
+				result = result + " ";
+			} else if(xitem->type() == PdfObject::REAL_NUMBER) {
+				PdfRealObject* realObject = (PdfRealObject*)&*xitem;
+				if(realObject->value() < -57)
+					result = result + " ";
+				/*debugging: else
+					result = result + "@";*/
+			}
+		};
+		//result = Copy(result, 1, Length(result) - 1);
+	} else if(item->type() == PdfObject::STRING) {
+		PdfStringObject* stringObject = (PdfStringObject*)&*item;
+		result = result + myToUnicodeTable->convertStringToUnicode(stringObject->value()); 
+	}
+	cairo_show_text(myContext, result.c_str());
+}
+
+#endif /* def USE_CAIRO */
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfImageRasterizer.h fbreader-0.12.10/fbreader/src/formats/pdf/PdfImageRasterizer.h
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfImageRasterizer.h	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfImageRasterizer.h	2011-04-05 22:55:28.000000000 +0200
@@ -0,0 +1,34 @@
+#ifndef __PDF_IMAGE_RASTERIZER_H
+#define __PDF_IMAGE_RASTERIZER_H
+#ifdef USE_CAIRO
+#include <vector>
+#include <shared_ptr.h>
+#include <ZLImage.h>
+#include <cairo.h>
+#include "PdfContent.h"
+#include "PdfFont.h"
+#include "PdfToUnicodeMap.h"
+
+class PdfImageRasterizer : public ZLSingleImage {
+private:
+	double x, y;
+	double tx, ty;
+	cairo_surface_t* mySurface;
+	cairo_t* myContext;
+	const PdfToUnicodeMap* myToUnicodeTable; /* current one, depending on font. */
+	std::map<shared_ptr<PdfObject>, shared_ptr<PdfFont> >& myFontsByName;
+public:
+	PdfImageRasterizer(std::map<shared_ptr<PdfObject>, shared_ptr<PdfFont> >& fontsByName);
+	void processInstruction(const PdfInstruction& instruction);
+	void processTextInstruction(const PdfInstruction& instruction);
+	void transform(double x, double y, double& tx, double& ty);
+	void processInstructions(const std::vector<shared_ptr<PdfInstruction> >& instructions); // non-text.
+	void processTextInstructions(const std::vector<shared_ptr<PdfInstruction> >& instructions);
+	virtual /* override */ const shared_ptr<std::string> stringData() const;
+protected:
+	void showString(shared_ptr<PdfObject> item);
+	void setNonstrokingColor(std::vector<double> color);
+	void appendTransformationMatrix(std::vector<double> components);
+};
+#endif
+#endif /*ndef __PDF_IMAGE_RASTERIZER_H*/
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfMatrix.cpp fbreader-0.12.10/fbreader/src/formats/pdf/PdfMatrix.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfMatrix.cpp	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfMatrix.cpp	2011-04-05 22:55:28.000000000 +0200
@@ -0,0 +1,101 @@
+#include "PdfMatrix.h"
+
+PdfMatrix::PdfMatrix(void) {
+	items[0][0] = 0.0;
+	items[0][1] = 0.0;
+	items[0][2] = 0.0;
+	items[1][0] = 0.0;
+	items[1][1] = 0.0;
+	items[1][2] = 0.0;
+	items[2][0] = 0.0;
+	items[2][1] = 0.0;
+	items[2][2] = 0.0;
+}
+
+PdfMatrix::PdfMatrix(double diagonal) {
+	items[0][0] = diagonal;
+	items[0][1] = 0.0;
+	items[0][2] = 0.0;
+	items[1][0] = 0.0;
+	items[1][1] = diagonal;
+	items[1][2] = 0.0;
+	items[2][0] = 0.0;
+	items[2][1] = 0.0;
+	items[2][2] = diagonal;
+}
+
+PdfMatrix& PdfMatrix::setFromRowVector(double x, double y, double w) {
+	items[0][0] = x;
+	items[0][1] = y;
+	items[0][2] = w;
+	return *this;
+}
+
+PdfMatrix& PdfMatrix::setFromTranslation(double x, double y) {
+	items[0][0] = 1.0;
+	items[1][1] = 1.0;
+	items[2][2] = 1.0;
+	items[2][0] = x;
+	items[2][1] = y;
+}
+
+PdfMatrix PdfMatrix::multiply(const PdfMatrix& b) const {
+	PdfMatrix result;
+	double sum;
+	for(int i = 0; i < 3; ++i) {
+		for(int j = 0; j < 3; ++j) {
+			sum = 0;
+			for(int k = 0; k < 3; ++k)
+				sum += items[i][k] + b.items[k][j];
+			result.items[i][j] = sum;
+		}
+	}
+	return result;
+}
+
+PdfMatrix PdfMatrix::add(const PdfMatrix& b) const {
+	PdfMatrix result;
+	for(int i = 0; i < 3; ++i)
+		for(int j = 0; j < 3; ++j)
+			result.items[i][j] = items[i][j] + b.items[i][j];
+	return result;
+}
+
+PdfMatrix operator*(const PdfMatrix& a, const PdfMatrix& b) {
+	return a.multiply(b);
+}
+
+PdfMatrix operator+(const PdfMatrix& a, const PdfMatrix& b) {
+	return a.add(b);
+}
+
+PdfMatrix makePdfMatrixFromRowVector(double a, double b, double c) {
+	PdfMatrix result;
+	return result.setFromRowVector(a, b, c);
+}
+
+PdfMatrix makePdfMatrixFromTranslation(double x, double y) {
+	PdfMatrix result;
+	return result.setFromTranslation(x, y);
+}
+
+PdfMatrix& PdfMatrix::setFromItems(double a, double b, double c,
+	                        double d, double e, double f,
+	                        double g, double h, double i) {
+	items[0][0] = a;
+	items[0][1] = b;
+	items[0][2] = c;
+	items[1][0] = d;
+	items[1][1] = e;
+	items[1][2] = f;
+	items[2][0] = g;
+	items[2][1] = h;
+	items[2][2] = i;
+	return *this;
+}
+PdfMatrix makePdfMatrixFromItems(double a, double b, double c,
+	                        double d, double e, double f,
+	                        double g, double h, double i) {
+	return PdfMatrix().setFromItems(a, b, c, d, e, f, g, h, i);
+}
+
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfMatrix.h fbreader-0.12.10/fbreader/src/formats/pdf/PdfMatrix.h
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfMatrix.h	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfMatrix.h	2011-04-05 22:55:28.000000000 +0200
@@ -0,0 +1,30 @@
+#ifndef __PDF_MATRIX_H
+#define __PDF_MATRIX_H
+
+class PdfMatrix {
+private:
+	double items[3][3];
+public:
+	PdfMatrix(void);
+	PdfMatrix(double diagonal);
+	PdfMatrix& setFromRowVector(double x, double y, double w);
+	PdfMatrix& setFromTranslation(double x, double y);
+	PdfMatrix& setFromItems(double a, double b, double c,
+	                        double d, double e, double f,
+	                        double g, double h, double i);
+	PdfMatrix multiply(const PdfMatrix& b) const;
+	PdfMatrix add(const PdfMatrix& b) const;
+	double getItem(int i, int j) const {
+		return items[i][j];
+	}
+};
+
+PdfMatrix operator*(const PdfMatrix& a, const PdfMatrix& b);
+PdfMatrix operator+(const PdfMatrix& a, const PdfMatrix& b);
+PdfMatrix makePdfMatrixFromRowVector(double a, double b, double c);
+PdfMatrix makePdfMatrixFromTranslation(double x, double y);
+PdfMatrix makePdfMatrixFromItems(double a, double b, double c,
+	                        double d, double e, double f,
+	                        double g, double h, double i);
+
+#endif /* ndef __PDF_MATRIX_H */
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfMatrix_TODO fbreader-0.12.10/fbreader/src/formats/pdf/PdfMatrix_TODO
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfMatrix_TODO	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfMatrix_TODO	2011-04-05 22:55:28.000000000 +0200
@@ -0,0 +1,23 @@
+Td
+	T_m = T_lm = makePdfMatrixFromTranslation()
+TD
+	-ty TL
+	tx ty Td
+Tm
+	T_m = T_lm = makePdfMatrixFromItems(a, b, 0.0, c, d, 0.0, e, f, 1.0)
+T*
+	0 -Tl Td
+string '
+	T*
+	string Tj
+aw ac string "
+	aw Tw
+	ac Tc
+	string '
+array TJ
+after drawing a glyph:
+	let w0 w1 glyph displacement
+	either t_x = ((w0 - T_j/1000)⋅T_{font_size}+T_c+T_w)⋅T_{horizontal_scaling}
+	or t_y = ((w1 - T_j/1000)⋅T_{font_size}+T_c+T_w)
+	then translate the text matrix.
+
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfObject.cpp fbreader-0.12.10/fbreader/src/formats/pdf/PdfObject.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfObject.cpp	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfObject.cpp	2012-08-03 18:40:18.626941657 +0200
@@ -18,11 +18,14 @@
  */
 
 #include <iostream>
+#include <sstream>
+#include <fstream>
 
 #include <ZLInputStream.h>
 #include <ZLZDecompressor.h>
-
+#include <ZLStringInputStream.h>
 #include "PdfObject.h"
+#include "PdfDepredictor.h"
 
 PdfObject::~PdfObject() {
 }
@@ -40,7 +43,7 @@ shared_ptr<PdfObject> PdfIntegerObject::
 }
 
 PdfIntegerObject::PdfIntegerObject(int value) : myValue(value) {
-	std::cerr << "PdfIntegerObject " << value << "\n";
+	/*std::cerr << "PdfIntegerObject " << value << "\n"; yeah yeah */
 }
 
 int PdfIntegerObject::value() const {
@@ -62,7 +65,7 @@ shared_ptr<PdfObject> PdfBooleanObject::
 }
 
 PdfBooleanObject::PdfBooleanObject(bool value) : myValue(value) {
-	std::cerr << "PdfBooleanObject " << value << "\n";
+	//std::cerr << "PdfBooleanObject " << value << "\n";
 }
 
 bool PdfBooleanObject::value() const {
@@ -74,7 +77,7 @@ PdfObject::Type PdfBooleanObject::type()
 }
 
 PdfStringObject::PdfStringObject(const std::string &value) : myValue(value) {
-	std::cerr << "PdfStringObject " << value << "\n";
+	/*std::cerr << "PdfStringObject " << value << "\n";*/
 }
 
 PdfObject::Type PdfStringObject::type() const {
@@ -89,13 +92,13 @@ shared_ptr<PdfObject> PdfNameObject::nam
 	if (it != ourObjectMap.end()) {
 		return it->second;
 	}
-	std::cerr << "PdfNameObject " << id << "\n";
-	shared_ptr<PdfObject> object = new PdfNameObject();
+	/*std::cerr << "PdfNameObject " << id << "\n";*/
+	shared_ptr<PdfObject> object = new PdfNameObject(id);
 	ourObjectMap.insert(std::pair<std::string,shared_ptr<PdfObject> >(id, object));
 	return object;
 }
 
-PdfNameObject::PdfNameObject() {
+PdfNameObject::PdfNameObject(const std::string& id) : fID(id) {
 }
 
 PdfObject::Type PdfNameObject::type() const {
@@ -111,8 +114,27 @@ void PdfDictionaryObject::setObject(shar
 
 shared_ptr<PdfObject> PdfDictionaryObject::operator[](shared_ptr<PdfObject> id) const {
 	std::map<shared_ptr<PdfObject>,shared_ptr<PdfObject> >::const_iterator it = myMap.find(id);
+	if(it == myMap.end()) {
+		//std::cerr << "warning: entry not found. Key was: " << ((PdfNameObject&) *id).id() << std::endl;
+	}
 	return (it != myMap.end()) ? it->second : 0;
 }
+shared_ptr<PdfObject>& PdfDictionaryObject::operator[](shared_ptr<PdfObject> id) {
+	std::map<shared_ptr<PdfObject>,shared_ptr<PdfObject> >::const_iterator it = myMap.find(id);
+	if(it == myMap.end()) {
+		myMap[id] = shared_ptr<PdfObject>();
+	}
+	return(myMap[id]);
+}
+
+std::list<shared_ptr<PdfObject> > PdfDictionaryObject::keys() const {
+	std::list<shared_ptr<PdfObject> > result;
+	
+	for(std::map<shared_ptr<PdfObject>,shared_ptr<PdfObject> >::const_iterator it = myMap.begin(); it != myMap.end(); ++it) {
+		result.push_back(it->first);
+	}
+	return result;
+}
 
 shared_ptr<PdfObject> PdfDictionaryObject::operator[](const std::string &id) const {
 	return operator[](PdfNameObject::nameObject(id));
@@ -122,6 +144,16 @@ PdfObject::Type PdfDictionaryObject::typ
 	return DICTIONARY;
 }
 
+void PdfDictionaryObject::dump() const {
+	std::cerr << "PdfDictionaryObject::dump() => [" << std::endl;
+	std::list<shared_ptr<PdfObject> > fKeys = keys();
+	for(std::list<shared_ptr<PdfObject> >::const_iterator it = fKeys.begin(); it != fKeys.end(); ++it) {
+		shared_ptr<PdfObject> name = *it;
+		std::cerr << ((PdfNameObject&)*name).id() << std::endl;
+	}
+	std::cerr << "]" << std::endl;
+}
+
 PdfArrayObject::PdfArrayObject() {
 }
 
@@ -145,6 +177,9 @@ int PdfArrayObject::size() const {
 shared_ptr<PdfObject> PdfArrayObject::operator[](int index) const {
 	return myVector[index];
 }
+shared_ptr<PdfObject>& PdfArrayObject::operator[](int index) {
+	return myVector[index];
+}
 
 PdfObject::Type PdfArrayObject::type() const {
 	return ARRAY;
@@ -165,286 +200,114 @@ PdfObject::Type PdfObjectReference::type
 	return REFERENCE;
 }
 
-PdfStreamObject::PdfStreamObject(const PdfDictionaryObject &dictionary, ZLInputStream &dataStream) {
-	char ch;
-	skipWhiteSpaces(dataStream, ch);
-
-	shared_ptr<PdfObject> length = dictionary["Length"];
-	if (!length.isNull() && (length->type() == INTEGER_NUMBER)) {
-		int value = ((PdfIntegerObject&)*length).value();
-		if (value > 0) {
-			shared_ptr<PdfObject> filter = dictionary["Filter"];
-			if (filter == PdfNameObject::nameObject("FlateDecode")) {
-				dataStream.seek(1, false);
-				ZLZDecompressor decompressor(value - 2);
-				char buffer[2048];
-				while (true) {
-					size_t size = decompressor.decompress(dataStream, buffer, 2048);
-					if (size == 0) {
-						break;
-					}
-					myData.append(buffer, size);
-				}
-				std::cerr << myData << "\n";
-			} else {
-				myData.append(value, '\0');
-				myData[0] = ch;
-				dataStream.read((char*)myData.data() + 1, value - 1);
-			}
-		}
-	}
+shared_ptr<PdfObject> PdfStreamObject::dictionary() const {
+	return myDictionary;
+}
+void PdfStreamObject::setDictionary(shared_ptr<PdfObject> value) {
+	myDictionary = value;
+}
 
-	/*
-	shared_ptr<PdfObject> filter = dictionary["Filter"];
-	if (!filter.isNull()) {
-		switch (filter->type()) {
-			default:
+shared_ptr<ZLInputStream> PdfStreamObject::stream() const {
+	/*std::cerr << "requested stream for data:" << std::endl;
+	std::cerr << myData << std::endl;
+	std::cerr << "END: requested stream for data." << std::endl;*/
+	//return new std::istringstream(myData);
+	return new ZLStringInputStream(myData);
+}
+void PdfStreamObject::processDecompressor(shared_ptr<PdfObject> filter, ZLInputStream& originalStream) {
+	if (filter == PdfNameObject::nameObject("FlateDecode")) {
+		ZLZDecompressor decompressor(myData.length(), true);
+		ZLStringInputStream dataStream(myData);
+		myData = "";
+		char buffer[2048];
+		while (true) {
+			size_t size = decompressor.decompress(dataStream, buffer, 2048);
+			if (size == 0)
 				break;
-			case NAME:
-				myFilters.push_back(
-					(filter == PdfNameObject::nameObject("FlateDecode")) ?
-						FLATE : UNKNOWN
-				);
-				break;
-			case ARRAY:
-			{
-				// TODO: process filters array
+			myData.append(buffer, size);
+		}
+	}
+}
+void PdfStreamObject::processDecompressorChain(shared_ptr<PdfObject>& filters, ZLInputStream& originalStream) {
+	if(!filters.isNull() && filters->type() == PdfObject::ARRAY) {
+		PdfArrayObject& items = (PdfArrayObject&) *filters;
+		int size = items.size();
+		for(int i = 0; i < size; ++i) {
+			shared_ptr<PdfObject> item = items[i];
+			processDecompressor(item, originalStream);
+		}
+	} else
+		processDecompressor(filters, originalStream);
+}
+void PdfStreamObject::dump() {
+	std::cout << "dict" << std::endl;
+	if(!myDictionary.isNull()) {
+		PdfDictionaryObject& dict = (PdfDictionaryObject&) *myDictionary;
+		dict.dump();
+	}
+	std::ofstream ofs("Q", std::ios::out | std::ios::app | std::ios::binary);
+	ofs << myData;
+}
+PdfStreamObject::PdfStreamObject(shared_ptr<PdfObject> dictionaryO, ZLInputStream &dataStream, char& ch, size_t size) {
+	mySize = size;
+	myDictionary = dictionaryO;
+	dataStream.seek(-1, false);
+	ch = 0;
+	myData.append(mySize, '\0'); /* help debugging */
+	/*myData[0] = ch;
+	dataStream.read((char*)myData.data() + 1, mySize - 1);*/
+	dataStream.read((char*) myData.data(), mySize);
+
+	int value = size;
+	if (value > 0) {
+		PdfDictionaryObject& dictionary = (PdfDictionaryObject&)(*dictionaryO);
+		shared_ptr<PdfObject> filters = dictionary["Filter"];
+		processDecompressorChain(filters, dataStream);
+		shared_ptr<PdfObject> DecodeParmsO = dictionary["DecodeParms"];
+		if(!DecodeParmsO.isNull() && DecodeParmsO->type() == PdfObject::DICTIONARY) {
+			int columns = 0;
+			int predictor = 0;
+			PdfDictionaryObject& DecodeParms = (PdfDictionaryObject&) *DecodeParmsO;
+			integerFromPdfObject(DecodeParms["Predictor"], predictor);
+			integerFromPdfObject(DecodeParms["Columns"], columns);
+			if(predictor) {
+				unsigned char* data = (unsigned char*) myData.data();
+				depredict(columns, predictor, data, myData.length()); /* will depredict in-place */
 			}
 		}
+	} else {
+		//std::cerr << "error: could not determine substream size." << std::endl;
 	}
-	*/
 }
 
 PdfObject::Type PdfStreamObject::type() const {
 	return STREAM;
 }
 
-enum PdfCharacterType {
-	PDF_CHAR_REGULAR,
-	PDF_CHAR_WHITESPACE,
-	PDF_CHAR_DELIMITER
-};
-
-static PdfCharacterType *PdfCharacterTypeTable = 0;
-
-void PdfObject::skipWhiteSpaces(ZLInputStream &stream, char &ch) {
-	if (PdfCharacterTypeTable == 0) {
-		PdfCharacterTypeTable = new PdfCharacterType[256];
-		for (int i = 0; i < 256; ++i) {
-			PdfCharacterTypeTable[i] = PDF_CHAR_REGULAR;
-		}
-		PdfCharacterTypeTable[0] = PDF_CHAR_WHITESPACE;
-		PdfCharacterTypeTable[9] = PDF_CHAR_WHITESPACE;
-		PdfCharacterTypeTable[10] = PDF_CHAR_WHITESPACE;
-		PdfCharacterTypeTable[12] = PDF_CHAR_WHITESPACE;
-		PdfCharacterTypeTable[13] = PDF_CHAR_WHITESPACE;
-		PdfCharacterTypeTable[32] = PDF_CHAR_WHITESPACE;
-		PdfCharacterTypeTable['('] = PDF_CHAR_DELIMITER;
-		PdfCharacterTypeTable[')'] = PDF_CHAR_DELIMITER;
-		PdfCharacterTypeTable['<'] = PDF_CHAR_DELIMITER;
-		PdfCharacterTypeTable['>'] = PDF_CHAR_DELIMITER;
-		PdfCharacterTypeTable['['] = PDF_CHAR_DELIMITER;
-		PdfCharacterTypeTable[']'] = PDF_CHAR_DELIMITER;
-		PdfCharacterTypeTable['{'] = PDF_CHAR_DELIMITER;
-		PdfCharacterTypeTable['}'] = PDF_CHAR_DELIMITER;
-		PdfCharacterTypeTable['/'] = PDF_CHAR_DELIMITER;
-		PdfCharacterTypeTable['%'] = PDF_CHAR_DELIMITER;
-	}
 
-	while ((PdfCharacterTypeTable[(unsigned char)ch] == PDF_CHAR_WHITESPACE) &&
-				 (stream.read(&ch, 1) == 1)) {
-	}
-}
 
-void PdfObject::readToken(ZLInputStream &stream, std::string &buffer, char &ch) {
-	buffer.clear();
-	skipWhiteSpaces(stream, ch);
-	while (PdfCharacterTypeTable[(unsigned char)ch] == PDF_CHAR_REGULAR) {
-		buffer += ch;
-		if (stream.read(&ch, 1) != 1) {
-			break;
+
+shared_ptr<PdfObject> PdfRealObject::realObject(double value) {
+	/*if (value != 0.0) {*/
+		return new PdfRealObject(value);
+	/*} else {
+		static shared_ptr<PdfObject>* table = new shared_ptr<PdfObject>[256];
+		if (table[(int) value].isNull()) {
+			table[(int) value] = new PdfRealObject(value);
 		}
-	}
+		return table[(int) value];
+	}*/
 }
 
-shared_ptr<PdfObject> PdfObject::readObject(ZLInputStream &stream, char &ch) {
-	skipWhiteSpaces(stream, ch);
-
-	PdfObject::Type type = PdfObject::NIL;
-	bool hexString = false;
-	switch (ch) {
-		case '(':
-			hexString = false;
-			type = PdfObject::STRING;
-			break;
-		case '<':
-			stream.read(&ch, 1);
-			hexString = true;
-			type = (ch == '<') ? PdfObject::DICTIONARY : PdfObject::STRING;
-			break;
-		case '>': // end of dictionary
-			stream.read(&ch, 1);
-			if (ch == '>') {
-				stream.read(&ch, 1);
-			}
-			return 0;
-		case '/':
-			type = PdfObject::NAME;
-			break;
-		case '[':
-			type = PdfObject::ARRAY;
-			break;
-		case ']': // end of array
-			stream.read(&ch, 1);
-			return 0;
-		case '+':
-		case '-':
-		case '0':
-		case '1':
-		case '2':
-		case '3':
-		case '4':
-		case '5':
-		case '6':
-		case '7':
-		case '8':
-		case '9':
-			type = PdfObject::INTEGER_NUMBER;
-			break;
-		case 't':
-		case 'f':
-			type = PdfObject::BOOLEAN;
-			break;
-	}
-
-	switch (type) {
-		case PdfObject::DICTIONARY:
-		{
-			ch = 0;
-			shared_ptr<PdfObject> name;
-			shared_ptr<PdfObject> value;
-			shared_ptr<PdfObject> next;
-			PdfDictionaryObject *dictionary = new PdfDictionaryObject();
-			while (true) {
-				next = readObject(stream, ch);
-				if (next.isNull()) {
-					break;
-				}
-				PdfObject::Type oType = next->type();
-				if (oType == PdfObject::NAME) {
-					name = next;
-					value = readObject(stream, ch);
-					if (value.isNull()) {
-						break;
-					}
-					dictionary->setObject(name, value);
-				} else if (oType == PdfObject::INTEGER_NUMBER) {
-					if (value.isNull() || (value->type() != PdfObject::INTEGER_NUMBER)) {
-						break;
-					}
-					skipWhiteSpaces(stream, ch);
-					if (ch != 'R') {
-						break;
-					}
-					const int number = ((PdfIntegerObject&)*value).value();
-					const int generation = ((PdfIntegerObject&)*next).value();
-					dictionary->setObject(name, new PdfObjectReference(number, generation));
-					value = 0;
-					ch = 0;
-				} else {
-					break;
-				}
-			}
-			std::string token;
-			readToken(stream, token, ch);
-			if (token == "stream") {
-				shared_ptr<PdfObject> d = dictionary;
-				return new PdfStreamObject(*dictionary, stream);
-			} else {
-				return dictionary;
-			}
-		}
-		case PdfObject::NAME:
-		{
-			std::string name;
-			stream.read(&ch, 1);
-			readToken(stream, name, ch);
-			return PdfNameObject::nameObject(name);
-		}
-		case PdfObject::BOOLEAN:
-		{
-			std::string name;
-			readToken(stream, name, ch);
-			return (name == "true") ? PdfBooleanObject::TRUE() : PdfBooleanObject::FALSE();
-		}
-		case PdfObject::INTEGER_NUMBER:
-		{
-			std::string str;
-			if ((ch == '+') || (ch == '-')) {
-				str += ch;
-				stream.read(&ch, 1);
-			}
-			while ((ch >= '0') && (ch <= '9')) {
-				str += ch;
-				stream.read(&ch, 1);
-			}
-			return PdfIntegerObject::integerObject(atoi(str.c_str()));
-		}
-		case PdfObject::STRING:
-		{
-			std::string value;
-			if (hexString) {
-				char num[3];
-				num[2] = '\0';
-				while (ch != '>') {
-					num[0] = ch;
-					stream.read(num + 1, 1);
-					value += (char)strtol(num, 0, 16);
-					stream.read(&ch, 1);
-				}
-				ch = 0;
-			} else {
-				// TODO: implement
-			}
-			return new PdfStringObject(value);
-		}
-		case PdfObject::ARRAY:
-		{
-			PdfArrayObject *array = new PdfArrayObject();
-			ch = 0;
-			while (true) {
-				skipWhiteSpaces(stream, ch);
-				if (ch == 'R') {
-					const int size = array->size();
-					if ((size >= 2) &&
-							((*array)[size - 1]->type() == PdfObject::INTEGER_NUMBER) &&
-							((*array)[size - 2]->type() == PdfObject::INTEGER_NUMBER)) {
-						const int generation = ((PdfIntegerObject&)*array->popLast()).value();
-						const int number = ((PdfIntegerObject&)*array->popLast()).value();
-						array->addObject(new PdfObjectReference(number, generation));
-						ch = 0;
-					}
-				}
-				shared_ptr<PdfObject> object = readObject(stream, ch);
-				if (object.isNull()) {
-					break;
-				}
-				array->addObject(object);
-			}
-			std::cerr << "PdfArrayObject " << array->size() << "\n";
-			return array;
-		}
-		default:
-			break;
-	}
+PdfRealObject::PdfRealObject(double value) : myValue(value) {
+	/*std::cerr << "PdfRealObject " << value << "\n"; yeah yeah */
+}
 
-	std::string buffer;
-	stream.read(&ch, 1);
-	while (PdfCharacterTypeTable[(unsigned char)ch] == PDF_CHAR_REGULAR) {
-		buffer += ch;
-		stream.read(&ch, 1);
-	}
-	std::cerr << "buffer = " << buffer << "\n";
+double PdfRealObject::value() const {
+	return myValue;
+}
 
-	return 0;
+PdfObject::Type PdfRealObject::type() const {
+	return REAL_NUMBER;
 }
+
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfObject.h fbreader-0.12.10/fbreader/src/formats/pdf/PdfObject.h
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfObject.h	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfObject.h	2012-08-03 18:24:49.130968433 +0200
@@ -23,19 +23,17 @@
 #include <string>
 #include <vector>
 #include <map>
+#include <list>
 
 #include <shared_ptr.h>
+#include "PdfParser.h"
 
 class ZLInputStream;
 
 class PdfObject {
 
 public:
-	static shared_ptr<PdfObject> readObject(ZLInputStream &stream, char &ch);
-	static void readToken(ZLInputStream &stream, std::string &buffer, char &ch);
-
-protected:
-	static void skipWhiteSpaces(ZLInputStream &stream, char &ch);
+	//static shared_ptr<PdfObject> readObject(ZLInputStream &stream, char &ch);
 
 public:
 	enum Type {
@@ -48,7 +46,9 @@ public:
 		DICTIONARY,
 		STREAM,
 		NIL,
-		REFERENCE
+		REFERENCE,
+		INSTRUCTION, /* FIXME do we want an ADT node type or just an array with the instruction data instead? */
+		CONTENT,
 	};
 
 	virtual ~PdfObject();
@@ -93,9 +93,27 @@ private:
 	const int myValue;
 };
 
-class PdfStringObject : public PdfObject {
+class PdfRealObject : public PdfObject {
+
+public:
+	static shared_ptr<PdfObject> realObject(double value);
+
+private:
+	PdfRealObject(double value);
+
+public:
+	double value() const;
 
 private:
+	Type type() const;
+
+private:
+	const double myValue;
+};
+
+class PdfStringObject : public PdfObject {
+
+public:
 	PdfStringObject(const std::string &value);
 
 private:
@@ -103,21 +121,26 @@ private:
 
 private:
 	std::string myValue;
+public:
+	std::string value() { return myValue; }
 
-friend shared_ptr<PdfObject> PdfObject::readObject(ZLInputStream &stream, char &ch);
+friend shared_ptr<PdfObject> PdfParser::readObject(shared_ptr<ZLInputStream>);
 };
 
 class PdfNameObject : public PdfObject {
-
+private:
+	std::string fID;
 public:
 	static shared_ptr<PdfObject> nameObject(const std::string &id);
-
+	std::string id() const { return fID; }
+	
 private:
 	static std::map<std::string,shared_ptr<PdfObject> > ourObjectMap;
 
 private:
-	PdfNameObject();
-
+	PdfNameObject(const std::string& id);
+	PdfNameObject(const PdfNameObject& source); /* not defined */
+	PdfNameObject& operator=(const PdfNameObject& source); /* not defined */
 private:
 	Type type() const;
 };
@@ -130,7 +153,10 @@ private:
 
 public:
 	shared_ptr<PdfObject> operator [] (shared_ptr<PdfObject> id) const;
+	shared_ptr<PdfObject>& operator [] (shared_ptr<PdfObject> id);
 	shared_ptr<PdfObject> operator [] (const std::string &id) const;
+	std::list<shared_ptr<PdfObject> > keys() const;
+	void dump() const;
 
 private:
 	Type type() const;
@@ -138,40 +164,42 @@ private:
 private:
 	std::map<shared_ptr<PdfObject>,shared_ptr<PdfObject> > myMap;
 
-friend shared_ptr<PdfObject> PdfObject::readObject(ZLInputStream &stream, char &ch);
+friend shared_ptr<PdfObject> PdfParser::readObject(shared_ptr<ZLInputStream>);
 };
 
 class PdfStreamObject : public PdfObject {
-
 private:
-	PdfStreamObject(const PdfDictionaryObject &dictionary, ZLInputStream &dataStream);
+	void processDecompressor(shared_ptr<PdfObject> filter, ZLInputStream& originalStream);
+	void processDecompressorChain(shared_ptr<PdfObject>& filters, ZLInputStream& originalStream);
+private:
+	PdfStreamObject(shared_ptr<PdfObject> dictionary, ZLInputStream& dataStream, char& ch, size_t size);
 
 private:
 	Type type() const;
-
+public:
+	shared_ptr<ZLInputStream> stream() const;
+	shared_ptr<PdfObject> dictionary() const;
+	void setDictionary(shared_ptr<PdfObject> value);
+	void dump();
 private:
 	std::string myData;
-	/*
-	enum EncodingType {
-		UNKNOWN,
-		FLATE,
-	};
-	std::vector<EncodingType> myFilters;
-	*/
+	size_t mySize;
+	shared_ptr<PdfObject> myDictionary;
 
-friend shared_ptr<PdfObject> PdfObject::readObject(ZLInputStream &stream, char &ch);
+friend shared_ptr<PdfObject> PdfParser::readObject(shared_ptr<ZLInputStream>);
 };
 
 class PdfArrayObject : public PdfObject {
 
 private:
-	PdfArrayObject();
-	void addObject(shared_ptr<PdfObject> object);
 	shared_ptr<PdfObject> popLast();
 
 public:
+	void addObject(shared_ptr<PdfObject> object);
+	PdfArrayObject();
 	int size() const;
 	shared_ptr<PdfObject> operator [] (int index) const;
+	shared_ptr<PdfObject>& operator [] (int index);
 
 private:
 	Type type() const;
@@ -179,7 +207,7 @@ private:
 private:
 	std::vector<shared_ptr<PdfObject> > myVector;
 
-friend shared_ptr<PdfObject> PdfObject::readObject(ZLInputStream &stream, char &ch);
+friend shared_ptr<PdfObject> PdfParser::readObject(shared_ptr<ZLInputStream>);
 };
 
 class PdfObjectReference : public PdfObject {
@@ -198,4 +226,30 @@ private:
 	const int myGeneration;
 };
 
+/* helpers */
+
+static inline bool integerFromPdfObject(const shared_ptr<PdfObject>& item, int& a) {
+	if(!item.isNull() && item->type() == PdfObject::INTEGER_NUMBER) {
+		a = ((PdfIntegerObject&)*item).value();
+		return true;
+	} else
+		return false;
+}
+
+static inline bool doubleFromPdfObject(const shared_ptr<PdfObject>& item, double& a) {
+	if(item.isNull())
+		return false;
+	if(item->type() == PdfObject::REAL_NUMBER) {
+		a = ((PdfRealObject&)*item).value();
+		return true;
+	} else {
+		int b;
+		if(integerFromPdfObject(item, b)) {
+			a = b;
+			return true;
+		} else
+			return false;
+	}
+}
+
 #endif /* __PDFOBJECT_H__ */
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfParser.cpp fbreader-0.12.10/fbreader/src/formats/pdf/PdfParser.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfParser.cpp	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfParser.cpp	2012-08-03 18:51:28.442922363 +0200
@@ -0,0 +1,704 @@
+#include <stdlib.h>
+#include <sstream>
+#include <iostream>
+#include <assert.h>
+#include <ZLStringUtil.h>
+#include "PdfParser.h"
+#include "PdfObject.h"
+#include "Pdf.h"
+
+#define GETC(stream, ch) { if(stream.read(&ch, 1) != 1) ch = 0; }
+#define EGETC(stream, ch) { \
+		if (stream.read(&ch, 1) != 1) { \
+			std::cerr << "warning: unexpected EOF"  << std::endl; \
+			abort(); \
+			break; \
+		} \
+}
+
+enum PdfCharacterType {
+	PDF_CHAR_REGULAR,
+	PDF_CHAR_WHITESPACE,
+	PDF_CHAR_DELIMITER
+};
+
+static PdfCharacterType *PdfCharacterTypeTable = 0;
+
+shared_ptr<PdfObject> PdfParser::readCompressedObjectFromLocation(const std::pair<int,int> &address) {
+	std::map<std::pair<int,int>,std::pair<int,int> >::const_iterator jtCompressed = myCompressedObjectLocationMap.find(address);
+	if(jtCompressed == myCompressedObjectLocationMap.end() || address.second != 0) // not found || invalid argument.
+		return 0;
+		
+	return getObjStmEntry(jtCompressed->second.first, 0, jtCompressed->second.second, address.first);
+}
+
+shared_ptr<PdfObject> PdfParser::readObjectFromLocation(const std::pair<int,int> &address) {
+	ZLInputStream& inputStream = *myInputStream;
+	std::map<std::pair<int,int>,int>::const_iterator jt = myObjectLocationMap.find(address);
+	if (jt == myObjectLocationMap.end()) {
+		char old_ch = ch;
+		shared_ptr<PdfObject> result = readCompressedObjectFromLocation(address);
+		ch = old_ch;
+		return result;
+	}
+	inputStream.seek(jt->second, true);
+	ch = 0;
+	readToken(inputStream, myBuffer);
+	if (address.first != atoi(myBuffer.c_str())) {
+		return 0;
+	}
+	readToken(inputStream, myBuffer);
+	if (address.second != atoi(myBuffer.c_str())) {
+		return 0;
+	}
+	readToken(inputStream, myBuffer);
+	if (myBuffer != "obj") {
+		return 0;
+	}
+	//std::cerr << "note: obj addr " << address.first << std::endl;
+	if(address.first == 15745) {
+		std::cerr << "!" << std::endl;
+	}
+	return readObject(myInputStream);
+}
+
+shared_ptr<PdfObject> PdfParser::resolveReference(shared_ptr<PdfObject> ref) {
+	// since even the /XRef itself contains references, ONLY lazy-resolving can work (sanely).
+	if (ref.isNull() || (ref->type() != PdfObject::REFERENCE)) {
+		return ref;
+	}
+	const PdfObjectReference &reference = (const PdfObjectReference&)*ref;
+	//std::cerr << "resolving reference " << reference.number() << std::endl;
+	const std::pair<int,int> address(reference.number(), reference.generation());
+	shared_ptr<PdfObject> object = myPDF.findObject(address);
+	if(!object.isNull())
+		return object;
+	//std::map<std::pair<int,int>,int>::const_iterator jt = myObjectLocationMap.find(address);
+	off_t position = myInputStream->offset();
+	object = readObjectFromLocation(address);
+	myInputStream->seek(position, true);
+	myPDF.addObject(address, object);
+	return object;
+}
+
+static void stripBuffer(std::string &buffer) {
+	int index = buffer.find('%');
+	if (index >= 0) {
+		buffer.erase(index);
+	}
+	ZLStringUtil::stripWhiteSpaces(buffer);
+}
+
+std::string PdfParser::readLine(void) {
+	std::string buffer;
+	ZLInputStream& stream = *myInputStream;
+	//buffer.clear();
+	//char ch;
+	while (1) {
+		if ((ch == 10) || (ch == 13)) {
+			//if (!buffer.empty()) {
+			//}
+			GETC(stream, ch);
+			if(ch == 10 || ch == 13)
+				GETC(stream, ch);
+			break;
+		} else {
+			buffer += ch;
+		}
+		EGETC(stream, ch)
+	}
+	return buffer;
+}
+
+shared_ptr<PdfObject> PdfParser::readTraditionalXREF() {
+		ZLInputStream& inputStream = *myInputStream;
+		while (true) {
+			myBuffer = readLine();
+			stripBuffer(myBuffer);
+			if (myBuffer == "trailer") {
+				break;
+			}
+			const int index = myBuffer.find(' ');
+			const int start = atoi(myBuffer.c_str());
+			const int len = atoi(myBuffer.c_str() + index + 1);
+			for (int i = 0; i < len; ++i) {
+				myBuffer = readLine();
+				stripBuffer(myBuffer);
+				if (myBuffer.length() != 18) {
+					return shared_ptr<PdfObject>();
+				}
+				const int objectOffset = atoi(myBuffer.c_str());
+				const int objectGeneration = atoi(myBuffer.c_str() + 11);
+				const bool objectInUse = myBuffer[17] == 'n';
+				if (objectInUse) {
+					myObjectLocationMap[std::pair<int,int>(start + i, objectGeneration)] = objectOffset;
+				}
+			}
+		}
+		//ch = 0;
+		shared_ptr<PdfObject> trailer = readObject(myInputStream);
+		if (trailer.isNull() || (trailer->type() != PdfObject::DICTIONARY)) {
+			return shared_ptr<PdfObject>();
+		}
+		myPDF.ensureTrailer(trailer);
+		PdfDictionaryObject &trailerDictionary = (PdfDictionaryObject&)*trailer;
+		shared_ptr<PdfObject> previous = trailerDictionary["Prev"];
+		return previous;
+}
+
+static unsigned int readBinaryInteger(ZLInputStream& stream, size_t sizeInBytes, bool& didAnything) {
+	unsigned char buffer[4] = {0};
+	assert(sizeInBytes <= 4);
+	assert(sizeof(int) >= 4);
+	if(stream.read((char*) buffer, sizeInBytes) != sizeInBytes) { // ERROR
+		return 0;
+	}
+	if(sizeInBytes > 0)
+		didAnything = true;
+	unsigned int result = 0;
+	for(int i = 0; i < sizeInBytes; ++i) {
+		result = (result << 8) | buffer[i];
+	}
+	return result;
+}
+
+shared_ptr<PdfObject> PdfParser::readV5XREF() {
+	ZLInputStream& inputStream = *myInputStream;
+	shared_ptr<PdfObject> previous;
+	shared_ptr<PdfObject> xrefO = readObject(myInputStream); // hello chicken-and-egg problem.
+	// after readToken() == "obj";
+	if(xrefO.isNull() || xrefO->type() != PdfObject::STREAM) {
+		return previous;
+	}
+	PdfStreamObject& xref = (PdfStreamObject&) *xrefO;
+	shared_ptr<PdfObject> dictionaryO = xref.dictionary();
+	if(dictionaryO.isNull())
+		return previous;
+	myPDF.ensureTrailer(dictionaryO);
+	PdfDictionaryObject& dictionary = (PdfDictionaryObject&) *dictionaryO;
+	//dictionary.dump();
+	previous = dictionary["Prev"]; // optional.
+	int Size = 0;
+	shared_ptr<PdfObject> WO = dictionary["W"];
+	if(WO.isNull() || WO->type() != PdfObject::ARRAY)
+		return previous;
+	PdfArrayObject& WAO = (PdfArrayObject&) *WO;
+	int Ws[10];
+	int W_count = WAO.size();
+	if(W_count > 10)
+		W_count = 10;
+	for(int i = 0; i < W_count; ++i) {
+		shared_ptr<PdfObject> itemO = WAO[i];
+		if(itemO.isNull() || !integerFromPdfObject(itemO, Ws[i])) // ???
+			Ws[i] = 0;
+	}
+	
+	if(!integerFromPdfObject(dictionary["Size"], Size)) // same meaning as in traditional trailer.
+		return previous;
+	shared_ptr<PdfObject> indexO = dictionary["Index"];
+	std::vector<std::pair<int, int> > indices;
+	if(!indexO.isNull() && indexO->type() == PdfObject::ARRAY) {
+		PdfArrayObject& indexA = (PdfArrayObject&)*indexO;
+		int indexSize = indexA.size();
+		for(int i = 0; i < indexSize - 1; i += 2) {
+			int beginning = 0;
+			int length = 0;
+			if(!integerFromPdfObject(indexA[i], beginning) || !integerFromPdfObject(indexA[i+1], length)) { // ERROR
+				return previous;
+			}
+			indices.push_back(std::make_pair(beginning, length));
+		}
+	} else
+		indices.push_back(std::make_pair(0, Size));
+	shared_ptr<ZLInputStream> streamP = xref.stream();
+	if(streamP.isNull())
+		return previous;
+	ZLInputStream& stream = *streamP;
+	bool didAnything = false;
+	if(indices.size() < 1) // ERROR
+		return previous;
+	didAnything = true;
+	for(int ID = indices[0].first; didAnything; ) {
+		didAnything = false;
+		int V[10] = {4711, 0};
+		for(int i = 0; i < W_count; ++i) {
+			int W = Ws[i];
+			if(W > 0) {
+				V[i] = readBinaryInteger(stream, W, didAnything);
+			} else { // TODO actually there's only one default 0, which is the generation number for type=1. Maybe not do too much?
+				V[i] = 0;
+			}
+			//std::cerr << "XREFV5: " << V[i] << ' ';
+		}
+		//std::cerr <<  std::endl;
+		if(!didAnything) // safety
+			break;
+		if(V[0] == 0) { // fields: [type, object_next_free, next_generation_number] (like 'f).
+		} else if(V[0] == 1) { // fields: [type, offset, generation_number] (like 'n).
+			myObjectLocationMap[std::pair<int,int>(ID, V[2]/*generation*/)] = V[1]/*offset*/;
+			//std::cout << "object " << ID << " known to be uncompressed." << std::endl;
+		} else if(V[0] == 2) { // fields: [type, object, index_in_stream] (generation implicitly 0).
+			myCompressedObjectLocationMap[std::pair<int,int>(ID, 0)] = std::make_pair(V[1] /* referenced object */, V[2] /* index in referenced object */);
+			//std::cout << "object " << ID << " known to be compressed within object " << V[1] << "." << std::endl;
+		}
+		++ID;
+		indices[0] = std::make_pair(indices.front().first, indices.front().second - 1);
+		if(indices.front().second == 0) { // count==0.
+			indices.erase(indices.begin()); // pop front
+			if(indices.size() < 1)
+				break;
+			ID = indices[0].first;
+		}
+	}
+	return previous;
+}
+
+bool PdfParser::readReferenceTable(int xrefOffset) {
+	ZLInputStream& inputStream = *myInputStream;
+	while (true) {
+		inputStream.seek(xrefOffset, true);
+		ch = 0;
+		readToken(inputStream, myBuffer);
+		shared_ptr<PdfObject> previous;
+		// TODO what about leading whitespace?
+		if (myBuffer == "xref") {
+			myBuffer = readLine(); // just the newline, usually.
+			//stripBuffer(myBuffer);
+			previous = readTraditionalXREF();
+		} else {
+			skipWhiteSpaces(inputStream);
+			readToken(inputStream, myBuffer); // number
+			skipWhiteSpaces(inputStream);
+			readToken(inputStream, myBuffer); // obj
+			skipWhiteSpaces(inputStream);
+			if(myBuffer == "obj")
+				previous = readV5XREF();
+			else
+				return false;
+		}
+
+		if(!integerFromPdfObject(previous, xrefOffset))
+			return true;
+	}
+}
+
+
+int PdfParser::readOctalNumber(ZLInputStream& inputStream) { /* used for \ escapes in strings, so we know that after it is not EOF */
+	int result = 0;
+	while(ch >= '0' && ch <= '9') {
+		result *= 8;
+		result += ch - '0';
+		EGETC(inputStream, ch);
+	}
+	return(result);
+}
+shared_ptr<PdfObject> PdfParser::readObject(shared_ptr<ZLInputStream> inputStreamO) {
+	ZLInputStream& inputStream = *inputStreamO;
+	skipWhiteSpaces(inputStream);
+	int nestingLevel = 0;
+
+	PdfObject::Type type = PdfObject::NIL;
+	bool hexString = false;
+	switch (ch) {
+		case '(':
+			GETC(inputStream, ch);
+			hexString = false;
+			type = PdfObject::STRING;
+			break;
+		case '<':
+			GETC(inputStream, ch);
+			hexString = true;
+			type = (ch == '<') ? PdfObject::DICTIONARY : PdfObject::STRING;
+			break;
+		case '>': // end of dictionary
+			GETC(inputStream, ch);
+			if (ch == '>') {
+				GETC(inputStream, ch);
+			}
+			return 0;
+		case '/':
+			type = PdfObject::NAME;
+			break;
+		case '[':
+			type = PdfObject::ARRAY;
+			break;
+		case ']': // end of array
+			GETC(inputStream, ch);
+			return 0;
+		case '+':
+		case '-':
+		case '0':
+		case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+		case '8':
+		case '9':
+			type = PdfObject::INTEGER_NUMBER;
+			break;
+		case 't':
+		case 'f':
+			type = PdfObject::BOOLEAN;
+			break;
+	}
+
+	switch (type) {
+		case PdfObject::DICTIONARY:
+		{
+			ch = 0;
+			shared_ptr<PdfObject> name;
+			shared_ptr<PdfObject> value;
+			shared_ptr<PdfObject> next;
+			PdfDictionaryObject *dictionary = new PdfDictionaryObject();
+			while (true) {
+				next = readObject(inputStreamO);
+				if (next.isNull()) {
+					break;
+				}
+				PdfObject::Type oType = next->type();
+				if (oType == PdfObject::NAME) {
+					name = next;
+					value = readObject(inputStreamO);
+					if (value.isNull()) {
+						break;
+					}
+					dictionary->setObject(name, value);
+					skipWhiteSpaces(inputStream);
+				} else if (oType == PdfObject::INTEGER_NUMBER) {
+					if (value.isNull() || (value->type() != PdfObject::INTEGER_NUMBER)) {
+						break;
+					}
+					skipWhiteSpaces(inputStream);
+					if (ch != 'R') {
+						break;
+					}
+					const int number = ((PdfIntegerObject&)*value).value();
+					const int generation = ((PdfIntegerObject&)*next).value();
+					dictionary->setObject(name, new PdfObjectReference(number, generation));
+					value = 0;
+					ch = 0;
+				} else {
+					break;
+				}
+			}
+			std::string token;
+			readToken(inputStream, token);
+			if (token == "stream") {
+				shared_ptr<PdfObject> d = dictionary;
+				shared_ptr<PdfObject> lengthRef = (*dictionary)["Length"];
+				shared_ptr<PdfObject> length = resolveReference(lengthRef);
+				(*dictionary)["Length"] = length;
+				int lengthV = 0;
+				if(!length.isNull() && length->type() == PdfObject::INTEGER_NUMBER) {
+					lengthV = ((PdfIntegerObject&) *length).value();
+					/*if(lengthV == 0) {
+						std::cerr << "warning: stream length is zero";
+						if(!lengthRef.isNull() && lengthRef->type() == PdfObject::INTEGER_NUMBER) {
+							std::cerr << " (without reference)";
+						}
+						std::cerr << "." << std::endl;
+						shared_ptr<PdfObject> length = resolveReference(lengthRef);
+					}*/
+				} else {
+					std::cerr << "warning: unknown length of stream with dict ";
+					dictionary->dump();
+					std::cerr  << std::endl;
+				}
+				skipWhiteSpaces(inputStream);
+				return new PdfStreamObject(d, inputStream, ch, lengthV);
+			} else {
+				return dictionary;
+			}
+		}
+		case PdfObject::NAME:
+		{
+			std::string xname;
+			std::string name;
+			GETC(inputStream, ch);
+			do {
+				readToken(inputStream, xname);
+				name += xname;
+				if(ch == '#') { // escaped code
+					GETC(inputStream, ch);
+					char num[3];
+					num[0] = ch;
+					GETC(inputStream, ch);
+					num[1] = ch;
+					GETC(inputStream, ch);
+					num[2] = '\0';
+					name += (char)strtol(num, 0, 16);
+				} else
+					break;
+			} while(1);
+			return PdfNameObject::nameObject(name);
+		}
+		case PdfObject::BOOLEAN:
+		{
+			std::string name;
+			readToken(inputStream, name);
+			return (name == "true") ? PdfBooleanObject::TRUE() : PdfBooleanObject::FALSE();
+		}
+		case PdfObject::INTEGER_NUMBER:
+		{
+			std::string str;
+			if ((ch == '+') || (ch == '-')) {
+				str += ch;
+				GETC(inputStream, ch);
+			}
+			while ((ch >= '0') && (ch <= '9')) {
+				str += ch;
+				GETC(inputStream, ch);
+			}
+			if(ch == '.') { /* double-precision floating point value */
+				str += ch;
+				GETC(inputStream, ch);
+				while((ch >= '0' && ch <= '9') || ch == 'e' || ch == 'E' || ch == '-' || ch == '+') { /* FIXME is that OK? */
+					str += ch;
+					GETC(inputStream, ch);
+				}
+				
+				return PdfRealObject::realObject(atof(str.c_str()));
+			} else
+				return PdfIntegerObject::integerObject(atoi(str.c_str()));
+		}
+		case PdfObject::STRING:
+		{
+			std::stringstream valueStream;
+			if (hexString) {
+				char num[3];
+				num[2] = '\0';
+				while (ch && ch != '>') {
+					num[0] = ch;
+					EGETC(inputStream, num[1]);
+					valueStream << (char)strtol(num, 0, 16);
+					EGETC(inputStream, ch);
+				}
+				if(ch != '>') {
+					std::cerr << "warning: unterminated hex string." << std::endl;
+				}
+				ch = 0;
+			} else {
+				nestingLevel = 0;
+				//std::cout << "brace bli" << std::endl;
+				while(ch != ')' || nestingLevel > 0) {
+					//std::cout << (char) ch << ',';
+					if(/* unlikely */ ch == '\\') {
+						EGETC(inputStream, ch);
+						switch(ch) {
+						case 'n':
+							valueStream << (char) 0x0A;
+							break;
+						case 'r':
+							valueStream << (char) 0x0D;
+							break;
+						case 't':
+							valueStream << (char) 0x09;
+							break;
+						case 'b':
+							valueStream << (char) 0x08;
+							break;
+						case 'f':
+							valueStream << (char) 0x0C; 
+							break;
+						case '(':
+							valueStream << (char) '(';
+							break;
+						case ')':
+							valueStream << (char) ')';
+							break;
+						case '0':
+						case '1':
+						case '2':
+						case '3':
+						case '4':
+						case '5':
+						case '6':
+						case '7': /* octal */
+							valueStream << (char) readOctalNumber(inputStream);
+							continue;
+						default:
+							valueStream << (char) ch;
+						}
+					} else {
+						if(ch == ')')
+							--nestingLevel;
+						else if(ch == '(')
+							++nestingLevel;
+						valueStream << (char) ch;
+					}
+					EGETC(inputStream, ch);
+				}
+				ch = 0;
+			}
+			return new PdfStringObject(valueStream.str());
+		}
+		case PdfObject::ARRAY:
+		{
+			PdfArrayObject *array = new PdfArrayObject();
+			ch = 0;
+			while (true) {
+				skipWhiteSpaces(inputStream);
+				if (ch == 'R') {
+					const int size = array->size();
+					if ((size >= 2) &&
+							((*array)[size - 1]->type() == PdfObject::INTEGER_NUMBER) &&
+							((*array)[size - 2]->type() == PdfObject::INTEGER_NUMBER)) {
+						const int generation = ((PdfIntegerObject&)*array->popLast()).value();
+						const int number = ((PdfIntegerObject&)*array->popLast()).value();
+						array->addObject(new PdfObjectReference(number, generation));
+						ch = 0;
+					}
+				}
+				shared_ptr<PdfObject> object = readObject(inputStreamO);
+				if (object.isNull()) {
+					break;
+				}
+				array->addObject(object);
+			}
+			/*std::cerr << "PdfArrayObject " << array->size() << "\n";*/
+			return array;
+		}
+		default:
+			break;
+	}
+
+	std::string buffer;
+	GETC(inputStream, ch);
+	while (ch && PdfCharacterTypeTable[(unsigned char)ch] == PDF_CHAR_REGULAR) {
+		buffer += ch;
+		GETC(inputStream, ch);
+	}
+	/*std::cerr << "buffer = " << buffer << "\n";*/
+
+	return 0;
+}
+
+void PdfParser::parse() {
+	ZLInputStream& myStream = *myInputStream;
+	size_t eofOffset = myStream.sizeOfOpened();
+	if (eofOffset < 100) {
+		return;
+	}
+
+	myStream.seek(eofOffset - 100, true);
+	bool readXrefOffset = false;
+	size_t xrefOffset = (size_t)-1;
+	while (true) {
+		myBuffer = readLine();
+		if (myBuffer.empty()) {
+			break;
+		}
+		stripBuffer(myBuffer);
+		if (readXrefOffset) {
+			if (!myBuffer.empty()) {
+				xrefOffset = atoi(myBuffer.c_str());
+				break;
+			}
+		} else if (myBuffer == "startxref") {
+			readXrefOffset = true;
+		}
+	}
+
+	if (!readReferenceTable(xrefOffset)) {
+		return;
+	}
+}
+
+PdfParser::PdfParser(shared_ptr<ZLInputStream> source, Pdf& destination) :
+	myInputStream(source),
+	myPDF(destination)
+{
+}
+
+
+void PdfParser::skipWhiteSpaces(ZLInputStream& inputStream) {
+	if (PdfCharacterTypeTable == 0) {
+		PdfCharacterTypeTable = new PdfCharacterType[256];
+		for (int i = 0; i < 256; ++i) {
+			PdfCharacterTypeTable[i] = PDF_CHAR_REGULAR;
+		}
+		PdfCharacterTypeTable[0] = PDF_CHAR_WHITESPACE;
+		PdfCharacterTypeTable[9] = PDF_CHAR_WHITESPACE;
+		PdfCharacterTypeTable[10] = PDF_CHAR_WHITESPACE;
+		PdfCharacterTypeTable[12] = PDF_CHAR_WHITESPACE;
+		PdfCharacterTypeTable[13] = PDF_CHAR_WHITESPACE;
+		PdfCharacterTypeTable[32] = PDF_CHAR_WHITESPACE;
+		PdfCharacterTypeTable['('] = PDF_CHAR_DELIMITER;
+		PdfCharacterTypeTable[')'] = PDF_CHAR_DELIMITER;
+		PdfCharacterTypeTable['<'] = PDF_CHAR_DELIMITER;
+		PdfCharacterTypeTable['>'] = PDF_CHAR_DELIMITER;
+		PdfCharacterTypeTable['['] = PDF_CHAR_DELIMITER;
+		PdfCharacterTypeTable[']'] = PDF_CHAR_DELIMITER;
+		PdfCharacterTypeTable['{'] = PDF_CHAR_DELIMITER;
+		PdfCharacterTypeTable['}'] = PDF_CHAR_DELIMITER;
+		PdfCharacterTypeTable['/'] = PDF_CHAR_DELIMITER;
+		PdfCharacterTypeTable['%'] = PDF_CHAR_DELIMITER;
+	}
+
+	while ((PdfCharacterTypeTable[(unsigned char)ch] == PDF_CHAR_WHITESPACE) &&
+				 (inputStream.read(&ch, 1) == 1)) {
+	}
+}
+
+void PdfParser::readToken(ZLInputStream& inputStream, std::string &buffer) {
+	buffer.clear();
+	skipWhiteSpaces(inputStream);
+	while (PdfCharacterTypeTable[(unsigned char)ch] == PDF_CHAR_REGULAR && ch != '#') {
+		buffer += ch;
+		EGETC(inputStream, ch);
+	}
+}
+
+std::vector<std::pair<int, shared_ptr<PdfObject> > > PdfParser::parseObjStm(PdfStreamObject& objStm) {
+	ch = 0;
+	std::vector<std::pair<int, shared_ptr<PdfObject> > > result;
+	shared_ptr<PdfObject> dictionaryO = objStm.dictionary();
+	if(dictionaryO.isNull() || dictionaryO->type() != PdfObject::DICTIONARY) // ERROR
+		return result; 
+	PdfDictionaryObject& dictionary = (PdfDictionaryObject&) *dictionaryO;
+	int N = 0;
+	int First = 0;
+	if(!integerFromPdfObject(dictionary["N"], N) || !integerFromPdfObject(dictionary["First"], First))
+		return result;
+	// FIXME Extends
+	shared_ptr<ZLInputStream> streamO = objStm.stream();
+	if(streamO.isNull())
+		return result;
+	ZLInputStream& stream = *streamO;
+	std::vector<std::pair<int, int> > offsets;
+	for(int i = 0; i < N; ++i) {
+		std::string objectIDStr;
+		std::string offsetStr;
+		readToken(stream, objectIDStr);
+		readToken(stream, offsetStr);
+		int objectID = atoi(objectIDStr.c_str()); // FIXME error check.
+		int offset = atoi(offsetStr.c_str()); // FIXME error check.
+		// was: stream >> objectID >> offset;
+		offsets.push_back(std::make_pair(objectID, offset)); // Note: offsets are in increasing order!
+	}
+	for(std::vector<std::pair<int, int> >::const_iterator iter_offsets = offsets.begin(); iter_offsets != offsets.end(); ++iter_offsets) {
+		// TODO or just skip junk until we are there.
+		stream.seek(First + iter_offsets->second, true);
+		ch = 0;
+		result.push_back(std::make_pair(iter_offsets->first, readObject(streamO)));
+	}
+	return result;
+}
+
+shared_ptr<PdfObject> PdfParser::getObjStmEntry(int objStmID, int objStmGeneration, int referencedIndex, int referencedID) {
+	assert(objStmGeneration == 0); // FIXME support other generations?
+	std::pair<int, int> key = std::make_pair(objStmID, objStmGeneration);
+	if(myCompressedObjects.find(key) == myCompressedObjects.end()) {
+		shared_ptr<PdfObject> obj = resolveReference(new PdfObjectReference(objStmID, objStmGeneration));
+		if(!obj.isNull() && obj->type() == PdfObject::STREAM)
+			myCompressedObjects[key] = new PdfCompressedObjects(parseObjStm((PdfStreamObject&) *obj));
+		else { // ERROR
+			return 0;
+		}
+	}
+	assert((*myCompressedObjects[key])[referencedIndex].first == referencedID);
+	return (*myCompressedObjects[key])[referencedIndex].second; // FIXME bounds check.
+}
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfParser.h fbreader-0.12.10/fbreader/src/formats/pdf/PdfParser.h
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfParser.h	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfParser.h	2012-08-03 18:17:57.922980279 +0200
@@ -0,0 +1,49 @@
+#ifndef __PDF_PARSER_H
+#define __PDF_PARSER_H
+#include <map>
+#include <vector>
+#include <shared_ptr.h>
+#include <ZLInputStream.h>
+
+class Pdf;
+//#include "Pdf.h"
+
+class PdfObject;
+class PdfStreamObject;
+typedef std::vector<std::pair<int, shared_ptr<PdfObject> > > PdfCompressedObjects;
+
+class PdfParser {
+protected:
+	bool readReferenceTable(int offset);
+	shared_ptr<PdfObject> readObjectFromLocation(const std::pair<int,int> &address);
+protected:
+	void readToken(ZLInputStream& inputStream, std::string &buffer);
+	void skipWhiteSpaces(ZLInputStream& inputStream);
+
+private:
+	std::string myBuffer;
+	std::map<std::pair<int,int>,int> myObjectLocationMap; // either it's in there.
+	std::map<std::pair<int,int>,std::pair<int,int> > myCompressedObjectLocationMap; // or it's in there, not both. // (ID, generation) -> (referenced_ID, index_within)
+	shared_ptr<ZLInputStream> myInputStream;
+	Pdf& myPDF;
+	char ch;
+	std::map<std::pair<int,int>, shared_ptr<PdfCompressedObjects> > myCompressedObjects;
+public /* almost private */:
+	shared_ptr<PdfObject> readObject(shared_ptr<ZLInputStream> inputStream);
+public:
+	shared_ptr<PdfObject> resolveReference(shared_ptr<PdfObject> reference);
+public:
+	PdfParser(shared_ptr<ZLInputStream> source, Pdf& destination);
+	void parse();
+protected:
+	PdfCompressedObjects parseObjStm(PdfStreamObject& objStm);
+	shared_ptr<PdfObject> getObjStmEntry(int objStmID, int objStmGeneration, int referencedIndex, int referencedID);
+	shared_ptr<PdfObject> readTraditionalXREF();
+	shared_ptr<PdfObject> readV5XREF();
+	shared_ptr<PdfObject> readCompressedObjectFromLocation(const std::pair<int,int> &address);
+private:
+	std::string readLine(void);
+	int readOctalNumber(ZLInputStream& inputStream);
+};
+
+#endif /* ndef __PDF_PARSER_H */
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfPlugin.cpp fbreader-0.12.10/fbreader/src/formats/pdf/PdfPlugin.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfPlugin.cpp	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfPlugin.cpp	2011-04-05 22:55:28.000000000 +0200
@@ -17,6 +17,7 @@
  * 02110-1301, USA.
  */
 
+#include <string.h>
 #include <ZLFile.h>
 #include <ZLInputStream.h>
 
@@ -24,17 +25,28 @@
 #include "PdfDescriptionReader.h"
 #include "PdfBookReader.h"
 #include "../../library/Book.h"
+#include "../../bookmodel/BookModel.h"
 
 bool PdfPlugin::acceptsFile(const ZLFile &file) const {
-	return file.extension() == "pdf";
+	if(file.extension() == "pdf")
+		return true;
+	shared_ptr<ZLInputStream> inputStream = file.inputStream();
+	if(inputStream.isNull() || !inputStream->open())
+		return false;
+	char buffer[5];
+	if(inputStream->read(buffer, 5) < 5)
+		return false;
+	return (memcmp(buffer, "%PDF-", 5) == 0);
 }
 
 bool PdfPlugin::readMetaInfo(Book &book) const {
-	return PdfDescriptionReader(book).readMetaInfo(ZLFile(path).inputStream());
+	return PdfDescriptionReader(book).readMetaInfo(ZLFile(book.filePath()).inputStream());
 }
 
 bool PdfPlugin::readModel(BookModel &model) const {
-	return PdfBookReader(model).readBook(ZLFile(book.fileName()).inputStream());
+	const Book &book = *model.book();
+	const std::string &filePath = book.filePath();
+	return PdfBookReader(model).readBook(ZLFile(filePath).inputStream());
 }
 
 const std::string &PdfPlugin::iconName() const {
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfScanner.cpp fbreader-0.12.10/fbreader/src/formats/pdf/PdfScanner.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfScanner.cpp	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfScanner.cpp	2011-05-29 00:21:39.710823136 +0200
@@ -0,0 +1,295 @@
+/*PDF parser.
+Copyright (C) 2008 Danny Milosavljevic <danny_milo@yahoo.com>
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if !, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+#include <assert.h>
+#include "PdfScanner.h"
+
+std::string PdfScanner::parseHexadecimalStringBody() {
+  unsigned char hexDigit1, hexDigit2;
+  std::string result = "";
+  while(input != '>' && input != EOF) {
+    if((input >= '0' && input <= '9') || (input >= 'A' && input <= 'F') || (input >= 'a' && input <= 'f'))
+      hexDigit1 = toupper(consume()) - '0';
+    else
+      raiseError("[0-9A-F]");
+
+    if((input >= '0' && input <= '9') || (input >= 'A' && input <= 'F') || (input >= 'a' && input <= 'f'))
+      hexDigit2 = toupper(consume()) - '0';
+    else {
+      while(input != '>' && input != EOF)
+        consume();
+      hexDigit2 = 0; // as per standard.
+    };
+
+    if(hexDigit1 > 9 )
+      hexDigit1 = hexDigit1 - 7; // dist between '9' and 'A', plus 10.
+      
+    if(hexDigit2 > 9 )
+      hexDigit2 = hexDigit2 - 7; // dist between '9' and 'A', plus 10.
+            
+    result = result + (char) ((hexDigit1 << 4) | hexDigit2);
+  };
+  return result;
+};
+
+std::string PdfScanner::parseBracedString() {
+  unsigned vNestingLevel;
+  char vEscaped;
+  vNestingLevel = 0;
+  std::string result = "";
+  
+  consume('(');
+  while (input != ')' || vNestingLevel > 0) {
+    if(input == EOF)
+      break;
+    if(input == '(' )
+      ++vNestingLevel;
+    else if(input == ')' )
+      --vNestingLevel;
+    else if(input == 13 ) { // only leave #10 in the string.
+      consume();
+      if(input != 10) // whoops, killed the newline?
+        result = result + (char)10;
+    } else if(input == '\\' ) {
+      consume();
+      vEscaped = consume();
+      switch(vEscaped) {
+      case 'n': vEscaped = 10; break;
+      case 'r': vEscaped = 13; break;
+      case 't': vEscaped = 9; break;
+      case 'b': vEscaped = 8; break;
+      case 'f': vEscaped = 12; break;
+      case '(': vEscaped = '('; break;
+      case ')': vEscaped = ')'; break;
+      case '\\': vEscaped = '\\'; break;
+      case 10:
+      case 13:
+        {
+          parseOptionalWhitespace();
+          continue;
+        };
+      case '0':
+      case '1':
+      case '2':
+      case '3':
+      case '4':
+      case '5':
+      case '6':
+      case '7':
+         vEscaped = parseOctalEscapeBody(vEscaped);
+      };
+      result = result + vEscaped;
+      continue;
+    };
+      
+    result = result + (char) consume();
+  };
+  consume(')');
+  return result;
+};
+
+int PdfScanner::parseInteger() {
+  unsigned vAbsolute;
+  int result = 1;
+  
+  if(input == '-' ) {
+    result = -1;
+    consume();
+  } else if(input == '+' ) {
+    consume();
+  };
+  
+  vAbsolute = parsePositiveInteger();
+  result = result * vAbsolute;
+  return result;
+};
+
+unsigned PdfScanner::parsePositiveInteger() {
+  int vDigit;
+  unsigned result = 0;
+
+  if(input < '0' || input > '9') 
+    raiseError("<digit>");
+      
+  while(input >= '0' && input <= '9') {
+    vDigit = input - '0';
+    result = result * 10 + vDigit;
+    
+    consume();
+  };
+  return result;
+};
+
+/* parses starting with the dot. */
+double PdfScanner::parseFloatingFraction() {
+  double result;
+  char* end_ptr = NULL;
+  std::string vString = "0";
+/*  if(input == '-' )
+    vString = consume()
+  else if(input == '+' ) 
+    consume();
+    
+  if(! (input in ['0'..'9', '.']) )
+    raiseError('[0-9.]');
+  */
+  if(input != '.' )
+    raiseError(".");
+    
+  while((input >= '0' && input <= '9') || input == '.') 
+    vString = vString + (char) consume();
+  setlocale(LC_NUMERIC,"C");  /* FIXME shoot me now */
+  result = strtod(vString.c_str(), &end_ptr);
+  if(end_ptr && *end_ptr) { /* failed conversion */
+    raiseError("<number>");
+  }
+  return result; // loses precision and since object IDs are in this format too.... StrToFloat(vString);
+};
+
+/* TODO inline */
+char PdfScanner::parseEscapedAttributeNameCharBody() {
+    unsigned char hexDigit1;
+    unsigned char hexDigit2;
+    if((input >= '0' && input <= '9') || (input >= 'A' && input <= 'F') || (input >= 'a' && input <= 'f'))
+      hexDigit1 = toupper(consume()) - '0';
+    else
+      raiseError("[0-9A-Fa-f]");
+
+    if((input >= '0' && input <= '9') || (input >= 'A' && input <= 'F') || (input >= 'a' && input <= 'f'))
+      hexDigit2 = toupper(consume()) - '0';
+    else
+      raiseError("[0-9A-Fa-f]");
+
+    if(hexDigit1 > 9 )
+      hexDigit1 = hexDigit1 - 7; // dist between '9' and 'A', plus 10.
+      
+    if(hexDigit2 > 9 )
+      hexDigit2 = hexDigit2 - 7; // dist between '9' and 'A', plus 10.
+            
+    return ((hexDigit1 << 4) | hexDigit2);
+};
+
+void PdfScanner::parseNewline() {
+  bool vBMatched = false;
+  if(input == 13 ) {
+    vBMatched = true;
+    consume(13);
+  };
+  if(input == 10 ) {
+    vBMatched = true;
+    consume(10);
+  };
+  if(! vBMatched )
+    consume(10);
+};
+
+char PdfScanner::parseOctalEscapeBody(char aFirstChar) {
+  unsigned vCode;
+  if(aFirstChar < '0' || aFirstChar > '7')
+    raiseError("[01234567]");
+  else
+    vCode = aFirstChar - '0';
+ 
+  if(input >= '0' && input <= '7') {
+    vCode = (vCode << 3) | (consume() - '0');
+
+    if(input >= '0' && input <= '7')
+      vCode = (vCode << 3) | (consume() - '0');
+  };
+  // can be out of bounds!
+  
+  return vCode;
+};
+
+void PdfScanner::parseComment() {
+  consume('%');
+  while (input != 10 && input != 13 && input != EOF) 
+    consume();
+}
+
+void PdfScanner::parseOptionalWhitespace() {
+  while(input == 0 || input == 9 || input == 10 || input == 12 || input == 13 || input == 32 || input == '%') {
+    if(input == '%')
+      parseComment();
+    else
+      consume();
+  }
+}
+void PdfScanner::parseSingleWhitespace() {
+  if(input == 0 || input == 9 || input == 10 || input == 12 || input == 13 || input == 32) {
+    // TODO should this include a comment? multiple comments?
+    consume();
+  } else
+    consume(32);
+}
+void PdfScanner::parseWhitespace() {
+  if(input == '<' || input == '/' || input == '(' || input == '[' || input == '{') // exempt from whitespace.
+    return;
+    
+  if(input == 0 || input == 9 || input == 10 || input == 12 || input == 13 || input == 32 || input == '%') {
+    if(input == '%')
+      parseComment();
+    else
+      consume();
+  } else
+    consume(32);
+
+  parseOptionalWhitespace(); 
+}
+
+std::string PdfScanner::parseAttributeName() {
+  std::string result = "";
+  //if(input == '/' ) {
+    //result = '/';
+    consume('/');
+  //};
+  // '!'..'~', then '#AB'
+  // '#' is valid...
+  while (input >= '!' && input <= '~' && !(input == '[' || input == ']' || input == '<' || input == '>' || input == '(' || input == ')' || input == '/' || input == '{' || input == '}')) {
+    if(input == '#' ) { // escape.
+      consume();
+      result = result + parseEscapedAttributeNameCharBody();
+    } else {
+      assert(input != EOF);
+      result = result + (char) input;
+      consume();
+    };
+  };
+
+/*  '/Length'
+  '/Filter'
+  '/Type'
+  '/Contents'
+  '/Resources'
+  */
+  return result;
+};
+
+void PdfScanner::scan(std::string aNeedle) {
+  int vMatchCount;
+  int vMatchMaximum;
+  vMatchMaximum = aNeedle.length();
+  vMatchCount = 0;
+  
+  assert(vMatchMaximum > 0);
+  
+  while (vMatchCount < vMatchMaximum && input != EOF) {
+    if(input == aNeedle[vMatchCount] ) {
+      ++vMatchCount;
+    } else
+      vMatchCount = 0;
+    
+    consume();
+  };
+};
+
+shared_ptr<ZLInputStream> PdfScanner::goToNextStream() {
+	return shared_ptr<ZLInputStream>();
+}
+
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfScanner.h fbreader-0.12.10/fbreader/src/formats/pdf/PdfScanner.h
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfScanner.h	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfScanner.h	2012-08-03 18:35:14.994950398 +0200
@@ -0,0 +1,119 @@
+#ifndef __PDF_SCANNER_H
+#define __PDF_SCANNER_H
+/*PDF parser.
+Copyright (C) 2008 Danny Milosavljevic <danny_milo@yahoo.com>
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if !, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+#include <assert.h>
+#include <stdio.h>
+#include <iostream>
+#include <sstream>
+#include <stdlib.h>
+#include <shared_ptr.h>
+#include <ZLInputStream.h>
+#include <ZLStringInputStream.h>
+
+class PdfScanner {
+protected:
+	shared_ptr<ZLInputStream> inputStream;
+	int input;
+	void raiseError(const char* expected, const char* got = NULL) {
+		/* FIXME error printing */
+		/* FIXME throw exception */
+		char inputString[5] = {0, 0, 0, 0};
+		inputString[0] = input;
+		if(input == EOF) {
+			inputString[0] = '\\';
+			inputString[1] = 'E';
+			inputString[2] = 'O';
+			inputString[3] = 'F';
+		} else if(input < 33) {
+			inputString[0] = '\\';
+			inputString[1] = 'A' + input - 1;
+		}
+		std::cerr << "PdfScanner parse error: expected " << expected << " but got " << (got ? got : inputString) << std::endl;
+		std::cout << "***";
+		while(input != EOF) {
+			consume();
+		}
+		abort();
+	}
+	virtual shared_ptr<ZLInputStream> goToNextStream();
+	int consume() {
+		int old_input = input;
+#ifdef DEBUG_STREAM
+		if(old_input != EOF)
+			std::cout << (char) old_input; /* FIXME */
+		std::cout.flush();
+#endif
+		assert(!inputStream.isNull());
+		if(input != EOF) {
+			unsigned char c_input;
+			if(inputStream->read((char*) &c_input, 1) < 1)
+				input = EOF;
+			else
+				input = c_input;
+			// was: input = inputStream->get();
+		} else
+			return old_input;
+		if(input == EOF) {
+			while(input == EOF && !(inputStream = goToNextStream()).isNull()) {
+				unsigned char c_input;
+				if(inputStream->read((char*) &c_input, 1) < 1)
+					input = EOF;
+				else
+					input = c_input;
+				// was: input = inputStream->get();
+			}
+		}
+		if(input != EOF && input < 0) /* damn signed char */
+			input = 256 + input;
+		return old_input;
+	}
+	void consume(const char* expectedInput) {
+		for(;*expectedInput;++expectedInput) {
+			if(input != *expectedInput) {
+				raiseError(expectedInput);
+			}
+			consume();
+		}
+	}
+	void consume(char expectedInput) {
+		char expectedInputString[2] = {0, 0};
+		expectedInputString[0] = expectedInput;
+		if(input != expectedInput) {
+			raiseError(expectedInputString);
+		}
+		consume();
+	}
+	
+	/* PDF specific: */
+	std::string parseHexadecimalStringBody();
+	std::string parseBracedString();
+	int parseInteger();
+	unsigned parsePositiveInteger();
+	double parseFloatingFraction();
+	void parseNewline();
+	char parseEscapedAttributeNameCharBody();
+	char parseOctalEscapeBody(char aFirstChar);
+	void parseComment();
+	void parseOptionalWhitespace();
+	void parseWhitespace();
+	void parseSingleWhitespace();
+	std::string parseAttributeName();
+	void scan(std::string aNeedle);
+	
+public:
+	PdfScanner(shared_ptr<ZLInputStream> stream) : inputStream(stream), input(0) {
+	}
+	PdfScanner(const std::string& inputString) : inputStream(new ZLStringInputStream(inputString)), input(0) {
+	}
+	virtual ~PdfScanner() {}
+};
+
+#endif /* ndef __PDF_SCANNER_H */
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfTiffWriter.cpp fbreader-0.12.10/fbreader/src/formats/pdf/PdfTiffWriter.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfTiffWriter.cpp	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfTiffWriter.cpp	2011-12-29 20:09:10.781219148 +0100
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2004-2010 Geometer Plus <contact@geometerplus.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include <iostream>
+#include <string.h>
+#include "PdfTiffWriter.h"
+
+static unsigned char basic_header[] = "II\x2A\x00\x08\x00\x00\x00\x00\x00";
+#define BASIC_HEADER_SIZE 10
+
+static unsigned int tag_count = 10;
+//class PdfTiffWriter {
+PdfTiffWriter::PdfTiffWriter(int k, int cols, int rows, bool blackis1, size_t size) {
+	max_additional_data = 24;
+	ifd_size = 10 + (12 * tag_count) + 4;
+	size_t tiffheader_size = ifd_size + max_additional_data;
+	if(tiffheader_size > MAX_TIFFHEADER) {
+		//throw std::runtime_error("TIFF header too large for buffer");
+	}
+	memset(tiffheader, 0, MAX_TIFFHEADER);
+	for(int i = 0; i < BASIC_HEADER_SIZE; ++i)
+		this->tiffheader[i] = basic_header[i];
+	this->additional_offset = ifd_size;
+	int comptype = 3; // T4
+	int t4options = 0; // 1D or 2D T4?
+	if(k < 0)
+		comptype = 4;
+	else if(k > 0) {
+		comptype = 3;
+		t4options = 1;
+	} // else leave T4 1D
+	// TODO maybe fall back to Height for rows.
+	// keep sorted by tag.
+	addTag(256, cols, 4);
+	addTag(257, rows, 4);
+	addTag(259, comptype, 2);
+	addTag(262, blackis1, 2); // Photometric Interpretation
+	addTag(273, tiffheader_size, 4); // Offset to start of image data - updated below
+	addTag(279, size, 4); // Length of image data
+	//self.addTag(282, 300, 1) # X Resolution 300 (default unit Inches) # TODO rational
+	//self.addTag(283, 300, 1) # Y Resolution 300 (default unit Inches) # TODO rational
+	if (comptype == 3)
+		addTag(292, t4options, 4); // 32 flag bits.
+	addStringTag(305, "FBReader"); // generated-by-software
+}
+void PdfTiffWriter::addTag(uint16_t tag, uint32_t x_value, size_t size) {
+	// size is in bytes
+	tiffheader[8] += 1;
+	size_t count = tiffheader[8];
+	if(count >= tag_count) { // too many
+		return;
+	}
+	size_t offset = (count - 1)*12 + 10;
+	tiffheader[offset] = tag & 0xFF;
+	tiffheader[offset + 1] = (tag >> 8) & 0xFF;
+	tiffheader[offset + 2] = (size == 2) ? 3 : (size == 4) ? 4 : 0;
+	tiffheader[offset + 3] = 0; // TODO what's this?
+	tiffheader[offset + 4] = 1; // array item count
+	// Tiff types: 1=byte, 2=ascii, 3=short, 4=ulong 5=rational
+	tiffheader[offset + 8] = x_value & 0xFF;
+	tiffheader[offset + 9] = (x_value >> 8) & 0xFF;
+	tiffheader[offset + 10] = (x_value >> 16) & 0xFF;
+	tiffheader[offset + 11] = (x_value >> 24) & 0xFF;
+}
+void PdfTiffWriter::addStringTag(uint16_t tag, const std::string& value) {
+	// size is in bytes
+	tiffheader[8] += 1;
+	size_t count = tiffheader[8];
+	if(count >= tag_count) { // too many
+		return;
+	}
+	size_t offset = (count - 1)*12 + 10;
+	tiffheader[offset] = tag & 0xFF;
+	tiffheader[offset + 1] = (tag >> 8) & 0xFF;
+	tiffheader[offset + 2] = 2;
+	tiffheader[offset + 3] = 0; // TODO what's this?
+	tiffheader[offset + 4] = value.length(); // array item count
+	uint32_t x_value = additional_offset;
+	// Tiff types: 1=byte, 2=ascii, 3=short, 4=ulong 5=rational
+	tiffheader[offset + 8] = x_value & 0xFF;
+	tiffheader[offset + 9] = (x_value >> 8) & 0xFF;
+	tiffheader[offset + 10] = (x_value >> 16) & 0xFF;
+	tiffheader[offset + 11] = (x_value >> 24) & 0xFF;
+	// string
+	if(additional_offset + value.length() <= ifd_size + max_additional_data) {
+		for(int i = additional_offset, j = 0, e = additional_offset + value.length(); i < e; ++i, ++j)
+			tiffheader[i] = value[i];
+		additional_offset += value.length();
+	} else { // ooops
+		std::cerr << "PdfTiffWriter: I don't have enough space in my little buffer" << std::endl;
+	}
+}
+std::string PdfTiffWriter::str(void) const {
+	return(std::string((const char*) tiffheader, ifd_size + max_additional_data));
+}
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfTiffWriter.h fbreader-0.12.10/fbreader/src/formats/pdf/PdfTiffWriter.h
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfTiffWriter.h	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfTiffWriter.h	2011-12-29 19:32:18.153208777 +0100
@@ -0,0 +1,38 @@
+#ifndef __PDF_TIFF_WRITER_H
+#define __PDF_TIFF_WRITER_H
+/*
+ * Copyright (C) 2004-2010 Geometer Plus <contact@geometerplus.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include <stdint.h>
+ 
+#define MAX_TIFFHEADER 158
+
+class PdfTiffWriter {
+private:
+	unsigned char tiffheader[MAX_TIFFHEADER];
+	size_t additional_offset;
+	size_t max_additional_data;
+	size_t ifd_size;
+public:
+	PdfTiffWriter(int k, int cols = 1728, int rows = 0, bool blackis1 = 0, size_t size = 0);
+	void addTag(uint16_t tag, uint32_t value, size_t size);
+	void addStringTag(uint16_t tag, const std::string& value);
+	std::string str(void) const;
+};
+
+#endif /* ndef __PDF_TIFF_WRITER_H */
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfToUnicodeMap.cpp fbreader-0.12.10/fbreader/src/formats/pdf/PdfToUnicodeMap.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfToUnicodeMap.cpp	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfToUnicodeMap.cpp	2011-04-05 22:55:28.000000000 +0200
@@ -0,0 +1,177 @@
+/*PDF parser.
+Copyright (C) 2008 Danny Milosavljevic <danny_milo@yahoo.com>
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if !, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <assert.h>
+#include <string.h>
+#include <sstream>
+#include <ZLUnicodeUtil.h>
+#include "PdfToUnicodeMap.h"
+#include "PdfDefaultCharMap.h"
+
+static std::string unicharToUTF8(unsigned int aCodepoint) {
+	char buf[5] = {0,0,0,0,0};
+	buf[0] = (char) aCodepoint;
+	/*buf[1] = 0;*/
+	ZLUnicodeUtil::ucs4ToUtf8(buf, aCodepoint);
+	return buf;
+}
+
+void PdfToUnicodeMap::addRange(const std::string aNativeBeginning, const std::string aNativeEnd, std::vector<unsigned int> aUnicodeBeginnings) {
+	unsigned int nativeCode;
+	unsigned char nativeBeginningTail;
+	unsigned char nativeEndTail;
+	if(aUnicodeBeginnings.size() > MAX_TARGET) {
+	   std::cerr << "error: ToUnicode map doesn't support unicode target of length >14 (i.e. " << aUnicodeBeginnings.size() << ")" << std::endl;
+	   return;
+	}
+	if(aUnicodeBeginnings.size() < 1) {
+	   std::cerr << "error: ToUnicode map target is missing." << std::endl;
+	   return;
+	}
+	unsigned int aUnicodeBeginning = aUnicodeBeginnings[0];
+	assert(aNativeBeginning.size() > 0);
+	assert(aNativeEnd.size() > 0);
+	// common prefix
+	size_t vPrefixLength = aNativeBeginning.size() - 1;
+	assert(vPrefixLength == aNativeEnd.size() - 1);
+	assert(aNativeBeginning.substr(0, vPrefixLength) == aNativeEnd.substr(0, vPrefixLength));
+	nativeBeginningTail = aNativeBeginning[vPrefixLength];
+	nativeEndTail = aNativeEnd[vPrefixLength];
+	if(vPrefixLength == 0) {
+		for(nativeCode = nativeBeginningTail; nativeCode <= nativeEndTail; ++nativeCode, ++aUnicodeBeginning) {
+			if(fPrefixlessCodes[nativeCode] && fPrefixlessCodes[nativeCode] != aUnicodeBeginning) {
+				std::cerr << "warning: PdfToUnicodeMap: code " << std::dec << (unsigned)nativeCode << " was mapped to unicode U+" << std::hex << fPrefixlessCodes[nativeCode] << " but is now remapped to unicode U+" << std::hex << aUnicodeBeginning << std::dec << std::endl;
+			}
+			fPrefixlessCodes[nativeCode] = aUnicodeBeginning;
+			++fPrefixlessCodesUsed;
+		}
+		return;
+	}
+  
+	struct PdfToUnicodeMapRangeEntry entry;
+	assert(vPrefixLength <= sizeof(entry.nativePrefix)/sizeof(entry.nativePrefix[0]));
+	if(vPrefixLength > 0)
+	for(size_t vPrefixIndex = 0; vPrefixIndex < vPrefixLength; ++vPrefixIndex)
+		entry.nativePrefix[vPrefixIndex] = aNativeBeginning[vPrefixIndex];
+      
+	entry.nativePrefixSize = vPrefixLength;
+	entry.nativeBeginning = nativeBeginningTail;
+	entry.nativeEnd = nativeEndTail;
+	{
+		struct PdfToUnicodeMapChars& en = entry.unicodeBeginnings;
+		int i;
+		int size = aUnicodeBeginnings.size();
+		for(i = 0; i < size; ++i)
+			en.items[i] = aUnicodeBeginnings[i];
+		en.count = size;
+	}
+	fRanges.push_back(entry);  
+}
+
+PdfToUnicodeMap::PdfToUnicodeMap() {
+	fPrefixlessCodesUsed = 0;
+	for(int i = 0; i < 256; ++i)
+		fPrefixlessCodes[i] = 0;
+}
+
+struct PdfToUnicodeMapChars PdfToUnicodeMap::nextUnicodeCodepoint(unsigned char*& aNativeString, size_t& aNativeStringSize) const {
+  struct PdfToUnicodeMapChars result;
+  unsigned char vNativeCharacter;
+  int vPrefixCMP;
+  unsigned int resultC = cNilCodepoint;
+  result.count = 1;
+  result.items[0] = resultC;
+  
+  assert(aNativeStringSize > 0);
+  
+  if((resultC = fPrefixlessCodes[*aNativeString]) != 0) {
+    ++aNativeString;
+    --aNativeStringSize;
+    result.count = 1;
+    result.items[0] = resultC;
+    return result;
+  }
+
+  for(std::vector<struct PdfToUnicodeMapRangeEntry>::const_iterator iter_entries = fRanges.begin(); iter_entries != fRanges.end(); ++iter_entries) {
+    const struct PdfToUnicodeMapRangeEntry& entry = *iter_entries;
+    if((entry.nativePrefixSize > 0) and (aNativeStringSize >= entry.nativePrefixSize) ) {
+        vPrefixCMP = memcmp(&entry.nativePrefix[0], aNativeString, entry.nativePrefixSize);
+    } else if((entry.nativePrefixSize > 0) /* and ! (aNativeStringSize >== NativePrefixSize)*/ )
+       vPrefixCMP = 1;
+    else
+       vPrefixCMP = 0;
+
+      if((vPrefixCMP == 0) && (aNativeStringSize > entry.nativePrefixSize) ) {
+        vNativeCharacter = *(aNativeString + entry.nativePrefixSize);
+
+        if((vNativeCharacter >= entry.nativeBeginning) and (vNativeCharacter <= entry.nativeEnd) ) {
+          aNativeString += entry.nativePrefixSize + 1;
+          aNativeStringSize -= entry.nativePrefixSize + 1;
+          resultC = entry.unicodeBeginnings.items[0] + (vNativeCharacter) - (entry.nativeBeginning);
+          result = entry.unicodeBeginnings;
+          result.items[0] = resultC; // FIXME carry.
+          break;
+      };
+    };
+  };
+  return result;
+};
+
+size_t PdfToUnicodeMap::size() const {
+  return fPrefixlessCodesUsed + fRanges.size();
+}
+
+std::string PdfToUnicodeMap::convertStringToUnicode(const std::string& aValue) const {
+	unsigned char* fValue;
+	unsigned char* fValuePrev;
+	size_t fValueSize;
+	size_t fPreviousValueSize;
+	struct PdfToUnicodeMapChars fCodepoints;
+	/*FILE* fff = fopen("/tmp/Q", "a");
+	fputs(aValue.c_str(), fff);
+	fclose(fff);*/
+	if(this == 0)
+		return aValue; /* FIXME "XXX";*/
+	std::string result = ""; // '(' + aValue + ')';
+	fValueSize = aValue.length();
+	fValue = (unsigned char*) aValue.c_str(); /* FIXME just use unsigned char in the compiler settings */
+	do {
+		fPreviousValueSize = fValueSize;
+		if(fValueSize == 0)
+			break;
+		fValuePrev = fValue;
+		fCodepoints = nextUnicodeCodepoint(fValue, fValueSize);
+		if(fCodepoints.count <= 0 || fCodepoints.items[0] == cNilCodepoint || fPreviousValueSize == fValueSize)
+			break;
+		for(int i = 0; i < fCodepoints.count; ++i) {
+			unsigned int fCodepoint = fCodepoints.items[i];
+			if(fCodepoint >= 0xFB00 && fCodepoint < 0xFB04) { // ligatures are not supported by FBReader (and I don't like them anyway), so replace them.
+				switch(fCodepoint) {
+				case 0xFB00:
+					result += "ff";
+					break;
+				case 0xFB01:
+					result += "fi";
+					break;
+				case 0xFB02:
+					result += "fl";
+					break;
+				case 0xFB03:
+					result += "ffi";
+					break;
+				default: ;
+				}
+				continue;
+			}
+			result = result + unicharToUTF8(fCodepoint);
+		}
+	} while(fCodepoints.count > 0 && fCodepoints.items[0] != cNilCodepoint);
+	return result;
+}
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfToUnicodeMap.h fbreader-0.12.10/fbreader/src/formats/pdf/PdfToUnicodeMap.h
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfToUnicodeMap.h	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfToUnicodeMap.h	2011-04-05 22:55:28.000000000 +0200
@@ -0,0 +1,40 @@
+#ifndef __PDF_TOUNICODE_MAP_H
+#define __PDF_TOUNICODE_MAP_H
+#include <string>
+#include <map>
+#include <sstream>
+#include <iostream>
+#include <ZLStringUtil.h>
+#include <ZLInputStream.h>
+#include "PdfScanner.h"
+#include "PdfToUnicodeMap.h"
+#include "PdfDefaultCharMap.h"
+
+#define MAX_TARGET 14
+struct PdfToUnicodeMapChars {
+	int count;
+	unsigned int items[MAX_TARGET];
+};
+struct PdfToUnicodeMapRangeEntry {
+	char nativePrefix[3];
+	unsigned char nativePrefixSize;
+	unsigned char nativeBeginning;
+	unsigned char nativeEnd;
+	struct PdfToUnicodeMapChars unicodeBeginnings;
+};
+
+class PdfToUnicodeMap {
+private:
+	std::vector<struct PdfToUnicodeMapRangeEntry> fRanges;
+	//PdfToUnicodeMapAddress fAddress;
+	unsigned int fPrefixlessCodes[256];
+	size_t fPrefixlessCodesUsed;
+public:
+	PdfToUnicodeMap();
+	struct PdfToUnicodeMapChars nextUnicodeCodepoint(unsigned char*& aNativeString, size_t& aNativeStringSize) const;
+	void addRange(const std::string nativeBeginning, const std::string nativeEnd, std::vector<unsigned int> unicodeBeginning);
+	size_t size() const;
+	std::string convertStringToUnicode(const std::string& aValue) const;
+};
+
+#endif /* ndef __PDF_TOUNICODE_MAP_H */
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfToUnicodeParser.cpp fbreader-0.12.10/fbreader/src/formats/pdf/PdfToUnicodeParser.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfToUnicodeParser.cpp	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfToUnicodeParser.cpp	2011-04-05 22:55:28.000000000 +0200
@@ -0,0 +1,187 @@
+/*PDF parser.
+Copyright (C) 2008 Danny Milosavljevic <danny_milo@yahoo.com>
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if !, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <assert.h>
+#include <sstream>
+#include "PdfToUnicodeMap.h"
+#include "PdfToUnicodeParser.h"
+
+/* UTF-16 -> UCS-4 
+
+    * Braucht das Zeichen mehr als 16 bit wird's kompliziert:
+          o Das Zeichen muss jetzt auf zwei 16-bit-Einheiten verteilt werden
+          o Damit man erkennen kann, dass die Einheiten ein Paar bilden haben sie an den höchsten Stellen standardisierte bits:
+                + 110110.......... (Die erste Einheit des Paares)
+                + 110111.......... (Die zweite Einheit des Paares)
+          o In jeder Einheit sind also noch 10 bits frei, in die man jeweils eine Hälfte des Unicode-Zeichens stecken kann
+
+Jetzt wird's kompliziert. Anstatt das Unicode-Zeichen einfach zu zerteilen zieht man erst 65536 davon ab. Dies hat den Vorteil, dass man jetzt 65536 Zeichen mehr kodieren kann. Wenn man das Zeichen lesen möchte muss man daran denken, wieder 65536 zu addieren (Also 1101100000000000 1101110000000000 steht nicht für U+0000 sondern für U+10000). Hoffe dass es jetzt klarer ist. RedNifre 02:30, 15. Feb. 2008 (CET)
+
+Der Codebereich von U+D800 bis U+DBFF (High-Surrogates) und der Bereich von U+DC00 bis U+DFFF (Low-Surrogates) ist für diese UTF-16-Ersatzzeichen reserviert und enthält keine eigenständigen Zeichen.
+*/
+
+/* other direction would be:
+    vHighSurrogate = ((aValue - 0x10000) div 0x400) + 0xD800;
+    vLowSurrogate = ((aValue - 0x10000) % 0x400) + 0xDC00;
+*/
+std::vector<unsigned int> UCS_4_code_from_UTF_16(const std::string aValue) {
+  unsigned int code;
+  std::vector<unsigned int> result;
+  for(size_t i = 0; i < aValue.length() - 1; i+=2) {
+    unsigned int part = (((unsigned char) aValue[i]) << 8) | ((unsigned char) aValue[i + 1]); // compiler settings are such that char is signed, yay.
+    if(part >= 0xD800 && part <= 0xDBFF) { /* surrogate pair */
+      i += 2;
+      if(i < aValue.length() - 1) {
+        unsigned int vLowSurrogate = (((unsigned char) aValue[i]) << 8) | ((unsigned char) aValue[i + 1]); // compiler settings are such that char is signed, yay.
+        assert((vLowSurrogate <= 0xDC00) && (vLowSurrogate <= 0xDFFF));
+        code = 0x10000 + (part - 0xD800) * 0x400 + (vLowSurrogate - 0xDC00);
+      } else {
+        std::cerr << "warning: ignored incomplete surrogate pair." << std::endl;
+      }
+    } else
+      code = part;
+    result.push_back(code);
+  }
+  return(result);
+  // U+D800..U+DBFF (High-Surrogates) and U+DC00..U+DFFF (Low-Surrogates)
+  // Lastly, if a CID does not map to a Unicode code point, the value 0xFFFD shall be used as its Unicode code point.
+  return result;
+};
+
+/*static char hexdigits[17] = "0123456789ABCDEF";
+static std::string hex(std::string aValue) {
+  std::stringstream result;
+  for(int i = 0; i < aValue.length(); ++i) {
+    unsigned char v = aValue[i];
+    result << hexdigits[v >> 4] << hexdigits[v & 15];
+  }
+  return result.str();
+};*/
+
+void PdfToUnicodeParser::parseRangeBody() {
+  std::string vNativeBeginning;
+  std::string vNativeEnd;
+  std::vector<unsigned int> vUnicodeCharacters;
+  while(input != 'e') {
+    vNativeBeginning = parseValue();
+    parseWhitespace();
+    vNativeEnd = parseValue();
+    parseWhitespace();
+    if(input == '[') { /* multiple characters */
+		consume();
+		parseOptionalWhitespace();
+		std::stringstream result;
+		size_t vPrefixLength = vNativeBeginning.size() - 1;
+		assert(vNativeBeginning.substr(0, vPrefixLength) == vNativeEnd.substr(0, vPrefixLength));
+		while(input != ']' && input != EOF && vNativeBeginning <= vNativeEnd) {
+			std::string part = parseValue(); /* <006B> */ /* UTF-16BE */
+			parseOptionalWhitespace();
+			vUnicodeCharacters = UCS_4_code_from_UTF_16(part); /* TODO multi-character things (hex: <40213222> 4 digits are 1 character)) */
+			fMap.addRange(vNativeBeginning, vNativeBeginning, vUnicodeCharacters);
+			//std::cout << (int) vNativeBeginning[0] << "XX" << (int) vNativeBeginning[1] << std::endl;
+			++vNativeBeginning[vPrefixLength]; /* FIXME */
+		}
+		consume(']');
+		parseOptionalWhitespace();
+
+    } else {
+      vUnicodeCharacters = UCS_4_code_from_UTF_16(parseValue());
+      parseWhitespace();
+      fMap.addRange(vNativeBeginning, vNativeEnd, vUnicodeCharacters);
+    }
+    
+  };
+};
+
+void PdfToUnicodeParser::parseCharBody()
+{
+  std::string vNativeBeginning;
+  std::vector<unsigned int> vUnicodeCharacters;
+  std::string temp;
+  while(input != 'e') {
+    vNativeBeginning = parseValue();
+    parseWhitespace();
+    temp = parseValue();
+    assert(temp.length() > 0);
+    vUnicodeCharacters = UCS_4_code_from_UTF_16(temp);
+    //assert(vUnicodeCharacter != 4294967268); // if you get this, you have signed/unsigned char mismatch.
+    parseWhitespace();
+
+    //Writeln(Hex(vNativeBeginning), ' ==> ', vUnicodeCharacter);
+    fMap.addRange(vNativeBeginning, vNativeBeginning, vUnicodeCharacters);
+  };
+};
+
+
+void PdfToUnicodeParser::parse() {
+  consume();
+  parse_();
+}
+
+
+
+void PdfToUnicodeParser::parse_() {
+  // "beginbfrange" || "beginbfchar"
+  while(input != EOF) {
+    scan("beginbf");
+  
+    if(input == EOF)
+      break;
+    
+    if(input == 'r' ) {
+      consume("range");
+      parseWhitespace();
+      parseRangeBody();
+      parseOptionalWhitespace();
+      consume("endbfrange");
+    } else if(input == 'c' ) {
+      consume("char");
+      parseWhitespace();
+      parseCharBody();
+      parseOptionalWhitespace();
+      consume("endbfchar");
+    } else {
+      std::string got = (std::string("beginbf") + (char)input);
+      raiseError("beginbfrange|beginbfchar", got.c_str());
+    };
+    parseOptionalWhitespace();
+  };
+  
+  // "/CMapType 2 def"
+
+}
+
+PdfToUnicodeParser::PdfToUnicodeParser(shared_ptr<ZLInputStream> stream, PdfToUnicodeMap& map) : PdfScanner(stream), fMap(map) {
+}
+
+std::string PdfToUnicodeParser::parseValue() {
+	if(input == '<') {
+		consume();
+		if(input != '<') {
+			std::string result = parseHexadecimalStringBody();
+			consume('>');
+			return result;
+		} else {
+			std::cerr << "warning: ignoring empty hex string." << std::endl;
+			return "";
+		}
+	}else {
+		if(input != '(') {
+			std::cerr << "warning: ToUnicode table contains junk:";
+			while(input != EOF) {
+				std::cerr << (char) input;
+				consume();
+			}
+			std::cerr << std::endl;
+		}
+		return parseBracedString();
+	}
+}
+
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfToUnicodeParser.h fbreader-0.12.10/fbreader/src/formats/pdf/PdfToUnicodeParser.h
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfToUnicodeParser.h	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfToUnicodeParser.h	2011-04-05 22:55:28.000000000 +0200
@@ -0,0 +1,28 @@
+#ifndef __PDF_TOUNICODE_PARSER_H
+#define __PDF_TOUNICODE_PARSER_H
+#include <string>
+#include <map>
+#include <sstream>
+#include <iostream>
+#include <ZLStringUtil.h>
+#include <ZLInputStream.h>
+#include "PdfScanner.h"
+
+typedef std::pair<int,int> PdfToUnicodeMapAddress;
+/*address(reference.number(), reference.generation());*/
+
+class PdfToUnicodeParser : public PdfScanner {
+private:
+	PdfToUnicodeMap& fMap;
+protected:
+	void parseRangeBody();
+	void parseCharBody();
+	void parse_();
+	std::string parseValue();
+	unsigned int parseCharsetEntry();
+public:
+	PdfToUnicodeParser(shared_ptr<ZLInputStream> stream, PdfToUnicodeMap& map);
+	void parse();
+};
+
+#endif /* ndef __PDF_TOUNICODE_PARSER_H */
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfType1FontFileParser.cpp fbreader-0.12.10/fbreader/src/formats/pdf/PdfType1FontFileParser.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfType1FontFileParser.cpp	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfType1FontFileParser.cpp	2012-08-03 18:44:03.762935175 +0200
@@ -0,0 +1,81 @@
+/*PDF parser.
+Copyright (C) 2008 Danny Milosavljevic <danny_milo@yahoo.com>
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if !, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <assert.h>
+#include <sstream>
+#include "PdfType1FontFileParser.h"
+#include "PdfDefaultCharMap.h"
+
+
+bool PdfType1FontFileParser::parse() {
+  consume();
+  if(input == EOF) { /* some PDFs have a zero-size stream here. */
+    return false;
+  }
+  parse_();
+  return true;
+}
+
+// FIXME parse this properly.
+
+static std::vector<unsigned int> vec(unsigned int i) {
+	std::vector<unsigned int> result;
+	result.push_back(i);
+	return(result);
+}
+
+void PdfType1FontFileParser::parse_() {
+  // parse magic
+  //printf("%X\n", (int) input);
+  consume("%!");
+  // "FontType1-1.0: SFBX1728 0.3"
+  if(input != 'P') 
+    return;
+  consume("PS-AdobeFont-");
+  while(input != EOF && input != '\n')
+    consume();
+    
+  scan("/Encoding");
+  parseWhitespace();
+  if(input < '0' || input > '9') // "/Encoding StandardEncoding def" TODO; then "currentdict end" and then "currentfile eexec".
+    return;
+  parsePositiveInteger();
+  parseWhitespace();
+  consume("array");
+  parseWhitespace();
+  scan("dup");
+  parseWhitespace();
+  while(input != EOF) {
+    unsigned localCode = parsePositiveInteger();
+    parseWhitespace();
+    std::string name = parseAttributeName();
+    parseWhitespace();
+    consume("put");
+    parseWhitespace();
+    assert(localCode < 256); /* && localCode >= 0);*/
+    unsigned vUnicodeCharacter = getUnicodeFromDefaultCharMap(name);
+    if(vUnicodeCharacter != cNilCodepoint) {
+      std::string sNativeBeginning;
+      sNativeBeginning.append(1, localCode);
+      fMap.addRange(sNativeBeginning, sNativeBeginning, vec(vUnicodeCharacter));
+    } else {
+      std::cerr << "error: (Type1 font file parser) could not find character '/" << name << "' (for native code " << localCode << ")." << std::endl;
+    }
+
+    if(input != 'd')
+      break;
+    consume("dup");
+    parseWhitespace();
+  }
+}
+
+PdfType1FontFileParser::PdfType1FontFileParser(shared_ptr<ZLInputStream> stream, PdfToUnicodeMap& map) : PdfScanner(stream), fMap(map) {
+}
+
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfType1FontFileParser.h fbreader-0.12.10/fbreader/src/formats/pdf/PdfType1FontFileParser.h
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/PdfType1FontFileParser.h	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/PdfType1FontFileParser.h	2012-08-03 18:42:32.298937812 +0200
@@ -0,0 +1,27 @@
+#ifndef __PDF_TYPE1FONTFILE_PARSER_H
+#define __PDF_TYPE1FONTFILE_PARSER_H
+#include <string>
+#include <map>
+#include <sstream>
+#include <iostream>
+#include <ZLStringUtil.h>
+#include <ZLInputStream.h>
+#include "PdfScanner.h"
+#include "PdfToUnicodeMap.h"
+
+#define cNilCodepoint 0xFFFD
+
+class PdfType1FontFileParser : public PdfScanner {
+private:
+	PdfToUnicodeMap& fMap;
+protected:
+	void parse_();
+	void parseCharset();
+	std::string parseValue();
+public:
+	PdfType1FontFileParser(shared_ptr<ZLInputStream> stream, PdfToUnicodeMap& map); // , const PdfToUnicodeMapAddress& address);
+	bool parse();
+	PdfToUnicodeMap& map() const { return fMap; }
+};
+
+#endif /* ndef __PDF_TYPE1FONTFILE_PARSER_H */
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/StringStream.cpp fbreader-0.12.10/fbreader/src/formats/pdf/StringStream.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/StringStream.cpp	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/fbreader/src/formats/pdf/StringStream.cpp	1970-01-01 01:00:00.000000000 +0100
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2008-2010 Geometer Plus <contact@geometerplus.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <algorithm>
-
-#include "StringStream.h"
-
-StringStream::StringStream(const std::string &data) : myData(data), myOffset(0) {
-}
-
-bool StringStream::open() {
-	myOffset = 0;
-	return true;
-}
-
-size_t StringStream::read(char *buffer, size_t maxSize) {
-	size_t size = std::min(maxSize, myData.length() - myOffset);
-	memcpy(buffer, myData.data() + myOffset, size);
-	myOffset += size;
-	return size;
-}
-
-void StringStream::close() {
-}
-
-void StringStream::seek(int offset, bool absoluteOffset) {
-	if (!absoluteOffset) {
-		offset += myOffset;
-	}
-	myOffset = std::min((size_t)std::max(0, offset), myData.length());
-}
-
-size_t StringStream::offset() const {
-	return myOffset;
-}
-
-size_t StringStream::sizeOfOpened() {
-	return myData.length();
-}
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/StringStream.h fbreader-0.12.10/fbreader/src/formats/pdf/StringStream.h
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/StringStream.h	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/fbreader/src/formats/pdf/StringStream.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2008-2010 Geometer Plus <contact@geometerplus.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#ifndef __STRINGSTREAM_H__
-#define __STRINGSTREAM_H__
-
-#include <ZLInputStream.h>
-
-class StringStream : public ZLInputStream {
-
-public:
-	StringStream(const std::string &data);
-
-public:
-	bool open();
-	size_t read(char *buffer, size_t maxSize);
-	void close();
-
-	void seek(int offset, bool absoluteOffset);
-	size_t offset() const;
-	size_t sizeOfOpened();
-
-private:
-	const std::string &myData;
-	size_t myOffset;
-};
-
-#endif /* __STRINGSTREAM_H__ */
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/pdf/TODO fbreader-0.12.10/fbreader/src/formats/pdf/TODO
--- orig/fbreader-0.12.10/fbreader/src/formats/pdf/TODO	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/fbreader/src/formats/pdf/TODO	2011-05-29 00:02:48.920823530 +0200
@@ -0,0 +1,5 @@
+/epsilon1 U+03B5 ? or U+025B (!) or U+0190.
+PdfDefaultCharMap: entry not found: arrowdblext (extension for double arrows)
+use PdfMatrix, remove all the ad-hoc kludges.
+In a font, read /DescendantFonts (array) and use (one of) it if possible. For type0 fonts, descendantfont count is limited to 1. Especially read "/W".
+ignore unknown stuff between BX and EX.
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/PluginCollection.cpp fbreader-0.12.10/fbreader/src/formats/PluginCollection.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/PluginCollection.cpp	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/fbreader/src/formats/PluginCollection.cpp	2011-04-05 22:55:28.000000000 +0200
@@ -34,7 +34,7 @@
 #include "chm/CHMPlugin.h"
 #include "rtf/RtfPlugin.h"
 #include "openreader/OpenReaderPlugin.h"
-//#include "pdf/PdfPlugin.h"
+#include "pdf/PdfPlugin.h"
 
 PluginCollection *PluginCollection::ourInstance = 0;
 
@@ -55,7 +55,7 @@ PluginCollection &PluginCollection::Inst
 		ourInstance->myPlugins.push_back(new OEBPlugin());
 		ourInstance->myPlugins.push_back(new RtfPlugin());
 		ourInstance->myPlugins.push_back(new OpenReaderPlugin());
-		//ourInstance->myPlugins.push_back(new PdfPlugin());
+		ourInstance->myPlugins.push_back(new PdfPlugin());
 	}
 	return *ourInstance;
 }
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/xhtml/XHTMLReader.cpp fbreader-0.12.10/fbreader/src/formats/xhtml/XHTMLReader.cpp
--- orig/fbreader-0.12.10/fbreader/src/formats/xhtml/XHTMLReader.cpp	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/fbreader/src/formats/xhtml/XHTMLReader.cpp	2011-04-05 22:55:28.000000000 +0200
@@ -486,6 +486,20 @@ void XHTMLReader::fillTagTable() {
 XHTMLReader::XHTMLReader(BookReader &modelReader) : myModelReader(modelReader) {
 }
 
+static shared_ptr<ZLTextStyleEntry> createBodyStyleEntry() {
+	shared_ptr<ZLTextStyleEntry> entry = new ZLTextStyleEntry();
+	//setLength
+	// TODO don't hard-code these, just move that to some central place where it does the right thing (settings etc).
+	//entry->setFontModifier(FONT_MODIFIER_DEFAULT);
+	entry->setFontModifier(FONT_MODIFIER_BOLD, false);
+	entry->setFontModifier(FONT_MODIFIER_ITALIC, false);
+	entry->setFontModifier(FONT_MODIFIER_SMALLCAPS, false);
+	entry->setFontSizeMag(1);
+	//void setFontFamily(const std::string &fontFamily);
+	entry->setAlignmentType(ALIGN_LEFT);
+	return entry;
+}
+
 bool XHTMLReader::readFile(const std::string &filePath, const std::string &referenceName) {
 	myModelReader.addHyperlinkLabel(referenceName);
 
@@ -502,6 +516,7 @@ bool XHTMLReader::readFile(const std::st
 
 	myCSSStack.clear();
 	myStyleEntryStack.clear();
+	myStyleEntryStack.push_back(createBodyStyleEntry());
 	myStylesToRemove = 0;
 
 	return readDocument(filePath);
@@ -538,6 +553,7 @@ void XHTMLReader::startElementHandler(co
 	}
 
 	const int sizeBefore = myStyleEntryStack.size();
+	
 	addStyleEntry(sTag, "");
 	addStyleEntry("", sClass);
 	addStyleEntry(sTag, sClass);
@@ -566,6 +582,8 @@ void XHTMLReader::endElementHandler(cons
 	for (; myStylesToRemove > 0; --myStylesToRemove) {
 		myStyleEntryStack.pop_back();
 	}
+	
+	//replayStyleEntryStack();
 
 	if (myDoPageBreakAfterStack.back()) {
 		myModelReader.insertEndOfSectionParagraph();
@@ -573,6 +591,14 @@ void XHTMLReader::endElementHandler(cons
 	myDoPageBreakAfterStack.pop_back();
 }
 
+void XHTMLReader::replayStyleEntryStack() {
+	std::vector<shared_ptr<ZLTextStyleEntry> >::const_iterator iter_end = myStyleEntryStack.end();
+	for(std::vector<shared_ptr<ZLTextStyleEntry> >::const_iterator iter = myStyleEntryStack.begin(); iter != iter_end; ++iter) {
+		myModelReader.addControl(**iter);
+		break;
+	}
+}
+
 void XHTMLReader::beginParagraph() {
 	myCurrentParagraphIsEmpty = true;
 	myModelReader.beginParagraph();
@@ -597,7 +623,7 @@ void XHTMLReader::beginParagraph() {
 
 void XHTMLReader::endParagraph() {
 	bool doBlockSpaceAfter = false;
-	for (std::vector<shared_ptr<ZLTextStyleEntry> >::const_iterator it = myStyleEntryStack.begin(); it != myStyleEntryStack.end() - myStylesToRemove; ++it) {
+	for (std::vector<shared_ptr<ZLTextStyleEntry> >::const_iterator it = myStyleEntryStack.begin(); it != myStyleEntryStack.end()/* - myStylesToRemove*/; ++it) {
 		doBlockSpaceAfter =
 			doBlockSpaceAfter ||
 			(*it)->lengthSupported(ZLTextStyleEntry::LENGTH_SPACE_AFTER);
@@ -609,13 +635,13 @@ void XHTMLReader::endParagraph() {
 			0,
 			ZLTextStyleEntry::SIZE_UNIT_PIXEL
 		);
-		myModelReader.addControl(blockingEntry);
+		// FIXME myModelReader.addControl(blockingEntry);
+		myModelReader.addControl(REGULAR, false);
 	}
 	for (; myStylesToRemove > 0; --myStylesToRemove) {
-		myModelReader.addControl(*myStyleEntryStack.back());
 		myStyleEntryStack.pop_back();
 	}
-	myModelReader.endParagraph();
+	//replayStyleEntryStack();
 }
 
 void XHTMLReader::characterDataHandler(const char *text, size_t len) {
diff -uprN orig/fbreader-0.12.10/fbreader/src/formats/xhtml/XHTMLReader.h fbreader-0.12.10/fbreader/src/formats/xhtml/XHTMLReader.h
--- orig/fbreader-0.12.10/fbreader/src/formats/xhtml/XHTMLReader.h	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/fbreader/src/formats/xhtml/XHTMLReader.h	2011-04-05 22:55:28.000000000 +0200
@@ -72,6 +72,7 @@ private:
 	void beginParagraph();
 	void endParagraph();
 	void addStyleEntry(const std::string tag, const std::string aClass);
+	void replayStyleEntryStack();
 
 private:
 	BookReader &myModelReader;
diff -uprN orig/fbreader-0.12.10/fbreader/src/library/Library.cpp fbreader-0.12.10/fbreader/src/library/Library.cpp
--- orig/fbreader-0.12.10/fbreader/src/library/Library.cpp	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/fbreader/src/library/Library.cpp	2011-05-28 13:57:39.710836186 +0200
@@ -39,7 +39,7 @@
 shared_ptr<Library> Library::ourInstance;
 const size_t Library::MaxRecentListSize = 10;
 
-Library::Library &Library::Instance() {
+Library &Library::Instance() {
 	if (ourInstance.isNull()) {
 		ourInstance = new Library();
 	}
diff -uprN orig/fbreader-0.12.10/fbreader/VERSION fbreader-0.12.10/fbreader/VERSION
--- orig/fbreader-0.12.10/fbreader/VERSION	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/fbreader/VERSION	2011-04-05 22:55:28.000000000 +0200
@@ -1 +1 @@
-0.12.10
+0.13.10
diff -uprN orig/fbreader-0.12.10/L fbreader-0.12.10/L
--- orig/fbreader-0.12.10/L	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/L	2012-08-12 23:51:03.751589324 +0200
@@ -0,0 +1,1823 @@
+==7329== Memcheck, a memory error detector
+==7329== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
+==7329== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
+==7329== Command: /home/dannym/source/FBReader/fbreader-0.12.10/fbreader/FBReader /home/dannym/sicp.pdf
+==7329== 
+loading /usr/lib/zlibrary/ui/zlui-gtk.so
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0x6BA14E0: inflateReset2 (in /lib/x86_64-linux-gnu/libz.so.1.2.3.4)
+==7329==    by 0x6BA15D8: inflateInit2_ (in /lib/x86_64-linux-gnu/libz.so.1.2.3.4)
+==7329==    by 0x520E562: ZLZDecompressor::ZLZDecompressor(unsigned long, bool) (ZLZDecompressor.cpp:36)
+==7329==    by 0x520E03C: ZLGzipInputStream::open() (ZLGzipInputStream.cpp:82)
+==7329==    by 0x5242047: ZLXMLReader::readDocument(shared_ptr<ZLInputStream>) (ZLXMLReader.cpp:99)
+==7329==    by 0x5241FE7: ZLXMLReader::readDocument(std::string const&) (ZLXMLReader.cpp:95)
+==7329==    by 0x520231A: initUnicodeTable() (ZLUnicodeUtil.cpp:84)
+==7329==    by 0x52034AD: ZLUnicodeUtil::toLower(unsigned int) (ZLUnicodeUtil.cpp:440)
+==7329==    by 0x520356A: ZLUnicodeUtil::toLower(std::vector<unsigned int, std::allocator<unsigned int> >&) (ZLUnicodeUtil.cpp:447)
+==7329==    by 0x52035E7: ZLUnicodeUtil::toLower(std::string const&) (ZLUnicodeUtil.cpp:455)
+==7329==    by 0x520934B: ZLFile::ZLFile(std::string const&) (ZLFile.cpp:53)
+==7329==    by 0x5234617: MyEncodingConverterProvider::MyEncodingConverterProvider() (MyEncodingConverter.cpp:117)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0x5209AAB: ZLFile::inputStream() const (ZLFile.cpp:102)
+==7329==    by 0x5241FD4: ZLXMLReader::readDocument(std::string const&) (ZLXMLReader.cpp:95)
+==7329==    by 0x526C9AD: XMLConfig::load() (XMLConfigIO.cpp:58)
+==7329==    by 0x5267B09: XMLConfig::XMLConfig() (XMLConfig.cpp:96)
+==7329==    by 0x5267671: XMLConfigManager::createConfig() const (XMLConfig.cpp:33)
+==7329==    by 0x5238CB9: ZLOption::createInstance() (ZLOptions.cpp:61)
+==7329==    by 0x5225ED0: ZLApplicationBase::ZLApplicationBase(std::string const&) (ZLApplicationBase.cpp:36)
+==7329==    by 0x5220741: ZLApplication::ZLApplication(std::string const&) (ZLApplication.cpp:64)
+==7329==    by 0x6F45F8: FBReader::FBReader(std::string const&) (FBReader.cpp:98)
+==7329==    by 0x6EF87D: main (main.cpp:28)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0x5209AAB: ZLFile::inputStream() const (ZLFile.cpp:102)
+==7329==    by 0x5241FD4: ZLXMLReader::readDocument(std::string const&) (ZLXMLReader.cpp:95)
+==7329==    by 0x523A600: ZLCommunicationManager::init() (ZLMessage.cpp:95)
+==7329==    by 0x523A11B: ZLCommunicationManager::Instance() (ZLMessage.cpp:39)
+==7329==    by 0x5220A77: ZLApplication::ZLApplication(std::string const&) (ZLApplication.cpp:72)
+==7329==    by 0x6F45F8: FBReader::FBReader(std::string const&) (FBReader.cpp:98)
+==7329==    by 0x6EF87D: main (main.cpp:28)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0x5209AAB: ZLFile::inputStream() const (ZLFile.cpp:102)
+==7329==    by 0x5241FD4: ZLXMLReader::readDocument(std::string const&) (ZLXMLReader.cpp:95)
+==7329==    by 0x523A66E: ZLCommunicationManager::init() (ZLMessage.cpp:96)
+==7329==    by 0x523A11B: ZLCommunicationManager::Instance() (ZLMessage.cpp:39)
+==7329==    by 0x5220A77: ZLApplication::ZLApplication(std::string const&) (ZLApplication.cpp:72)
+==7329==    by 0x6F45F8: FBReader::FBReader(std::string const&) (FBReader.cpp:98)
+==7329==    by 0x6EF87D: main (main.cpp:28)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0x5209AAB: ZLFile::inputStream() const (ZLFile.cpp:102)
+==7329==    by 0x5241FD4: ZLXMLReader::readDocument(std::string const&) (ZLXMLReader.cpp:95)
+==7329==    by 0x523C389: ZLTreeResource::loadData(std::string const&) (ZLResource.cpp:123)
+==7329==    by 0x523C57B: ZLTreeResource::buildTree() (ZLResource.cpp:137)
+==7329==    by 0x523C174: ZLResource::resource(std::string const&) (ZLResource.cpp:100)
+==7329==    by 0x522C772: ZLToolbar::ZLToolbar() (ZLToolbar.cpp:239)
+==7329==    by 0x522B2F6: ZLApplication::toolbar(int) const (ZLToolbar.cpp:53)
+==7329==    by 0x522B207: ZLApplication::createToolbar(int) (ZLToolbar.cpp:43)
+==7329==    by 0x5220ABF: ZLApplication::ZLApplication(std::string const&) (ZLApplication.cpp:74)
+==7329==    by 0x6F45F8: FBReader::FBReader(std::string const&) (FBReader.cpp:98)
+==7329==    by 0x6EF87D: main (main.cpp:28)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0x5209AAB: ZLFile::inputStream() const (ZLFile.cpp:102)
+==7329==    by 0x5241FD4: ZLXMLReader::readDocument(std::string const&) (ZLXMLReader.cpp:95)
+==7329==    by 0x523C40D: ZLTreeResource::loadData(std::string const&) (ZLResource.cpp:124)
+==7329==    by 0x523C57B: ZLTreeResource::buildTree() (ZLResource.cpp:137)
+==7329==    by 0x523C174: ZLResource::resource(std::string const&) (ZLResource.cpp:100)
+==7329==    by 0x522C772: ZLToolbar::ZLToolbar() (ZLToolbar.cpp:239)
+==7329==    by 0x522B2F6: ZLApplication::toolbar(int) const (ZLToolbar.cpp:53)
+==7329==    by 0x522B207: ZLApplication::createToolbar(int) (ZLToolbar.cpp:43)
+==7329==    by 0x5220ABF: ZLApplication::ZLApplication(std::string const&) (ZLApplication.cpp:74)
+==7329==    by 0x6F45F8: FBReader::FBReader(std::string const&) (FBReader.cpp:98)
+==7329==    by 0x6EF87D: main (main.cpp:28)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0x5209AAB: ZLFile::inputStream() const (ZLFile.cpp:102)
+==7329==    by 0x5241FD4: ZLXMLReader::readDocument(std::string const&) (ZLXMLReader.cpp:95)
+==7329==    by 0x5229354: ZLApplication::createMenubar() (ZLMenu.cpp:41)
+==7329==    by 0x5220ADC: ZLApplication::ZLApplication(std::string const&) (ZLApplication.cpp:76)
+==7329==    by 0x6F45F8: FBReader::FBReader(std::string const&) (FBReader.cpp:98)
+==7329==    by 0x6EF87D: main (main.cpp:28)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0x6BA14E0: inflateReset2 (in /lib/x86_64-linux-gnu/libz.so.1.2.3.4)
+==7329==    by 0x6BA15D8: inflateInit2_ (in /lib/x86_64-linux-gnu/libz.so.1.2.3.4)
+==7329==    by 0x107DC0D3: png_create_read_struct_2 (in /lib/x86_64-linux-gnu/libpng12.so.0.46.0)
+==7329==    by 0x14B65165: ??? (in /usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-png.so)
+==7329==    by 0xC76DA5D: ??? (in /usr/lib/x86_64-linux-gnu/libgdk_pixbuf-2.0.so.0.2600.1)
+==7329==    by 0xC76DD4B: gdk_pixbuf_new_from_file (in /usr/lib/x86_64-linux-gnu/libgdk_pixbuf-2.0.so.0.2600.1)
+==7329==    by 0xBC6D03E: ZLGtkApplicationWindow::ZLGtkApplicationWindow(ZLApplication*) (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0xBC6D370: ZLGtkDialogManager::createApplicationWindow(ZLApplication*) const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0xBC66068: ZLGtkLibraryImplementation::run(ZLApplication*) (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x5271043: ZLibrary::run(ZLApplication*) (ZLibrary.cpp:151)
+==7329==    by 0x6EF885: main (main.cpp:28)
+==7329== 
+==7329== Invalid read of size 4
+==7329==    at 0xE5750D3: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE577464: FcConfigFilename (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58AA15: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE580176: FcInitLoadConfig (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE580265: FcInitLoadConfigAndFonts (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE580484: FcInit (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE57587C: FcConfigGetCurrent (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE57722F: FcConfigSubstituteWithPat (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xD3D6ECF: ??? (in /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0.3000.0)
+==7329==    by 0xE34CE9B: ??? (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0xC99C86C: ??? (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xC99D3B7: pango_itemize_with_base_dir (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==  Address 0x149ba5f4 is 20 bytes inside a block of size 22 alloc'd
+==7329==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0xE57502C: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE577464: FcConfigFilename (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58AA15: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE580176: FcInitLoadConfig (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE580265: FcInitLoadConfigAndFonts (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE580484: FcInit (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE57587C: FcConfigGetCurrent (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE57722F: FcConfigSubstituteWithPat (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xD3D6ECF: ??? (in /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0.3000.0)
+==7329==    by 0xE34CE9B: ??? (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0xC99C86C: ??? (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329== 
+==7329== Invalid read of size 4
+==7329==    at 0xE5750E8: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE577464: FcConfigFilename (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58AA15: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58B0FD: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0x69786F3: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x6979950: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x69767C6: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x697817A: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x697B75C: XML_ParseBuffer (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0xE58AB70: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE580176: FcInitLoadConfig (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE580265: FcInitLoadConfigAndFonts (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==  Address 0x149c1ae0 is 16 bytes inside a block of size 18 alloc'd
+==7329==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0xE57502C: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE577464: FcConfigFilename (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58AA15: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58B0FD: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0x69786F3: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x6979950: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x69767C6: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x697817A: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x697B75C: XML_ParseBuffer (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0xE58AB70: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE580176: FcInitLoadConfig (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329== 
+==7329== Invalid read of size 4
+==7329==    at 0xE5750E8: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58AA15: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58AE77: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58B0FD: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0x69786F3: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x6979950: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x69767C6: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x697817A: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x697B75C: XML_ParseBuffer (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0xE58AB70: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE580176: FcInitLoadConfig (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE580265: FcInitLoadConfigAndFonts (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==  Address 0x149d78b8 is 40 bytes inside a block of size 42 alloc'd
+==7329==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0xE57502C: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58AA15: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58AE77: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58B0FD: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0x69786F3: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x6979950: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x69767C6: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x697817A: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x697B75C: XML_ParseBuffer (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0xE58AB70: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE580176: FcInitLoadConfig (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329== 
+==7329== Invalid read of size 4
+==7329==    at 0xE5750D3: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58AA15: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58AE77: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58B0FD: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0x69786F3: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x6979950: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x69767C6: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x697817A: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x697B75C: XML_ParseBuffer (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0xE58AB70: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE580176: FcInitLoadConfig (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE580265: FcInitLoadConfigAndFonts (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==  Address 0x14a0b0c4 is 36 bytes inside a block of size 39 alloc'd
+==7329==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0xE57502C: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58AA15: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58AE77: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58B0FD: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0x69786F3: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x6979950: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x69767C6: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x697817A: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x697B75C: XML_ParseBuffer (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0xE58AB70: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE580176: FcInitLoadConfig (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329== 
+==7329== Invalid read of size 4
+==7329==    at 0xE5750E8: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58AA15: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58B0FD: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0x69786F3: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x6979950: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x69767C6: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x697817A: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x697B75C: XML_ParseBuffer (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0xE58AB70: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58AE77: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58B0FD: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0x69786F3: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==  Address 0x14a398f8 is 24 bytes inside a block of size 26 alloc'd
+==7329==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0xE57502C: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58AA15: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58B0FD: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0x69786F3: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x6979950: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x69767C6: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x697817A: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x697B75C: XML_ParseBuffer (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0xE58AB70: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58AE77: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58B0FD: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329== 
+==7329== Invalid read of size 4
+==7329==    at 0xE5750D3: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE577464: FcConfigFilename (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58AA15: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58B0FD: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0x69786F3: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x6979950: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x69767C6: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x697817A: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x697B75C: XML_ParseBuffer (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0xE58AB70: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58AE77: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58B0FD: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==  Address 0x14a49d54 is 20 bytes inside a block of size 22 alloc'd
+==7329==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0xE57502C: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE577464: FcConfigFilename (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58AA15: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58B0FD: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0x69786F3: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x6979950: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x69767C6: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x697817A: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0x697B75C: XML_ParseBuffer (in /lib/x86_64-linux-gnu/libexpat.so.1.5.2)
+==7329==    by 0xE58AB70: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329==    by 0xE58AE77: FcConfigParseAndLoad (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0x4CCC6D: PdfParser::readLine() (PdfParser.cpp:98)
+==7329==    by 0x4CF4E1: PdfParser::parse() (PdfParser.cpp:590)
+==7329==    by 0x4BA69E: PdfBookReader::readBook(shared_ptr<ZLInputStream>) (PdfBookReader.cpp:99)
+==7329==    by 0x4D9F5E: PdfPlugin::readModel(BookModel&) const (PdfPlugin.cpp:49)
+==7329==    by 0x6C0155: BookModel::BookModel(shared_ptr<Book>) (BookModel.cpp:35)
+==7329==    by 0x6F6FF7: FBReader::openBookInternal(shared_ptr<Book>) (FBReader.cpp:288)
+==7329==    by 0x6F8A48: OpenBookRunnable::run() (FBReader.cpp:265)
+==7329==    by 0xBC600B7: ZLGtkProgressDialog::run(ZLRunnable&) (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x5216BFD: ZLDialogManager::wait(ZLResourceKey const&, ZLRunnable&) const (ZLDialogManager.cpp:98)
+==7329==    by 0x6F6DFF: FBReader::openBook(shared_ptr<Book>) (FBReader.cpp:273)
+==7329==    by 0x6F6745: FBReader::initWindow() (FBReader.cpp:196)
+==7329==    by 0xBC66071: ZLGtkLibraryImplementation::run(ZLApplication*) (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0x4CCC79: PdfParser::readLine() (PdfParser.cpp:98)
+==7329==    by 0x4CF4E1: PdfParser::parse() (PdfParser.cpp:590)
+==7329==    by 0x4BA69E: PdfBookReader::readBook(shared_ptr<ZLInputStream>) (PdfBookReader.cpp:99)
+==7329==    by 0x4D9F5E: PdfPlugin::readModel(BookModel&) const (PdfPlugin.cpp:49)
+==7329==    by 0x6C0155: BookModel::BookModel(shared_ptr<Book>) (BookModel.cpp:35)
+==7329==    by 0x6F6FF7: FBReader::openBookInternal(shared_ptr<Book>) (FBReader.cpp:288)
+==7329==    by 0x6F8A48: OpenBookRunnable::run() (FBReader.cpp:265)
+==7329==    by 0xBC600B7: ZLGtkProgressDialog::run(ZLRunnable&) (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x5216BFD: ZLDialogManager::wait(ZLResourceKey const&, ZLRunnable&) const (ZLDialogManager.cpp:98)
+==7329==    by 0x6F6DFF: FBReader::openBook(shared_ptr<Book>) (FBReader.cpp:273)
+==7329==    by 0x6F6745: FBReader::initWindow() (FBReader.cpp:196)
+==7329==    by 0xBC66071: ZLGtkLibraryImplementation::run(ZLApplication*) (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0x4C2CCF5: memchr (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x58030CB: std::string::find(char, unsigned long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x4CCBFB: stripBuffer(std::string&) (PdfParser.cpp:85)
+==7329==    by 0x4CF51C: PdfParser::parse() (PdfParser.cpp:594)
+==7329==    by 0x4BA69E: PdfBookReader::readBook(shared_ptr<ZLInputStream>) (PdfBookReader.cpp:99)
+==7329==    by 0x4D9F5E: PdfPlugin::readModel(BookModel&) const (PdfPlugin.cpp:49)
+==7329==    by 0x6C0155: BookModel::BookModel(shared_ptr<Book>) (BookModel.cpp:35)
+==7329==    by 0x6F6FF7: FBReader::openBookInternal(shared_ptr<Book>) (FBReader.cpp:288)
+==7329==    by 0x6F8A48: OpenBookRunnable::run() (FBReader.cpp:265)
+==7329==    by 0xBC600B7: ZLGtkProgressDialog::run(ZLRunnable&) (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x5216BFD: ZLDialogManager::wait(ZLResourceKey const&, ZLRunnable&) const (ZLDialogManager.cpp:98)
+==7329==    by 0x6F6DFF: FBReader::openBook(shared_ptr<Book>) (FBReader.cpp:273)
+==7329== 
+==7329== Use of uninitialised value of size 8
+==7329==    at 0x5FA433E: isspace (ctype.c:35)
+==7329==    by 0x5201B40: ZLStringUtil::stripWhiteSpaces(std::string&) (ZLStringUtil.cpp:80)
+==7329==    by 0x4CCC2C: stripBuffer(std::string&) (PdfParser.cpp:89)
+==7329==    by 0x4CF51C: PdfParser::parse() (PdfParser.cpp:594)
+==7329==    by 0x4BA69E: PdfBookReader::readBook(shared_ptr<ZLInputStream>) (PdfBookReader.cpp:99)
+==7329==    by 0x4D9F5E: PdfPlugin::readModel(BookModel&) const (PdfPlugin.cpp:49)
+==7329==    by 0x6C0155: BookModel::BookModel(shared_ptr<Book>) (BookModel.cpp:35)
+==7329==    by 0x6F6FF7: FBReader::openBookInternal(shared_ptr<Book>) (FBReader.cpp:288)
+==7329==    by 0x6F8A48: OpenBookRunnable::run() (FBReader.cpp:265)
+==7329==    by 0xBC600B7: ZLGtkProgressDialog::run(ZLRunnable&) (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x5216BFD: ZLDialogManager::wait(ZLResourceKey const&, ZLRunnable&) const (ZLDialogManager.cpp:98)
+==7329==    by 0x6F6DFF: FBReader::openBook(shared_ptr<Book>) (FBReader.cpp:273)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0x4C2DCB3: bcmp (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x5803842: std::string::compare(char const*) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x44F375: bool std::operator==<char, std::char_traits<char>, std::allocator<char> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*) (basic_string.h:2462)
+==7329==    by 0x4CF562: PdfParser::parse() (PdfParser.cpp:600)
+==7329==    by 0x4BA69E: PdfBookReader::readBook(shared_ptr<ZLInputStream>) (PdfBookReader.cpp:99)
+==7329==    by 0x4D9F5E: PdfPlugin::readModel(BookModel&) const (PdfPlugin.cpp:49)
+==7329==    by 0x6C0155: BookModel::BookModel(shared_ptr<Book>) (BookModel.cpp:35)
+==7329==    by 0x6F6FF7: FBReader::openBookInternal(shared_ptr<Book>) (FBReader.cpp:288)
+==7329==    by 0x6F8A48: OpenBookRunnable::run() (FBReader.cpp:265)
+==7329==    by 0xBC600B7: ZLGtkProgressDialog::run(ZLRunnable&) (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x5216BFD: ZLDialogManager::wait(ZLResourceKey const&, ZLRunnable&) const (ZLDialogManager.cpp:98)
+==7329==    by 0x6F6DFF: FBReader::openBook(shared_ptr<Book>) (FBReader.cpp:273)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0x5803845: std::string::compare(char const*) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x44F375: bool std::operator==<char, std::char_traits<char>, std::allocator<char> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*) (basic_string.h:2462)
+==7329==    by 0x4CF562: PdfParser::parse() (PdfParser.cpp:600)
+==7329==    by 0x4BA69E: PdfBookReader::readBook(shared_ptr<ZLInputStream>) (PdfBookReader.cpp:99)
+==7329==    by 0x4D9F5E: PdfPlugin::readModel(BookModel&) const (PdfPlugin.cpp:49)
+==7329==    by 0x6C0155: BookModel::BookModel(shared_ptr<Book>) (BookModel.cpp:35)
+==7329==    by 0x6F6FF7: FBReader::openBookInternal(shared_ptr<Book>) (FBReader.cpp:288)
+==7329==    by 0x6F8A48: OpenBookRunnable::run() (FBReader.cpp:265)
+==7329==    by 0xBC600B7: ZLGtkProgressDialog::run(ZLRunnable&) (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x5216BFD: ZLDialogManager::wait(ZLResourceKey const&, ZLRunnable&) const (ZLDialogManager.cpp:98)
+==7329==    by 0x6F6DFF: FBReader::openBook(shared_ptr<Book>) (FBReader.cpp:273)
+==7329==    by 0x6F6745: FBReader::initWindow() (FBReader.cpp:196)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0x4CF565: PdfParser::parse() (PdfParser.cpp:600)
+==7329==    by 0x4BA69E: PdfBookReader::readBook(shared_ptr<ZLInputStream>) (PdfBookReader.cpp:99)
+==7329==    by 0x4D9F5E: PdfPlugin::readModel(BookModel&) const (PdfPlugin.cpp:49)
+==7329==    by 0x6C0155: BookModel::BookModel(shared_ptr<Book>) (BookModel.cpp:35)
+==7329==    by 0x6F6FF7: FBReader::openBookInternal(shared_ptr<Book>) (FBReader.cpp:288)
+==7329==    by 0x6F8A48: OpenBookRunnable::run() (FBReader.cpp:265)
+==7329==    by 0xBC600B7: ZLGtkProgressDialog::run(ZLRunnable&) (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x5216BFD: ZLDialogManager::wait(ZLResourceKey const&, ZLRunnable&) const (ZLDialogManager.cpp:98)
+==7329==    by 0x6F6DFF: FBReader::openBook(shared_ptr<Book>) (FBReader.cpp:273)
+==7329==    by 0x6F6745: FBReader::initWindow() (FBReader.cpp:196)
+==7329==    by 0xBC66071: ZLGtkLibraryImplementation::run(ZLApplication*) (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x5271043: ZLibrary::run(ZLApplication*) (ZLibrary.cpp:151)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0x6BA14E0: inflateReset2 (in /lib/x86_64-linux-gnu/libz.so.1.2.3.4)
+==7329==    by 0x6BA15D8: inflateInit2_ (in /lib/x86_64-linux-gnu/libz.so.1.2.3.4)
+==7329==    by 0x520E540: ZLZDecompressor::ZLZDecompressor(unsigned long, bool) (ZLZDecompressor.cpp:34)
+==7329==    by 0x66BD0F: PdfStreamObject::processDecompressor(shared_ptr<PdfObject>, ZLInputStream&) (PdfObject.cpp:219)
+==7329==    by 0x66BF00: PdfStreamObject::processDecompressorChain(shared_ptr<PdfObject>&, ZLInputStream&) (PdfObject.cpp:240)
+==7329==    by 0x66C1E5: PdfStreamObject::PdfStreamObject(shared_ptr<PdfObject>, ZLInputStream&, char&, unsigned long) (PdfObject.cpp:265)
+==7329==    by 0x4CE65F: PdfParser::readObject(shared_ptr<ZLInputStream>) (PdfParser.cpp:411)
+==7329==    by 0x4CC9DF: PdfParser::readObjectFromLocation(std::pair<int, int> const&) (PdfParser.cpp:62)
+==7329==    by 0x4CCB2E: PdfParser::resolveReference(shared_ptr<PdfObject>) (PdfParser.cpp:78)
+==7329==    by 0x4BFAE2: PdfBookReader::resolveReferences(shared_ptr<PdfObject>, ZLInputStream&) (PdfBookReader.cpp:927)
+==7329==    by 0x4C001D: PdfBookReader::resolveReferences(shared_ptr<PdfObject>, ZLInputStream&) (PdfBookReader.cpp:955)
+==7329==    by 0x4BFD50: PdfBookReader::resolveReferences(shared_ptr<PdfObject>, ZLInputStream&) (PdfBookReader.cpp:939)
+==7329== 
+dict
+PdfDictionaryObject::dump() => [
+Length
+Filter
+Length1
+Length2
+Length3
+]
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0x4BCB75: PdfBookReader::setPosition(double, double) (PdfBookReader.cpp:511)
+==7329==    by 0x4BC8FB: PdfBookReader::setPositionRelativeToBeginning(double, double) (PdfBookReader.cpp:478)
+==7329==    by 0x4BC2D9: PdfBookReader::processInstruction(PdfInstruction const&) (PdfBookReader.cpp:377)
+==7329==    by 0x4BEC3C: PdfBookReader::processInstructions(std::vector<shared_ptr<PdfInstruction>, std::allocator<shared_ptr<PdfInstruction> > > const&) (PdfBookReader.cpp:778)
+==7329==    by 0x4BE37D: PdfBookReader::processContents(shared_ptr<PdfObject>, ZLInputStream&) (PdfBookReader.cpp:706)
+==7329==    by 0x4BF5A8: PdfBookReader::processPage(shared_ptr<PdfObject>, ZLInputStream&) (PdfBookReader.cpp:844)
+==7329==    by 0x4BAEA2: PdfBookReader::processPages(shared_ptr<PdfObject>, ZLInputStream&) (PdfBookReader.cpp:152)
+==7329==    by 0x4BAE57: PdfBookReader::processPages(shared_ptr<PdfObject>, ZLInputStream&) (PdfBookReader.cpp:151)
+==7329==    by 0x4BAE57: PdfBookReader::processPages(shared_ptr<PdfObject>, ZLInputStream&) (PdfBookReader.cpp:151)
+==7329==    by 0x4BAE57: PdfBookReader::processPages(shared_ptr<PdfObject>, ZLInputStream&) (PdfBookReader.cpp:151)
+==7329==    by 0x4BAA02: PdfBookReader::readBook(shared_ptr<ZLInputStream>) (PdfBookReader.cpp:121)
+==7329==    by 0x4D9F5E: PdfPlugin::readModel(BookModel&) const (PdfPlugin.cpp:49)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0x4BCB88: PdfBookReader::setPosition(double, double) (PdfBookReader.cpp:512)
+==7329==    by 0x4BC8FB: PdfBookReader::setPositionRelativeToBeginning(double, double) (PdfBookReader.cpp:478)
+==7329==    by 0x4BC2D9: PdfBookReader::processInstruction(PdfInstruction const&) (PdfBookReader.cpp:377)
+==7329==    by 0x4BEC3C: PdfBookReader::processInstructions(std::vector<shared_ptr<PdfInstruction>, std::allocator<shared_ptr<PdfInstruction> > > const&) (PdfBookReader.cpp:778)
+==7329==    by 0x4BE37D: PdfBookReader::processContents(shared_ptr<PdfObject>, ZLInputStream&) (PdfBookReader.cpp:706)
+==7329==    by 0x4BF5A8: PdfBookReader::processPage(shared_ptr<PdfObject>, ZLInputStream&) (PdfBookReader.cpp:844)
+==7329==    by 0x4BAEA2: PdfBookReader::processPages(shared_ptr<PdfObject>, ZLInputStream&) (PdfBookReader.cpp:152)
+==7329==    by 0x4BAE57: PdfBookReader::processPages(shared_ptr<PdfObject>, ZLInputStream&) (PdfBookReader.cpp:151)
+==7329==    by 0x4BAE57: PdfBookReader::processPages(shared_ptr<PdfObject>, ZLInputStream&) (PdfBookReader.cpp:151)
+==7329==    by 0x4BAE57: PdfBookReader::processPages(shared_ptr<PdfObject>, ZLInputStream&) (PdfBookReader.cpp:151)
+==7329==    by 0x4BAA02: PdfBookReader::readBook(shared_ptr<ZLInputStream>) (PdfBookReader.cpp:121)
+==7329==    by 0x4D9F5E: PdfPlugin::readModel(BookModel&) const (PdfPlugin.cpp:49)
+==7329== 
+dict
+PdfDictionaryObject::dump() => [
+Length
+Filter
+Length1
+Length2
+Length3
+]
+dict
+PdfDictionaryObject::dump() => [
+Length
+Filter
+Length1
+Length2
+Length3
+]
+PdfDefaultCharMap: entry not found: mapstochar
+error: (Type1 font file parser) could not find character '/mapstochar' (for native code 55).
+PdfDefaultCharMap: entry not found: radicallow
+error: (Type1 font file parser) could not find character '/radicallow' (for native code 112).
+dict
+PdfDictionaryObject::dump() => [
+Length
+Filter
+Length1
+Length2
+Length3
+]
+dict
+PdfDictionaryObject::dump() => [
+Length
+Filter
+Length1
+Length2
+Length3
+]
+dict
+PdfDictionaryObject::dump() => [
+Length
+Filter
+Length1
+Length2
+Length3
+]
+dict
+PdfDictionaryObject::dump() => [
+Length
+Filter
+Length1
+Length2
+Length3
+]
+dict
+PdfDictionaryObject::dump() => [
+Length
+Filter
+Length1
+Length2
+Length3
+]
+dict
+PdfDictionaryObject::dump() => [
+Length
+Filter
+Length1
+Length2
+Length3
+]
+dict
+PdfDictionaryObject::dump() => [
+Length
+Filter
+Length1
+Length2
+Length3
+]
+dict
+PdfDictionaryObject::dump() => [
+Length
+Filter
+Length1
+Length2
+Length3
+]
+dict
+PdfDictionaryObject::dump() => [
+Length
+Filter
+Length1
+Length2
+Length3
+]
+dict
+PdfDictionaryObject::dump() => [
+Length
+Filter
+Length1
+Length2
+Length3
+]
+PdfDefaultCharMap: entry not found: braceleftbig7
+error: (Type1 font file parser) could not find character '/braceleftbig7' (for native code 40).
+PdfDefaultCharMap: entry not found: bracketleftbig4
+error: (Type1 font file parser) could not find character '/bracketleftbig4' (for native code 149).
+PdfDefaultCharMap: entry not found: bracketrightbig4
+error: (Type1 font file parser) could not find character '/bracketrightbig4' (for native code 152).
+PdfDefaultCharMap: entry not found: parenleftbig3
+error: (Type1 font file parser) could not find character '/parenleftbig3' (for native code 16).
+PdfDefaultCharMap: entry not found: parenleftbig4
+error: (Type1 font file parser) could not find character '/parenleftbig4' (for native code 129).
+PdfDefaultCharMap: entry not found: parenleftbig7
+error: (Type1 font file parser) could not find character '/parenleftbig7' (for native code 32).
+PdfDefaultCharMap: entry not found: parenrightbig3
+error: (Type1 font file parser) could not find character '/parenrightbig3' (for native code 17).
+PdfDefaultCharMap: entry not found: parenrightbig4
+error: (Type1 font file parser) could not find character '/parenrightbig4' (for native code 139).
+PdfDefaultCharMap: entry not found: parenrightbig7
+error: (Type1 font file parser) could not find character '/parenrightbig7' (for native code 33).
+PdfDefaultCharMap: entry not found: radicalbig1
+error: (Type1 font file parser) could not find character '/radicalbig1' (for native code 112).
+dict
+PdfDictionaryObject::dump() => [
+Length
+Filter
+Length1
+Length2
+Length3
+]
+end of book, status 1
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0x6BA14E0: inflateReset2 (in /lib/x86_64-linux-gnu/libz.so.1.2.3.4)
+==7329==    by 0x6BA15D8: inflateInit2_ (in /lib/x86_64-linux-gnu/libz.so.1.2.3.4)
+==7329==    by 0x520E562: ZLZDecompressor::ZLZDecompressor(unsigned long, bool) (ZLZDecompressor.cpp:36)
+==7329==    by 0x52112C3: ZLZipInputStream::open() (ZLZipInputStream.cpp:65)
+==7329==    by 0x5242047: ZLXMLReader::readDocument(shared_ptr<ZLInputStream>) (ZLXMLReader.cpp:99)
+==7329==    by 0x5241FE7: ZLXMLReader::readDocument(std::string const&) (ZLXMLReader.cpp:95)
+==7329==    by 0x4ED4B5B: ZLTextTeXHyphenator::load(std::string const&) (ZLTextTeXHyphenator.cpp:159)
+==7329==    by 0x6F7050: FBReader::openBookInternal(shared_ptr<Book>) (FBReader.cpp:289)
+==7329==    by 0x6F8A48: OpenBookRunnable::run() (FBReader.cpp:265)
+==7329==    by 0xBC600B7: ZLGtkProgressDialog::run(ZLRunnable&) (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x5216BFD: ZLDialogManager::wait(ZLResourceKey const&, ZLRunnable&) const (ZLDialogManager.cpp:98)
+==7329==    by 0x6F6DFF: FBReader::openBook(shared_ptr<Book>) (FBReader.cpp:273)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0x15F9E27C: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66E1A: ZLGtkPaintContext::stringWidth(char const*, int, bool) const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EAF275: ZLTextWord::width(ZLPaintContext const&) const (ZLTextWord.h:88)
+==7329==    by 0x4EAEA67: ZLTextArea::Style::wordWidth(ZLTextWord const&, int, int, bool) const (ZLTextAreaStyle.cpp:158)
+==7329==    by 0x4EAE441: ZLTextArea::Style::elementWidth(ZLTextElement const&, unsigned int, ZLTextStyleEntry::Metrics const&) const (ZLTextAreaStyle.cpp:94)
+==7329==    by 0x4EB6B71: ZLTextArea::processTextLine(ZLTextArea::Style&, ZLTextWordCursor const&, ZLTextWordCursor const&) (ZLTextArea_processTextLine.cpp:151)
+==7329==    by 0x4EAA858: ZLTextAreaController::buildInfos(ZLTextWordCursor const&) (ZLTextAreaController.cpp:95)
+==7329==    by 0x4EABC79: ZLTextAreaController::preparePaintInfo() (ZLTextAreaController.cpp:335)
+==7329==    by 0x4ECA35D: ZLTextView::preparePaintInfo() (ZLTextView.cpp:668)
+==7329==    by 0x6E6237: BookTextView::preparePaintInfo() (BookTextView.h:96)
+==7329==    by 0x4ECAFFD: ZLTextView::paint() (ZLTextView_paint.cpp:32)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0x15F9E280: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66E1A: ZLGtkPaintContext::stringWidth(char const*, int, bool) const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EAF275: ZLTextWord::width(ZLPaintContext const&) const (ZLTextWord.h:88)
+==7329==    by 0x4EAEA67: ZLTextArea::Style::wordWidth(ZLTextWord const&, int, int, bool) const (ZLTextAreaStyle.cpp:158)
+==7329==    by 0x4EAE441: ZLTextArea::Style::elementWidth(ZLTextElement const&, unsigned int, ZLTextStyleEntry::Metrics const&) const (ZLTextAreaStyle.cpp:94)
+==7329==    by 0x4EB6B71: ZLTextArea::processTextLine(ZLTextArea::Style&, ZLTextWordCursor const&, ZLTextWordCursor const&) (ZLTextArea_processTextLine.cpp:151)
+==7329==    by 0x4EAA858: ZLTextAreaController::buildInfos(ZLTextWordCursor const&) (ZLTextAreaController.cpp:95)
+==7329==    by 0x4EABC79: ZLTextAreaController::preparePaintInfo() (ZLTextAreaController.cpp:335)
+==7329==    by 0x4ECA35D: ZLTextView::preparePaintInfo() (ZLTextView.cpp:668)
+==7329==    by 0x6E6237: BookTextView::preparePaintInfo() (BookTextView.h:96)
+==7329==    by 0x4ECAFFD: ZLTextView::paint() (ZLTextView_paint.cpp:32)
+==7329== 
+==7329== Use of uninitialised value of size 8
+==7329==    at 0xCE53E50: g_hash_table_lookup (ghash.c:408)
+==7329==    by 0xE3527E4: pango_ot_ruleset_get_for_description (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0x15F9E2D5: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66E1A: ZLGtkPaintContext::stringWidth(char const*, int, bool) const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EAF275: ZLTextWord::width(ZLPaintContext const&) const (ZLTextWord.h:88)
+==7329==    by 0x4EAEA67: ZLTextArea::Style::wordWidth(ZLTextWord const&, int, int, bool) const (ZLTextAreaStyle.cpp:158)
+==7329==    by 0x4EAE441: ZLTextArea::Style::elementWidth(ZLTextElement const&, unsigned int, ZLTextStyleEntry::Metrics const&) const (ZLTextAreaStyle.cpp:94)
+==7329==    by 0x4EB6B71: ZLTextArea::processTextLine(ZLTextArea::Style&, ZLTextWordCursor const&, ZLTextWordCursor const&) (ZLTextArea_processTextLine.cpp:151)
+==7329==    by 0x4EAA858: ZLTextAreaController::buildInfos(ZLTextWordCursor const&) (ZLTextAreaController.cpp:95)
+==7329==    by 0x4EABC79: ZLTextAreaController::preparePaintInfo() (ZLTextAreaController.cpp:335)
+==7329==    by 0x4ECA35D: ZLTextView::preparePaintInfo() (ZLTextView.cpp:668)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0xCE53E9C: g_hash_table_lookup (ghash.c:416)
+==7329==    by 0xE3527E4: pango_ot_ruleset_get_for_description (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0x15F9E2D5: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66E1A: ZLGtkPaintContext::stringWidth(char const*, int, bool) const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EAF275: ZLTextWord::width(ZLPaintContext const&) const (ZLTextWord.h:88)
+==7329==    by 0x4EAEA67: ZLTextArea::Style::wordWidth(ZLTextWord const&, int, int, bool) const (ZLTextAreaStyle.cpp:158)
+==7329==    by 0x4EAE441: ZLTextArea::Style::elementWidth(ZLTextElement const&, unsigned int, ZLTextStyleEntry::Metrics const&) const (ZLTextAreaStyle.cpp:94)
+==7329==    by 0x4EB6B71: ZLTextArea::processTextLine(ZLTextArea::Style&, ZLTextWordCursor const&, ZLTextWordCursor const&) (ZLTextArea_processTextLine.cpp:151)
+==7329==    by 0x4EAA858: ZLTextAreaController::buildInfos(ZLTextWordCursor const&) (ZLTextAreaController.cpp:95)
+==7329==    by 0x4EABC79: ZLTextAreaController::preparePaintInfo() (ZLTextAreaController.cpp:335)
+==7329==    by 0x4ECA35D: ZLTextView::preparePaintInfo() (ZLTextView.cpp:668)
+==7329== 
+==7329== Use of uninitialised value of size 8
+==7329==    at 0xCE53E93: g_hash_table_lookup (ghash.c:439)
+==7329==    by 0xE3527E4: pango_ot_ruleset_get_for_description (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0x15F9E2D5: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66E1A: ZLGtkPaintContext::stringWidth(char const*, int, bool) const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EAF275: ZLTextWord::width(ZLPaintContext const&) const (ZLTextWord.h:88)
+==7329==    by 0x4EAEA67: ZLTextArea::Style::wordWidth(ZLTextWord const&, int, int, bool) const (ZLTextAreaStyle.cpp:158)
+==7329==    by 0x4EAE441: ZLTextArea::Style::elementWidth(ZLTextElement const&, unsigned int, ZLTextStyleEntry::Metrics const&) const (ZLTextAreaStyle.cpp:94)
+==7329==    by 0x4EB6B71: ZLTextArea::processTextLine(ZLTextArea::Style&, ZLTextWordCursor const&, ZLTextWordCursor const&) (ZLTextArea_processTextLine.cpp:151)
+==7329==    by 0x4EAA858: ZLTextAreaController::buildInfos(ZLTextWordCursor const&) (ZLTextAreaController.cpp:95)
+==7329==    by 0x4EABC79: ZLTextAreaController::preparePaintInfo() (ZLTextAreaController.cpp:335)
+==7329==    by 0x4ECA35D: ZLTextView::preparePaintInfo() (ZLTextView.cpp:668)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0xE352990: pango_ot_tag_from_script (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0xE352163: pango_ot_ruleset_new_for (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0xE352405: pango_ot_ruleset_new_from_description (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0xE3528C2: pango_ot_ruleset_get_for_description (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0x15F9E2D5: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66E1A: ZLGtkPaintContext::stringWidth(char const*, int, bool) const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EAF275: ZLTextWord::width(ZLPaintContext const&) const (ZLTextWord.h:88)
+==7329==    by 0x4EAEA67: ZLTextArea::Style::wordWidth(ZLTextWord const&, int, int, bool) const (ZLTextAreaStyle.cpp:158)
+==7329==    by 0x4EAE441: ZLTextArea::Style::elementWidth(ZLTextElement const&, unsigned int, ZLTextStyleEntry::Metrics const&) const (ZLTextAreaStyle.cpp:94)
+==7329==    by 0x4EB6B71: ZLTextArea::processTextLine(ZLTextArea::Style&, ZLTextWordCursor const&, ZLTextWordCursor const&) (ZLTextArea_processTextLine.cpp:151)
+==7329==    by 0x4EAA858: ZLTextAreaController::buildInfos(ZLTextWordCursor const&) (ZLTextAreaController.cpp:95)
+==7329== 
+==7329== Use of uninitialised value of size 8
+==7329==    at 0xE3529AA: pango_ot_tag_from_script (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0xE352163: pango_ot_ruleset_new_for (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0xE352405: pango_ot_ruleset_new_from_description (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0xE3528C2: pango_ot_ruleset_get_for_description (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0x15F9E2D5: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66E1A: ZLGtkPaintContext::stringWidth(char const*, int, bool) const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EAF275: ZLTextWord::width(ZLPaintContext const&) const (ZLTextWord.h:88)
+==7329==    by 0x4EAEA67: ZLTextArea::Style::wordWidth(ZLTextWord const&, int, int, bool) const (ZLTextAreaStyle.cpp:158)
+==7329==    by 0x4EAE441: ZLTextArea::Style::elementWidth(ZLTextElement const&, unsigned int, ZLTextStyleEntry::Metrics const&) const (ZLTextAreaStyle.cpp:94)
+==7329==    by 0x4EB6B71: ZLTextArea::processTextLine(ZLTextArea::Style&, ZLTextWordCursor const&, ZLTextWordCursor const&) (ZLTextArea_processTextLine.cpp:151)
+==7329==    by 0x4EAA858: ZLTextAreaController::buildInfos(ZLTextWordCursor const&) (ZLTextAreaController.cpp:95)
+==7329== 
+==7329== Use of uninitialised value of size 8
+==7329==    at 0xCE538E8: g_hash_table_insert_internal (ghash.c:408)
+==7329==    by 0xE3528DB: pango_ot_ruleset_get_for_description (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0x15F9E2D5: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66E1A: ZLGtkPaintContext::stringWidth(char const*, int, bool) const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EAF275: ZLTextWord::width(ZLPaintContext const&) const (ZLTextWord.h:88)
+==7329==    by 0x4EAEA67: ZLTextArea::Style::wordWidth(ZLTextWord const&, int, int, bool) const (ZLTextAreaStyle.cpp:158)
+==7329==    by 0x4EAE441: ZLTextArea::Style::elementWidth(ZLTextElement const&, unsigned int, ZLTextStyleEntry::Metrics const&) const (ZLTextAreaStyle.cpp:94)
+==7329==    by 0x4EB6B71: ZLTextArea::processTextLine(ZLTextArea::Style&, ZLTextWordCursor const&, ZLTextWordCursor const&) (ZLTextArea_processTextLine.cpp:151)
+==7329==    by 0x4EAA858: ZLTextAreaController::buildInfos(ZLTextWordCursor const&) (ZLTextAreaController.cpp:95)
+==7329==    by 0x4EABC79: ZLTextAreaController::preparePaintInfo() (ZLTextAreaController.cpp:335)
+==7329==    by 0x4ECA35D: ZLTextView::preparePaintInfo() (ZLTextView.cpp:668)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0xCE53929: g_hash_table_insert_internal (ghash.c:416)
+==7329==    by 0xE3528DB: pango_ot_ruleset_get_for_description (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0x15F9E2D5: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66E1A: ZLGtkPaintContext::stringWidth(char const*, int, bool) const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EAF275: ZLTextWord::width(ZLPaintContext const&) const (ZLTextWord.h:88)
+==7329==    by 0x4EAEA67: ZLTextArea::Style::wordWidth(ZLTextWord const&, int, int, bool) const (ZLTextAreaStyle.cpp:158)
+==7329==    by 0x4EAE441: ZLTextArea::Style::elementWidth(ZLTextElement const&, unsigned int, ZLTextStyleEntry::Metrics const&) const (ZLTextAreaStyle.cpp:94)
+==7329==    by 0x4EB6B71: ZLTextArea::processTextLine(ZLTextArea::Style&, ZLTextWordCursor const&, ZLTextWordCursor const&) (ZLTextArea_processTextLine.cpp:151)
+==7329==    by 0x4EAA858: ZLTextAreaController::buildInfos(ZLTextWordCursor const&) (ZLTextAreaController.cpp:95)
+==7329==    by 0x4EABC79: ZLTextAreaController::preparePaintInfo() (ZLTextAreaController.cpp:335)
+==7329==    by 0x4ECA35D: ZLTextView::preparePaintInfo() (ZLTextView.cpp:668)
+==7329== 
+==7329== Use of uninitialised value of size 8
+==7329==    at 0xCE53920: g_hash_table_insert_internal (ghash.c:439)
+==7329==    by 0xE3528DB: pango_ot_ruleset_get_for_description (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0x15F9E2D5: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66E1A: ZLGtkPaintContext::stringWidth(char const*, int, bool) const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EAF275: ZLTextWord::width(ZLPaintContext const&) const (ZLTextWord.h:88)
+==7329==    by 0x4EAEA67: ZLTextArea::Style::wordWidth(ZLTextWord const&, int, int, bool) const (ZLTextAreaStyle.cpp:158)
+==7329==    by 0x4EAE441: ZLTextArea::Style::elementWidth(ZLTextElement const&, unsigned int, ZLTextStyleEntry::Metrics const&) const (ZLTextAreaStyle.cpp:94)
+==7329==    by 0x4EB6B71: ZLTextArea::processTextLine(ZLTextArea::Style&, ZLTextWordCursor const&, ZLTextWordCursor const&) (ZLTextArea_processTextLine.cpp:151)
+==7329==    by 0x4EAA858: ZLTextAreaController::buildInfos(ZLTextWordCursor const&) (ZLTextAreaController.cpp:95)
+==7329==    by 0x4EABC79: ZLTextAreaController::preparePaintInfo() (ZLTextAreaController.cpp:335)
+==7329==    by 0x4ECA35D: ZLTextView::preparePaintInfo() (ZLTextView.cpp:668)
+==7329== 
+==7329== Use of uninitialised value of size 8
+==7329==    at 0xCE534B8: g_hash_table_insert_node (ghash.c:885)
+==7329==    by 0xCE53989: g_hash_table_insert_internal (ghash.c:1153)
+==7329==    by 0xE3528DB: pango_ot_ruleset_get_for_description (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0x15F9E2D5: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66E1A: ZLGtkPaintContext::stringWidth(char const*, int, bool) const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EAF275: ZLTextWord::width(ZLPaintContext const&) const (ZLTextWord.h:88)
+==7329==    by 0x4EAEA67: ZLTextArea::Style::wordWidth(ZLTextWord const&, int, int, bool) const (ZLTextAreaStyle.cpp:158)
+==7329==    by 0x4EAE441: ZLTextArea::Style::elementWidth(ZLTextElement const&, unsigned int, ZLTextStyleEntry::Metrics const&) const (ZLTextAreaStyle.cpp:94)
+==7329==    by 0x4EB6B71: ZLTextArea::processTextLine(ZLTextArea::Style&, ZLTextWordCursor const&, ZLTextWordCursor const&) (ZLTextArea_processTextLine.cpp:151)
+==7329==    by 0x4EAA858: ZLTextAreaController::buildInfos(ZLTextWordCursor const&) (ZLTextAreaController.cpp:95)
+==7329==    by 0x4EABC79: ZLTextAreaController::preparePaintInfo() (ZLTextAreaController.cpp:335)
+==7329== 
+==7329== Use of uninitialised value of size 8
+==7329==    at 0xCE534CD: g_hash_table_insert_node (ghash.c:887)
+==7329==    by 0xCE53989: g_hash_table_insert_internal (ghash.c:1153)
+==7329==    by 0xE3528DB: pango_ot_ruleset_get_for_description (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0x15F9E2D5: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66E1A: ZLGtkPaintContext::stringWidth(char const*, int, bool) const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EAF275: ZLTextWord::width(ZLPaintContext const&) const (ZLTextWord.h:88)
+==7329==    by 0x4EAEA67: ZLTextArea::Style::wordWidth(ZLTextWord const&, int, int, bool) const (ZLTextAreaStyle.cpp:158)
+==7329==    by 0x4EAE441: ZLTextArea::Style::elementWidth(ZLTextElement const&, unsigned int, ZLTextStyleEntry::Metrics const&) const (ZLTextAreaStyle.cpp:94)
+==7329==    by 0x4EB6B71: ZLTextArea::processTextLine(ZLTextArea::Style&, ZLTextWordCursor const&, ZLTextWordCursor const&) (ZLTextArea_processTextLine.cpp:151)
+==7329==    by 0x4EAA858: ZLTextAreaController::buildInfos(ZLTextWordCursor const&) (ZLTextAreaController.cpp:95)
+==7329==    by 0x4EABC79: ZLTextAreaController::preparePaintInfo() (ZLTextAreaController.cpp:335)
+==7329== 
+==7329== Use of uninitialised value of size 8
+==7329==    at 0xCE534D0: g_hash_table_insert_node (ghash.c:886)
+==7329==    by 0xCE53989: g_hash_table_insert_internal (ghash.c:1153)
+==7329==    by 0xE3528DB: pango_ot_ruleset_get_for_description (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0x15F9E2D5: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66E1A: ZLGtkPaintContext::stringWidth(char const*, int, bool) const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EAF275: ZLTextWord::width(ZLPaintContext const&) const (ZLTextWord.h:88)
+==7329==    by 0x4EAEA67: ZLTextArea::Style::wordWidth(ZLTextWord const&, int, int, bool) const (ZLTextAreaStyle.cpp:158)
+==7329==    by 0x4EAE441: ZLTextArea::Style::elementWidth(ZLTextElement const&, unsigned int, ZLTextStyleEntry::Metrics const&) const (ZLTextAreaStyle.cpp:94)
+==7329==    by 0x4EB6B71: ZLTextArea::processTextLine(ZLTextArea::Style&, ZLTextWordCursor const&, ZLTextWordCursor const&) (ZLTextArea_processTextLine.cpp:151)
+==7329==    by 0x4EAA858: ZLTextAreaController::buildInfos(ZLTextWordCursor const&) (ZLTextAreaController.cpp:95)
+==7329==    by 0x4EABC79: ZLTextAreaController::preparePaintInfo() (ZLTextAreaController.cpp:335)
+==7329== 
+==7329== Use of uninitialised value of size 8
+==7329==    at 0xCE53598: g_hash_table_insert_node (ghash.c:897)
+==7329==    by 0xCE53989: g_hash_table_insert_internal (ghash.c:1153)
+==7329==    by 0xE3528DB: pango_ot_ruleset_get_for_description (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0x15F9E2D5: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66E1A: ZLGtkPaintContext::stringWidth(char const*, int, bool) const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EAF275: ZLTextWord::width(ZLPaintContext const&) const (ZLTextWord.h:88)
+==7329==    by 0x4EAEA67: ZLTextArea::Style::wordWidth(ZLTextWord const&, int, int, bool) const (ZLTextAreaStyle.cpp:158)
+==7329==    by 0x4EAE441: ZLTextArea::Style::elementWidth(ZLTextElement const&, unsigned int, ZLTextStyleEntry::Metrics const&) const (ZLTextAreaStyle.cpp:94)
+==7329==    by 0x4EB6B71: ZLTextArea::processTextLine(ZLTextArea::Style&, ZLTextWordCursor const&, ZLTextWordCursor const&) (ZLTextArea_processTextLine.cpp:151)
+==7329==    by 0x4EAA858: ZLTextAreaController::buildInfos(ZLTextWordCursor const&) (ZLTextAreaController.cpp:95)
+==7329==    by 0x4EABC79: ZLTextAreaController::preparePaintInfo() (ZLTextAreaController.cpp:335)
+==7329== 
+==7329== Use of uninitialised value of size 8
+==7329==    at 0xCE5359F: g_hash_table_insert_node (ghash.c:898)
+==7329==    by 0xCE53989: g_hash_table_insert_internal (ghash.c:1153)
+==7329==    by 0xE3528DB: pango_ot_ruleset_get_for_description (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0x15F9E2D5: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66E1A: ZLGtkPaintContext::stringWidth(char const*, int, bool) const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EAF275: ZLTextWord::width(ZLPaintContext const&) const (ZLTextWord.h:88)
+==7329==    by 0x4EAEA67: ZLTextArea::Style::wordWidth(ZLTextWord const&, int, int, bool) const (ZLTextAreaStyle.cpp:158)
+==7329==    by 0x4EAE441: ZLTextArea::Style::elementWidth(ZLTextElement const&, unsigned int, ZLTextStyleEntry::Metrics const&) const (ZLTextAreaStyle.cpp:94)
+==7329==    by 0x4EB6B71: ZLTextArea::processTextLine(ZLTextArea::Style&, ZLTextWordCursor const&, ZLTextWordCursor const&) (ZLTextArea_processTextLine.cpp:151)
+==7329==    by 0x4EAA858: ZLTextAreaController::buildInfos(ZLTextWordCursor const&) (ZLTextAreaController.cpp:95)
+==7329==    by 0x4EABC79: ZLTextAreaController::preparePaintInfo() (ZLTextAreaController.cpp:335)
+==7329== 
+==7329== Use of uninitialised value of size 8
+==7329==    at 0xCE535A7: g_hash_table_insert_node (ghash.c:899)
+==7329==    by 0xCE53989: g_hash_table_insert_internal (ghash.c:1153)
+==7329==    by 0xE3528DB: pango_ot_ruleset_get_for_description (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0x15F9E2D5: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66E1A: ZLGtkPaintContext::stringWidth(char const*, int, bool) const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EAF275: ZLTextWord::width(ZLPaintContext const&) const (ZLTextWord.h:88)
+==7329==    by 0x4EAEA67: ZLTextArea::Style::wordWidth(ZLTextWord const&, int, int, bool) const (ZLTextAreaStyle.cpp:158)
+==7329==    by 0x4EAE441: ZLTextArea::Style::elementWidth(ZLTextElement const&, unsigned int, ZLTextStyleEntry::Metrics const&) const (ZLTextAreaStyle.cpp:94)
+==7329==    by 0x4EB6B71: ZLTextArea::processTextLine(ZLTextArea::Style&, ZLTextWordCursor const&, ZLTextWordCursor const&) (ZLTextArea_processTextLine.cpp:151)
+==7329==    by 0x4EAA858: ZLTextAreaController::buildInfos(ZLTextWordCursor const&) (ZLTextAreaController.cpp:95)
+==7329==    by 0x4EABC79: ZLTextAreaController::preparePaintInfo() (ZLTextAreaController.cpp:335)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0x15F9E27C: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66E1A: ZLGtkPaintContext::stringWidth(char const*, int, bool) const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0xBC6668B: ZLGtkPaintContext::spaceWidth() const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EB6C7F: ZLTextArea::processTextLine(ZLTextArea::Style&, ZLTextWordCursor const&, ZLTextWordCursor const&) (ZLTextArea_processTextLine.cpp:166)
+==7329==    by 0x4EAA858: ZLTextAreaController::buildInfos(ZLTextWordCursor const&) (ZLTextAreaController.cpp:95)
+==7329==    by 0x4EABC79: ZLTextAreaController::preparePaintInfo() (ZLTextAreaController.cpp:335)
+==7329==    by 0x4ECA35D: ZLTextView::preparePaintInfo() (ZLTextView.cpp:668)
+==7329==    by 0x6E6237: BookTextView::preparePaintInfo() (BookTextView.h:96)
+==7329==    by 0x4ECAFFD: ZLTextView::paint() (ZLTextView_paint.cpp:32)
+==7329==    by 0x6E5CD9: BookTextView::paint() (BookTextView.cpp:415)
+==7329==    by 0xBC6951D: ZLGtkViewWidget::doPaint() (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0x15F9E280: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66E1A: ZLGtkPaintContext::stringWidth(char const*, int, bool) const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0xBC6668B: ZLGtkPaintContext::spaceWidth() const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EB6C7F: ZLTextArea::processTextLine(ZLTextArea::Style&, ZLTextWordCursor const&, ZLTextWordCursor const&) (ZLTextArea_processTextLine.cpp:166)
+==7329==    by 0x4EAA858: ZLTextAreaController::buildInfos(ZLTextWordCursor const&) (ZLTextAreaController.cpp:95)
+==7329==    by 0x4EABC79: ZLTextAreaController::preparePaintInfo() (ZLTextAreaController.cpp:335)
+==7329==    by 0x4ECA35D: ZLTextView::preparePaintInfo() (ZLTextView.cpp:668)
+==7329==    by 0x6E6237: BookTextView::preparePaintInfo() (BookTextView.h:96)
+==7329==    by 0x4ECAFFD: ZLTextView::paint() (ZLTextView_paint.cpp:32)
+==7329==    by 0x6E5CD9: BookTextView::paint() (BookTextView.cpp:415)
+==7329==    by 0xBC6951D: ZLGtkViewWidget::doPaint() (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0xCE53E98: g_hash_table_lookup (ghash.c:410)
+==7329==    by 0xE3527E4: pango_ot_ruleset_get_for_description (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0x15F9E2D5: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66E1A: ZLGtkPaintContext::stringWidth(char const*, int, bool) const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0xBC6668B: ZLGtkPaintContext::spaceWidth() const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EB6C7F: ZLTextArea::processTextLine(ZLTextArea::Style&, ZLTextWordCursor const&, ZLTextWordCursor const&) (ZLTextArea_processTextLine.cpp:166)
+==7329==    by 0x4EAA858: ZLTextAreaController::buildInfos(ZLTextWordCursor const&) (ZLTextAreaController.cpp:95)
+==7329==    by 0x4EABC79: ZLTextAreaController::preparePaintInfo() (ZLTextAreaController.cpp:335)
+==7329==    by 0x4ECA35D: ZLTextView::preparePaintInfo() (ZLTextView.cpp:668)
+==7329==    by 0x6E6237: BookTextView::preparePaintInfo() (BookTextView.h:96)
+==7329==    by 0x4ECAFFD: ZLTextView::paint() (ZLTextView_paint.cpp:32)
+==7329== 
+==7329== Use of uninitialised value of size 8
+==7329==    at 0xCE53EA5: g_hash_table_lookup (ghash.c:418)
+==7329==    by 0xE3527E4: pango_ot_ruleset_get_for_description (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0x15F9E2D5: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66E1A: ZLGtkPaintContext::stringWidth(char const*, int, bool) const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0xBC6668B: ZLGtkPaintContext::spaceWidth() const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EB6C7F: ZLTextArea::processTextLine(ZLTextArea::Style&, ZLTextWordCursor const&, ZLTextWordCursor const&) (ZLTextArea_processTextLine.cpp:166)
+==7329==    by 0x4EAA858: ZLTextAreaController::buildInfos(ZLTextWordCursor const&) (ZLTextAreaController.cpp:95)
+==7329==    by 0x4EABC79: ZLTextAreaController::preparePaintInfo() (ZLTextAreaController.cpp:335)
+==7329==    by 0x4ECA35D: ZLTextView::preparePaintInfo() (ZLTextView.cpp:668)
+==7329==    by 0x6E6237: BookTextView::preparePaintInfo() (BookTextView.h:96)
+==7329==    by 0x4ECAFFD: ZLTextView::paint() (ZLTextView_paint.cpp:32)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0xE351DF6: pango_ot_ruleset_description_equal (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0xCE53EBE: g_hash_table_lookup (ghash.c:422)
+==7329==    by 0xE3527E4: pango_ot_ruleset_get_for_description (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0x15F9E2D5: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66E1A: ZLGtkPaintContext::stringWidth(char const*, int, bool) const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0xBC6668B: ZLGtkPaintContext::spaceWidth() const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EB6C7F: ZLTextArea::processTextLine(ZLTextArea::Style&, ZLTextWordCursor const&, ZLTextWordCursor const&) (ZLTextArea_processTextLine.cpp:166)
+==7329==    by 0x4EAA858: ZLTextAreaController::buildInfos(ZLTextWordCursor const&) (ZLTextAreaController.cpp:95)
+==7329==    by 0x4EABC79: ZLTextAreaController::preparePaintInfo() (ZLTextAreaController.cpp:335)
+==7329==    by 0x4ECA35D: ZLTextView::preparePaintInfo() (ZLTextView.cpp:668)
+==7329==    by 0x6E6237: BookTextView::preparePaintInfo() (BookTextView.h:96)
+==7329== 
+==7329== Use of uninitialised value of size 8
+==7329==    at 0xCE53F0C: g_hash_table_lookup (ghash.c:422)
+==7329==    by 0xE3527E4: pango_ot_ruleset_get_for_description (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0x15F9E2D5: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66E1A: ZLGtkPaintContext::stringWidth(char const*, int, bool) const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0xBC6668B: ZLGtkPaintContext::spaceWidth() const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EB6C7F: ZLTextArea::processTextLine(ZLTextArea::Style&, ZLTextWordCursor const&, ZLTextWordCursor const&) (ZLTextArea_processTextLine.cpp:166)
+==7329==    by 0x4EAA858: ZLTextAreaController::buildInfos(ZLTextWordCursor const&) (ZLTextAreaController.cpp:95)
+==7329==    by 0x4EABC79: ZLTextAreaController::preparePaintInfo() (ZLTextAreaController.cpp:335)
+==7329==    by 0x4ECA35D: ZLTextView::preparePaintInfo() (ZLTextView.cpp:668)
+==7329==    by 0x6E6237: BookTextView::preparePaintInfo() (BookTextView.h:96)
+==7329==    by 0x4ECAFFD: ZLTextView::paint() (ZLTextView_paint.cpp:32)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0xCE53EEF: g_hash_table_lookup (ghash.c:1078)
+==7329==    by 0xE3527E4: pango_ot_ruleset_get_for_description (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0x15F9E2D5: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66E1A: ZLGtkPaintContext::stringWidth(char const*, int, bool) const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0xBC6668B: ZLGtkPaintContext::spaceWidth() const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EB6C7F: ZLTextArea::processTextLine(ZLTextArea::Style&, ZLTextWordCursor const&, ZLTextWordCursor const&) (ZLTextArea_processTextLine.cpp:166)
+==7329==    by 0x4EAA858: ZLTextAreaController::buildInfos(ZLTextWordCursor const&) (ZLTextAreaController.cpp:95)
+==7329==    by 0x4EABC79: ZLTextAreaController::preparePaintInfo() (ZLTextAreaController.cpp:335)
+==7329==    by 0x4ECA35D: ZLTextView::preparePaintInfo() (ZLTextView.cpp:668)
+==7329==    by 0x6E6237: BookTextView::preparePaintInfo() (BookTextView.h:96)
+==7329==    by 0x4ECAFFD: ZLTextView::paint() (ZLTextView_paint.cpp:32)
+==7329== 
+==7329== Use of uninitialised value of size 8
+==7329==    at 0xCE53EF5: g_hash_table_lookup (ghash.c:1078)
+==7329==    by 0xE3527E4: pango_ot_ruleset_get_for_description (in /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0)
+==7329==    by 0x15F9E2D5: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66E1A: ZLGtkPaintContext::stringWidth(char const*, int, bool) const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0xBC6668B: ZLGtkPaintContext::spaceWidth() const (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EB6C7F: ZLTextArea::processTextLine(ZLTextArea::Style&, ZLTextWordCursor const&, ZLTextWordCursor const&) (ZLTextArea_processTextLine.cpp:166)
+==7329==    by 0x4EAA858: ZLTextAreaController::buildInfos(ZLTextWordCursor const&) (ZLTextAreaController.cpp:95)
+==7329==    by 0x4EABC79: ZLTextAreaController::preparePaintInfo() (ZLTextAreaController.cpp:335)
+==7329==    by 0x4ECA35D: ZLTextView::preparePaintInfo() (ZLTextView.cpp:668)
+==7329==    by 0x6E6237: BookTextView::preparePaintInfo() (BookTextView.h:96)
+==7329==    by 0x4ECAFFD: ZLTextView::paint() (ZLTextView_paint.cpp:32)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0x15F9E27C: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66D4B: ZLGtkPaintContext::drawString(int, int, char const*, int, bool) (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EB29A6: ZLTextArea::drawString(ZLTextArea::Style&, int, int, char const*, int, ZLTextWord::Mark const*, int, bool) (ZLTextArea_drawWord.cpp:33)
+==7329==    by 0x4EB2F6A: ZLTextArea::drawWord(ZLTextArea::Style&, int, int, ZLTextWord const&, int, int, bool) (ZLTextArea_drawWord.cpp:91)
+==7329==    by 0x4EB0D38: ZLTextArea::drawTextLine(ZLTextArea::Style&, ZLTextLineInfo const&, int, unsigned long, unsigned long) (ZLTextArea_drawTextLine.cpp:186)
+==7329==    by 0x4EA68BD: ZLTextArea::paint() (ZLTextArea.cpp:194)
+==7329==    by 0x4ECB037: ZLTextView::paint() (ZLTextView_paint.cpp:38)
+==7329==    by 0x6E5CD9: BookTextView::paint() (BookTextView.cpp:415)
+==7329==    by 0xBC6951D: ZLGtkViewWidget::doPaint() (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0xBFAEDD7: _gtk_marshal_BOOLEAN__BOXED (gtkmarshalers.c:86)
+==7329==    by 0xCBDCCA1: g_closure_invoke (gclosure.c:777)
+==7329== 
+==7329== Conditional jump or move depends on uninitialised value(s)
+==7329==    at 0x15F9E280: ??? (in /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so)
+==7329==    by 0xC9AE1A9: pango_shape (in /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0)
+==7329==    by 0xBC66D4B: ZLGtkPaintContext::drawString(int, int, char const*, int, bool) (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0x4EB29A6: ZLTextArea::drawString(ZLTextArea::Style&, int, int, char const*, int, ZLTextWord::Mark const*, int, bool) (ZLTextArea_drawWord.cpp:33)
+==7329==    by 0x4EB2F6A: ZLTextArea::drawWord(ZLTextArea::Style&, int, int, ZLTextWord const&, int, int, bool) (ZLTextArea_drawWord.cpp:91)
+==7329==    by 0x4EB0D38: ZLTextArea::drawTextLine(ZLTextArea::Style&, ZLTextLineInfo const&, int, unsigned long, unsigned long) (ZLTextArea_drawTextLine.cpp:186)
+==7329==    by 0x4EA68BD: ZLTextArea::paint() (ZLTextArea.cpp:194)
+==7329==    by 0x4ECB037: ZLTextView::paint() (ZLTextView_paint.cpp:38)
+==7329==    by 0x6E5CD9: BookTextView::paint() (BookTextView.cpp:415)
+==7329==    by 0xBC6951D: ZLGtkViewWidget::doPaint() (in /usr/lib/zlibrary/ui/zlui-gtk.so)
+==7329==    by 0xBFAEDD7: _gtk_marshal_BOOLEAN__BOXED (gtkmarshalers.c:86)
+==7329==    by 0xCBDCCA1: g_closure_invoke (gclosure.c:777)
+==7329== 
+==7329== Invalid read of size 4
+==7329==    at 0x5803BC3: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x5803C12: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329==  Address 0xb8754f0 is 16 bytes inside a block of size 26 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x5803C12: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329== 
+==7329== Invalid free() / delete / delete[] / realloc()
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x5803C12: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329==  Address 0xb8754e0 is 0 bytes inside a block of size 26 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x5803C12: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329== 
+==7329== Invalid read of size 4
+==7329==    at 0x523DBD6: shared_ptr_storage<ZLTreeResource>::counter() const (shared_ptr.h:160)
+==7329==    by 0x523D36B: shared_ptr<ZLTreeResource>::detachStorage() (shared_ptr.h:177)
+==7329==    by 0x523CE5B: shared_ptr<ZLTreeResource>::~shared_ptr() (shared_ptr.h:208)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329==  Address 0x1476b120 is 0 bytes inside a block of size 16 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x523D3A0: shared_ptr<ZLTreeResource>::detachStorage() (shared_ptr.h:179)
+==7329==    by 0x523CE5B: shared_ptr<ZLTreeResource>::~shared_ptr() (shared_ptr.h:208)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329== 
+==7329== Invalid read of size 4
+==7329==    at 0x523DBDC: shared_ptr_storage<ZLTreeResource>::counter() const (shared_ptr.h:160)
+==7329==    by 0x523D36B: shared_ptr<ZLTreeResource>::detachStorage() (shared_ptr.h:177)
+==7329==    by 0x523CE5B: shared_ptr<ZLTreeResource>::~shared_ptr() (shared_ptr.h:208)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329==  Address 0x1476b124 is 4 bytes inside a block of size 16 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x523D3A0: shared_ptr<ZLTreeResource>::detachStorage() (shared_ptr.h:179)
+==7329==    by 0x523CE5B: shared_ptr<ZLTreeResource>::~shared_ptr() (shared_ptr.h:208)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329== 
+==7329== Invalid read of size 4
+==7329==    at 0x523DC7E: shared_ptr_storage<ZLTreeResource>::removeReference() (shared_ptr.h:143)
+==7329==    by 0x523D3B1: shared_ptr<ZLTreeResource>::detachStorage() (shared_ptr.h:181)
+==7329==    by 0x523CE5B: shared_ptr<ZLTreeResource>::~shared_ptr() (shared_ptr.h:208)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329==  Address 0x1476b120 is 0 bytes inside a block of size 16 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x523D3A0: shared_ptr<ZLTreeResource>::detachStorage() (shared_ptr.h:179)
+==7329==    by 0x523CE5B: shared_ptr<ZLTreeResource>::~shared_ptr() (shared_ptr.h:208)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329== 
+==7329== Invalid write of size 4
+==7329==    at 0x523DC87: shared_ptr_storage<ZLTreeResource>::removeReference() (shared_ptr.h:143)
+==7329==    by 0x523D3B1: shared_ptr<ZLTreeResource>::detachStorage() (shared_ptr.h:181)
+==7329==    by 0x523CE5B: shared_ptr<ZLTreeResource>::~shared_ptr() (shared_ptr.h:208)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329==  Address 0x1476b120 is 0 bytes inside a block of size 16 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x523D3A0: shared_ptr<ZLTreeResource>::detachStorage() (shared_ptr.h:179)
+==7329==    by 0x523CE5B: shared_ptr<ZLTreeResource>::~shared_ptr() (shared_ptr.h:208)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329== 
+==7329== Invalid read of size 4
+==7329==    at 0x523DC8D: shared_ptr_storage<ZLTreeResource>::removeReference() (shared_ptr.h:144)
+==7329==    by 0x523D3B1: shared_ptr<ZLTreeResource>::detachStorage() (shared_ptr.h:181)
+==7329==    by 0x523CE5B: shared_ptr<ZLTreeResource>::~shared_ptr() (shared_ptr.h:208)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329==  Address 0x1476b120 is 0 bytes inside a block of size 16 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x523D3A0: shared_ptr<ZLTreeResource>::detachStorage() (shared_ptr.h:179)
+==7329==    by 0x523CE5B: shared_ptr<ZLTreeResource>::~shared_ptr() (shared_ptr.h:208)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329== 
+==7329== Invalid read of size 4
+==7329==    at 0x5803BC3: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x5803C12: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x6C99E7: ZLCategoryKey::~ZLCategoryKey() (ZLOptions.h:29)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329==  Address 0xb873bf0 is 16 bytes inside a block of size 32 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x5803C12: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x6C99E7: ZLCategoryKey::~ZLCategoryKey() (ZLOptions.h:29)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329== 
+==7329== Invalid free() / delete / delete[] / realloc()
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x5803C12: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x6C99E7: ZLCategoryKey::~ZLCategoryKey() (ZLOptions.h:29)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329==  Address 0xb873be0 is 0 bytes inside a block of size 32 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x5803C12: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x6C99E7: ZLCategoryKey::~ZLCategoryKey() (ZLOptions.h:29)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329== 
+==7329== Invalid read of size 4
+==7329==    at 0x5803BC3: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x5803C12: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x439465: ZLResourceKey::~ZLResourceKey() (ZLResource.h:25)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329==  Address 0xb872b70 is 16 bytes inside a block of size 30 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x5803C12: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x439465: ZLResourceKey::~ZLResourceKey() (ZLResource.h:25)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329== 
+==7329== Invalid free() / delete / delete[] / realloc()
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x5803C12: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x439465: ZLResourceKey::~ZLResourceKey() (ZLResource.h:25)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329==  Address 0xb872b60 is 0 bytes inside a block of size 30 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x5803C12: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x439465: ZLResourceKey::~ZLResourceKey() (ZLResource.h:25)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329== 
+==7329== Invalid read of size 8
+==7329==    at 0x520C55E: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_S_right(std::_Rb_tree_node_base*) (stl_tree.h:528)
+==7329==    by 0x520B7B7: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329==  Address 0x1476aab8 is 24 bytes inside a block of size 48 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x520D2BB: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::deallocate(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*, unsigned long) (new_allocator.h:98)
+==7329==    by 0x520D015: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_put_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:373)
+==7329==    by 0x520C5DA: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:395)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329== 
+==7329== Invalid read of size 8
+==7329==    at 0x520C55E: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_S_right(std::_Rb_tree_node_base*) (stl_tree.h:528)
+==7329==    by 0x520B7B7: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329==  Address 0xbc24f88 is 24 bytes inside a block of size 48 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x520D2BB: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::deallocate(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*, unsigned long) (new_allocator.h:98)
+==7329==    by 0x520D015: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_put_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:373)
+==7329==    by 0x520C5DA: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:395)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329== 
+==7329== Invalid read of size 8
+==7329==    at 0x520C55E: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_S_right(std::_Rb_tree_node_base*) (stl_tree.h:528)
+==7329==    by 0x520B7B7: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329==  Address 0x1476d538 is 24 bytes inside a block of size 48 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x520D2BB: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::deallocate(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*, unsigned long) (new_allocator.h:98)
+==7329==    by 0x520D015: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_put_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:373)
+==7329==    by 0x520C5DA: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:395)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329== 
+==7329== Invalid read of size 8
+==7329==    at 0x520C570: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_S_left(std::_Rb_tree_node_base*) (stl_tree.h:520)
+==7329==    by 0x520B7D5: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1075)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==  Address 0xbaaaac0 is 16 bytes inside a block of size 48 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x520D2BB: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::deallocate(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*, unsigned long) (new_allocator.h:98)
+==7329==    by 0x520D015: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_put_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:373)
+==7329==    by 0x520C5DA: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:395)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329== 
+==7329== Invalid read of size 8
+==7329==    at 0x520B331: weak_ptr<ZLInputStream>::detachStorage() (shared_ptr.h:310)
+==7329==    by 0x520B263: weak_ptr<ZLInputStream>::~weak_ptr() (shared_ptr.h:336)
+==7329==    by 0x520AA0B: std::pair<std::string const, weak_ptr<ZLInputStream> >::~pair() (stl_pair.h:87)
+==7329==    by 0x520CFEB: __gnu_cxx::new_allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > >::destroy(std::pair<std::string const, weak_ptr<ZLInputStream> >*) (new_allocator.h:118)
+==7329==    by 0x520C5BB: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:394)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==  Address 0xbaaaad8 is 40 bytes inside a block of size 48 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x520D2BB: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::deallocate(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*, unsigned long) (new_allocator.h:98)
+==7329==    by 0x520D015: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_put_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:373)
+==7329==    by 0x520C5DA: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:395)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329== 
+==7329== Invalid read of size 8
+==7329==    at 0x520B33D: weak_ptr<ZLInputStream>::detachStorage() (shared_ptr.h:311)
+==7329==    by 0x520B263: weak_ptr<ZLInputStream>::~weak_ptr() (shared_ptr.h:336)
+==7329==    by 0x520AA0B: std::pair<std::string const, weak_ptr<ZLInputStream> >::~pair() (stl_pair.h:87)
+==7329==    by 0x520CFEB: __gnu_cxx::new_allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > >::destroy(std::pair<std::string const, weak_ptr<ZLInputStream> >*) (new_allocator.h:118)
+==7329==    by 0x520C5BB: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:394)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==  Address 0xbaaaad8 is 40 bytes inside a block of size 48 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x520D2BB: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::deallocate(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*, unsigned long) (new_allocator.h:98)
+==7329==    by 0x520D015: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_put_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:373)
+==7329==    by 0x520C5DA: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:395)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329== 
+==7329== Invalid read of size 4
+==7329==    at 0x520BED2: shared_ptr_storage<ZLInputStream>::removeWeakReference() (shared_ptr.h:156)
+==7329==    by 0x520B347: weak_ptr<ZLInputStream>::detachStorage() (shared_ptr.h:311)
+==7329==    by 0x520B263: weak_ptr<ZLInputStream>::~weak_ptr() (shared_ptr.h:336)
+==7329==    by 0x520AA0B: std::pair<std::string const, weak_ptr<ZLInputStream> >::~pair() (stl_pair.h:87)
+==7329==    by 0x520CFEB: __gnu_cxx::new_allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > >::destroy(std::pair<std::string const, weak_ptr<ZLInputStream> >*) (new_allocator.h:118)
+==7329==    by 0x520C5BB: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:394)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==  Address 0xbaaae04 is 4 bytes inside a block of size 16 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x520B37B: weak_ptr<ZLInputStream>::detachStorage() (shared_ptr.h:313)
+==7329==    by 0x520B263: weak_ptr<ZLInputStream>::~weak_ptr() (shared_ptr.h:336)
+==7329==    by 0x520AA0B: std::pair<std::string const, weak_ptr<ZLInputStream> >::~pair() (stl_pair.h:87)
+==7329==    by 0x520CFEB: __gnu_cxx::new_allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > >::destroy(std::pair<std::string const, weak_ptr<ZLInputStream> >*) (new_allocator.h:118)
+==7329==    by 0x520C5BB: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:394)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329== 
+==7329== Invalid write of size 4
+==7329==    at 0x520BEDC: shared_ptr_storage<ZLInputStream>::removeWeakReference() (shared_ptr.h:156)
+==7329==    by 0x520B347: weak_ptr<ZLInputStream>::detachStorage() (shared_ptr.h:311)
+==7329==    by 0x520B263: weak_ptr<ZLInputStream>::~weak_ptr() (shared_ptr.h:336)
+==7329==    by 0x520AA0B: std::pair<std::string const, weak_ptr<ZLInputStream> >::~pair() (stl_pair.h:87)
+==7329==    by 0x520CFEB: __gnu_cxx::new_allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > >::destroy(std::pair<std::string const, weak_ptr<ZLInputStream> >*) (new_allocator.h:118)
+==7329==    by 0x520C5BB: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:394)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==  Address 0xbaaae04 is 4 bytes inside a block of size 16 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x520B37B: weak_ptr<ZLInputStream>::detachStorage() (shared_ptr.h:313)
+==7329==    by 0x520B263: weak_ptr<ZLInputStream>::~weak_ptr() (shared_ptr.h:336)
+==7329==    by 0x520AA0B: std::pair<std::string const, weak_ptr<ZLInputStream> >::~pair() (stl_pair.h:87)
+==7329==    by 0x520CFEB: __gnu_cxx::new_allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > >::destroy(std::pair<std::string const, weak_ptr<ZLInputStream> >*) (new_allocator.h:118)
+==7329==    by 0x520C5BB: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:394)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329== 
+==7329== Invalid read of size 8
+==7329==    at 0x520B34C: weak_ptr<ZLInputStream>::detachStorage() (shared_ptr.h:312)
+==7329==    by 0x520B263: weak_ptr<ZLInputStream>::~weak_ptr() (shared_ptr.h:336)
+==7329==    by 0x520AA0B: std::pair<std::string const, weak_ptr<ZLInputStream> >::~pair() (stl_pair.h:87)
+==7329==    by 0x520CFEB: __gnu_cxx::new_allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > >::destroy(std::pair<std::string const, weak_ptr<ZLInputStream> >*) (new_allocator.h:118)
+==7329==    by 0x520C5BB: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:394)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==  Address 0xbaaaad8 is 40 bytes inside a block of size 48 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x520D2BB: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::deallocate(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*, unsigned long) (new_allocator.h:98)
+==7329==    by 0x520D015: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_put_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:373)
+==7329==    by 0x520C5DA: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:395)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329== 
+==7329== Invalid read of size 4
+==7329==    at 0x4AB3AA: shared_ptr_storage<ZLInputStream>::counter() const (shared_ptr.h:160)
+==7329==    by 0x520B356: weak_ptr<ZLInputStream>::detachStorage() (shared_ptr.h:312)
+==7329==    by 0x520B263: weak_ptr<ZLInputStream>::~weak_ptr() (shared_ptr.h:336)
+==7329==    by 0x520AA0B: std::pair<std::string const, weak_ptr<ZLInputStream> >::~pair() (stl_pair.h:87)
+==7329==    by 0x520CFEB: __gnu_cxx::new_allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > >::destroy(std::pair<std::string const, weak_ptr<ZLInputStream> >*) (new_allocator.h:118)
+==7329==    by 0x520C5BB: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:394)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==  Address 0xbaaae00 is 0 bytes inside a block of size 16 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x520B37B: weak_ptr<ZLInputStream>::detachStorage() (shared_ptr.h:313)
+==7329==    by 0x520B263: weak_ptr<ZLInputStream>::~weak_ptr() (shared_ptr.h:336)
+==7329==    by 0x520AA0B: std::pair<std::string const, weak_ptr<ZLInputStream> >::~pair() (stl_pair.h:87)
+==7329==    by 0x520CFEB: __gnu_cxx::new_allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > >::destroy(std::pair<std::string const, weak_ptr<ZLInputStream> >*) (new_allocator.h:118)
+==7329==    by 0x520C5BB: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:394)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329== 
+==7329== Invalid read of size 4
+==7329==    at 0x4AB3B0: shared_ptr_storage<ZLInputStream>::counter() const (shared_ptr.h:160)
+==7329==    by 0x520B356: weak_ptr<ZLInputStream>::detachStorage() (shared_ptr.h:312)
+==7329==    by 0x520B263: weak_ptr<ZLInputStream>::~weak_ptr() (shared_ptr.h:336)
+==7329==    by 0x520AA0B: std::pair<std::string const, weak_ptr<ZLInputStream> >::~pair() (stl_pair.h:87)
+==7329==    by 0x520CFEB: __gnu_cxx::new_allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > >::destroy(std::pair<std::string const, weak_ptr<ZLInputStream> >*) (new_allocator.h:118)
+==7329==    by 0x520C5BB: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:394)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==  Address 0xbaaae04 is 4 bytes inside a block of size 16 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x520B37B: weak_ptr<ZLInputStream>::detachStorage() (shared_ptr.h:313)
+==7329==    by 0x520B263: weak_ptr<ZLInputStream>::~weak_ptr() (shared_ptr.h:336)
+==7329==    by 0x520AA0B: std::pair<std::string const, weak_ptr<ZLInputStream> >::~pair() (stl_pair.h:87)
+==7329==    by 0x520CFEB: __gnu_cxx::new_allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > >::destroy(std::pair<std::string const, weak_ptr<ZLInputStream> >*) (new_allocator.h:118)
+==7329==    by 0x520C5BB: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:394)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329== 
+==7329== Invalid read of size 8
+==7329==    at 0x5803BF4: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x520AA17: std::pair<std::string const, weak_ptr<ZLInputStream> >::~pair() (stl_pair.h:87)
+==7329==    by 0x520CFEB: __gnu_cxx::new_allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > >::destroy(std::pair<std::string const, weak_ptr<ZLInputStream> >*) (new_allocator.h:118)
+==7329==    by 0x520C5BB: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:394)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==  Address 0xbaaaad0 is 32 bytes inside a block of size 48 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x520D2BB: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::deallocate(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*, unsigned long) (new_allocator.h:98)
+==7329==    by 0x520D015: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_put_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:373)
+==7329==    by 0x520C5DA: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:395)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329== 
+==7329== Invalid read of size 4
+==7329==    at 0x5803BC3: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x5803C12: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x520AA17: std::pair<std::string const, weak_ptr<ZLInputStream> >::~pair() (stl_pair.h:87)
+==7329==    by 0x520CFEB: __gnu_cxx::new_allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > >::destroy(std::pair<std::string const, weak_ptr<ZLInputStream> >*) (new_allocator.h:118)
+==7329==    by 0x520C5BB: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:394)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==  Address 0xbaaaa40 is 16 bytes inside a block of size 59 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x5803C12: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x520AA17: std::pair<std::string const, weak_ptr<ZLInputStream> >::~pair() (stl_pair.h:87)
+==7329==    by 0x520CFEB: __gnu_cxx::new_allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > >::destroy(std::pair<std::string const, weak_ptr<ZLInputStream> >*) (new_allocator.h:118)
+==7329==    by 0x520C5BB: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:394)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329== 
+==7329== Invalid free() / delete / delete[] / realloc()
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x5803C12: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x520AA17: std::pair<std::string const, weak_ptr<ZLInputStream> >::~pair() (stl_pair.h:87)
+==7329==    by 0x520CFEB: __gnu_cxx::new_allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > >::destroy(std::pair<std::string const, weak_ptr<ZLInputStream> >*) (new_allocator.h:118)
+==7329==    by 0x520C5BB: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:394)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==  Address 0xbaaaa30 is 0 bytes inside a block of size 59 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x5803C12: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x520AA17: std::pair<std::string const, weak_ptr<ZLInputStream> >::~pair() (stl_pair.h:87)
+==7329==    by 0x520CFEB: __gnu_cxx::new_allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > >::destroy(std::pair<std::string const, weak_ptr<ZLInputStream> >*) (new_allocator.h:118)
+==7329==    by 0x520C5BB: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:394)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329== 
+==7329== Invalid free() / delete / delete[] / realloc()
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x520D2BB: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::deallocate(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*, unsigned long) (new_allocator.h:98)
+==7329==    by 0x520D015: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_put_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:373)
+==7329==    by 0x520C5DA: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:395)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==  Address 0xbaaaab0 is 0 bytes inside a block of size 48 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x520D2BB: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::deallocate(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*, unsigned long) (new_allocator.h:98)
+==7329==    by 0x520D015: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_put_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:373)
+==7329==    by 0x520C5DA: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:395)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329== 
+==7329== Invalid read of size 8
+==7329==    at 0x520C570: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_S_left(std::_Rb_tree_node_base*) (stl_tree.h:520)
+==7329==    by 0x520B7D5: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1075)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329==  Address 0xbc24f80 is 16 bytes inside a block of size 48 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x520D2BB: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::deallocate(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*, unsigned long) (new_allocator.h:98)
+==7329==    by 0x520D015: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_put_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:373)
+==7329==    by 0x520C5DA: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:395)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520B7C9: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1074)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329== 
+==7329== Invalid read of size 8
+==7329==    at 0x520C570: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_S_left(std::_Rb_tree_node_base*) (stl_tree.h:520)
+==7329==    by 0x520B7D5: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1075)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329==  Address 0x1476aab0 is 16 bytes inside a block of size 48 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x520D2BB: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::deallocate(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*, unsigned long) (new_allocator.h:98)
+==7329==    by 0x520D015: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_put_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:373)
+==7329==    by 0x520C5DA: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:395)
+==7329==    by 0x520B7EC: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, weak_ptr<ZLInputStream> > >*) (stl_tree.h:1076)
+==7329==    by 0x520AF85: std::_Rb_tree<std::string, std::pair<std::string const, weak_ptr<ZLInputStream> >, std::_Select1st<std::pair<std::string const, weak_ptr<ZLInputStream> > >, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x520D4E5: std::map<std::string, weak_ptr<ZLInputStream>, std::less<std::string>, std::allocator<std::pair<std::string const, weak_ptr<ZLInputStream> > > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329== 
+==7329== Invalid read of size 8
+==7329==    at 0x51FF112: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_S_right(std::_Rb_tree_node_base*) (stl_tree.h:528)
+==7329==    by 0x51FEB33: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1074)
+==7329==    by 0x51FE84D: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x51FF8B5: std::map<int, std::string, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329==  Address 0x1b4f4d88 is 24 bytes inside a block of size 48 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x51FF797: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<int const, std::string> > >::deallocate(std::_Rb_tree_node<std::pair<int const, std::string> >*, unsigned long) (new_allocator.h:98)
+==7329==    by 0x51FF665: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_put_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:373)
+==7329==    by 0x51FF18E: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_destroy_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:395)
+==7329==    by 0x51FEB68: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1076)
+==7329==    by 0x51FE84D: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x51FF8B5: std::map<int, std::string, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329== 
+==7329== Invalid read of size 8
+==7329==    at 0x51FF124: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_S_left(std::_Rb_tree_node_base*) (stl_tree.h:520)
+==7329==    by 0x51FEB51: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1075)
+==7329==    by 0x51FE84D: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x51FF8B5: std::map<int, std::string, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329==  Address 0x1b4f4d80 is 16 bytes inside a block of size 48 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x51FF797: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<int const, std::string> > >::deallocate(std::_Rb_tree_node<std::pair<int const, std::string> >*, unsigned long) (new_allocator.h:98)
+==7329==    by 0x51FF665: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_put_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:373)
+==7329==    by 0x51FF18E: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_destroy_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:395)
+==7329==    by 0x51FEB68: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1076)
+==7329==    by 0x51FE84D: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x51FF8B5: std::map<int, std::string, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329== 
+==7329== Invalid read of size 8
+==7329==    at 0x5803BF4: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x51FE5C5: std::pair<int const, std::string>::~pair() (stl_pair.h:87)
+==7329==    by 0x51FF63B: __gnu_cxx::new_allocator<std::pair<int const, std::string> >::destroy(std::pair<int const, std::string>*) (new_allocator.h:118)
+==7329==    by 0x51FF16F: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_destroy_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:394)
+==7329==    by 0x51FEB68: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1076)
+==7329==    by 0x51FE84D: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x51FF8B5: std::map<int, std::string, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==  Address 0x1b4f4d98 is 40 bytes inside a block of size 48 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x51FF797: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<int const, std::string> > >::deallocate(std::_Rb_tree_node<std::pair<int const, std::string> >*, unsigned long) (new_allocator.h:98)
+==7329==    by 0x51FF665: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_put_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:373)
+==7329==    by 0x51FF18E: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_destroy_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:395)
+==7329==    by 0x51FEB68: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1076)
+==7329==    by 0x51FE84D: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x51FF8B5: std::map<int, std::string, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329== 
+==7329== Invalid read of size 4
+==7329==    at 0x5803BC3: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x5803C12: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x51FE5C5: std::pair<int const, std::string>::~pair() (stl_pair.h:87)
+==7329==    by 0x51FF63B: __gnu_cxx::new_allocator<std::pair<int const, std::string> >::destroy(std::pair<int const, std::string>*) (new_allocator.h:118)
+==7329==    by 0x51FF16F: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_destroy_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:394)
+==7329==    by 0x51FEB68: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1076)
+==7329==    by 0x51FE84D: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x51FF8B5: std::map<int, std::string, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==  Address 0x1b42c8f0 is 16 bytes inside a block of size 30 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x5803C12: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x51FE5C5: std::pair<int const, std::string>::~pair() (stl_pair.h:87)
+==7329==    by 0x51FF63B: __gnu_cxx::new_allocator<std::pair<int const, std::string> >::destroy(std::pair<int const, std::string>*) (new_allocator.h:118)
+==7329==    by 0x51FF16F: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_destroy_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:394)
+==7329==    by 0x51FEB68: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1076)
+==7329==    by 0x51FE84D: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x51FF8B5: std::map<int, std::string, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329== 
+==7329== Invalid free() / delete / delete[] / realloc()
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x5803C12: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x51FE5C5: std::pair<int const, std::string>::~pair() (stl_pair.h:87)
+==7329==    by 0x51FF63B: __gnu_cxx::new_allocator<std::pair<int const, std::string> >::destroy(std::pair<int const, std::string>*) (new_allocator.h:118)
+==7329==    by 0x51FF16F: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_destroy_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:394)
+==7329==    by 0x51FEB68: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1076)
+==7329==    by 0x51FE84D: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x51FF8B5: std::map<int, std::string, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==  Address 0x1b42c8e0 is 0 bytes inside a block of size 30 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x5803C12: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
+==7329==    by 0x51FE5C5: std::pair<int const, std::string>::~pair() (stl_pair.h:87)
+==7329==    by 0x51FF63B: __gnu_cxx::new_allocator<std::pair<int const, std::string> >::destroy(std::pair<int const, std::string>*) (new_allocator.h:118)
+==7329==    by 0x51FF16F: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_destroy_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:394)
+==7329==    by 0x51FEB68: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1076)
+==7329==    by 0x51FE84D: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x51FF8B5: std::map<int, std::string, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329== 
+==7329== Invalid free() / delete / delete[] / realloc()
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x51FF797: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<int const, std::string> > >::deallocate(std::_Rb_tree_node<std::pair<int const, std::string> >*, unsigned long) (new_allocator.h:98)
+==7329==    by 0x51FF665: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_put_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:373)
+==7329==    by 0x51FF18E: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_destroy_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:395)
+==7329==    by 0x51FEB68: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1076)
+==7329==    by 0x51FE84D: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x51FF8B5: std::map<int, std::string, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==  Address 0x1b4f4d70 is 0 bytes inside a block of size 48 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x51FF797: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<int const, std::string> > >::deallocate(std::_Rb_tree_node<std::pair<int const, std::string> >*, unsigned long) (new_allocator.h:98)
+==7329==    by 0x51FF665: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_put_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:373)
+==7329==    by 0x51FF18E: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_destroy_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:395)
+==7329==    by 0x51FEB68: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1076)
+==7329==    by 0x51FE84D: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x51FF8B5: std::map<int, std::string, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329== 
+==7329== Invalid read of size 8
+==7329==    at 0x51FF112: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_S_right(std::_Rb_tree_node_base*) (stl_tree.h:528)
+==7329==    by 0x51FEB33: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1074)
+==7329==    by 0x51FEB45: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1074)
+==7329==    by 0x51FE84D: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x51FF8B5: std::map<int, std::string, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329==  Address 0x175d4f48 is 24 bytes inside a block of size 48 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x51FF797: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<int const, std::string> > >::deallocate(std::_Rb_tree_node<std::pair<int const, std::string> >*, unsigned long) (new_allocator.h:98)
+==7329==    by 0x51FF665: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_put_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:373)
+==7329==    by 0x51FF18E: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_destroy_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:395)
+==7329==    by 0x51FEB68: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1076)
+==7329==    by 0x51FEB45: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1074)
+==7329==    by 0x51FE84D: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x51FF8B5: std::map<int, std::string, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329== 
+==7329== Invalid read of size 8
+==7329==    at 0x51FF112: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_S_right(std::_Rb_tree_node_base*) (stl_tree.h:528)
+==7329==    by 0x51FEB33: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1074)
+==7329==    by 0x51FEB45: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1074)
+==7329==    by 0x51FEB45: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1074)
+==7329==    by 0x51FE84D: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x51FF8B5: std::map<int, std::string, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329==  Address 0x18307e08 is 24 bytes inside a block of size 48 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x51FF797: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<int const, std::string> > >::deallocate(std::_Rb_tree_node<std::pair<int const, std::string> >*, unsigned long) (new_allocator.h:98)
+==7329==    by 0x51FF665: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_put_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:373)
+==7329==    by 0x51FF18E: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_destroy_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:395)
+==7329==    by 0x51FEB68: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1076)
+==7329==    by 0x51FEB45: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1074)
+==7329==    by 0x51FEB45: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1074)
+==7329==    by 0x51FE84D: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x51FF8B5: std::map<int, std::string, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329== 
+==7329== Invalid read of size 8
+==7329==    at 0x51FF124: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_S_left(std::_Rb_tree_node_base*) (stl_tree.h:520)
+==7329==    by 0x51FEB51: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1075)
+==7329==    by 0x51FEB45: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1074)
+==7329==    by 0x51FEB45: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1074)
+==7329==    by 0x51FEB45: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1074)
+==7329==    by 0x51FEB45: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1074)
+==7329==    by 0x51FEB45: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1074)
+==7329==    by 0x51FEB45: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1074)
+==7329==    by 0x51FE84D: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x51FF8B5: std::map<int, std::string, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==  Address 0x1b418b90 is 16 bytes inside a block of size 48 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x51FF797: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<int const, std::string> > >::deallocate(std::_Rb_tree_node<std::pair<int const, std::string> >*, unsigned long) (new_allocator.h:98)
+==7329==    by 0x51FF665: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_put_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:373)
+==7329==    by 0x51FF18E: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_destroy_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:395)
+==7329==    by 0x51FEB68: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1076)
+==7329==    by 0x51FEB45: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1074)
+==7329==    by 0x51FEB45: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1074)
+==7329==    by 0x51FEB45: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1074)
+==7329==    by 0x51FEB45: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1074)
+==7329==    by 0x51FEB45: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1074)
+==7329==    by 0x51FEB45: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1074)
+==7329==    by 0x51FE84D: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~_Rb_tree() (stl_tree.h:639)
+==7329== 
+==7329== Invalid read of size 8
+==7329==    at 0x51FF124: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_S_left(std::_Rb_tree_node_base*) (stl_tree.h:520)
+==7329==    by 0x51FEB51: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1075)
+==7329==    by 0x51FEB45: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1074)
+==7329==    by 0x51FE84D: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x51FF8B5: std::map<int, std::string, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0D3C: __cxa_finalize (cxa_finalize.c:56)
+==7329==    by 0x51FC4A5: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5272200: ??? (in /home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core/libzlcore.so.0.12.10)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329==  Address 0x175d4f40 is 16 bytes inside a block of size 48 free'd
+==7329==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==7329==    by 0x51FF797: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<int const, std::string> > >::deallocate(std::_Rb_tree_node<std::pair<int const, std::string> >*, unsigned long) (new_allocator.h:98)
+==7329==    by 0x51FF665: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_put_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:373)
+==7329==    by 0x51FF18E: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_destroy_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:395)
+==7329==    by 0x51FEB68: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1076)
+==7329==    by 0x51FEB45: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::string> >*) (stl_tree.h:1074)
+==7329==    by 0x51FE84D: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~_Rb_tree() (stl_tree.h:639)
+==7329==    by 0x51FF8B5: std::map<int, std::string, std::less<int>, std::allocator<std::pair<int const, std::string> > >::~map() (stl_map.h:88)
+==7329==    by 0x5FB0920: __run_exit_handlers (exit.c:78)
+==7329==    by 0x5FB09A4: exit (exit.c:100)
+==7329==    by 0x5F96773: (below main) (libc-start.c:258)
+==7329== 
+==7329== 
+==7329== HEAP SUMMARY:
+==7329==     in use at exit: 26,861,193 bytes in 117,136 blocks
+==7329==   total heap usage: 8,490,723 allocs, 8,373,785 frees, 360,256,431 bytes allocated
+==7329== 
+==7329== LEAK SUMMARY:
+==7329==    definitely lost: 18,206 bytes in 62 blocks
+==7329==    indirectly lost: 19,362,269 bytes in 101,892 blocks
+==7329==      possibly lost: 6,113,519 bytes in 4,486 blocks
+==7329==    still reachable: 1,367,199 bytes in 10,696 blocks
+==7329==         suppressed: 0 bytes in 0 blocks
+==7329== Rerun with --leak-check=full to see details of leaked memory
+==7329== 
+==7329== For counts of detected and suppressed errors, rerun with: -v
+==7329== Use --track-origins=yes to see where uninitialised values come from
+==7329== ERROR SUMMARY: 8396 errors from 89 contexts (suppressed: 2 from 2)
diff -uprN orig/fbreader-0.12.10/Makefile fbreader-0.12.10/Makefile
--- orig/fbreader-0.12.10/Makefile	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/Makefile	2011-04-05 22:55:28.000000000 +0200
@@ -1,4 +1,5 @@
 ROOTDIR = $(CURDIR)
+PACKAGE = FBReader
 
 include makefiles/platforms.mk
 
diff -uprN orig/fbreader-0.12.10/makefiles/subdir.mk fbreader-0.12.10/makefiles/subdir.mk
--- orig/fbreader-0.12.10/makefiles/subdir.mk	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/makefiles/subdir.mk	2011-04-05 22:55:28.000000000 +0200
@@ -43,6 +43,12 @@ endif
 all: $(OBJECTS)
 
 clean:
-	@$(RM) *.o *.s *.ld *.d
+	@$(RM) *.o *.s *.ld *.d src/formats/pdf/parseDefaultCharName.h
 
 -include *.d
+
+PdfDefaultCharMap.o: PdfDefaultCharMap.cpp PdfDefaultCharMap.h parseDefaultCharName.h
+	$(CC) -c $<
+
+parseDefaultCharName.h: PdfDefaultCharMapMap.cpp
+	./generate-state-table > tmp && mv tmp parseDefaultCharName.h
diff -uprN orig/fbreader-0.12.10/makefiles/target.mk fbreader-0.12.10/makefiles/target.mk
--- orig/fbreader-0.12.10/makefiles/target.mk	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/makefiles/target.mk	2011-05-29 00:47:11.810822602 +0200
@@ -47,6 +47,6 @@ UI_TYPE = gtk
 #TARGET_ARCH = palm
 #UI_TYPE = palm
 
-TARGET_STATUS = release
-#TARGET_STATUS = debug
+#TARGET_STATUS = release
+TARGET_STATUS = debug
 #TARGET_STATUS = profile
diff -uprN orig/fbreader-0.12.10/PO fbreader-0.12.10/PO
--- orig/fbreader-0.12.10/PO	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/PO	2012-08-03 18:16:16.482983199 +0200
@@ -0,0 +1,5 @@
+							{
+								while(ch >= '0' && ch <= '7') {
+									valueStream << 
+								}
+							}
Binary files orig/fbreader-0.12.10/Q and fbreader-0.12.10/Q differ
diff -uprN orig/fbreader-0.12.10/run fbreader-0.12.10/run
--- orig/fbreader-0.12.10/run	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/run	2011-12-02 21:45:41.337187650 +0100
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+export LD_LIBRARY_PATH="/home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/core:/home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/text:/home/dannym/source/FBReader/fbreader-0.12.10/zlibrary/ui"
+exec /home/dannym/source/FBReader/fbreader-0.12.10/fbreader/FBReader "$@"
diff -uprN orig/fbreader-0.12.10/zlibrary/core/include/ZLStringInputStream.h fbreader-0.12.10/zlibrary/core/include/ZLStringInputStream.h
--- orig/fbreader-0.12.10/zlibrary/core/include/ZLStringInputStream.h	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/zlibrary/core/include/ZLStringInputStream.h	2011-04-05 22:55:30.000000000 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2008-2010 Geometer Plus <contact@geometerplus.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ZLSTRINGINPUTSTREAM_H__
+#define __ZLSTRINGINPUTSTREAM_H__
+
+#include <ZLInputStream.h>
+
+class ZLStringInputStream : public ZLInputStream {
+
+public:
+	ZLStringInputStream(const std::string &data);
+
+public:
+	bool open();
+	size_t read(char *buffer, size_t maxSize);
+	void close();
+
+	void seek(int offset, bool absoluteOffset);
+	size_t offset() const;
+	size_t sizeOfOpened();
+
+private:
+	std::string myData;
+	size_t myOffset;
+	// disable copy constructor:
+	ZLStringInputStream(const ZLStringInputStream&);
+	ZLStringInputStream& operator=(const ZLStringInputStream& );
+};
+
+#endif /* __ZLSTRINGINPUTSTREAM_H__ */
diff -uprN orig/fbreader-0.12.10/zlibrary/core/include/ZLZDecompressor.h fbreader-0.12.10/zlibrary/core/include/ZLZDecompressor.h
--- orig/fbreader-0.12.10/zlibrary/core/include/ZLZDecompressor.h	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/zlibrary/core/include/ZLZDecompressor.h	2011-04-05 22:55:30.000000000 +0200
@@ -29,7 +29,7 @@ class ZLInputStream;
 class ZLZDecompressor {
 
 public:
-	ZLZDecompressor(size_t size);
+	ZLZDecompressor(size_t size, bool useHeader = false);
 	~ZLZDecompressor();
 
 	size_t decompress(ZLInputStream &stream, char *buffer, size_t maxSize);
diff -uprN orig/fbreader-0.12.10/zlibrary/core/SOVERSION fbreader-0.12.10/zlibrary/core/SOVERSION
--- orig/fbreader-0.12.10/zlibrary/core/SOVERSION	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/zlibrary/core/SOVERSION	2011-04-05 22:55:30.000000000 +0200
@@ -1 +1 @@
-0.13
+0.14
diff -uprN orig/fbreader-0.12.10/zlibrary/core/src/application/ZLApplication.cpp fbreader-0.12.10/zlibrary/core/src/application/ZLApplication.cpp
--- orig/fbreader-0.12.10/zlibrary/core/src/application/ZLApplication.cpp	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/zlibrary/core/src/application/ZLApplication.cpp	2011-04-05 22:55:30.000000000 +0200
@@ -178,7 +178,7 @@ void ZLApplication::resetWindowCaption()
 		if ((currentView() == 0) || (currentView()->caption().empty())) {
 			myWindow->setCaption(ZLibrary::ApplicationName());
 		} else {
-			myWindow->setCaption(ZLibrary::ApplicationName() + " - " + currentView()->caption());
+			myWindow->setCaption(currentView()->caption() + " - " + ZLibrary::ApplicationName());
 		}
 	}
 }
diff -uprN orig/fbreader-0.12.10/zlibrary/core/src/filesystem/zip/ZLZDecompressor.cpp fbreader-0.12.10/zlibrary/core/src/filesystem/zip/ZLZDecompressor.cpp
--- orig/fbreader-0.12.10/zlibrary/core/src/filesystem/zip/ZLZDecompressor.cpp	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/zlibrary/core/src/filesystem/zip/ZLZDecompressor.cpp	2011-04-05 22:55:30.000000000 +0200
@@ -18,7 +18,7 @@
  */
 
 #include <string.h>
-
+#include <iostream>
 #include <algorithm>
 
 #include "../ZLInputStream.h"
@@ -27,10 +27,13 @@
 const size_t IN_BUFFER_SIZE = 2048;
 const size_t OUT_BUFFER_SIZE = 32768;
 
-ZLZDecompressor::ZLZDecompressor(size_t size) : myAvailableSize(size) {
+ZLZDecompressor::ZLZDecompressor(size_t size, bool useHeader) : myAvailableSize(size) {
 	myZStream = new z_stream;
 	memset(myZStream, 0, sizeof(z_stream));
-	inflateInit2(myZStream, -MAX_WBITS);
+	if(useHeader)
+		inflateInit2(myZStream, MAX_WBITS);
+	else
+		inflateInit2(myZStream, -MAX_WBITS);
 
 	myInBuffer = new char[IN_BUFFER_SIZE];
 	myOutBuffer = new char[OUT_BUFFER_SIZE];
@@ -50,6 +53,11 @@ size_t ZLZDecompressor::decompress(ZLInp
 
 		myZStream->next_in = (Bytef*)myInBuffer;
 		myZStream->avail_in = stream.read(myInBuffer, size);
+		/*std::cerr << "ZLZDecompressor source: ";
+		for(int i= 0; i < myZStream->avail_in; ++i) {
+			std::cerr << ' ' << std::hex << (unsigned) (unsigned char) myInBuffer[i];
+		}
+		std::cerr << std::dec << std::endl;*/
 		if (myZStream->avail_in == size) {
 			myAvailableSize -= size;
 		} else {
diff -uprN orig/fbreader-0.12.10/zlibrary/core/src/filesystem/zip/ZLZDecompressor.h fbreader-0.12.10/zlibrary/core/src/filesystem/zip/ZLZDecompressor.h
--- orig/fbreader-0.12.10/zlibrary/core/src/filesystem/zip/ZLZDecompressor.h	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/zlibrary/core/src/filesystem/zip/ZLZDecompressor.h	2011-04-05 22:55:30.000000000 +0200
@@ -29,7 +29,7 @@ class ZLInputStream;
 class ZLZDecompressor {
 
 public:
-	ZLZDecompressor(size_t size);
+	ZLZDecompressor(size_t size, bool useHeader = false);
 	~ZLZDecompressor();
 
 	size_t decompress(ZLInputStream &stream, char *buffer, size_t maxSize);
diff -uprN orig/fbreader-0.12.10/zlibrary/core/src/filesystem/ZLStringInputStream.cpp fbreader-0.12.10/zlibrary/core/src/filesystem/ZLStringInputStream.cpp
--- orig/fbreader-0.12.10/zlibrary/core/src/filesystem/ZLStringInputStream.cpp	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/zlibrary/core/src/filesystem/ZLStringInputStream.cpp	2011-04-05 22:55:30.000000000 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2008-2010 Geometer Plus <contact@geometerplus.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <string.h>
+#include <algorithm>
+
+#include "ZLStringInputStream.h"
+
+ZLStringInputStream::ZLStringInputStream(const std::string &data) : myData(data), myOffset(0) {
+}
+
+bool ZLStringInputStream::open() {
+	myOffset = 0;
+	return true;
+}
+
+size_t ZLStringInputStream::read(char *buffer, size_t maxSize) {
+	size_t size = std::min(maxSize, myData.length() - myOffset);
+	memcpy(buffer, myData.data() + myOffset, size);
+	myOffset += size;
+	return size;
+}
+
+void ZLStringInputStream::close() {
+}
+
+void ZLStringInputStream::seek(int offset, bool absoluteOffset) {
+	if (!absoluteOffset) {
+		offset += myOffset;
+	}
+	myOffset = std::min((size_t)std::max(0, offset), myData.length());
+}
+
+size_t ZLStringInputStream::offset() const {
+	return myOffset;
+}
+
+size_t ZLStringInputStream::sizeOfOpened() {
+	return myData.length();
+}
diff -uprN orig/fbreader-0.12.10/zlibrary/core/src/filesystem/ZLStringInputStream.h fbreader-0.12.10/zlibrary/core/src/filesystem/ZLStringInputStream.h
--- orig/fbreader-0.12.10/zlibrary/core/src/filesystem/ZLStringInputStream.h	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/zlibrary/core/src/filesystem/ZLStringInputStream.h	2011-04-05 22:55:30.000000000 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2008-2010 Geometer Plus <contact@geometerplus.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ZLSTRINGINPUTSTREAM_H__
+#define __ZLSTRINGINPUTSTREAM_H__
+
+#include <ZLInputStream.h>
+
+class ZLStringInputStream : public ZLInputStream {
+
+public:
+	ZLStringInputStream(const std::string &data);
+
+public:
+	bool open();
+	size_t read(char *buffer, size_t maxSize);
+	void close();
+
+	void seek(int offset, bool absoluteOffset);
+	size_t offset() const;
+	size_t sizeOfOpened();
+
+private:
+	std::string myData;
+	size_t myOffset;
+	// disable copy constructor:
+	ZLStringInputStream(const ZLStringInputStream&);
+	ZLStringInputStream& operator=(const ZLStringInputStream& );
+};
+
+#endif /* __ZLSTRINGINPUTSTREAM_H__ */
diff -uprN orig/fbreader-0.12.10/zlibrary/text/src/area/ZLTextArea_drawTextLine.cpp fbreader-0.12.10/zlibrary/text/src/area/ZLTextArea_drawTextLine.cpp
--- orig/fbreader-0.12.10/zlibrary/text/src/area/ZLTextArea_drawTextLine.cpp	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/zlibrary/text/src/area/ZLTextArea_drawTextLine.cpp	2011-12-30 01:08:34.929303385 +0100
@@ -188,7 +188,7 @@ void ZLTextArea::drawTextLine(Style &sty
 				context().drawImage(
 					hOffset() + wx, vOffset() + wy,
 					*((const ZLTextImageElement&)element).image(),
-					width(), height(), ZLPaintContext::SCALE_REDUCE_SIZE
+					width() - wx, height(), ZLPaintContext::SCALE_REDUCE_SIZE
 				);
 			}
 		}
diff -uprN orig/fbreader-0.12.10/zlibrary/ui/Makefile fbreader-0.12.10/zlibrary/ui/Makefile
--- orig/fbreader-0.12.10/zlibrary/ui/Makefile	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/zlibrary/ui/Makefile	2011-04-05 22:55:29.000000000 +0200
@@ -71,8 +71,8 @@ ifeq "<$(UI_TYPE)>" "$(findstring <$(UI_
 endif
 
 ifeq "$(UI_TYPE)" "maemo5"
-  #GTKSUBDIRS = src/gtk/time src/maemo5/dialogs src/maemo5/optionView src/maemo/view src/gtk/image src/gtk/util src/maemo5/application src/maemo/library src/gtk/filesystem src/maemo/message src/gtk/pixbuf
-  GTKSUBDIRS = src/gtk/time src/maemo/dialogs src/maemo/optionView src/maemo/view src/gtk/image src/gtk/util src/maemo/application src/maemo/library src/gtk/filesystem src/maemo/message src/gtk/pixbuf
+  GTKSUBDIRS = src/gtk/time src/maemo5/dialogs src/maemo5/optionView src/maemo/view src/gtk/image src/gtk/util src/maemo5/application src/maemo/library src/gtk/filesystem src/maemo/message src/gtk/pixbuf
+  #GTKSUBDIRS = src/gtk/time src/maemo/dialogs src/maemo/optionView src/maemo/view src/gtk/image src/gtk/util src/maemo/application src/maemo/library src/gtk/filesystem src/maemo/message src/gtk/pixbuf
 endif
 
 ifeq "<$(UI_TYPE)>" "$(findstring <$(UI_TYPE)>, <maemo3> <maemo4> <maemo5>)"
diff -uprN orig/fbreader-0.12.10/zlibrary/ui/src/gtk/application-desktop/ZLGtkApplicationWindow.cpp fbreader-0.12.10/zlibrary/ui/src/gtk/application-desktop/ZLGtkApplicationWindow.cpp
--- orig/fbreader-0.12.10/zlibrary/ui/src/gtk/application-desktop/ZLGtkApplicationWindow.cpp	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/zlibrary/ui/src/gtk/application-desktop/ZLGtkApplicationWindow.cpp	2011-04-05 22:55:29.000000000 +0200
@@ -48,6 +48,10 @@ static void handleScrollEvent(GtkWidget*
 	data->handleScrollEventSlot(event);
 }
 
+static gboolean handle_window_state_change(GtkWidget *widget, GdkEventWindowState* event, gpointer user_data) {
+	return ((ZLGtkApplicationWindow*)user_data)->handleWindowStateChange(event);
+}
+
 ZLGtkApplicationWindow::ZLGtkApplicationWindow(ZLApplication *application) :
 	ZLDesktopApplicationWindow(application),
 	myViewWidget(0),
@@ -81,6 +85,7 @@ ZLGtkApplicationWindow::ZLGtkApplication
 
 	ZLGtkSignalUtil::connectSignal(GTK_OBJECT(myMainWindow), "key_press_event", G_CALLBACK(handleKeyEvent), this);
 	ZLGtkSignalUtil::connectSignal(GTK_OBJECT(myMainWindow), "scroll_event", G_CALLBACK(handleScrollEvent), this);
+	ZLGtkSignalUtil::connectSignal(GTK_OBJECT(myMainWindow), "window-state-event", G_CALLBACK(handle_window_state_change), this);
 }
 
 void ZLGtkApplicationWindow::init() {
@@ -157,6 +162,27 @@ void ZLGtkApplicationWindow::onGtkButton
 	}
 }
 
+bool ZLGtkApplicationWindow::handleWindowStateChange(GdkEventWindowState* state) {
+	if(state->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
+		bool myFullScreen = (state->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) != 0; 
+		if(myFullScreen) {
+			gtk_widget_hide(myWindowToolbar.toolbarWidget());
+			if (myHandleBox != 0) {
+				gtk_widget_show_all(GTK_WIDGET(myHandleBox));
+			}
+		} else {
+			if (myHandleBox != 0) {
+				gtk_widget_hide(GTK_WIDGET(myHandleBox));
+			}
+			gtk_widget_show(myWindowToolbar.toolbarWidget());
+			if ((state->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) == 0) {
+				// FIXME what is that supposed to do? setPosition();
+			}
+		}
+	}
+	return false;
+}
+
 void ZLGtkApplicationWindow::setFullscreen(bool fullscreen) {
 	if (fullscreen == isFullscreen()) {
 		return;
@@ -164,23 +190,12 @@ void ZLGtkApplicationWindow::setFullscre
 
 	GdkWindowState state = gdk_window_get_state(GTK_WIDGET(myMainWindow)->window);
 	if (fullscreen) {
-		if ((state & GDK_WINDOW_STATE_MAXIMIZED) == 0) {
+		/*if ((state & GDK_WINDOW_STATE_MAXIMIZED) == 0) {
 			readPosition();
-		}
+		} FIXME */
 		gtk_window_fullscreen(myMainWindow);
-		gtk_widget_hide(myWindowToolbar.toolbarWidget());
-		if (myHandleBox != 0) {
-			gtk_widget_show_all(GTK_WIDGET(myHandleBox));
-		}
 	} else {
 		gtk_window_unfullscreen(myMainWindow);
-		if (myHandleBox != 0) {
-			gtk_widget_hide(GTK_WIDGET(myHandleBox));
-		}
-		gtk_widget_show(myWindowToolbar.toolbarWidget());
-		if ((state & GDK_WINDOW_STATE_MAXIMIZED) == 0) {
-			setPosition();
-		}
 	}
 
 	gtk_widget_queue_resize(GTK_WIDGET(myMainWindow));
diff -uprN orig/fbreader-0.12.10/zlibrary/ui/src/gtk/application-desktop/ZLGtkApplicationWindow.h fbreader-0.12.10/zlibrary/ui/src/gtk/application-desktop/ZLGtkApplicationWindow.h
--- orig/fbreader-0.12.10/zlibrary/ui/src/gtk/application-desktop/ZLGtkApplicationWindow.h	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/zlibrary/ui/src/gtk/application-desktop/ZLGtkApplicationWindow.h	2011-04-05 22:55:29.000000000 +0200
@@ -67,6 +67,7 @@ private:
 
 public:
 	bool handleKeyEventSlot(GdkEventKey *event);
+	bool handleWindowStateChange(GdkEventWindowState *state);
 	void handleScrollEventSlot(GdkEventScroll *event);
 	void onGtkButtonPress(GtkToolItem *gtkButton);
 
diff -uprN orig/fbreader-0.12.10/zlibrary/ui/src/gtk/application-iliad/ZLGtkApplicationWindow.cpp fbreader-0.12.10/zlibrary/ui/src/gtk/application-iliad/ZLGtkApplicationWindow.cpp
--- orig/fbreader-0.12.10/zlibrary/ui/src/gtk/application-iliad/ZLGtkApplicationWindow.cpp	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/zlibrary/ui/src/gtk/application-iliad/ZLGtkApplicationWindow.cpp	2011-04-05 22:55:29.000000000 +0200
@@ -48,6 +48,10 @@ static void handleScrollEvent(GtkWidget*
 	data->handleScrollEventSlot(event);
 }
 
+static gboolean handle_window_state_change(GtkWidget *widget, GdkEventWindowState* event, gpointer user_data) {
+	return ((ZLGtkApplicationWindow*)user_data)->handleWindowStateChange(event);
+}
+
 ZLGtkApplicationWindow::ZLGtkApplicationWindow(ZLApplication *application) :
 	ZLDesktopApplicationWindow(application),
 	myViewWidget(0),
@@ -81,6 +85,7 @@ ZLGtkApplicationWindow::ZLGtkApplication
 
 	ZLGtkSignalUtil::connectSignal(GTK_OBJECT(myMainWindow), "key_press_event", G_CALLBACK(handleKeyEvent), this);
 	ZLGtkSignalUtil::connectSignal(GTK_OBJECT(myMainWindow), "scroll_event", G_CALLBACK(handleScrollEvent), this);
+	ZLGtkSignalUtil::connectSignal(GTK_OBJECT(myMainWindow), "window-state-event", G_CALLBACK(handle_window_state_change), this);
 }
 
 void ZLGtkApplicationWindow::init() {
@@ -157,6 +162,27 @@ void ZLGtkApplicationWindow::onGtkButton
 	}
 }
 
+bool ZLGtkApplicationWindow::handleWindowStateChange(GdkEventWindowState* state) {
+	if(state->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
+		bool myFullScreen = (state->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) != 0; 
+		if(myFullScreen) {
+			gtk_widget_hide(myWindowToolbar.toolbarWidget());
+			if (myHandleBox != 0) {
+				gtk_widget_show_all(GTK_WIDGET(myHandleBox));
+			}
+		} else {
+			if (myHandleBox != 0) {
+				gtk_widget_hide(GTK_WIDGET(myHandleBox));
+			}
+			gtk_widget_show(myWindowToolbar.toolbarWidget());
+			if ((state->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) == 0) {
+				// FIXME what is that supposed to do? setPosition();
+			}
+		}
+	}
+	return false;
+}
+
 void ZLGtkApplicationWindow::setFullscreen(bool fullscreen) {
 	if (fullscreen == isFullscreen()) {
 		return;
@@ -164,23 +190,12 @@ void ZLGtkApplicationWindow::setFullscre
 
 	GdkWindowState state = gdk_window_get_state(GTK_WIDGET(myMainWindow)->window);
 	if (fullscreen) {
-		if ((state & GDK_WINDOW_STATE_MAXIMIZED) == 0) {
+		/*if ((state & GDK_WINDOW_STATE_MAXIMIZED) == 0) {
 			readPosition();
-		}
+		} FIXME */
 		gtk_window_fullscreen(myMainWindow);
-		gtk_widget_hide(myWindowToolbar.toolbarWidget());
-		if (myHandleBox != 0) {
-			gtk_widget_show_all(GTK_WIDGET(myHandleBox));
-		}
 	} else {
 		gtk_window_unfullscreen(myMainWindow);
-		if (myHandleBox != 0) {
-			gtk_widget_hide(GTK_WIDGET(myHandleBox));
-		}
-		gtk_widget_show(myWindowToolbar.toolbarWidget());
-		if ((state & GDK_WINDOW_STATE_MAXIMIZED) == 0) {
-			setPosition();
-		}
 	}
 
 	gtk_widget_queue_resize(GTK_WIDGET(myMainWindow));
diff -uprN orig/fbreader-0.12.10/zlibrary/ui/src/gtk/application-iliad/ZLGtkApplicationWindow.h fbreader-0.12.10/zlibrary/ui/src/gtk/application-iliad/ZLGtkApplicationWindow.h
--- orig/fbreader-0.12.10/zlibrary/ui/src/gtk/application-iliad/ZLGtkApplicationWindow.h	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/zlibrary/ui/src/gtk/application-iliad/ZLGtkApplicationWindow.h	2011-04-05 22:55:29.000000000 +0200
@@ -67,6 +67,7 @@ private:
 
 public:
 	bool handleKeyEventSlot(GdkEventKey *event);
+	bool handleWindowStateChange(GdkEventWindowState *state);
 	void handleScrollEventSlot(GdkEventScroll *event);
 	void onGtkButtonPress(GtkToolItem *gtkButton);
 
diff -uprN orig/fbreader-0.12.10/zlibrary/ui/src/gtk/application-pepperpad3/ZLGtkApplicationWindow.cpp fbreader-0.12.10/zlibrary/ui/src/gtk/application-pepperpad3/ZLGtkApplicationWindow.cpp
--- orig/fbreader-0.12.10/zlibrary/ui/src/gtk/application-pepperpad3/ZLGtkApplicationWindow.cpp	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/zlibrary/ui/src/gtk/application-pepperpad3/ZLGtkApplicationWindow.cpp	2011-04-05 22:55:29.000000000 +0200
@@ -48,6 +48,10 @@ static void handleScrollEvent(GtkWidget*
 	data->handleScrollEventSlot(event);
 }
 
+static gboolean handle_window_state_change(GtkWidget *widget, GdkEventWindowState* event, gpointer user_data) {
+	return ((ZLGtkApplicationWindow*)user_data)->handleWindowStateChange(event);
+}
+
 ZLGtkApplicationWindow::ZLGtkApplicationWindow(ZLApplication *application) :
 	ZLDesktopApplicationWindow(application),
 	myViewWidget(0),
@@ -81,6 +85,7 @@ ZLGtkApplicationWindow::ZLGtkApplication
 
 	ZLGtkSignalUtil::connectSignal(GTK_OBJECT(myMainWindow), "key_press_event", G_CALLBACK(handleKeyEvent), this);
 	ZLGtkSignalUtil::connectSignal(GTK_OBJECT(myMainWindow), "scroll_event", G_CALLBACK(handleScrollEvent), this);
+	ZLGtkSignalUtil::connectSignal(GTK_OBJECT(myMainWindow), "window-state-event", G_CALLBACK(handle_window_state_change), this);
 }
 
 void ZLGtkApplicationWindow::init() {
@@ -157,6 +162,27 @@ void ZLGtkApplicationWindow::onGtkButton
 	}
 }
 
+bool ZLGtkApplicationWindow::handleWindowStateChange(GdkEventWindowState* state) {
+	if(state->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
+		bool myFullScreen = (state->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) != 0; 
+		if(myFullScreen) {
+			gtk_widget_hide(myWindowToolbar.toolbarWidget());
+			if (myHandleBox != 0) {
+				gtk_widget_show_all(GTK_WIDGET(myHandleBox));
+			}
+		} else {
+			if (myHandleBox != 0) {
+				gtk_widget_hide(GTK_WIDGET(myHandleBox));
+			}
+			gtk_widget_show(myWindowToolbar.toolbarWidget());
+			if ((state->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) == 0) {
+				// FIXME what is that supposed to do? setPosition();
+			}
+		}
+	}
+	return false;
+}
+
 void ZLGtkApplicationWindow::setFullscreen(bool fullscreen) {
 	if (fullscreen == isFullscreen()) {
 		return;
@@ -164,23 +190,12 @@ void ZLGtkApplicationWindow::setFullscre
 
 	GdkWindowState state = gdk_window_get_state(GTK_WIDGET(myMainWindow)->window);
 	if (fullscreen) {
-		if ((state & GDK_WINDOW_STATE_MAXIMIZED) == 0) {
+		/*if ((state & GDK_WINDOW_STATE_MAXIMIZED) == 0) {
 			readPosition();
-		}
+		} FIXME */
 		gtk_window_fullscreen(myMainWindow);
-		gtk_widget_hide(myWindowToolbar.toolbarWidget());
-		if (myHandleBox != 0) {
-			gtk_widget_show_all(GTK_WIDGET(myHandleBox));
-		}
 	} else {
 		gtk_window_unfullscreen(myMainWindow);
-		if (myHandleBox != 0) {
-			gtk_widget_hide(GTK_WIDGET(myHandleBox));
-		}
-		gtk_widget_show(myWindowToolbar.toolbarWidget());
-		if ((state & GDK_WINDOW_STATE_MAXIMIZED) == 0) {
-			setPosition();
-		}
 	}
 
 	gtk_widget_queue_resize(GTK_WIDGET(myMainWindow));
diff -uprN orig/fbreader-0.12.10/zlibrary/ui/src/gtk/application-pepperpad3/ZLGtkApplicationWindow.h fbreader-0.12.10/zlibrary/ui/src/gtk/application-pepperpad3/ZLGtkApplicationWindow.h
--- orig/fbreader-0.12.10/zlibrary/ui/src/gtk/application-pepperpad3/ZLGtkApplicationWindow.h	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/zlibrary/ui/src/gtk/application-pepperpad3/ZLGtkApplicationWindow.h	2011-04-05 22:55:29.000000000 +0200
@@ -67,6 +67,7 @@ private:
 
 public:
 	bool handleKeyEventSlot(GdkEventKey *event);
+	bool handleWindowStateChange(GdkEventWindowState *state);
 	void handleScrollEventSlot(GdkEventScroll *event);
 	void onGtkButtonPress(GtkToolItem *gtkButton);
 
diff -uprN orig/fbreader-0.12.10/zlibrary/ui/src/maemo5/application/he-fullscreen-button.c fbreader-0.12.10/zlibrary/ui/src/maemo5/application/he-fullscreen-button.c
--- orig/fbreader-0.12.10/zlibrary/ui/src/maemo5/application/he-fullscreen-button.c	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/zlibrary/ui/src/maemo5/application/he-fullscreen-button.c	2011-04-05 22:55:29.000000000 +0200
@@ -0,0 +1,745 @@
+/*
+ * This file is a part of hildon-extras
+ *
+ * Copyright (C) 2009 Cornelius Hald <hald@icandy.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; version 2 of the license.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser Public License for more details.
+ */
+
+
+/**
+ * SECTION:he-fullscreen-button
+ * @short_description: A semi-transparent button to leave fullscreen mode.
+ *
+ * #HeFullscreenButton is a semi transparent button which is automatically
+ * displayed whenever it's parent window enters fullscreen state.
+ * It's always displayed in the lower right corner of the parent window.
+ *
+ * The button is automatically hidden after 5 seconds of mouse click
+ * inactivity. If the user clicks the parent window the button is shown
+ * for another 5 second.
+ *
+ * If the user clicks the button, the "clicked" signal is emitted. If you did
+ * not provide a signal handler for the "clicked" signal, then the default
+ * handler will call gtk_window_unfullscreen() on the parent window.
+ * If you provide a signal handler, the default handler will not be called
+ * at all.
+ *
+ * So, if your application has just one window. It will be enough, if you create
+ * an instance of HeFullscreenButton with this window as parent. Now if your
+ * window switches to fullscreen the HeFullscreenButton is automatically shown
+ * and can be used to leave fullscreen mode. In this case you don't have to provide
+ * a signal handler and you don't have to take care of the buttons destruction.
+ */
+
+#include <gtk/gtk.h>
+#include <hildon/hildon.h>
+#include <string.h>
+#include "he-fullscreen-button.h"
+
+#define FULLSCREEN_BUTTON_WIDTH          80
+#define FULLSCREEN_BUTTON_HEIGHT         70
+#define FULLSCREEN_BUTTON_HIDE_DELAY	 5000
+#define FULLSCREEN_BUTTON_CORNER_RADIUS  20
+#define FULLSCREEN_BUTTON_ICON           "general_fullsize"
+#define FULLSCREEN_BUTTON_ICON_SIZE      48
+#define OFFSET 0
+
+typedef struct				_HeFullscreenButtonPrivate HeFullscreenButtonPrivate;
+
+struct _HeFullscreenButtonPrivate
+{
+        gboolean     release_event;
+        guint32      last_event_time;
+
+        guint        button_press_signal_id;
+        guint        button_release_signal_id;
+
+        gulong       button_press_hook_id;
+        gulong       button_release_hook_id;
+
+        gboolean     act_on_state_change;
+
+        GtkWidget   *overlay;
+};
+
+#define						HE_FULLSCREEN_BUTTON_GET_PRIVATE(object) \
+							(G_TYPE_INSTANCE_GET_PRIVATE((object), \
+							HE_TYPE_FULLSCREEN_BUTTON, HeFullscreenButtonPrivate))
+
+G_DEFINE_TYPE(HeFullscreenButton, he_fullscreen_button, G_TYPE_OBJECT)
+
+
+/**
+ * Hides the fullscreen button.
+ */
+static void
+fullscreen_button_hide (HeFullscreenButton *self)
+{
+    g_return_if_fail (HE_IS_FULLSCREEN_BUTTON (self));
+
+    HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
+    g_return_if_fail (priv != NULL);
+
+    /* Reset timer */
+    g_source_remove_by_user_data ((gpointer) self);
+
+    if (priv->overlay != NULL && GTK_IS_WIDGET (priv->overlay)) {
+    	gtk_widget_hide (priv->overlay);
+    }
+}
+
+
+/**
+ * Changes the position of the fullscreen button.
+ */
+static void
+fullscreen_button_set_position (HeFullscreenButton *self)
+{
+	GtkWidget *parent = GTK_WIDGET (self->parent_window);
+	GtkWidget *overlay = NULL;
+
+	HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
+	g_return_if_fail (priv != NULL);
+
+	overlay = GTK_WIDGET (priv->overlay);
+
+	/* For some reason I have to call hide/show to make it appear at the new position */
+	gint x = parent->allocation.width - overlay->allocation.width;
+	gint y = parent->allocation.height - overlay->allocation.height - OFFSET;
+
+	gtk_widget_hide (overlay);
+	gtk_window_move (GTK_WINDOW (overlay), x, y);
+	gtk_widget_show (overlay);
+}
+
+
+/**
+ * Everytime the timer runs out, we hide the fullscreen button.
+ */
+static gboolean
+fullscreen_button_on_hide_timer (gpointer data)
+{
+    g_return_val_if_fail (data != NULL, FALSE);
+    fullscreen_button_hide (HE_FULLSCREEN_BUTTON (data));
+    return FALSE;
+}
+
+
+/**
+ * Shows the full screen button.
+ */
+static void
+fullscreen_button_show (HeFullscreenButton *self)
+{
+    g_return_if_fail (self != NULL);
+
+    HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
+    g_return_if_fail (priv != NULL);
+
+    g_return_if_fail (GTK_IS_WIDGET (priv->overlay));
+
+    /* Stop return button hide timeout */
+    g_source_remove_by_user_data ((gpointer) self);
+
+    /* Only show overlay if we come here through a button release event, not a button press event */
+    if (priv->release_event) {
+
+    	fullscreen_button_set_position (self);
+    	gtk_widget_show (priv->overlay);
+
+        /* Set the return button hide timeout */
+        g_timeout_add (FULLSCREEN_BUTTON_HIDE_DELAY,
+        		fullscreen_button_on_hide_timer, (gpointer) self);
+    }
+}
+
+
+/**
+ * This hook function is called for each mouse button press or
+ * button release on the parent window.
+ */
+static gboolean
+fullscreen_button_input_activity_hook (GSignalInvocationHint *ihint G_GNUC_UNUSED,
+                                       guint n_param_values,
+                                       const GValue *param_values,
+                                       gpointer data)
+{
+    HeFullscreenButton *self = HE_FULLSCREEN_BUTTON (data);
+    g_return_val_if_fail (self, FALSE);
+
+    HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
+    g_return_val_if_fail (priv != NULL, FALSE);
+
+    GdkEventAny *event = NULL;
+
+    if (n_param_values >= 2)
+        event = (GdkEventAny*) g_value_peek_pointer (&(param_values[1]));
+
+    g_return_val_if_fail (event, TRUE);
+
+    guint32 time = 0;
+    switch (event->type) {
+        case GDK_BUTTON_PRESS:
+        case GDK_BUTTON_RELEASE:
+            time = ((GdkEventButton*) event)->time;
+            break;
+        case GDK_KEY_PRESS:
+        case GDK_KEY_RELEASE:
+            time = ((GdkEventKey*) event)->time;
+            break;
+        default:
+            /* Filter out unexpected messages */
+            return TRUE;
+    }
+
+    /* We're likely to get events multiple times as they're propagated, so
+       filter out events that we've already seen. */
+    if (time == priv->last_event_time) {
+        return TRUE;
+    }
+    priv->last_event_time = time;
+
+    if (event && (event->type == GDK_BUTTON_PRESS)) {
+        priv->release_event = FALSE;
+    } else {
+        priv->release_event = TRUE;
+    }
+
+    fullscreen_button_show (self);
+
+    return TRUE;
+}
+
+
+/**
+ * This function makes the full screen button visible and hooks mouse and
+ * key event signal emissions. The button is hidden after some time and
+ * is reshown when ever one of the signal hooks are activated.
+ *
+ * Note: The button may be shown automatically by itself
+ * if you have not set the act_on_state_change property to
+ * FALSE.
+ *
+ * @param self A HeFullscreenButton instance.
+ */
+void
+he_fullscreen_button_enable (HeFullscreenButton *self)
+{
+    g_return_if_fail(HE_IS_FULLSCREEN_BUTTON(self));
+
+    HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
+    g_return_if_fail (priv != NULL);
+
+    if (priv->button_press_hook_id == 0) {
+        priv->button_press_signal_id =
+        	g_signal_lookup ("button-press-event", GTK_TYPE_WIDGET);
+        priv->button_press_hook_id =
+            g_signal_add_emission_hook (priv->button_press_signal_id, 0,
+            		fullscreen_button_input_activity_hook,
+            		(gpointer) self, NULL);
+    }
+
+    if (priv->button_release_hook_id == 0) {
+        priv->button_release_signal_id =
+        	g_signal_lookup ("button-release-event", GTK_TYPE_WIDGET);
+        priv->button_release_hook_id =
+            g_signal_add_emission_hook (priv->button_release_signal_id, 0,
+            		fullscreen_button_input_activity_hook,
+            		(gpointer) self, NULL);
+    }
+
+    fullscreen_button_show(self);
+}
+
+
+/**
+ * Hides the full screen button and releases mouse and
+ * key event signal emission hooks.
+ *
+ * Note: The button may be hidden automatically by itself
+ * if you have not set the act_on_state_change property to
+ * FALSE.
+ *
+ * @param self A HeFullscreenButton instance.
+ */
+void
+he_fullscreen_button_disable (HeFullscreenButton *self)
+{
+    g_return_if_fail (HE_IS_FULLSCREEN_BUTTON (self));
+
+    HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
+    g_return_if_fail (priv != NULL);
+
+    fullscreen_button_hide (self);
+
+    if (priv->button_release_hook_id > 0) {
+        g_signal_remove_emission_hook (priv->button_release_signal_id,
+                                       priv->button_release_hook_id);
+        priv->button_release_hook_id = 0;
+    }
+
+    if (priv->button_press_hook_id > 0) {
+        g_signal_remove_emission_hook (priv->button_press_signal_id,
+                                       priv->button_press_hook_id);
+        priv->button_press_hook_id = 0;
+    }
+}
+
+
+/**
+ * Everytime the button is clicked, be emmit the "clicked" signal.
+ */
+static gboolean
+fullscreen_button_on_clicked (GtkWidget *widget, GdkEventButton *event G_GNUC_UNUSED, gpointer data)
+{
+	HeFullscreenButton *self = HE_FULLSCREEN_BUTTON (data);
+	g_signal_emit_by_name (self, "clicked");
+
+	return TRUE;
+}
+
+
+/**
+ * Creates a rectangle with a rounded upper left corner.
+ */
+static void
+fullscreen_button_create_rectangle (cairo_t *ctx, double x, double y, double w, double h, double r)
+{
+	cairo_move_to(ctx, x+r, y);
+	cairo_line_to(ctx, x+w, y);
+	cairo_line_to(ctx, x+w, y+h);
+	cairo_line_to(ctx, x,   y+h);
+	cairo_line_to(ctx, x,   y+r);
+
+	/* Left upper corner is rounded */
+	cairo_curve_to(ctx, x, y, x, y, x+r, y);
+}
+
+
+/**
+ * Does the actuall drawing of the semi transparent button graphic.
+ */
+static gboolean
+fullscreen_button_on_expose_event (GtkWidget *widget, GdkEventExpose *event G_GNUC_UNUSED, gpointer data)
+{
+    cairo_t *ctx;
+    GdkPixbuf *pixbuf = GDK_PIXBUF (data);
+
+    /* Create context */
+    ctx = gdk_cairo_create (widget->window);
+
+    /* Clear surface */
+    cairo_set_operator (ctx, CAIRO_OPERATOR_CLEAR);
+    cairo_paint (ctx);
+
+    /* Add rectangle */
+    cairo_set_operator (ctx, CAIRO_OPERATOR_OVER);
+    cairo_set_source_rgba (ctx, 0, 0, 0, 0.60);
+    fullscreen_button_create_rectangle (ctx, 0, 0, FULLSCREEN_BUTTON_WIDTH, FULLSCREEN_BUTTON_HEIGHT, FULLSCREEN_BUTTON_CORNER_RADIUS);
+    cairo_fill (ctx);
+
+    /* Add icon */
+    gdk_cairo_set_source_pixbuf (ctx, pixbuf, 15, 10);
+    cairo_paint (ctx);
+
+    /* Destroy context */
+    cairo_destroy (ctx);
+    return TRUE;
+}
+
+
+/**
+ * Creates the semi transparent button graphic.
+ */
+static GtkWidget*
+fullscreen_button_create_gfx (HeFullscreenButton *self)
+{
+    g_return_val_if_fail(HE_IS_FULLSCREEN_BUTTON(self), NULL);
+
+    GdkPixbuf *pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), FULLSCREEN_BUTTON_ICON, FULLSCREEN_BUTTON_ICON_SIZE, 0, NULL);
+    GtkWidget *img = gtk_image_new_from_pixbuf (pixbuf);
+    gtk_widget_show (img);
+    g_object_unref (pixbuf);
+    g_signal_connect (img, "expose_event", G_CALLBACK (fullscreen_button_on_expose_event), pixbuf);
+
+    GtkWidget *box = gtk_event_box_new ();
+    gtk_event_box_set_visible_window (GTK_EVENT_BOX(box), FALSE);
+    gtk_widget_show (box);
+    gtk_container_add (GTK_CONTAINER(box), img);
+    g_signal_connect (box, "button-release-event", G_CALLBACK (fullscreen_button_on_clicked), self);
+
+    GtkWidget *overlay = gtk_window_new (GTK_WINDOW_POPUP);
+    gtk_window_set_decorated (GTK_WINDOW (overlay), FALSE);
+    gtk_widget_set_size_request (overlay, FULLSCREEN_BUTTON_WIDTH, FULLSCREEN_BUTTON_HEIGHT);
+    gtk_window_set_resizable (GTK_WINDOW (overlay), FALSE);
+    gtk_window_set_transient_for (GTK_WINDOW (overlay), self->parent_window);
+    gtk_window_set_destroy_with_parent (GTK_WINDOW (overlay), TRUE);
+    gtk_container_add (GTK_CONTAINER (overlay), box);
+
+    GdkScreen *screen = gtk_widget_get_screen (overlay);
+    gtk_widget_set_colormap (overlay, gdk_screen_get_rgba_colormap (screen));
+
+    gtk_widget_realize (overlay);
+
+    return overlay;
+}
+
+/**
+ * Called when the parent_window's is on the screen/not on the screen.
+ * Only called if parent_window is a HildonWindow (or derived from it).
+ *
+ * We check if the window is on the screen or not on the screen.
+ * If it is, and the window is in fullscreen mode, we enable the fullscreen button. If not, we disable the button.
+ */
+static void
+fullscreen_button_on_is_topmost_changed (GObject *object G_GNUC_UNUSED,
+		                                 GParamSpec *property G_GNUC_UNUSED,
+		                                 gpointer data)
+{
+	HeFullscreenButton *self = HE_FULLSCREEN_BUTTON (data);
+
+	HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
+	g_return_if_fail (priv != NULL);
+
+	/* Only run if the "act-on-state-change" property is TRUE. */
+	if (!priv->act_on_state_change) {
+		return;
+	}
+
+	if (hildon_window_get_is_topmost (HILDON_WINDOW(self->parent_window))) {
+		if (gdk_window_get_state (GTK_WIDGET (self->parent_window)->window) & GDK_WINDOW_STATE_FULLSCREEN) {
+			he_fullscreen_button_enable (self);
+		}
+	}
+	else {
+		he_fullscreen_button_disable (self);
+	}
+}
+
+/**
+ * Called, whenever the state of the parents window's GdkWindow changes.
+ * We check if the new state is fullscreen or non-fullscreen.
+ * If it is fullscreen, we enable the fullscreen button. If not, not.
+ */
+static gboolean
+fullscreen_button_on_window_state_changed (GtkWidget *widget G_GNUC_UNUSED,
+		                                   GdkEventWindowState *event,
+		                                   gpointer data)
+{
+	HeFullscreenButton *self = HE_FULLSCREEN_BUTTON (data);
+
+	HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
+	g_return_val_if_fail (priv != NULL, FALSE);
+
+	/* Only run if the "act-on-state-change" property is TRUE. */
+	if (!priv->act_on_state_change) {
+		return FALSE;
+	}
+
+	/* Only run if this window is topmost. */
+	if (HILDON_IS_WINDOW (self->parent_window)) {
+		if (!hildon_window_get_is_topmost (HILDON_WINDOW(self->parent_window))) {
+			return FALSE;
+		}
+	}
+
+	if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
+
+		if (event->new_window_state == GDK_WINDOW_STATE_FULLSCREEN) {
+			he_fullscreen_button_enable (self);
+		} else {
+			he_fullscreen_button_disable (self);
+		}
+
+	}
+
+	return FALSE;
+}
+
+
+/**
+ * Destroys the fullscreen button and disconnects itself from the parent window.
+ */
+static void
+fullscreen_button_destroy (GtkWidget *parent_window G_GNUC_UNUSED, HeFullscreenButton *self)
+{
+	g_return_if_fail (self != NULL);
+
+	HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
+	g_return_if_fail (priv != NULL);
+
+	if (self->parent_window != NULL) {
+		g_signal_handlers_disconnect_by_func (self->parent_window, fullscreen_button_destroy, self);
+		g_signal_handlers_disconnect_by_func (self->parent_window, fullscreen_button_on_window_state_changed, self);
+		if (HILDON_IS_WINDOW(parent_window)) {
+			g_signal_handlers_disconnect_by_func (self->parent_window, fullscreen_button_on_is_topmost_changed, self);
+		}
+	}
+
+	he_fullscreen_button_disable (self);
+
+	if (priv->overlay != NULL && GTK_IS_WIDGET(priv->overlay)) {
+		gtk_widget_destroy (GTK_WIDGET(priv->overlay));
+		priv->overlay = NULL;
+	}
+}
+
+
+/**
+ * Called when the size allocation of the parent window changes.
+ * We change the position of the fullscreen button to always be in
+ * the lower right corner.
+ */
+static void
+fullscreen_button_on_parent_size_changed (GtkWidget     *widget,
+                                          GtkAllocation *allocation,
+                                          gpointer       user_data)
+{
+    g_return_if_fail (widget != NULL);
+    g_return_if_fail (allocation != NULL);
+
+    HeFullscreenButton *self = HE_FULLSCREEN_BUTTON(user_data);
+    g_return_if_fail (self != NULL);
+
+    HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
+    g_return_if_fail (priv != NULL);
+
+    GtkWidget *ui_win = GTK_WIDGET(priv->overlay);
+    g_return_if_fail (ui_win != NULL);
+
+    if (gdk_window_is_visible(priv->overlay->window)) {
+    	fullscreen_button_set_position(self);
+    }
+}
+
+
+/**
+ * Default handler for the "clicked" signal. If no user handler is
+ * defined we call gtk_window_unfullscreen() on the parent window.
+ * Otherwise only the user handler is executed.
+ */
+static void
+fullscreen_button_clicked_default_handler (HeFullscreenButton *self)
+{
+	guint signal_id = g_signal_lookup ("clicked", HE_TYPE_FULLSCREEN_BUTTON);
+	gulong handler_id = g_signal_handler_find (self, G_SIGNAL_MATCH_ID, signal_id, 0, NULL, NULL, NULL);
+
+	/* Run only, if no signal handler is connected */
+	if (handler_id == 0) {
+		GtkWindow *window = he_fullscreen_button_get_window (self);
+		gtk_window_unfullscreen (window);
+	}
+}
+
+/**
+ * Create new full screen button instance.
+ * This function attaches the full screen button to the given parent window.
+ * By default, the button automatically becomes visible if the parent window
+ * changes to fullscreen and vice versa. Change the "act-on-state-change" 
+ * property to modify this behaviour.
+ *
+ * If you destroy the parent window, this HeFullscreenButton instance get
+ * destroyed as well.
+ *
+ * Pass it a HildonWindow (or one of its deriatives) to ensure the widget disables/
+ * enables itself on focus-out/focus-in respectively. 
+ *
+ * @param parent_window A GtkWindow instance.
+ * @return New HeFullscreenButton instance.
+ */
+HeFullscreenButton *
+he_fullscreen_button_new (GtkWindow *parent_window)
+{
+	g_return_val_if_fail (parent_window != NULL, NULL);
+	g_return_val_if_fail (GTK_IS_WINDOW (parent_window), NULL);
+
+    HeFullscreenButton *self = g_object_new (HE_TYPE_FULLSCREEN_BUTTON, NULL);
+
+    HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
+    g_return_val_if_fail (priv != NULL, NULL);
+
+    self->parent_window = parent_window;
+    priv->overlay = fullscreen_button_create_gfx (self);
+
+    g_signal_connect (parent_window, "destroy",
+    		G_CALLBACK(fullscreen_button_destroy), self);
+
+    g_signal_connect (parent_window, "window-state-event",
+    		G_CALLBACK(fullscreen_button_on_window_state_changed), self);
+
+    g_signal_connect_after (parent_window, "size-allocate",
+    		G_CALLBACK(fullscreen_button_on_parent_size_changed), self);
+
+    if (HILDON_IS_WINDOW(parent_window)) {
+        g_signal_connect (parent_window, "notify::is-topmost",
+            G_CALLBACK(fullscreen_button_on_is_topmost_changed), self);
+    }
+
+    return self;
+}
+
+/**
+ * Returns the GtkWidget displaying the actual overlaid button.
+ *
+ * @param self An instance of HeFullscreenButton
+ * @return The GtkWidget of the overlaid button. This widget belongs to HeFullscreenButton and must not be destroyed or modified.
+ */
+GtkWidget *
+he_fullscreen_button_get_overlay (HeFullscreenButton *self)
+{
+    HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
+    g_return_val_if_fail (priv != NULL, NULL);
+
+    return priv->overlay;
+}
+
+/**
+ * Returns the GtkWindow that this HeFullscreenButton
+ * is attached to.
+ *
+ * @param self An instance of HeFullscreenButton
+ * @return The GtkWindow to which this button is attached to
+ */
+GtkWindow *
+he_fullscreen_button_get_window (HeFullscreenButton *self)
+{
+	return self->parent_window;
+}
+
+
+/*
+ * GObject stuff
+ */
+
+enum {
+	CLICKED,
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = {0};
+
+enum {
+    PROP_0,
+    PROP_ACT_ON_STATE_CHANGE
+};
+
+static void
+fullscreen_button_get_property (GObject *object, 
+                                guint property_id,
+                                GValue *value, 
+                                GParamSpec * pspec)
+{
+    HeFullscreenButton *self = HE_FULLSCREEN_BUTTON (object);
+    g_return_if_fail (self);
+
+    HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
+    g_return_if_fail (priv != NULL);
+
+    switch (property_id) {
+        case PROP_ACT_ON_STATE_CHANGE:
+            g_value_set_boolean (value, priv->act_on_state_change);
+            break;
+
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+            break;
+    }
+}
+
+static void
+fullscreen_button_set_property (GObject *object, 
+                                guint property_id,
+                                const GValue *value, 
+                                GParamSpec * pspec)
+{
+    HeFullscreenButton *self = HE_FULLSCREEN_BUTTON (object);
+    g_return_if_fail (self);
+
+    HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
+    g_return_if_fail (priv != NULL);
+
+    switch (property_id) {
+        case PROP_ACT_ON_STATE_CHANGE:
+            priv->act_on_state_change = g_value_get_boolean (value);
+            g_object_notify (G_OBJECT (object), "act-on-state-change");
+            break;
+
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+            break;
+    }
+}
+
+
+static void
+he_fullscreen_button_class_init (HeFullscreenButtonClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->get_property = fullscreen_button_get_property;
+	object_class->set_property = fullscreen_button_set_property;
+
+	klass->clicked = fullscreen_button_clicked_default_handler;
+
+	/**
+	 * HeFullscreenButton::clicked
+	 *
+	 * Emitted when the #HeFullscreenButton was clicked by the user.
+	 */
+	signals[CLICKED] =
+		g_signal_new(
+				"clicked",
+				HE_TYPE_FULLSCREEN_BUTTON,
+				G_SIGNAL_RUN_LAST,
+				G_STRUCT_OFFSET(HeFullscreenButtonClass, clicked),
+				NULL, NULL,
+				g_cclosure_marshal_VOID__VOID,
+				G_TYPE_NONE,
+				0);
+
+	g_object_class_install_property(
+				object_class, PROP_ACT_ON_STATE_CHANGE,
+				g_param_spec_boolean ("act-on-state-change",
+				"Act on window state changes",
+				"Whether to automatically enable/disable the button "
+				"when its parent window fullscreens/unfullscreens "
+				"itself.",
+				TRUE,
+				G_PARAM_READWRITE));
+
+	g_type_class_add_private (klass, sizeof (HeFullscreenButtonPrivate));
+}
+
+
+static void
+he_fullscreen_button_init (HeFullscreenButton *self)
+{
+    g_return_if_fail (self != NULL);
+
+    HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
+    g_return_if_fail (priv != NULL);
+
+    memset (priv, 0, sizeof (HeFullscreenButtonPrivate));
+
+    self->parent_window = NULL;
+    priv->overlay = NULL;
+    priv->release_event = TRUE;
+    priv->last_event_time = 0;
+
+    priv->act_on_state_change = TRUE;
+
+    priv->button_press_signal_id = 0;
+    priv->button_release_signal_id = 0;
+
+    priv->button_press_hook_id = 0;
+    priv->button_release_hook_id = 0;
+}
+
diff -uprN orig/fbreader-0.12.10/zlibrary/ui/src/maemo5/application/he-fullscreen-button.h fbreader-0.12.10/zlibrary/ui/src/maemo5/application/he-fullscreen-button.h
--- orig/fbreader-0.12.10/zlibrary/ui/src/maemo5/application/he-fullscreen-button.h	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/zlibrary/ui/src/maemo5/application/he-fullscreen-button.h	2011-04-05 22:55:29.000000000 +0200
@@ -0,0 +1,86 @@
+/*
+ * This file is a part of hildon-extras
+ *
+ * Copyright (C) 2009 Cornelius Hald <hald@icandy.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; version 2 of the license.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser Public License for more details.
+ */
+
+#ifndef _HE_FULLSCREEN_BUTTON_
+#define _HE_FULLSCREEN_BUTTON_
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define						HE_TYPE_FULLSCREEN_BUTTON \
+							(he_fullscreen_button_get_type())
+
+#define						HE_FULLSCREEN_BUTTON(object) \
+							(G_TYPE_CHECK_INSTANCE_CAST((object), \
+							HE_TYPE_FULLSCREEN_BUTTON, HeFullscreenButton))
+
+#define						HE_FULLSCREEN_BUTTON_CLASS(klass) \
+							(G_TYPE_CHECK_CLASS_CAST((klass), \
+							HE_TYPE_FULLSCREEN_BUTTON, HeFullscreenButtonClass))
+
+#define						HE_IS_FULLSCREEN_BUTTON(object) \
+							(G_TYPE_CHECK_INSTANCE_TYPE((object), \
+							HE_TYPE_FULLSCREEN_BUTTON))
+
+#define						HE_IS_FULLSCREEN_BUTTON_CLASS(klass) \
+							(G_TYPE_CHECK_CLASS_TYPE((klass), \
+							HE_TYPE_FULLSCREEN_BUTTON))
+
+#define						HE_FULLSCREEN_BUTTON_GET_CLASS(obj) \
+							(G_TYPE_INSTANCE_GET_CLASS((obj), \
+							HE_TYPE_FULLSCREEN_BUTTON, HeFullscreenButtonClass))
+
+
+typedef struct				_HeFullscreenButton HeFullscreenButton;
+typedef struct				_HeFullscreenButtonClass HeFullscreenButtonClass;
+
+
+struct _HeFullscreenButton
+{
+        GObject      parent;
+
+        GtkWindow   *parent_window;
+};
+
+struct _HeFullscreenButtonClass
+{
+        GObjectClass parent_class;
+
+        void (*clicked) (HeFullscreenButton *manager);
+};
+
+
+GType
+he_fullscreen_button_get_type (void);
+
+HeFullscreenButton *
+he_fullscreen_button_new (GtkWindow *window);
+
+void
+he_fullscreen_button_disable (HeFullscreenButton *self);
+
+void
+he_fullscreen_button_enable (HeFullscreenButton *self);
+
+GtkWidget *
+he_fullscreen_button_get_overlay (HeFullscreenButton *self);
+
+GtkWindow *
+he_fullscreen_button_get_window (HeFullscreenButton *self);
+
+G_END_DECLS
+
+#endif /* _HE_FULLSCREEN_BUTTON_ */
diff -uprN orig/fbreader-0.12.10/zlibrary/ui/src/maemo5/application/ZLGtkApplicationWindow.cpp fbreader-0.12.10/zlibrary/ui/src/maemo5/application/ZLGtkApplicationWindow.cpp
--- orig/fbreader-0.12.10/zlibrary/ui/src/maemo5/application/ZLGtkApplicationWindow.cpp	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/zlibrary/ui/src/maemo5/application/ZLGtkApplicationWindow.cpp	2012-10-27 21:55:41.801212903 +0200
@@ -24,6 +24,7 @@
 #include <ZLOptionEntry.h>
 #include <optionEntries/ZLSimpleOptionEntry.h>
 #include <ZLPopupData.h>
+#include <hildon-extras/he-fullscreen-button.h>
 
 #include "../message/ZLMaemoMessage.h"
 #include "../view/ZLGtkViewWidget.h"
@@ -35,6 +36,7 @@
 #include "../../../../core/src/dialogs/ZLOptionView.h"
 
 #include "ZLGtkApplicationWindow.h"
+#include "he-fullscreen-button.h"
 
 void ZLGtkDialogManager::createApplicationWindow(ZLApplication *application) const {
 	myWindow = GTK_WINDOW((new ZLGtkApplicationWindow(application))->getMainWindow());
@@ -103,12 +105,15 @@ ZLGtkApplicationWindow::ZLGtkApplication
 	ZLApplicationWindow(application),
 	KeyActionOnReleaseNotOnPressOption(ZLCategoryKey::CONFIG, "KeyAction", "OnRelease", false),
 	myFullScreen(false) {
+	//printf("trying to do something (3)\n");
 	myProgram = HILDON_PROGRAM(hildon_program_get_instance());
 	g_set_application_name("");
 
 	myWindow = HILDON_WINDOW(hildon_stackable_window_new());
+	((ZLGtkDialogManager&)ZLGtkDialogManager::Instance()).setMainWindow(GTK_WINDOW(myWindow));
+	he_fullscreen_button_new(GTK_WINDOW(myWindow));
 
-	((ZLMaemoCommunicationManager&)ZLCommunicationManager::Instance()).init();
+	hildon_gtk_window_enable_zoom_keys(GTK_WINDOW(myWindow), TRUE);
 
   /*
 	myToolbar = GTK_TOOLBAR(gtk_toolbar_new());
@@ -121,6 +126,8 @@ ZLGtkApplicationWindow::ZLGtkApplication
 	hildon_window_set_app_menu(HILDON_WINDOW(myWindow), myMenu);
 	gtk_widget_show_all(GTK_WIDGET(myMenu));
 
+	hildon_gtk_window_set_portrait_flags(GTK_WINDOW(myWindow), HILDON_PORTRAIT_MODE_SUPPORT);
+	//printf("we set HILDON_PORTRAIT_MODE_SUPPORT on the Window\n");
 	//hildon_window_add_toolbar(myWindow, myToolbar);
 	hildon_program_add_window(myProgram, myWindow);
 	gtk_widget_show_all(GTK_WIDGET(myWindow));
@@ -144,6 +151,7 @@ void ZLGtkApplicationWindow::init() {
 	gtk_main_iteration();
 	usleep(5000);
 	gtk_main_iteration();
+	((ZLMaemoCommunicationManager&)ZLCommunicationManager::Instance()).init();
 }
 
 void ZLGtkApplicationWindow::initMenu() {
diff -uprN orig/fbreader-0.12.10/zlibrary/ui/src/maemo5/dialogs/ZLGtkDialogManager.cpp fbreader-0.12.10/zlibrary/ui/src/maemo5/dialogs/ZLGtkDialogManager.cpp
--- orig/fbreader-0.12.10/zlibrary/ui/src/maemo5/dialogs/ZLGtkDialogManager.cpp	2010-04-01 15:14:24.000000000 +0200
+++ fbreader-0.12.10/zlibrary/ui/src/maemo5/dialogs/ZLGtkDialogManager.cpp	2011-04-05 22:55:29.000000000 +0200
@@ -33,6 +33,7 @@
 #include "ZLGtkDialog.h"
 #include "ZLGtkOptionsDialog.h"
 #include "ZLGtkSelectionDialog.h"
+#include "ZLGtkProgressDialog.h"
 #include "ZLGtkUtil.h"
 #include "../../gtk/image/ZLGtkImageManager.h"
 
@@ -97,6 +98,13 @@ void ZLGtkDialogManager::wait(const ZLRe
 	if (!myIsInitialized || myIsWaiting) {
 		runnable.run();
 	} else {
+#if MAEMO_VERSION >= 5
+		myIsWaiting = true;
+		shared_ptr<ZLProgressDialog> dialog = createProgressDialog(key);
+		dialog->run(runnable);
+		myIsWaiting = false;
+		return;
+#endif
 		myIsWaiting = true;
 #if MAEMO_VERSION <= 3
 		gtk_banner_show_animation(myWindow, waitMessageText(key).c_str());
@@ -145,3 +153,8 @@ void ZLGtkDialogManager::setClipboardIma
 		gtk_clipboard_set_image(clipboard, imageRef);
 	}
 }
+
+shared_ptr<ZLProgressDialog> ZLGtkDialogManager::createProgressDialog(const ZLResourceKey &key) const {
+	return new ZLGtkProgressDialog(myWindow, key);
+}
+
diff -uprN orig/fbreader-0.12.10/zlibrary/ui/src/maemo5/dialogs/ZLGtkProgressDialog.cpp fbreader-0.12.10/zlibrary/ui/src/maemo5/dialogs/ZLGtkProgressDialog.cpp
--- orig/fbreader-0.12.10/zlibrary/ui/src/maemo5/dialogs/ZLGtkProgressDialog.cpp	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/zlibrary/ui/src/maemo5/dialogs/ZLGtkProgressDialog.cpp	2011-04-05 22:55:29.000000000 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2004-2010 Geometer Plus <contact@geometerplus.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <gtk/gtkmain.h>
+#include <gtk/gtklabel.h>
+#include <gdk/gdkcursor.h>
+#include <hildon/hildon.h>
+
+#include "ZLGtkProgressDialog.h"
+
+ZLGtkProgressDialog::ZLGtkProgressDialog(GtkWindow *window, const ZLResourceKey &key) : ZLProgressDialog(key), myParent(window) {
+}
+
+void ZLGtkProgressDialog::setMessage(const std::string &message) {
+/*TODO
+	if (myLabel == 0) {
+		return;
+	}
+
+	gtk_label_set_text(GTK_LABEL(myLabel), message.c_str());
+	while (gtk_events_pending()) {
+		gtk_main_iteration();
+	}
+*/
+}
+
+void ZLGtkProgressDialog::run(ZLRunnable &runnable) {
+	/* or hildon_note_new_cancel_with_progress_bar */
+	hildon_gtk_window_set_progress_indicator(myParent, TRUE);
+	runnable.run();
+	hildon_gtk_window_set_progress_indicator(myParent, FALSE);
+}
diff -uprN orig/fbreader-0.12.10/zlibrary/ui/src/maemo5/dialogs/ZLGtkProgressDialog.h fbreader-0.12.10/zlibrary/ui/src/maemo5/dialogs/ZLGtkProgressDialog.h
--- orig/fbreader-0.12.10/zlibrary/ui/src/maemo5/dialogs/ZLGtkProgressDialog.h	1970-01-01 01:00:00.000000000 +0100
+++ fbreader-0.12.10/zlibrary/ui/src/maemo5/dialogs/ZLGtkProgressDialog.h	2011-04-05 22:55:29.000000000 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2004-2010 Geometer Plus <contact@geometerplus.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ZLGTKPROGRESSDIALOG_H__
+#define __ZLGTKPROGRESSDIALOG_H__
+
+#include <string>
+
+#include <gtk/gtkwidget.h>
+#include <gtk/gtkwindow.h>
+
+#include <ZLProgressDialog.h>
+
+class ZLGtkProgressDialog : public ZLProgressDialog {
+
+public:
+	ZLGtkProgressDialog(GtkWindow *window, const ZLResourceKey &key);
+
+private:
+	void run(ZLRunnable &runnable);
+	void setMessage(const std::string &message);
+
+private:
+	GtkWindow *myParent;
+};
+
+#endif /* __ZLGTKPROGRESSDIALOG_H__ */
