commit 71f6baaafaba8880aca9d7aeaa6ca3d28945f649
Author: simon987 <me@simon987.net>
Date:   Thu Nov 12 16:52:36 2020 -0500

    antiword 0.37 original source

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..14e54d1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*.o
+antiword
diff --git a/Docs/COPYING b/Docs/COPYING
new file mode 100644
index 0000000..57e438a
--- /dev/null
+++ b/Docs/COPYING
@@ -0,0 +1,342 @@
+
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
diff --git a/Docs/ChangeLog b/Docs/ChangeLog
new file mode 100644
index 0000000..4bf9e5e
--- /dev/null
+++ b/Docs/ChangeLog
@@ -0,0 +1,219 @@
+****************************************************************************
+* Changes in Antiword from versions 0.22 to 0.37                           *
+****************************************************************************
+
+Changes 0.36 to 0.37
+--------------------
+Bug fixes:
+- Bug reported by Suzanne Skinner <tril@igs.net> (and others) fixed
+New features:
+- XML/DocBook output now contains <footnote> tags
+- Antiword is now based on DeskLib instead of RISC_OSLib (RISC OS only)
+- Show page headers and footers (PostScript and PDF output only)
+- Show text that was removed by the revisioning system
+- Improved kantiword, based on information from Stefan Wiens <s.wi@gmx.net>
+
+Changes 0.35 to 0.36
+--------------------
+Bug fixes:
+- Bug reported by Michael Minn <mail@michaelminn.com> fixed
+New features:
+- The default mapping file is now based on the locale (Unix/Linux) or on
+  the active codepage (DOS)
+- A Word document can now be saved as "formatted" text. That means with things
+  like *bold* to show bold text, /italics/ to show italics and _undeline_ to
+  show underlined text are added to the plain text. Based on patches send by
+  Ofir Reichenberg <ofir@qlusters.com>
+- Improved table parsing. Based on information supplied by Bastien Legras
+  <bastien.legras@nectech.fr> and Alex de Kruijff <freebsd@akruijff.dds.nl>
+- A Word document can now be saved in PDF.
+- First attempt to support PostScript output in the Cyrillic alphabet. Based
+  on work done by Alexander Belyaev <isle@free.kursknet.ru>
+- Better support for the Cyrillic alphabet
+
+Changes 0.34 to 0.35
+--------------------
+Bug fixes:
+- Fixed the bug in the use of the environment variable ANTIWORDHOME
+New features:
+- The XML/DocBook output is slightly better.
+- Scale view window is closed when the main window is closed. Thanks to Tony
+  Moore <old_coaster@yahoo.co.uk> (RISC OS only)
+- More support for WinWord 1.x documents
+
+Changes 0.33 to 0.34
+--------------------
+Bug fixes:
+- Bug in UTF-8 tables fixed
+- Bug reported by Stewart Goldwater <sg@janus.freeserve.co.uk> fixed
+- Bug reported by Karl-Otto Linn <linn@informatik.fh-wiesbaden.de> fixed
+- Fixed a bug that made DOS hang when Antiword processed a document > 8 MB.
+New features:
+- Better approximations for fancy characters in the output
+- A Word document can now be saved as XML/DocBook.
+- Linux Makefile is now closer to conventions.
+- Support for Text Boxes
+- An environment variable ANTIWORDHOME was added to create a more flexable
+  place for the fontnames file and the mapping files.
+- Antiword is now Latin9 enabled. Thanks to Stefan Bellon
+  <sbellon@sbellon.de> (RISC OS only)
+- Some support for MacWord 4 and 5 documents
+- More support for Word-for-DOS documents
+- Support for superscripts and subscripts
+- Displays slightly more images.
+- Improved lists, especially in documents from Word 97 or later.
+
+Changes 0.32 to 0.33
+--------------------
+Bug fixes:
+- Bug reported by Yannick PERRET <yperret@bat710.univ-lyon1.fr> fixed
+Old features:
+- The -X option is no longer supported. Replace "-X 2" by "-m 8859-2.txt"
+New features:
+- Slightly more accurate font translation
+- Full support for WinWord 2.0 documents
+- Some support for Word-for-DOS and WinWord 1.x documents
+- Selective header numbering
+- Implementation of stylesheets
+- The system-wide directory for the mapping files was changed from
+  "/opt/antiword/share" to "/usr/share/antiword", in accordance with FHS,
+  the file-system hierarchy standard, as suggested by Anand Buddhdev
+  <arb@anand.org>.
+- Antiword now turns white text into light gray text.
+- Antiword is now closer to "64-bit clean". Based on information supplied by
+  Duncan Haldane <f.duncan.m.haldane@worldnet.att.net>.
+
+Changes 0.31 to 0.32
+--------------------
+Bug fixes:
+- Bug reported by Forrest J. Cavalier III <mibsoft@mibsoftware.com> fixed
+- Bug reported by Jan ONDREJ (SAL) <ondrejj@salstar.sk> fixed
+- Bug in dealing with RLE compressed bitmap images fixed
+- Bug in image scaling fixed (RISC OS only)
+New features:
+- Improved leading (Unix only; PostScript version only)
+- Antiword can now read from the standard input. This is based on an idea by
+  Matthew Miller <mattdm@mattdm.org>. (Unix only)
+- A white background looks much better. (RISC OS only)
+- A system-wide directory for the mapping files, as suggested by Sven Geggus
+  <sven@geggus.net> and many others. (Unix only)
+- Antiword can now deal with documents larger than 7 MB.
+
+Changes 0.30 to 0.31
+--------------------
+Bug fixes:
+- Bug in the "Show hidden (by Word) text" feature fixed
+- Bug reported by David Aspinwall <aspinwall@timesten.com> fixed
+- Bug reported by Robert Steinmetz <rob@steinmetznet.com> fixed
+Old features:
+- The -g and -c options are no longer supported. The -c option was the default
+  and is now used automatically. (Unix only)
+New features:
+- Ability to display some of the images
+- Ability to use landscape mode (Unix only; PostScript version only)
+- Support for all ISO-8859 character sets plus KOI8 and some code pages
+  (Unix only; text version only)
+- Antiword will now give a warning if the specified PostScript paper size is
+  unsupported. Thanks to Greg Robinson <Greg.Robinson@dsto.defence.gov.au>
+- Changed from PostScript version 1 to version 2
+- Antiword now returns 1 if no Word document is found among the files listed
+  on the command line, as suggested by Jens Schleusener
+  <Jens.Schleusener@dlr.de>.
+- Takes the right margin into account
+- The PostScript part now supports the AvantGarde, Bookman, Helvetica-Narrow,
+  NewCenturySchlbk and Palatino fonts (Unix only)
+- More accurate fontnames translation table
+- Initial scale factor is now configurable (RISC OS only)
+
+Changes 0.29 to 0.30
+--------------------
+Bug fixes:
+- Bug in the generated PostScript (nocurrentpoint) fixed
+- Bug reported by Keith Bamford <kbamford@eurobell.co.uk> fixed
+- Bug in the chapter numbering font fixed
+New features:
+- Improved handling of changes in the font size on a single line.
+- Some support for long file names (RISC OS only)
+- Thanks to David Kanareck <david@davidkanareck.demon.co.uk>, Antiword can
+  now deal with documents made by "Word for Asian languages", but only
+  when these documents are written in a European language.
+- Character properties "Caps" and "SmallCaps" for accented characters
+- More accurate fontnames translation table. (RISC OS only)
+- PostScript part now supports the Times and Helvetica fonts. (Unix only)
+
+Changes 0.28 to 0.29
+--------------------
+Bug fixes:
+- Bug reported by Paul McCann <P.J.McCann@cfm1220.x400.icl.co.uk> fixed
+- Character property "SmallCaps" works better now
+- Bug reported by Richard Lambley <richard@wireless.demon.co.uk> fixed
+- Fixed a bug in the linewidth computation (Unix only)
+New features:
+- A Word document can now be saved as PostScript (Unix only, Courier font only)
+- Left, Center, Right and Justify alignment added for Word 97
+- Supports the Macintosh character set
+
+Changes 0.27 to 0.28
+--------------------
+Licence:
+- Distributed under the GNU General Public License
+Bug fixes:
+- Bug reported by Richard Lambley <richard@wireless.demon.co.uk> has not
+  been fixed yet.
+- Deals correctly with fancy quotes in files from a Macintosh
+New features:
+- Supports character properties "SmallCaps", "Caps" and "Hidden Text"
+- The use of fonts and font sizes for "fast saved" documents is now supported.
+- Separators between the text, the footnotes and the endnotes
+- Footnotes are now numbered in Arabic numericals (1, 2, 3), endnotes are now
+  numbered in Roman numericals (i, ii, iii).
+
+Changes 0.26 to 0.27
+--------------------
+Bug fixes:
+- The main title now shows the first 12 characters of the file name.
+New features:
+- "Fast saved" documents are now supported for Word 97.
+- All tables are now supported for Word 97.
+- It is now possible to scale the text.
+
+Changes 0.25 to 0.26
+--------------------
+Bug fixes:
+- Fixed several problems with the Choices file
+- Closed a small memory leak
+New features:
+- The use of fonts and font sizes for "full saved" documents is now supported.
+- Most tables are now supported for Word 97.
+- Header numbers are now supported for Word 97.
+
+Changes 0.24 to 0.25
+--------------------
+Bug fixes:
+- Improved handling of memory shortages
+- Some special tables were messed up.
+New features:
+- "Fast saved" documents are now supported for Word 6 and 7.
+- A new option to permit Antiword to change the filetype of Word documents to
+  MSWord (&ae6).
+- A Wordfile can now be saved as a Drawfile.
+- The look and feel has been changed from editor-like to browser-like
+
+Changes 0.23 to 0.24
+--------------------
+Bug fixes:
+- Empty paragraphs in numbered list were not always numbered correctly.
+- In very complex tables some text could get lost.
+New features:
+- F3 is now a shortcut to the "Save as" dialogue box.
+- Left, Center, Right and Justify alignment added for Word 6 and 7
+- [pic] marks the place where an image should have been.
+- It is now possible to have a writeable Choices file, even when Antiword
+  itself is on a read-only medium.
+
+Changes 0.22 to 0.23
+--------------------
+New features:
+- Paragraph breaks are now an option.
+- Bulleted single level lists for files from Word 6 and 7
+- Numbered single level lists (some styles) for files from Word 6 and 7
diff --git a/Docs/Emacs b/Docs/Emacs
new file mode 100644
index 0000000..c2d9ba1
--- /dev/null
+++ b/Docs/Emacs
@@ -0,0 +1,134 @@
+From: Alex Schroeder <alex@emacswiki.org>
+Subject: Re: MS Word mode?
+Date: Fri, 08 Nov 2002 00:40:15 +0100
+
+Roger Mason <rmason@sparky2.esd.mun.ca> writes:
+
+> There was a question about this recently on this forum.  Look for
+> undoc.el, I got it from the wiki (I think).  It has worked very well for
+> me to date, although I have not attempted ro read complex documents.
+
+Well, it makes things readable, but it is far from perfect -- it seems
+to just delete any non-ascii characters, such that sometimes you will
+see words such as "Alex8" where "8" is some garbage that just looked
+like being part of a real word...  In other words, interfacing to
+something like catdoc, antiword, or wvText (included with AbiWord)
+might be cool.  Actually all you need is this:
+
+(add-to-list 'auto-mode-alist '("\\.doc\\'" . no-word))
+
+(defun no-word ()
+  "Run antiword on the entire buffer."
+  (shell-command-on-region (point-min) (point-max) "antiword - " t t))
+
+Alex.
+
+===============================================================================
+
+From: Arnaldo Mandel <am@ime.usp.br>
+Subject: Re: MS Word mode?
+Date: Fri, 8 Nov 2002 11:52:33 -0200
+
+Alex Schroeder wrote (on Nov 8, 2002):
+
+ >                 Actually all you need is this:
+ > 
+ > (add-to-list 'auto-mode-alist '("\\.doc\\'" . no-word))
+ > 
+ > (defun no-word ()
+ >   "Run antiword on the entire buffer."
+ >   (shell-command-on-region (point-min) (point-max) "antiword - " t t))
+
+On my system there are lots of filenames ending in .doc whose files
+are not Word files.  So I modified your function thusly
+
+(defun no-word ()
+  "Run antiword on the entire buffer."
+  (if (string-match "Microsoft "
+		    (shell-command-to-string (concat "file " buffer-file-name)))
+      (shell-command-on-region (point-min) (point-max) "antiword - " t t)))
+
+Works in Solaris and Linux, and should work on other unixes as well.
+
+am
+
+===============================================================================
+
+From: Alex Schroeder <alex@emacswiki.org>
+Subject: Re: MS Word mode?
+Date: Fri, 08 Nov 2002 18:24:07 +0100
+
+Arnaldo Mandel <am@ime.usp.br> writes:
+
+> (defun no-word ()
+>   "Run antiword on the entire buffer."
+>   (if (string-match "Microsoft "
+> 		    (shell-command-to-string (concat "file " buffer-file-name)))
+>       (shell-command-on-region (point-min) (point-max) "antiword - " t t)))
+
+Cool.  I did not know about "file"...  :)
+
+My stuff is on the wiki, btw:
+
+* http://www.emacswiki.org/cgi-bin/wiki.pl?AntiWord
+
+Alex.
+
+===============================================================================
+
+From: Benjamin Riefenstahl <Benjamin.Riefenstahl@epost.de>
+Subject: Re: emacs rmail. How to convert .doc to plain text
+Date: 24 Nov 2002 18:08:22 +0100
+
+Hi,
+
+Puff Addison <puff@theaddisons.demon.co.uk> writes:
+> Yes, please post your Emacs integration code.
+
+Ok, see below.  I should note that it is probably also possible to
+(ab-)use jka-compr for this, which would make my two functions
+obsolete.
+
+so long, benny
+
+>>>>>>>
+
+(defun benny-antiword-file-handler (operation &rest args)
+  ;; First check for the specific operations
+  ;; that we have special handling for.
+  (cond ((eq operation 'insert-file-contents)
+	 (apply 'benny-antiword-insert-file args))
+	((eq operation 'file-writable-p)
+	 nil)
+	((eq operation 'write-region)
+	 (error "Word documents can't be written"))
+	;; Handle any operation we don't know about.
+	(t (let ((inhibit-file-name-handlers
+		  (cons 'benny-antiword-file-handler
+			(and (eq inhibit-file-name-operation operation)
+			     inhibit-file-name-handlers)))
+		 (inhibit-file-name-operation operation))
+	     (apply operation args)))))
+
+(defun benny-antiword-insert-file (filename &optional visit beg end replace)
+  (set-buffer-modified-p nil)
+  (setq buffer-file-name (file-truename filename))
+  (setq buffer-read-only t)
+  (let ((start (point))
+	(inhibit-read-only t))
+    (if replace (delete-region (point-min) (point-max)))
+    (save-excursion
+      (let ((coding-system-for-read 'utf-8)
+	    (filename (encode-coding-string
+		       buffer-file-name
+		       (or file-name-coding-system
+			   default-file-name-coding-system))))
+	(call-process "antiword" nil t nil "-m" "UTF-8.txt"
+		      filename))
+      (list buffer-file-name (- (point) start)))))
+
+(setq file-name-handler-alist
+      (cons '("\\.doc\\'" . benny-antiword-file-handler)
+	    file-name-handler-alist))
+
+<<<<<<<
diff --git a/Docs/Exmh b/Docs/Exmh
new file mode 100644
index 0000000..d9da5b0
--- /dev/null
+++ b/Docs/Exmh
@@ -0,0 +1,14 @@
+From: Glenn Burkhardt <glenn@vtecus.com>
+Subject: It's great!
+Date: Wed, 22 Aug 2001 12:02:54 -0400
+
+Thank you for this program.  Thank you very much!  Thank you immensely!!
+
+
+P.S.  I find entry helpful as a /etc/mailcap rule:
+
+application/msword;/usr/local/bin/antiword -t %s | less; needsterminal; \
+copiousoutput; print=antiword -p letter %s|lpr
+
+I completely integrates the text mode with my mailer, exmh.  You might
+want to include it in your documentation.
diff --git a/Docs/FAQ b/Docs/FAQ
new file mode 100644
index 0000000..0a15f80
--- /dev/null
+++ b/Docs/FAQ
@@ -0,0 +1,113 @@
+Frequently Asked Questions
+==========================
+
+These questions and answers are mainly Linux/Unix oriented. For other
+Operating Systems you may want to read the documentation provided by the
+people who ported Antiword.
+
+Q1: How do I install Antiword?
+A1: (a) Make a suitable directory such as '$HOME/src/antiword' and copy the
+        'antiword.tar.gz' file to this directory.
+    (b) decompress: 'gunzip antiword.tar.gz'
+    (c) unpack: 'tar xvf antiword.tar'
+    (d) compile: 'make all'
+    (e) install: 'make install'. This will install Antiword in the $HOME/bin
+        directory.
+    (f) copy the file 'fontnames' and one or more mapping files from the
+        Resources directory to the $HOME/.antiword directory (note the dot
+        before antiword!).
+    NOTE: you can skip point (f) if your system administrator already copied
+          these files to /usr/share/antiword.
+
+Q2: I get the message "I can't open your mapping file (xxxx-x.txt)"
+A2: This means that the mapping file has not been installed. The installation
+    may have to be done manually. See above answer A1, point (f).
+    NOTE: Antiword assumes that a file that can't be opened for reading is a
+          file that doesn't exist.
+
+Q3: How do I use Antiword?
+A3: Type antiword -h and see.
+
+Q4: I tried "antiword -m /some/directory/8859-1.txt word.doc", but this
+    doesn't work.
+A4: The -m option is followed by the name of a mapping file, a full pathname
+    won't work.
+
+Q5: How does Antiword deal with Word macro viruses?
+A5: Antiword does not run any Word macros because it can't do so.
+    Therefore such a virus will not harm your computer system.
+
+Q6: What is the purpose of the file 'fontnames' in the '/usr/share/antiword/'
+    or '$HOME/.antiword' directory?
+A6: This file provides a translation table from the font names used in a Word
+    document to the font names used by a PostScript printer.
+    The file 'fontnames' can be edited to match the font collection used by
+    your PostScript printer.
+
+Q7: What is 'Hidden Text'?
+A7: Hidden Text is Microsoft speak for text that may or may not be shown
+    on the screen, subject to the user's preferences, but such text is never
+    printed.
+
+Q8: Antiword claims to support all ISO-8859 character sets, but I can't see
+    any of this.
+A8: There is support for all ISO-8859 character sets, but only in the text
+    output, not in the PostScript output.
+    The result can only be seen if your xterm, vtterm, kvt or similar
+    terminal emulation program uses a font compatible with that ISO-8859
+    character set.
+
+Q9: Which mapping file (-m option) is correct in my situation?
+A9: The correct mapping file depends on the character set you need for output
+    in a specific language.
+    For Western European languages (like English, French, German) this is
+    8859-1.txt. (OS/2: cp1252.txt) (DOS: cp850.txt)
+    For Eastern European languages (like Polish, Czech, Slovak, Croatian) this
+    is 8859-2.txt. (OS/2: cp1250.txt) (DOS: cp852.txt)
+    For Esperanto use 8859-3.txt.
+    For Russian use 8859-5.txt or koi8-r.txt. (OS/2: cp1251.txt)
+     (DOS: cp866.txt)
+    For Ukrainian use koi8-u.txt.
+    For Arabic use 8859-6.txt. (DOS: cp864.txt)
+    For Hebrew use 8859-8.txt. (DOS: cp862.txt)
+    For Thai use 8859-11.txt.
+    If your system supports it, you might also try UTF-8.txt.
+
+    NOTE: UTF-8 also enables Antiword to show text in languages like Chinese,
+          Japanese and Korean.
+
+Q10: I tried UTF-8, but some documents show more garbage than text. Why?
+A10: UTF-8 will only work if the document was saved by a Unicode enabled
+    version of Word (or if Word used ISO-8859-1 as its internal encoding).
+    The following versions of Word are known to be Unicode enabled:
+    Word 6 and Word 7 for Asian languages, all versions of Word 97,
+    Word 98 (Mac), Word 2000, Word 2001 (Mac) and Word 2002 (aka Word XP).
+
+Q11: Why can't Antiword read from stdin directly? Why use a temporary file?
+A11: The information in a Word document is not stored sequentially. Therefore
+    the use of the "fseek" function can't be avoided. So Antiword must copy
+    stdin to a temporary file first and then process that file.
+
+Q12: Why does the XML output of Antiword sometimes contain such a strange
+     structure or practically no structure at all?
+A12: Remember that Word is basically 'text plus appearance' and XML is
+     basically 'text plus structure'. If a Word document is written by a
+     competent person there will be a balance between appearance and structure,
+     but if a Word document is written by an inexperienced or incompetent
+     person the Word document can end up without a structure, or worse, with a
+     terrible structure.
+     Antiword can't create a structure when there is none.
+
+Q13: Why is the Postscript output in Cyrillic in ISO-8869-5? Nobody uses that
+     character set.
+A13: For Cyrillic you a have:
+     (a) koi8 does not cover all languages that use Cyrillic,
+     (b) cp866, cp1251 and Mac-Cyrillic are proprietary,
+     (c) Unicode and UTF-8 are not supported by PostScript yet and
+     (d) ISO-8859-5, the character set that nobody uses.
+
+Q14: I have used "antiword -p a4 -m 8869-5.txt file.doc > file.ps", but I get
+     no Cyrillic characters.
+A14: Programs like Ghostscript and Ghostview need Cyrillic enabled fonts in
+     order to show Cyrillic characters. A PostScript printer needs to be
+     Cyrillic enabled in order to show Cyrillic characters.
diff --git a/Docs/History b/Docs/History
new file mode 100644
index 0000000..5175df2
--- /dev/null
+++ b/Docs/History
@@ -0,0 +1,44 @@
+History of Antiword by (C) Adri van Os
+------------------------------------
+
+
+The Name
+--------
+The name comes from: "The antidote against people who send Microsoft(R) Word
+files to everybody, because they believe that everybody runs Windows(R) and
+therefore runs Word".
+
+
+Version 0.37 (21 Oct 2005)
+--------------------------
+Beta release, for evaluation by the public.
+
+
+Known Limitations
+-----------------
+
+1) The layout of Word documents is kept secret by Microsoft(R). Therefore
+   Antiword is based on information gathered from the Internet and on
+   guesswork.
+2) Antiword doesn't show all the images included in a Word document.
+3) Antiword doesn't do any hyphenation, because hyphenation is language
+   dependent.
+4) Antiword places footnotes at the end of the text.
+5) Antiword places box text after normal text and not in a box.
+6) Antiword doesn't try to emulate any of Word's DTP abilities.
+7) PostScript ouput will not work in combination with UTF-8. It only works in
+   combination with character sets ISO-8859-1, ISO-8859-2 and ISO-8859-5.
+8) Antiword's error messages are not very helpful.
+
+
+Known Bugs
+----------
+
+1) Antiword cannot handle encrypted documents.
+2) Antiword assumes default tab stops.
+3) Antiword doesn't handle frames.
+4) Antiword ignores page headers and footers.
+5) Antiword only handles lists in some of the styles.
+6) Antiword cannot handle some types of multilevel lists.
+7) Antiword assumes that all Word documents made on a Macintosh with Word
+   version 6 or older use the MacRoman character set.
diff --git a/Docs/Mozilla b/Docs/Mozilla
new file mode 100644
index 0000000..b1f1f82
--- /dev/null
+++ b/Docs/Mozilla
@@ -0,0 +1,88 @@
+Date: Mon, 11 Nov 2002 11:36:21 +0000
+From: Cam <camilo@mesias.co.uk>
+Subject: Re: antiword
+
+Hi
+
+I have updated the script for the latest Mozilla with plugger, as found 
+in RedHat 8. This makes the default action a very quick text view of a 
+document, much better IMHO than starting ooffice or abiword. If users 
+want to edit the file they can still save as.
+
+Here is a slightly improved script for gnome users:
+
+#!/bin/bash
+
+tmpfile=/tmp/aw$$.txt
+
+lastditch=`which vi`
+
+editor=${EDITOR:-$lastditch}
+
+if [ ! -x $editor ] ; then
+   editor=$lastditch
+fi
+
+
+tmpfile=/tmp/aw$$.txt
+
+gtopts="-t antiword-helper --hide-menubar"
+
+antiword "$1" > $tmpfile
+chmod -w $tmpfile
+gnome-terminal $gtopts -x $editor $tmpfile ; chmod +w $tmpfile ; rm $tmpfile
+
+
+
+Here is the script for non-gnome users:
+
+#!/bin/bash
+
+tmpfile=/tmp/aw$$.txt
+
+lastditch=`which vi`
+
+editor=${EDITOR:-$lastditch}
+
+if [ ! -x $editor ] ; then
+   editor=$lastditch
+fi
+
+
+antiword "$1" > $tmpfile
+chmod -w $tmpfile
+xterm -T "antiword-helper" -e $editor $tmpfile
+chmod +w $tmpfile
+rm $tmpfile
+
+
+
+To use the scripts add an entry into your plugger config file 
+(pluggerrc, for locations check man plugger). Mine is in 
+/home/cxm/.netscape/pluggerrc:
+
+The line to add is (it has a leading tab):
+
+   ignore_errors exits: antiword-helper "$file"
+
+
+Here is my config file after I added the line
+
+application/rtf: rtf: Rich Text Format
+application/x-msword: doc, dot: Microsoft Word Document
+application/msword: doc, dot: Microsoft Word Document
+         ignore_errors exits: antiword-helper "$file"
+         nokill exits: oowriter "$file"
+         repeat swallow(AbiWord) fill: AbiWord -nosplash -geometry 
++9000+9000 "$file" >/dev/null 2>/dev/null
+         repeat swallow(PCFileViewer) fill: sdtpcv "$file"
+         repeat swallow(PCFileViewer) fill: /opt/SUNWdtpcv/bin/sdtpcv 
+"$file"
+
+
+Then start Mozilla / Netscape and you should be able to quickly view 
+word docs from the browser and as email attachments.
+
+Hope that helps,
+
+-Cam
diff --git a/Docs/Mutt b/Docs/Mutt
new file mode 100644
index 0000000..fdf0ef5
--- /dev/null
+++ b/Docs/Mutt
@@ -0,0 +1,24 @@
+From: Sven Geggus (sven@geggus.net)
+Subject: Re: Word attachments in Mutt
+Newsgroups: comp.mail.mutt
+Date: 2001-05-16 01:21:11 PST
+
+Bob Zimmerman <bobzim@no.spam.org> wrote:
+
+> I receive MS Word attachments in Mutt reguarly. Is there a way to
+> read these via Mutt in a Linux/Solaris environment? (e.g. Lynx or
+> some type of viewer)?
+
+The best M$-word to ASCII converter has to be antiword!
+
+Just put the following line into .mailcap:
+
+application/msword; antiword %s; copiousoutput
+
+Sven
+
+--
+"We just typed make"
+(Stephen Lambrigh, Director of Server Product Marketing at Informix
+                                      about porting their Database to Linux)
+/me is giggls@ircnet, http://geggus.net/sven/ on the Web
diff --git a/Docs/Netscape b/Docs/Netscape
new file mode 100644
index 0000000..022a669
--- /dev/null
+++ b/Docs/Netscape
@@ -0,0 +1,129 @@
+From: "Craig D. Miller" <Craig.D.Miller@jpl.nasa.gov>
+
+Hi,
+
+Steps to integrate antiword into NetScape 4.73 (should also work with earlier
+versions).
+
+Programs that launch from netscape must startup an X window to display their
+output (otherwise output ends up it the bit bucket on your system).  I wrote the
+following script to do this for antiword (and saved it as
+"/usr/local/bin/xantiword":
+
+#!/bin/csh -f
+setenv FILE $1
+setenv NEWFILE ${FILE}.xantiword
+/usr/local/bin/antiword $FILE >&$NEWFILE
+/usr/bin/X11/xterm -title "$FILE (MS Word)" -e /usr/bsd/more $NEWFILE
+rm -f $NEWFILE
+
+The above script works, but may not be the best way to do it.  If you come up
+with a more elegant solution, then please let me know.
+
+Next you'll have to tell netscape to execute the "/usr/local/bin/xantiword"
+script when word documents are clicked on.  The easiest way to do this is to
+change the /usr/local/lib/netscape/mailcap netscape configuration file.  For
+SGI version of netscape the following two lines are changed.  For other versions
+of netscape, one should find similar lines or will need to add the new lines.
+
+Old lines (try to run SoftWindows, which is not installed on my system):
+
+    application/x-dos_ms_word; /usr/local/lib/netscape/swinexec %s winword; \
+        description="Microsoft Word-for-Windows Document";
+    application/msword; /usr/local/lib/netscape/swinexec %s winword; \
+        description="Microsoft Word-for-Windows Document";
+
+New lines (for antiword execution), which replace old lines on my system:
+
+    application/x-dos_ms_word; /usr/local/bin/xantiword %s; \
+        description="Microsoft Word-for-Windows Document";
+    application/msword; /usr/local/bin/xantiword %s; \
+        description="Microsoft Word-for-Windows Document";
+
+These changes can also be made via the netscape preferences, under
+Navigator/Applications, but then the changes would only be for the user that
+changed them.  The above change to the mailcap file affects all users, which is
+what you'll usually want.
+
+ Note that the above file paths may be different for your system.  On our linux
+box, a quick search DID NOT show where the mailcap for netscape was stored, but
+I did find one in /etc/mailcap.  I don't have time to experiment to see if this
+is the same one that netscape uses.
+
+If you have questions then please E-mail me.
+
+- Craig
+
+===============================================================================
+
+From: "Craig D. Miller" <Craig.D.Miller@jpl.nasa.gov>
+
+Hi,
+
+I just discovered a program called "xless".  It would actually be easier to use
+than my previous xterm/more solution.  To use it change the
+"/usr/local/bin/xantiword" script to: 
+
+#!/bin/csh -f
+setenv FILE $1
+/usr/local/bin/antiword $FILE | /usr/freeware/bin/xless \
+            -title "$FILE (MS Word)" -geometry 100x60
+
+Note that one also needs to have xless installed.  It can be found on the
+SGI Freeware Feb 1999 (or later) CD-ROM.
+
+- Craig
+
+===============================================================================
+
+From: Bruno Crochet <bruno.crochet@pse.unige.ch>
+
+Hi!
+
+Another way to integrate antiword into netscape is to copy the following
+line in your .mailcap file :
+
+application/msword; ns="%s"\; nf="${ns}".ps\; antiword -pa4 "${ns}" >
+"${nf}"\; gv "${nf}"\; sleep 2 \; rm "${nf}"
+
+Bruno.
+
+===============================================================================
+
+From: Andoni Zarate <azarate@saincotrafico.com>
+
+In order to view the file into netscape you can write the xantiword file
+like this:
+ 
+#!/bin/csh -f
+setenv FILE $1
+setenv NEWFILE ${FILE}.xantiword
+/usr/local/bin/antiword $FILE >&$NEWFILE
+netscape -remote 'openFile('$NEWFILE')'
+ 
+Andoni Z�rate.
+
+===============================================================================
+
+From: Evelyne Pinter <epinter@ptcs.ch>
+
+I include a script for netscape to see the document with ghostview.
+ 
+#!/bin/csh -f
+setenv FILE $1
+setenv NEWFILE ${FILE}.xantiword
+/usr/local/bin/antiword -pa4 $FILE >&$NEWFILE
+/usr/X11R6/bin/gv $NEWFILE
+rm -f $NEWFILE
+ 
+In netscape the application must be called like that
+"/usr/local/bin/xantiword %s"
+ 
+This is just a small change(done by Roger Luechinger) to the xantiword
+you included in the distribution 0.31
+ 
+Thanks
+ 
+SG E.M.S.P.
+
+===============================================================================
diff --git a/Docs/QandA b/Docs/QandA
new file mode 100644
index 0000000..0b60513
--- /dev/null
+++ b/Docs/QandA
@@ -0,0 +1,59 @@
+Questions and Answers (RISC OS version)
+=======================================
+
+Q1: How do I install Antiword?
+A1: Copy the application-directory and all the files within it to a
+    suitable directory.
+
+Q2: How do I use Antiword?
+A2: Double click on a Word document, filetype MSWord (&ae6). Or drag and drop
+    a file onto the Antiword icon on the iconbar.
+
+Q3: How does Antiword deal with Word macro viruses?
+A3: Antiword does not run any Word macros because it cannot do so.
+    Therefore your Archimedes will not be harmed by such a virus.
+
+Q4: What does the 'Paragraph breaks' option do?
+A4: This option controls the maximum number of characters per line in
+    paragraphs. If your screen is 640 pixels wide (like modes 20 and 27)
+    than 76 is probably best. If your screen is 800 or more pixels wide
+    (like mode 31) then numbers near 94 work best. You can switch this
+    option off if the (text only) output of Antiword will be the input to a
+    wordprocessor or a DTP program.
+    The pagebreak setting refers to the number of characters when you use
+    the system font. When you use an outline font only the width of that
+    number of characters in the system font is used.
+
+Q5: What does the 'Auto filetype' option do?
+A5: When auto filetype is allowed, Antiword will change the filetype of
+    Word documents to MSWord (&ae6)
+
+Q6: When Antiword uses outline fonts it becomes terribly slow. What can I
+    do about this?
+A6: When Antiword uses outline fonts it needs a large font cache. A small
+    font cache will make Antiword (very) slow. The larger the font cache the
+    better, but usually 160K or 256K will do.
+
+Q7: What is the purpose of the file 'FontNames' in the Choices directory?
+A7: This file provides a translation table from the font names found in a
+    Word document to the font names used by the RISC OS font-manager.
+    The file 'FontNames' is can be edited to match your font collection.
+    Some examples are provided in the Resources directory.
+
+Q8: What is 'Hidden Text'?
+A8: Hidden Text is Microsoft speak for text that may or may not be shown
+    on the screen, subject to the user's preferences, but such text is never
+    printed.
+
+Q9: After upgrading to a new version of Antiword, I found that Antiword does
+    not put a new _updated_ version of FontNames in !Choices. Why not?
+A9: The user can change the file Fontnames to reflect the fonts available
+    on a specific computer. Antiword cannot be permitted to overwrite changes
+    made by a user. So after upgrading you should remove or rename the old
+    FontNames file.
+
+Q10: Why does Antiword freeze my computer while converting the Word document?
+A10: This can happen when the Word document contains a very large image and
+     the image must be scaled to a much smaller size before displaying. The
+     delay occurs while RISC OS does the scaling, so there is not much
+     Antiword can do about it.
diff --git a/Docs/ReadMe b/Docs/ReadMe
new file mode 100644
index 0000000..5e783b1
--- /dev/null
+++ b/Docs/ReadMe
@@ -0,0 +1,114 @@
+                    ___        _   _                       _
+                   / _ \      | | (_)                     | |
+                  | |_| |_ __ | |_ ___      _____  _ __ __| |
+                  |  _  | '_ \| __| \ \ /\ / / _ \| '__/ _` |
+                  | | | | | | | |_| |\ V  V / (_) | | | (_| |
+                  |_| |_|_| |_|\__|_| \_/\_/ \___/|_|  \__,_|
+
+Antiword
+========
+
+Version 0.37 (21 Oct 2005)
+--------------------------     
+
+Introduction
+------------
+
+Antiword is an application for displaying Microsoft(R) Word documents.
+
+
+License
+-------
+
+This program is distributed under the GNU General Public License - see the
+accompanying COPYING file for more details.
+
+
+Problems
+--------
+
+Any bugs found should be reported to the author with full details of how to
+get the problem to occur, but don't *expect* support for a product that you
+have not paid for!
+
+Please include Antiword's version number and version date, otherwise you
+make it impossible for the author to help.
+
+
+Thanks To
+---------
+
+Victor B. Wagner <vitus@agropc.msk.su> creator of "catdoc"
+Duncan Simpson <word2x@duncan.telstar.net> creator of "word2x"
+Martin Schwartz <schwartz@cs.tu-berlin.de> creator of "laola" and "elser"
+Caolan McNamara <Caolan.McNamara@ul.ie> creator of "mswordview"
+Andrew Scriven <andy.scriven@research.natpower.co.uk> creator of "OLEdecode"
+Craig Southeren <geoffw@extro.ucc.oz.au> creator of "nenscript"
+Thomas Merz <tm@muc.de> creator of "jpeg2ps"
+Ulrich von Zadow <uzadow@cs.tu-berlin.de> creator of "paintlib"
+
+
+Contributors
+------------
+
+ISO-8859-2 support by: Pawel Turnau <uzturnau@cyf-kr.edu.pl>
+Character set mapping by: Dmitry Chernyak
+                          <Dmitry.Chernyak@p998.f983.n5030.z2.fidonet.org>
+UTF-8 support by: Karl Koehler <koehler@or.uni-bonn.de> and
+                  Markus Kuhn <Markus.Kuhn@cl.cam.ac.uk>
+PostScript Cyrillic by: Alexander Belyaev <isle@free.kursknet.ru>
+
+
+Ports
+-----
+
+Antiword was ported to BeOS by Pete Goodeve <pete@jwgibbs.cchem.berkeley.edu>
+Antiword was ported to OS/2 by Dave Yeo <dave_yeo@paralynx.com>
+Antiword was ported to Mac OS X by Ronaldo Nascimento <ronaldo@ronaldo.com>
+Antiword was ported to Amiga by Raffaele Pisapia <rafpis@libero.it>
+Antiword was ported to VMS by Joseph Huber <huber@mppmu.mpg.de>
+Antiword was ported to NetWare by Guenter Knauf <info@gknw.de>
+Antiword was ported to EPOC by Max Tomin <tomin@samaramail.ru>
+Antiword was ported to Zaurus PDA by Piotr Jachimczyk
+                                     <P.Jachimczyk@prioris.mini.pw.edu.pl>
+Antiword was ported to DOS by myself ;-)
+Yen-Ming Lee <leeym@freebsd.org> is the maintainer of the FreeBSD version of
+Antiword.
+
+
+Acknowledgements
+----------------
+
+Microsoft is a registered trademark and Windows is a trademark of Microsoft
+Corporation.
+UNIX is a registered trademark of the X/Open Company, Ltd.
+Linux is a registered trademark of Linus Torvalds.
+Postscript is a trademark of Adobe Systems Incorporated.
+All other trademarks are acknowledged.
+
+
+Future Versions
+---------------
+
+If you have any comments, bug reports or suggestions for future versions
+don't hesitate to write to me.
+New versions of the program will only be available if sufficient people
+are using this program. So let me know!
+
+
+Most recent version
+-------------------
+
+Most recent version of Antiword can be found on the author's website:
+==>>  http://www.winfield.demon.nl/index.html  <<==
+==>>  http://antiword.cjb.net/  <<==
+
+
+Author
+------
+
+The author can be reached by e-mail:
+antiword@winfield.demon.nl
+comments@antiword.cjb.net
+
+But PLEASE read the FAQ before you write!!
diff --git a/Docs/antiword.1 b/Docs/antiword.1
new file mode 100644
index 0000000..1bae2f4
--- /dev/null
+++ b/Docs/antiword.1
@@ -0,0 +1,158 @@
+.TH ANTIWORD 1 "Oct 29, 2005" "Antiword 0.37" "Linux User's Manual"
+.SH NAME
+antiword - show the text and images of MS Word documents
+.SH SYNOPSIS
+.B antiword
+[
+.I options
+]
+.I wordfiles
+.SH DESCRIPTION
+.I Antiword
+is an application that displays the text and the images of Microsoft Word
+documents.
+.br
+A wordfile named - stands for a Word document read from the standard input.
+.br
+Only documents made by MS Word version 2 and version 6 or later are supported.
+.SH OPTIONS
+.TP
+.BI "\-a " papersize
+Output in Adobe PDF form. Printable on paper of the specified size: 10x14,
+a3, a4, a5, b4, b5, executive, folio, legal, letter, note, quarto, statement
+or tabloid.
+.TP
+.B \-f
+Output in formatted text form. That means that bold text is printed like
+*bold*, italics like /italics/ and underlined text as _underlined_.
+.TP
+.B \-h
+Give a help message.
+.TP
+.BI "\-i " "image level"
+The image level determines how images will be shown.
+.RS
+.TP 3
+0:
+Use non-standard extensions from Ghostscript. This output may not print on
+any PostScript printer, but is useful in case no hard copy is needed. It is
+also useful when Ghostscript is used as a filter to print a PostScript file to
+a non-PostScript printer.
+.TP 3
+1:
+Show no images.
+.TP 3
+2:
+PostScript level 2 compatible. (default)
+.TP 3
+3:
+PostScript level 3 compatible. (EXPERIMENTAL, Portable Network Graphics (PNG)
+images are not printed correctly)
+.RE
+.TP
+.BI "\-m " "mapping file"
+This file is used to map Unicode characters to your local character set.
+The default mapping file depends on the locale.
+.TP
+.BI "\-p " papersize
+Output in PostScript form. Printable on paper of the specified size: 10x14,
+a3, a4, a5, b4, b5, executive, folio, legal, letter, note, quarto, statement
+or tabloid.
+.TP
+.B \-r
+Include text removed by the revisioning system.
+.TP
+.B \-s
+Include text with the so-called "hidden text" attribute.
+.TP
+.B \-t
+Output in text form. (default)
+.TP
+.BI "\-w " width
+In text mode this is the line width in characters. A value of zero puts an
+entire paragraph on a line, useful when the text is to used as input for
+another wordprocessor. This value is ignored in PostScript mode.
+.TP
+.BI "\-x " "document type definition"
+Output in XML form. Currently the only document type definition is db
+(for DocBook).
+.TP
+.B \-L
+In PostScript mode: use landscape mode.
+.RE
+.SH FILES
+.TP
+Mapping files like 8859-1.txt
+.br
+Antiword looks for its mapping files in three directories, in the order given:
+.br
+(1) The directory specified by $ANTIWORDHOME
+.br
+(2) The directory specified by $HOME/.antiword
+.br
+(3) Directory /usr/share/antiword
+.TP
+The fontnames file
+.br
+Antiword will look for its fontname file in the same directories as used for the
+mapping files.
+.br
+The fontnames file contains the translation table from font names used by MS
+Word to font names used by PostScript.
+.TP
+NOTE:
+.br
+Antiword cannot tell the difference between a file that does not exist and a
+file that cannot be opened for reading.
+.SH ENVIRONMENT
+Antiword uses the environment variable ``ANTIWORDHOME'' as the first directory
+to look for its files. Antiword uses the environment variable ``HOME'' to find
+the user's home directory. When in text mode it uses the variable ``COLUMNS''
+to set the width of the output (unless overridden by the -w option).
+
+Antiword uses the environment variables ``LC_ALL'', ``LC_CTYPE'' and ``LANG''
+(in that order) to get the current locale and uses this information to
+select the default mapping file.
+.SH BUGS
+Antiword is far from complete. Many features are still missing. Many images are
+not shown yet. Some of the images that are shown, are shown in the wrong place.
+PostScript output is only available in ISO 8859-1 and ISO 8859-2.
+.SH WEB SITES
+The most recent released version of Antiword is always available from:
+.br
+http://www.winfield.demon.nl/index.html
+.br
+or try
+.br
+http://antiword.cjb.net/
+.SH AUTHOR
+Adri van Os <antiword@winfield.demon.nl>
+.br
+or try <comments@antiword.cjb.net>
+.sp
+R.F. Smith <rsmith@xs4all.nl> and
+.br
+Sindi Keesan <keesan@cyberspace.org>
+.br
+contributed to this manual page.
+.SH LICENSE
+Antiword 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.,
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+.SH ACKNOWLEDGEMENTS
+Linux is a registered trademark of Linus Torvalds.
+.br
+Adobe, PDF and PostScript are trademarks of Adobe Systems Incorporated.
+.br
+Microsoft is a registered trademark and Windows is a trademark of Microsoft
+Corporation.
diff --git a/Docs/antiword.man b/Docs/antiword.man
new file mode 100644
index 0000000..270b8ce
--- /dev/null
+++ b/Docs/antiword.man
@@ -0,0 +1,146 @@
+ANTIWORD(1)                   Linux User's Manual                  ANTIWORD(1)
+
+
+
+NAME
+       antiword - show the text and images of MS Word documents
+
+SYNOPSIS
+       antiword [ options ] wordfiles
+
+DESCRIPTION
+       Antiword  is  an  application  that displays the text and the images of
+       Microsoft Word documents.
+       A wordfile named - stands for a Word document read  from  the  standard
+       input.
+       Only  documents  made  by  MS Word version 2 and version 6 or later are
+       supported.
+
+OPTIONS
+       -a papersize
+              Output in Adobe PDF form. Printable on paper  of  the  specified
+              size:  10x14,  a3, a4, a5, b4, b5, executive, folio, legal, let-
+              ter, note, quarto, statement or tabloid.
+
+       -f     Output in formatted text form. That  means  that  bold  text  is
+              printed  like *bold*, italics like /italics/ and underlined text
+              as _underlined_.
+
+       -h     Give a help message.
+
+       -i image level
+              The image level determines how images will be shown.
+
+              0: Use non-standard extensions from Ghostscript. This output may
+                 not print on any PostScript printer, but is useful in case no
+                 hard copy is needed. It is also useful  when  Ghostscript  is
+                 used  as  a  filter  to  print  a  PostScript  file to a non-
+                 PostScript printer.
+
+              1: Show no images.
+
+              2: PostScript level 2 compatible. (default)
+
+              3: PostScript level 3 compatible. (EXPERIMENTAL,  Portable  Net-
+                 work Graphics (PNG) images are not printed correctly)
+
+       -m mapping file
+              This  file is used to map Unicode characters to your local char-
+              acter set.  The default mapping file depends on the locale.
+
+       -p papersize
+              Output in PostScript form. Printable on paper of  the  specified
+              size:  10x14,  a3, a4, a5, b4, b5, executive, folio, legal, let-
+              ter, note, quarto, statement or tabloid.
+
+       -r     Include text removed by the revisioning system.
+
+       -s     Include text with the so-called "hidden text" attribute.
+
+       -t     Output in text form. (default)
+
+       -w width
+              In text mode this is the line width in characters.  A  value  of
+              zero puts an entire paragraph on a line, useful when the text is
+              to used as  input  for  another  wordprocessor.  This  value  is
+              ignored in PostScript mode.
+
+       -x document type definition
+              Output  in XML form. Currently the only document type definition
+              is db (for DocBook).
+
+       -L     In PostScript mode: use landscape mode.
+
+FILES
+       Mapping files like 8859-1.txt
+              Antiword looks for its mapping files in  three  directories,  in
+              the order given:
+              (1) The directory specified by $ANTIWORDHOME
+              (2) The directory specified by $HOME/.antiword
+              (3) Directory /usr/share/antiword
+
+       The fontnames file
+              Antiword will look for its fontname file in the same directories
+              as used for the mapping files.
+              The fontnames file contains  the  translation  table  from  font
+              names used by MS Word to font names used by PostScript.
+
+       NOTE:
+              Antiword cannot tell the difference between a file that does not
+              exist and a file that cannot be opened for reading.
+
+ENVIRONMENT
+       Antiword uses the environment variable ``ANTIWORDHOME''  as  the  first
+       directory to look for its files. Antiword uses the environment variable
+       ``HOME'' to find the user's home directory. When in text mode  it  uses
+       the  variable  ``COLUMNS'' to set the width of the output (unless over-
+       ridden by the -w option).
+
+       Antiword uses the environment variables  ``LC_ALL'',  ``LC_CTYPE''  and
+       ``LANG'' (in that order) to get the current locale and uses this infor-
+       mation to select the default mapping file.
+
+BUGS
+       Antiword is far from complete. Many features are  still  missing.  Many
+       images  are not shown yet. Some of the images that are shown, are shown
+       in the wrong place.  PostScript output is only available in ISO  8859-1
+       and ISO 8859-2.
+
+WEB SITES
+       The most recent released version of Antiword is always available from:
+       http://www.winfield.demon.nl/index.html
+       or try
+       http://antiword.cjb.net/
+
+AUTHOR
+       Adri van Os <antiword@winfield.demon.nl>
+       or try <comments@antiword.cjb.net>
+
+       R.F. Smith <rsmith@xs4all.nl> and
+       Sindi Keesan <keesan@cyberspace.org>
+       contributed to this manual page.
+
+LICENSE
+       Antiword  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 MER-
+       CHANTABILITY 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.,
+       59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ACKNOWLEDGEMENTS
+       Linux is a registered trademark of Linus Torvalds.
+       Adobe, PDF and PostScript are trademarks of Adobe Systems Incorporated.
+       Microsoft is a registered trademark  and  Windows  is  a  trademark  of
+       Microsoft Corporation.
+
+
+
+Antiword 0.37                    Oct 29, 2005                      ANTIWORD(1)
diff --git a/Docs/antiword.old.php b/Docs/antiword.old.php
new file mode 100644
index 0000000..8025b24
--- /dev/null
+++ b/Docs/antiword.old.php
@@ -0,0 +1,34 @@
+From: Paul Southworth <pauls@etext.org>
+Subject: antiword PHP script
+Date: Thu, 24 Oct 2002 14:01:05 -0700 (PDT)
+
+Please find attached a trivial example of using a web form to process an
+uploaded Word doc to text using antiword.  Perhaps other antiword users
+would find it useful.
+
+--Paul
+
+<?
+/* antiword.php
+   A PHP script to convert uploaded MS Word docs to text using antiword.
+   This script is public domain, no copyright.
+   September 11, 2002
+   Paul Southworth
+*/
+function print_form() {
+?>
+<html><head><title>antiword</title></head><body>
+<form method=post action=antiword.php enctype="multipart/form-data">
+<input name=upload type=file>
+<input type=submit name=submit value=convert>
+</form>
+</body></html>
+<?
+}
+if ($_FILES['upload']) {
+    header ("Content-type: text/plain");
+    system("/usr/local/bin/antiword " . $_FILES['upload']['tmp_name']);
+} else {
+    print_form();
+}
+?>
diff --git a/Docs/antiword.php b/Docs/antiword.php
new file mode 100644
index 0000000..f30c48d
--- /dev/null
+++ b/Docs/antiword.php
@@ -0,0 +1,141 @@
+| <?php
+/*
+(C) 2005 Vidar L�kken <vidarlo@vestdata.no>
+
+V.3: I've added escapeshellcmd to all user input that shows up directly
+in exec()
+*/
+switch ($_REQUEST['output']) {
+case "PostScript":
+   $output=escapeshellcmd("-p $_REQUEST[paper]");
+   break;
+case "PDF":
+   $output=escapeshellcmd("-a $_REQUEST[paper]");
+   $pdf=1;
+   break;
+case "InLine":
+   $output="-t";
+   break;
+}
+if (isset($_FILES['userfile']['name'])) {
+  $uploaddir = '/tmp/';
+  $uploadfile = $uploaddir . $_FILES['userfile']['name'];
+  $userfile =  $_FILES['userfile']['name'];
+  if (move_uploaded_file($_FILES['userfile']['tmp_name'],$uploadfile)) {
+    $delims=".";
+    if (strstr($output,"-p")) {
+      $psfile=strtok($userfile,$delims).".ps";
+      header("Content-Type: Application/PostScript");
+      header("Content-Disposition: attachment; filename=".$psfile);
+      $file=escapeshellcmd($uploadfile);
+      $command="antiword $output $file";
+      passthru($command);
+      unlink($uploadfile);
+    } elseif (strstr($output,"-a")) {
+      $psfile=strtok($userfile,$delims).".pdf";
+      header("Content-Type: Application/PDF");
+      //      header("Content-Disposition: attachment; filename=".$psfile);
+      //      $command="antiword $output $uploadfile";
+      $file=escapeshellcmd($uploadfile);
+      $command="antiword $output $file";
+      passthru($command);
+      unlink($uploadfile);
+    } else {
+      echo "<pre>";
+      $file=escapeshellcmd($uploadfile);
+      $command="antiword $output $file";
+      //      echo $command;
+      //      $command="antiword $output $uploadfile";
+      passthru($command);
+      unlink($uploadfile);
+    }
+  }
+  elseif (isset($_REQUEST['url'])) {
+    echo $command;
+    $url=$_REQUEST['url'];
+    $uri=escapeshellcmd($_REQUEST['url']);
+    $delim="/";
+    $docfile=explode($delim,$uri);
+    exec("wget -O /tmp/$docfile $url");
+    if (strstr($output,"-p")) {
+      $psfile=strtok(end($docfile),".").".ps";
+      $safe=escapeshellcmd($docfile);
+      $command="antiword $output /tmp/$safe";
+      header("Content-Type: Application/PostScript");
+      header("Content-Disposition: attachment; filename=".$psfile);
+      passthru($command);
+      @@      unlink("/tmp/$docfile");
+    } elseif (strstr($output,"-a")) {
+      $psfile=strtok(end($docfile),".").".pdf";
+      $safe=escapeshellcmd($docfile);
+      $command="antiword $output /tmp/$safe";
+      header("Content-Type: Application/PDF");
+      header("Content-Disposition: attachment; filename=".$psfile);
+      passthru($command);
+@@      unlink("/tmp/$docfile");
+    } else {
+      echo "<pre>";
+      $safe=escapeshellcmd($docfile);
+      $command="antiword $output /tmp/$safe";
+      passthru($command);
+@@      unlink("/tmp/$docfile");
+    }
+  }
+}
+if (!isset($_FILES['userfile']['name'])) {
+  ?>
+<p>
+   This script converts a word file (most versions supported) into a
+pure ASCII, a PDF or a PostScript version. Currently, only PostScript
+and PDF carry images, and those images might be distorted or such. It's
+based on the nice program antiword. see <a
+href=http://antiword.cjb.net>antiword.cjb.net</a> for more information
+about antiword. Currently, max file size is 3MiB for the upload. This
+should be enough!
+</p><p>Currently, I tend to end up with the ascii version being 1/100th
+of the word document, and the pdf/ps versions being 1/10th of the size.
+So if you're gonna send me a word document, rethink that. I'll not read
+it. I'll read ascii, and probably pdf/ps too.</p>
+</p>
+<form enctype="multipart/form-data" action="antiword.php" method="post">
+  <input type="hidden" name="MAX_FILE_SIZE" value="30000" />
+  URL:<br /><input type="text" name="url" size=50 /><br />
+  Send this file:<br /> <input name="userfile" type="file"/>
+  <br />Output: <br />
+  <SELECT name="output">
+  <OPTGROUP>
+  <OPTION name=txt>InLine</OPTION>
+  <OPTION name=ps>PostScript</OPTION>
+  <OPTION name=PDF>PDF</OPTION>
+  </OPTGROUP>
+  </SELECT>
+Papersize: <SELECT name="paper"/>
+<OPTGROUP>
+<OPTION>a4</OPTION>
+<OPTION>a3</OPTION>
+<OPTION>a5</OPTION>
+<OPTION>b4</OPTION>
+<OPTION>b5</OPTION>
+<OPTION>10x14</OPTION>
+<OPTION>executive</OPTION>
+<OPTION>folio</OPTION>
+<OPTION>legal</OPTION>
+<OPTION>letter</OPTION>
+<OPTION>note</OPTION>
+<OPTION>quarto</OPTION>
+<OPTION>statement</OPTION>
+<OPTION>tabloid</OPTION>
+</select>
+<br />
+  <input type="submit" value="Send File" />
+  </form>
+<p>This is running <a href="http://antiword.cjb.net">antiword</a> 0.36. <br>
+   Please drop me a note at antiword (at) bitsex.net if you have
+comments for this.
+<hr>
+<font size=-1>(C)Vidar L&oslash;kken 2005</font>
+<!-- Version: 0.2 as of 19. oct. 2005 -->
+<?php
+}
+?>
+|
diff --git a/Docs/testdoc.doc b/Docs/testdoc.doc
new file mode 100644
index 0000000..3f78d77
Binary files /dev/null and b/Docs/testdoc.doc differ
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..eeb2d15
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,97 @@
+#
+# Makefile for antiword (Linux version)
+#
+
+CC	= gcc
+LD	= gcc
+
+INSTALL		= cp -f
+INSTALL_PROGRAM	= $(INSTALL)
+INSTALL_DATA	= $(INSTALL)
+
+# must be equal to DEBUG or NDEBUG
+DB	= NDEBUG
+# Optimization: -O<n> or debugging: -g
+OPT	= -O2
+
+LDLIBS	=
+
+CFLAGS	= -Wall -pedantic $(OPT) -D$(DB)
+LDFLAGS	=
+
+OBJS	=\
+	main_u.o asc85enc.o blocklist.o chartrans.o datalist.o depot.o\
+	dib2eps.o doclist.o fail.o finddata.o findtext.o fmt_text.o fontlist.o\
+	fonts.o fonts_u.o hdrftrlist.o imgexam.o imgtrans.o jpeg2eps.o\
+	listlist.o misc.o notes.o options.o out2window.o output.o pdf.o\
+	pictlist.o png2eps.o postscript.o prop0.o prop2.o prop6.o prop8.o\
+	properties.o propmod.o rowlist.o sectlist.o stylelist.o stylesheet.o\
+	summary.o tabstop.o text.o unix.o utf8.o word2text.o worddos.o\
+	wordlib.o wordmac.o wordole.o wordwin.o xmalloc.o xml.o
+
+PROGS =\
+	antiword\
+	kantiword
+
+LOCAL_INSTALL_DIR = $(HOME)/bin
+LOCAL_RESOURCES_DIR = $(HOME)/.antiword
+
+GLOBAL_INSTALL_DIR = /usr/local/bin
+GLOBAL_RESOURCES_DIR = /usr/share/antiword
+
+all:		$(PROGS)
+
+install:	all
+	mkdir -p $(LOCAL_INSTALL_DIR)
+	cp -pf $(PROGS) $(LOCAL_INSTALL_DIR)
+	mkdir -p $(LOCAL_RESOURCES_DIR)
+	cp -pf Resources/* $(LOCAL_RESOURCES_DIR)
+
+# NOTE: you might have to be root to do this
+global_install:	all
+#	@[ `id -u` -eq 0 ] || (echo "You must be root to do this" && false)
+	mkdir -p $(DESTDIR)$(GLOBAL_INSTALL_DIR)
+	$(INSTALL_PROGRAM) $(PROGS) $(DESTDIR)$(GLOBAL_INSTALL_DIR)
+	cd $(DESTDIR)$(GLOBAL_INSTALL_DIR); chmod 755 $(PROGS)
+	mkdir -p $(DESTDIR)$(GLOBAL_RESOURCES_DIR)
+	chmod 755 $(DESTDIR)$(GLOBAL_RESOURCES_DIR)
+	$(INSTALL_DATA) Resources/*.txt $(DESTDIR)$(GLOBAL_RESOURCES_DIR)
+	$(INSTALL_DATA) Resources/fontnames $(DESTDIR)$(GLOBAL_RESOURCES_DIR)
+	cd $(DESTDIR)$(GLOBAL_RESOURCES_DIR); chmod 644 *.txt fontnames
+
+# NOTE: you might have to be root to do this
+global_uninstall:
+#	@[ `id -u` -eq 0 ] || (echo "You must be root to do this" && false)
+	cd $(DESTDIR)$(GLOBAL_INSTALL_DIR); rm -f $(PROGS)
+	-rmdir $(DESTDIR)$(GLOBAL_INSTALL_DIR)
+	cd $(DESTDIR)$(GLOBAL_RESOURCES_DIR); rm -f *.txt fontnames
+	-rmdir $(DESTDIR)$(GLOBAL_RESOURCES_DIR)
+
+clean:
+	rm -f $(OBJS)
+	rm -f $(PROGS)
+
+antiword:	$(OBJS)
+	@rm -f $@
+	$(LD) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $@
+	@chmod 750 $@
+
+kantiword:	Unix-only/KDE3-only/kantiword.sh
+	@rm -f $@
+	echo "#!/bin/bash" > $@
+	cat $? >> $@
+	@chmod 750 $@
+
+.c.o:
+	$(CC) $(CFLAGS) -c $<
+
+main_u.o:	version.h
+postscript.o:	version.h
+pdf.o:		version.h
+fonts_u.o:	fontinfo.h
+
+fontinfo.h:	Unix-only/fontinfo.h
+	cp -rp $? $@
+
+Unix-only/fontinfo.h:	Unix-only/fontinfo.pl
+	Unix-only/fontinfo.pl > Unix-only/fontinfo.h
diff --git a/Resources/8859-1.txt b/Resources/8859-1.txt
new file mode 100644
index 0000000..473ecab
--- /dev/null
+++ b/Resources/8859-1.txt
@@ -0,0 +1,303 @@
+#
+#	Name:             ISO/IEC 8859-1:1998 to Unicode
+#	Unicode version:  3.0
+#	Table version:    1.0
+#	Table format:     Format A
+#	Date:             1999 July 27
+#	Authors:          Ken Whistler <kenw@sybase.com>
+#
+#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
+#
+#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+#	No claims are made as to fitness for any particular purpose.  No
+#	warranties of any kind are expressed or implied.  The recipient
+#	agrees to determine applicability of information provided.  If this
+#	file has been provided on optical media by Unicode, Inc., the sole
+#	remedy for any claim will be exchange of defective media within 90
+#	days of receipt.
+#
+#	Unicode, Inc. hereby grants the right to freely use the information
+#	supplied in this file in the creation of products supporting the
+#	Unicode Standard, and to make copies of this file in any form for
+#	internal or external distribution as long as this notice remains
+#	attached.
+#
+#	General notes:
+#
+#	This table contains the data the Unicode Consortium has on how
+#       ISO/IEC 8859-1:1998 characters map into Unicode.
+#
+#	Format:  Three tab-separated columns
+#		 Column #1 is the ISO/IEC 8859-1 code (in hex as 0xXX)
+#		 Column #2 is the Unicode (in hex as 0xXXXX)
+#		 Column #3 the Unicode name (follows a comment sign, '#')
+#
+#	The entries are in ISO/IEC 8859-1 order.
+#
+#	Version history
+#	1.0 version updates 0.1 version by adding mappings for all
+#	control characters.
+#
+#	Updated versions of this file may be found in:
+#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
+#
+#	Any comments or problems, contact <errata@unicode.org>
+#	Please note that <errata@unicode.org> is an archival address;
+#	notices will be checked, but do not expect an immediate response.
+#
+0x00	0x0000	#	NULL
+0x01	0x0001	#	START OF HEADING
+0x02	0x0002	#	START OF TEXT
+0x03	0x0003	#	END OF TEXT
+0x04	0x0004	#	END OF TRANSMISSION
+0x05	0x0005	#	ENQUIRY
+0x06	0x0006	#	ACKNOWLEDGE
+0x07	0x0007	#	BELL
+0x08	0x0008	#	BACKSPACE
+0x09	0x0009	#	HORIZONTAL TABULATION
+0x0A	0x000A	#	LINE FEED
+0x0B	0x000B	#	VERTICAL TABULATION
+0x0C	0x000C	#	FORM FEED
+0x0D	0x000D	#	CARRIAGE RETURN
+0x0E	0x000E	#	SHIFT OUT
+0x0F	0x000F	#	SHIFT IN
+0x10	0x0010	#	DATA LINK ESCAPE
+0x11	0x0011	#	DEVICE CONTROL ONE
+0x12	0x0012	#	DEVICE CONTROL TWO
+0x13	0x0013	#	DEVICE CONTROL THREE
+0x14	0x0014	#	DEVICE CONTROL FOUR
+0x15	0x0015	#	NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#	SYNCHRONOUS IDLE
+0x17	0x0017	#	END OF TRANSMISSION BLOCK
+0x18	0x0018	#	CANCEL
+0x19	0x0019	#	END OF MEDIUM
+0x1A	0x001A	#	SUBSTITUTE
+0x1B	0x001B	#	ESCAPE
+0x1C	0x001C	#	FILE SEPARATOR
+0x1D	0x001D	#	GROUP SEPARATOR
+0x1E	0x001E	#	RECORD SEPARATOR
+0x1F	0x001F	#	UNIT SEPARATOR
+0x20	0x0020	#	SPACE
+0x21	0x0021	#	EXCLAMATION MARK
+0x22	0x0022	#	QUOTATION MARK
+0x23	0x0023	#	NUMBER SIGN
+0x24	0x0024	#	DOLLAR SIGN
+0x25	0x0025	#	PERCENT SIGN
+0x26	0x0026	#	AMPERSAND
+0x27	0x0027	#	APOSTROPHE
+0x28	0x0028	#	LEFT PARENTHESIS
+0x29	0x0029	#	RIGHT PARENTHESIS
+0x2A	0x002A	#	ASTERISK
+0x2B	0x002B	#	PLUS SIGN
+0x2C	0x002C	#	COMMA
+0x2D	0x002D	#	HYPHEN-MINUS
+0x2E	0x002E	#	FULL STOP
+0x2F	0x002F	#	SOLIDUS
+0x30	0x0030	#	DIGIT ZERO
+0x31	0x0031	#	DIGIT ONE
+0x32	0x0032	#	DIGIT TWO
+0x33	0x0033	#	DIGIT THREE
+0x34	0x0034	#	DIGIT FOUR
+0x35	0x0035	#	DIGIT FIVE
+0x36	0x0036	#	DIGIT SIX
+0x37	0x0037	#	DIGIT SEVEN
+0x38	0x0038	#	DIGIT EIGHT
+0x39	0x0039	#	DIGIT NINE
+0x3A	0x003A	#	COLON
+0x3B	0x003B	#	SEMICOLON
+0x3C	0x003C	#	LESS-THAN SIGN
+0x3D	0x003D	#	EQUALS SIGN
+0x3E	0x003E	#	GREATER-THAN SIGN
+0x3F	0x003F	#	QUESTION MARK
+0x40	0x0040	#	COMMERCIAL AT
+0x41	0x0041	#	LATIN CAPITAL LETTER A
+0x42	0x0042	#	LATIN CAPITAL LETTER B
+0x43	0x0043	#	LATIN CAPITAL LETTER C
+0x44	0x0044	#	LATIN CAPITAL LETTER D
+0x45	0x0045	#	LATIN CAPITAL LETTER E
+0x46	0x0046	#	LATIN CAPITAL LETTER F
+0x47	0x0047	#	LATIN CAPITAL LETTER G
+0x48	0x0048	#	LATIN CAPITAL LETTER H
+0x49	0x0049	#	LATIN CAPITAL LETTER I
+0x4A	0x004A	#	LATIN CAPITAL LETTER J
+0x4B	0x004B	#	LATIN CAPITAL LETTER K
+0x4C	0x004C	#	LATIN CAPITAL LETTER L
+0x4D	0x004D	#	LATIN CAPITAL LETTER M
+0x4E	0x004E	#	LATIN CAPITAL LETTER N
+0x4F	0x004F	#	LATIN CAPITAL LETTER O
+0x50	0x0050	#	LATIN CAPITAL LETTER P
+0x51	0x0051	#	LATIN CAPITAL LETTER Q
+0x52	0x0052	#	LATIN CAPITAL LETTER R
+0x53	0x0053	#	LATIN CAPITAL LETTER S
+0x54	0x0054	#	LATIN CAPITAL LETTER T
+0x55	0x0055	#	LATIN CAPITAL LETTER U
+0x56	0x0056	#	LATIN CAPITAL LETTER V
+0x57	0x0057	#	LATIN CAPITAL LETTER W
+0x58	0x0058	#	LATIN CAPITAL LETTER X
+0x59	0x0059	#	LATIN CAPITAL LETTER Y
+0x5A	0x005A	#	LATIN CAPITAL LETTER Z
+0x5B	0x005B	#	LEFT SQUARE BRACKET
+0x5C	0x005C	#	REVERSE SOLIDUS
+0x5D	0x005D	#	RIGHT SQUARE BRACKET
+0x5E	0x005E	#	CIRCUMFLEX ACCENT
+0x5F	0x005F	#	LOW LINE
+0x60	0x0060	#	GRAVE ACCENT
+0x61	0x0061	#	LATIN SMALL LETTER A
+0x62	0x0062	#	LATIN SMALL LETTER B
+0x63	0x0063	#	LATIN SMALL LETTER C
+0x64	0x0064	#	LATIN SMALL LETTER D
+0x65	0x0065	#	LATIN SMALL LETTER E
+0x66	0x0066	#	LATIN SMALL LETTER F
+0x67	0x0067	#	LATIN SMALL LETTER G
+0x68	0x0068	#	LATIN SMALL LETTER H
+0x69	0x0069	#	LATIN SMALL LETTER I
+0x6A	0x006A	#	LATIN SMALL LETTER J
+0x6B	0x006B	#	LATIN SMALL LETTER K
+0x6C	0x006C	#	LATIN SMALL LETTER L
+0x6D	0x006D	#	LATIN SMALL LETTER M
+0x6E	0x006E	#	LATIN SMALL LETTER N
+0x6F	0x006F	#	LATIN SMALL LETTER O
+0x70	0x0070	#	LATIN SMALL LETTER P
+0x71	0x0071	#	LATIN SMALL LETTER Q
+0x72	0x0072	#	LATIN SMALL LETTER R
+0x73	0x0073	#	LATIN SMALL LETTER S
+0x74	0x0074	#	LATIN SMALL LETTER T
+0x75	0x0075	#	LATIN SMALL LETTER U
+0x76	0x0076	#	LATIN SMALL LETTER V
+0x77	0x0077	#	LATIN SMALL LETTER W
+0x78	0x0078	#	LATIN SMALL LETTER X
+0x79	0x0079	#	LATIN SMALL LETTER Y
+0x7A	0x007A	#	LATIN SMALL LETTER Z
+0x7B	0x007B	#	LEFT CURLY BRACKET
+0x7C	0x007C	#	VERTICAL LINE
+0x7D	0x007D	#	RIGHT CURLY BRACKET
+0x7E	0x007E	#	TILDE
+0x7F	0x007F	#	DELETE
+0x80	0x0080	#	<control>
+0x81	0x0081	#	<control>
+0x82	0x0082	#	<control>
+0x83	0x0083	#	<control>
+0x84	0x0084	#	<control>
+0x85	0x0085	#	<control>
+0x86	0x0086	#	<control>
+0x87	0x0087	#	<control>
+0x88	0x0088	#	<control>
+0x89	0x0089	#	<control>
+0x8A	0x008A	#	<control>
+0x8B	0x008B	#	<control>
+0x8C	0x008C	#	<control>
+0x8D	0x008D	#	<control>
+0x8E	0x008E	#	<control>
+0x8F	0x008F	#	<control>
+0x90	0x0090	#	<control>
+0x91	0x0091	#	<control>
+0x92	0x0092	#	<control>
+0x93	0x0093	#	<control>
+0x94	0x0094	#	<control>
+0x95	0x0095	#	<control>
+0x96	0x0096	#	<control>
+0x97	0x0097	#	<control>
+0x98	0x0098	#	<control>
+0x99	0x0099	#	<control>
+0x9A	0x009A	#	<control>
+0x9B	0x009B	#	<control>
+0x9C	0x009C	#	<control>
+0x9D	0x009D	#	<control>
+0x9E	0x009E	#	<control>
+0x9F	0x009F	#	<control>
+0xA0	0x00A0	#	NO-BREAK SPACE
+0xA1	0x00A1	#	INVERTED EXCLAMATION MARK
+0xA2	0x00A2	#	CENT SIGN
+0xA3	0x00A3	#	POUND SIGN
+0xA4	0x00A4	#	CURRENCY SIGN
+0xA5	0x00A5	#	YEN SIGN
+0xA6	0x00A6	#	BROKEN BAR
+0xA7	0x00A7	#	SECTION SIGN
+0xA8	0x00A8	#	DIAERESIS
+0xA9	0x00A9	#	COPYRIGHT SIGN
+0xAA	0x00AA	#	FEMININE ORDINAL INDICATOR
+0xAB	0x00AB	#	LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC	0x00AC	#	NOT SIGN
+0xAD	0x00AD	#	SOFT HYPHEN
+0xAE	0x00AE	#	REGISTERED SIGN
+0xAF	0x00AF	#	MACRON
+0xB0	0x00B0	#	DEGREE SIGN
+0xB1	0x00B1	#	PLUS-MINUS SIGN
+0xB2	0x00B2	#	SUPERSCRIPT TWO
+0xB3	0x00B3	#	SUPERSCRIPT THREE
+0xB4	0x00B4	#	ACUTE ACCENT
+0xB5	0x00B5	#	MICRO SIGN
+0xB6	0x00B6	#	PILCROW SIGN
+0xB7	0x00B7	#	MIDDLE DOT
+0xB8	0x00B8	#	CEDILLA
+0xB9	0x00B9	#	SUPERSCRIPT ONE
+0xBA	0x00BA	#	MASCULINE ORDINAL INDICATOR
+0xBB	0x00BB	#	RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC	0x00BC	#	VULGAR FRACTION ONE QUARTER
+0xBD	0x00BD	#	VULGAR FRACTION ONE HALF
+0xBE	0x00BE	#	VULGAR FRACTION THREE QUARTERS
+0xBF	0x00BF	#	INVERTED QUESTION MARK
+0xC0	0x00C0	#	LATIN CAPITAL LETTER A WITH GRAVE
+0xC1	0x00C1	#	LATIN CAPITAL LETTER A WITH ACUTE
+0xC2	0x00C2	#	LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3	0x00C3	#	LATIN CAPITAL LETTER A WITH TILDE
+0xC4	0x00C4	#	LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5	0x00C5	#	LATIN CAPITAL LETTER A WITH RING ABOVE
+0xC6	0x00C6	#	LATIN CAPITAL LETTER AE
+0xC7	0x00C7	#	LATIN CAPITAL LETTER C WITH CEDILLA
+0xC8	0x00C8	#	LATIN CAPITAL LETTER E WITH GRAVE
+0xC9	0x00C9	#	LATIN CAPITAL LETTER E WITH ACUTE
+0xCA	0x00CA	#	LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xCB	0x00CB	#	LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC	0x00CC	#	LATIN CAPITAL LETTER I WITH GRAVE
+0xCD	0x00CD	#	LATIN CAPITAL LETTER I WITH ACUTE
+0xCE	0x00CE	#	LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF	0x00CF	#	LATIN CAPITAL LETTER I WITH DIAERESIS
+0xD0	0x00D0	#	LATIN CAPITAL LETTER ETH (Icelandic)
+0xD1	0x00D1	#	LATIN CAPITAL LETTER N WITH TILDE
+0xD2	0x00D2	#	LATIN CAPITAL LETTER O WITH GRAVE
+0xD3	0x00D3	#	LATIN CAPITAL LETTER O WITH ACUTE
+0xD4	0x00D4	#	LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5	0x00D5	#	LATIN CAPITAL LETTER O WITH TILDE
+0xD6	0x00D6	#	LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7	0x00D7	#	MULTIPLICATION SIGN
+0xD8	0x00D8	#	LATIN CAPITAL LETTER O WITH STROKE
+0xD9	0x00D9	#	LATIN CAPITAL LETTER U WITH GRAVE
+0xDA	0x00DA	#	LATIN CAPITAL LETTER U WITH ACUTE
+0xDB	0x00DB	#	LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xDC	0x00DC	#	LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD	0x00DD	#	LATIN CAPITAL LETTER Y WITH ACUTE
+0xDE	0x00DE	#	LATIN CAPITAL LETTER THORN (Icelandic)
+0xDF	0x00DF	#	LATIN SMALL LETTER SHARP S (German)
+0xE0	0x00E0	#	LATIN SMALL LETTER A WITH GRAVE
+0xE1	0x00E1	#	LATIN SMALL LETTER A WITH ACUTE
+0xE2	0x00E2	#	LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3	0x00E3	#	LATIN SMALL LETTER A WITH TILDE
+0xE4	0x00E4	#	LATIN SMALL LETTER A WITH DIAERESIS
+0xE5	0x00E5	#	LATIN SMALL LETTER A WITH RING ABOVE
+0xE6	0x00E6	#	LATIN SMALL LETTER AE
+0xE7	0x00E7	#	LATIN SMALL LETTER C WITH CEDILLA
+0xE8	0x00E8	#	LATIN SMALL LETTER E WITH GRAVE
+0xE9	0x00E9	#	LATIN SMALL LETTER E WITH ACUTE
+0xEA	0x00EA	#	LATIN SMALL LETTER E WITH CIRCUMFLEX
+0xEB	0x00EB	#	LATIN SMALL LETTER E WITH DIAERESIS
+0xEC	0x00EC	#	LATIN SMALL LETTER I WITH GRAVE
+0xED	0x00ED	#	LATIN SMALL LETTER I WITH ACUTE
+0xEE	0x00EE	#	LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF	0x00EF	#	LATIN SMALL LETTER I WITH DIAERESIS
+0xF0	0x00F0	#	LATIN SMALL LETTER ETH (Icelandic)
+0xF1	0x00F1	#	LATIN SMALL LETTER N WITH TILDE
+0xF2	0x00F2	#	LATIN SMALL LETTER O WITH GRAVE
+0xF3	0x00F3	#	LATIN SMALL LETTER O WITH ACUTE
+0xF4	0x00F4	#	LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5	0x00F5	#	LATIN SMALL LETTER O WITH TILDE
+0xF6	0x00F6	#	LATIN SMALL LETTER O WITH DIAERESIS
+0xF7	0x00F7	#	DIVISION SIGN
+0xF8	0x00F8	#	LATIN SMALL LETTER O WITH STROKE
+0xF9	0x00F9	#	LATIN SMALL LETTER U WITH GRAVE
+0xFA	0x00FA	#	LATIN SMALL LETTER U WITH ACUTE
+0xFB	0x00FB	#	LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xFC	0x00FC	#	LATIN SMALL LETTER U WITH DIAERESIS
+0xFD	0x00FD	#	LATIN SMALL LETTER Y WITH ACUTE
+0xFE	0x00FE	#	LATIN SMALL LETTER THORN (Icelandic)
+0xFF	0x00FF	#	LATIN SMALL LETTER Y WITH DIAERESIS
diff --git a/Resources/8859-10.txt b/Resources/8859-10.txt
new file mode 100644
index 0000000..374a42b
--- /dev/null
+++ b/Resources/8859-10.txt
@@ -0,0 +1,303 @@
+#
+#	Name:             ISO/IEC 8859-10:1998 to Unicode
+#	Unicode version:  3.0
+#	Table version:    1.1
+#	Table format:     Format A
+#	Date:             1999 October 11
+#	Authors:          Ken Whistler <kenw@sybase.com>
+#
+#	Copyright (c) 1999 Unicode, Inc.  All Rights reserved.
+#
+#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+#	No claims are made as to fitness for any particular purpose.  No
+#	warranties of any kind are expressed or implied.  The recipient
+#	agrees to determine applicability of information provided.  If this
+#	file has been provided on optical media by Unicode, Inc., the sole
+#	remedy for any claim will be exchange of defective media within 90
+#	days of receipt.
+#
+#	Unicode, Inc. hereby grants the right to freely use the information
+#	supplied in this file in the creation of products supporting the
+#	Unicode Standard, and to make copies of this file in any form for
+#	internal or external distribution as long as this notice remains
+#	attached.
+#
+#	General notes:
+#
+#	This table contains the data the Unicode Consortium has on how
+#       ISO/IEC 8859-10:1998 characters map into Unicode.
+#
+#	Format:  Three tab-separated columns
+#		 Column #1 is the ISO/IEC 8859-10 code (in hex as 0xXX)
+#		 Column #2 is the Unicode (in hex as 0xXXXX)
+#		 Column #3 the Unicode name (follows a comment sign, '#')
+#
+#	The entries are in ISO/IEC 8859-10 order.
+#
+#	Version history
+#	1.0 version new.
+#       1.1 corrected mistake in mapping of 0xA4
+#
+#	Updated versions of this file may be found in:
+#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
+#
+#	Any comments or problems, contact <errata@unicode.org>
+#	Please note that <errata@unicode.org> is an archival address;
+#	notices will be checked, but do not expect an immediate response.
+#
+0x00	0x0000	#	NULL
+0x01	0x0001	#	START OF HEADING
+0x02	0x0002	#	START OF TEXT
+0x03	0x0003	#	END OF TEXT
+0x04	0x0004	#	END OF TRANSMISSION
+0x05	0x0005	#	ENQUIRY
+0x06	0x0006	#	ACKNOWLEDGE
+0x07	0x0007	#	BELL
+0x08	0x0008	#	BACKSPACE
+0x09	0x0009	#	HORIZONTAL TABULATION
+0x0A	0x000A	#	LINE FEED
+0x0B	0x000B	#	VERTICAL TABULATION
+0x0C	0x000C	#	FORM FEED
+0x0D	0x000D	#	CARRIAGE RETURN
+0x0E	0x000E	#	SHIFT OUT
+0x0F	0x000F	#	SHIFT IN
+0x10	0x0010	#	DATA LINK ESCAPE
+0x11	0x0011	#	DEVICE CONTROL ONE
+0x12	0x0012	#	DEVICE CONTROL TWO
+0x13	0x0013	#	DEVICE CONTROL THREE
+0x14	0x0014	#	DEVICE CONTROL FOUR
+0x15	0x0015	#	NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#	SYNCHRONOUS IDLE
+0x17	0x0017	#	END OF TRANSMISSION BLOCK
+0x18	0x0018	#	CANCEL
+0x19	0x0019	#	END OF MEDIUM
+0x1A	0x001A	#	SUBSTITUTE
+0x1B	0x001B	#	ESCAPE
+0x1C	0x001C	#	FILE SEPARATOR
+0x1D	0x001D	#	GROUP SEPARATOR
+0x1E	0x001E	#	RECORD SEPARATOR
+0x1F	0x001F	#	UNIT SEPARATOR
+0x20	0x0020	#	SPACE
+0x21	0x0021	#	EXCLAMATION MARK
+0x22	0x0022	#	QUOTATION MARK
+0x23	0x0023	#	NUMBER SIGN
+0x24	0x0024	#	DOLLAR SIGN
+0x25	0x0025	#	PERCENT SIGN
+0x26	0x0026	#	AMPERSAND
+0x27	0x0027	#	APOSTROPHE
+0x28	0x0028	#	LEFT PARENTHESIS
+0x29	0x0029	#	RIGHT PARENTHESIS
+0x2A	0x002A	#	ASTERISK
+0x2B	0x002B	#	PLUS SIGN
+0x2C	0x002C	#	COMMA
+0x2D	0x002D	#	HYPHEN-MINUS
+0x2E	0x002E	#	FULL STOP
+0x2F	0x002F	#	SOLIDUS
+0x30	0x0030	#	DIGIT ZERO
+0x31	0x0031	#	DIGIT ONE
+0x32	0x0032	#	DIGIT TWO
+0x33	0x0033	#	DIGIT THREE
+0x34	0x0034	#	DIGIT FOUR
+0x35	0x0035	#	DIGIT FIVE
+0x36	0x0036	#	DIGIT SIX
+0x37	0x0037	#	DIGIT SEVEN
+0x38	0x0038	#	DIGIT EIGHT
+0x39	0x0039	#	DIGIT NINE
+0x3A	0x003A	#	COLON
+0x3B	0x003B	#	SEMICOLON
+0x3C	0x003C	#	LESS-THAN SIGN
+0x3D	0x003D	#	EQUALS SIGN
+0x3E	0x003E	#	GREATER-THAN SIGN
+0x3F	0x003F	#	QUESTION MARK
+0x40	0x0040	#	COMMERCIAL AT
+0x41	0x0041	#	LATIN CAPITAL LETTER A
+0x42	0x0042	#	LATIN CAPITAL LETTER B
+0x43	0x0043	#	LATIN CAPITAL LETTER C
+0x44	0x0044	#	LATIN CAPITAL LETTER D
+0x45	0x0045	#	LATIN CAPITAL LETTER E
+0x46	0x0046	#	LATIN CAPITAL LETTER F
+0x47	0x0047	#	LATIN CAPITAL LETTER G
+0x48	0x0048	#	LATIN CAPITAL LETTER H
+0x49	0x0049	#	LATIN CAPITAL LETTER I
+0x4A	0x004A	#	LATIN CAPITAL LETTER J
+0x4B	0x004B	#	LATIN CAPITAL LETTER K
+0x4C	0x004C	#	LATIN CAPITAL LETTER L
+0x4D	0x004D	#	LATIN CAPITAL LETTER M
+0x4E	0x004E	#	LATIN CAPITAL LETTER N
+0x4F	0x004F	#	LATIN CAPITAL LETTER O
+0x50	0x0050	#	LATIN CAPITAL LETTER P
+0x51	0x0051	#	LATIN CAPITAL LETTER Q
+0x52	0x0052	#	LATIN CAPITAL LETTER R
+0x53	0x0053	#	LATIN CAPITAL LETTER S
+0x54	0x0054	#	LATIN CAPITAL LETTER T
+0x55	0x0055	#	LATIN CAPITAL LETTER U
+0x56	0x0056	#	LATIN CAPITAL LETTER V
+0x57	0x0057	#	LATIN CAPITAL LETTER W
+0x58	0x0058	#	LATIN CAPITAL LETTER X
+0x59	0x0059	#	LATIN CAPITAL LETTER Y
+0x5A	0x005A	#	LATIN CAPITAL LETTER Z
+0x5B	0x005B	#	LEFT SQUARE BRACKET
+0x5C	0x005C	#	REVERSE SOLIDUS
+0x5D	0x005D	#	RIGHT SQUARE BRACKET
+0x5E	0x005E	#	CIRCUMFLEX ACCENT
+0x5F	0x005F	#	LOW LINE
+0x60	0x0060	#	GRAVE ACCENT
+0x61	0x0061	#	LATIN SMALL LETTER A
+0x62	0x0062	#	LATIN SMALL LETTER B
+0x63	0x0063	#	LATIN SMALL LETTER C
+0x64	0x0064	#	LATIN SMALL LETTER D
+0x65	0x0065	#	LATIN SMALL LETTER E
+0x66	0x0066	#	LATIN SMALL LETTER F
+0x67	0x0067	#	LATIN SMALL LETTER G
+0x68	0x0068	#	LATIN SMALL LETTER H
+0x69	0x0069	#	LATIN SMALL LETTER I
+0x6A	0x006A	#	LATIN SMALL LETTER J
+0x6B	0x006B	#	LATIN SMALL LETTER K
+0x6C	0x006C	#	LATIN SMALL LETTER L
+0x6D	0x006D	#	LATIN SMALL LETTER M
+0x6E	0x006E	#	LATIN SMALL LETTER N
+0x6F	0x006F	#	LATIN SMALL LETTER O
+0x70	0x0070	#	LATIN SMALL LETTER P
+0x71	0x0071	#	LATIN SMALL LETTER Q
+0x72	0x0072	#	LATIN SMALL LETTER R
+0x73	0x0073	#	LATIN SMALL LETTER S
+0x74	0x0074	#	LATIN SMALL LETTER T
+0x75	0x0075	#	LATIN SMALL LETTER U
+0x76	0x0076	#	LATIN SMALL LETTER V
+0x77	0x0077	#	LATIN SMALL LETTER W
+0x78	0x0078	#	LATIN SMALL LETTER X
+0x79	0x0079	#	LATIN SMALL LETTER Y
+0x7A	0x007A	#	LATIN SMALL LETTER Z
+0x7B	0x007B	#	LEFT CURLY BRACKET
+0x7C	0x007C	#	VERTICAL LINE
+0x7D	0x007D	#	RIGHT CURLY BRACKET
+0x7E	0x007E	#	TILDE
+0x7F	0x007F	#	DELETE
+0x80	0x0080	#	<control>
+0x81	0x0081	#	<control>
+0x82	0x0082	#	<control>
+0x83	0x0083	#	<control>
+0x84	0x0084	#	<control>
+0x85	0x0085	#	<control>
+0x86	0x0086	#	<control>
+0x87	0x0087	#	<control>
+0x88	0x0088	#	<control>
+0x89	0x0089	#	<control>
+0x8A	0x008A	#	<control>
+0x8B	0x008B	#	<control>
+0x8C	0x008C	#	<control>
+0x8D	0x008D	#	<control>
+0x8E	0x008E	#	<control>
+0x8F	0x008F	#	<control>
+0x90	0x0090	#	<control>
+0x91	0x0091	#	<control>
+0x92	0x0092	#	<control>
+0x93	0x0093	#	<control>
+0x94	0x0094	#	<control>
+0x95	0x0095	#	<control>
+0x96	0x0096	#	<control>
+0x97	0x0097	#	<control>
+0x98	0x0098	#	<control>
+0x99	0x0099	#	<control>
+0x9A	0x009A	#	<control>
+0x9B	0x009B	#	<control>
+0x9C	0x009C	#	<control>
+0x9D	0x009D	#	<control>
+0x9E	0x009E	#	<control>
+0x9F	0x009F	#	<control>
+0xA0	0x00A0	#	NO-BREAK SPACE
+0xA1	0x0104	#	LATIN CAPITAL LETTER A WITH OGONEK
+0xA2	0x0112	#	LATIN CAPITAL LETTER E WITH MACRON
+0xA3	0x0122	#	LATIN CAPITAL LETTER G WITH CEDILLA
+0xA4	0x012A	#	LATIN CAPITAL LETTER I WITH MACRON
+0xA5	0x0128	#	LATIN CAPITAL LETTER I WITH TILDE
+0xA6	0x0136	#	LATIN CAPITAL LETTER K WITH CEDILLA
+0xA7	0x00A7	#	SECTION SIGN
+0xA8	0x013B	#	LATIN CAPITAL LETTER L WITH CEDILLA
+0xA9	0x0110	#	LATIN CAPITAL LETTER D WITH STROKE
+0xAA	0x0160	#	LATIN CAPITAL LETTER S WITH CARON
+0xAB	0x0166	#	LATIN CAPITAL LETTER T WITH STROKE
+0xAC	0x017D	#	LATIN CAPITAL LETTER Z WITH CARON
+0xAD	0x00AD	#	SOFT HYPHEN
+0xAE	0x016A	#	LATIN CAPITAL LETTER U WITH MACRON
+0xAF	0x014A	#	LATIN CAPITAL LETTER ENG
+0xB0	0x00B0	#	DEGREE SIGN
+0xB1	0x0105	#	LATIN SMALL LETTER A WITH OGONEK
+0xB2	0x0113	#	LATIN SMALL LETTER E WITH MACRON
+0xB3	0x0123	#	LATIN SMALL LETTER G WITH CEDILLA
+0xB4	0x012B	#	LATIN SMALL LETTER I WITH MACRON
+0xB5	0x0129	#	LATIN SMALL LETTER I WITH TILDE
+0xB6	0x0137	#	LATIN SMALL LETTER K WITH CEDILLA
+0xB7	0x00B7	#	MIDDLE DOT
+0xB8	0x013C	#	LATIN SMALL LETTER L WITH CEDILLA
+0xB9	0x0111	#	LATIN SMALL LETTER D WITH STROKE
+0xBA	0x0161	#	LATIN SMALL LETTER S WITH CARON
+0xBB	0x0167	#	LATIN SMALL LETTER T WITH STROKE
+0xBC	0x017E	#	LATIN SMALL LETTER Z WITH CARON
+0xBD	0x2015	#	HORIZONTAL BAR
+0xBE	0x016B	#	LATIN SMALL LETTER U WITH MACRON
+0xBF	0x014B	#	LATIN SMALL LETTER ENG
+0xC0	0x0100	#	LATIN CAPITAL LETTER A WITH MACRON
+0xC1	0x00C1	#	LATIN CAPITAL LETTER A WITH ACUTE
+0xC2	0x00C2	#	LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3	0x00C3	#	LATIN CAPITAL LETTER A WITH TILDE
+0xC4	0x00C4	#	LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5	0x00C5	#	LATIN CAPITAL LETTER A WITH RING ABOVE
+0xC6	0x00C6	#	LATIN CAPITAL LETTER AE
+0xC7	0x012E	#	LATIN CAPITAL LETTER I WITH OGONEK
+0xC8	0x010C	#	LATIN CAPITAL LETTER C WITH CARON
+0xC9	0x00C9	#	LATIN CAPITAL LETTER E WITH ACUTE
+0xCA	0x0118	#	LATIN CAPITAL LETTER E WITH OGONEK
+0xCB	0x00CB	#	LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC	0x0116	#	LATIN CAPITAL LETTER E WITH DOT ABOVE
+0xCD	0x00CD	#	LATIN CAPITAL LETTER I WITH ACUTE
+0xCE	0x00CE	#	LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF	0x00CF	#	LATIN CAPITAL LETTER I WITH DIAERESIS
+0xD0	0x00D0	#	LATIN CAPITAL LETTER ETH (Icelandic)
+0xD1	0x0145	#	LATIN CAPITAL LETTER N WITH CEDILLA
+0xD2	0x014C	#	LATIN CAPITAL LETTER O WITH MACRON
+0xD3	0x00D3	#	LATIN CAPITAL LETTER O WITH ACUTE
+0xD4	0x00D4	#	LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5	0x00D5	#	LATIN CAPITAL LETTER O WITH TILDE
+0xD6	0x00D6	#	LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7	0x0168	#	LATIN CAPITAL LETTER U WITH TILDE
+0xD8	0x00D8	#	LATIN CAPITAL LETTER O WITH STROKE
+0xD9	0x0172	#	LATIN CAPITAL LETTER U WITH OGONEK
+0xDA	0x00DA	#	LATIN CAPITAL LETTER U WITH ACUTE
+0xDB	0x00DB	#	LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xDC	0x00DC	#	LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD	0x00DD	#	LATIN CAPITAL LETTER Y WITH ACUTE
+0xDE	0x00DE	#	LATIN CAPITAL LETTER THORN (Icelandic)
+0xDF	0x00DF	#	LATIN SMALL LETTER SHARP S (German)
+0xE0	0x0101	#	LATIN SMALL LETTER A WITH MACRON
+0xE1	0x00E1	#	LATIN SMALL LETTER A WITH ACUTE
+0xE2	0x00E2	#	LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3	0x00E3	#	LATIN SMALL LETTER A WITH TILDE
+0xE4	0x00E4	#	LATIN SMALL LETTER A WITH DIAERESIS
+0xE5	0x00E5	#	LATIN SMALL LETTER A WITH RING ABOVE
+0xE6	0x00E6	#	LATIN SMALL LETTER AE
+0xE7	0x012F	#	LATIN SMALL LETTER I WITH OGONEK
+0xE8	0x010D	#	LATIN SMALL LETTER C WITH CARON
+0xE9	0x00E9	#	LATIN SMALL LETTER E WITH ACUTE
+0xEA	0x0119	#	LATIN SMALL LETTER E WITH OGONEK
+0xEB	0x00EB	#	LATIN SMALL LETTER E WITH DIAERESIS
+0xEC	0x0117	#	LATIN SMALL LETTER E WITH DOT ABOVE
+0xED	0x00ED	#	LATIN SMALL LETTER I WITH ACUTE
+0xEE	0x00EE	#	LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF	0x00EF	#	LATIN SMALL LETTER I WITH DIAERESIS
+0xF0	0x00F0	#	LATIN SMALL LETTER ETH (Icelandic)
+0xF1	0x0146	#	LATIN SMALL LETTER N WITH CEDILLA
+0xF2	0x014D	#	LATIN SMALL LETTER O WITH MACRON
+0xF3	0x00F3	#	LATIN SMALL LETTER O WITH ACUTE
+0xF4	0x00F4	#	LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5	0x00F5	#	LATIN SMALL LETTER O WITH TILDE
+0xF6	0x00F6	#	LATIN SMALL LETTER O WITH DIAERESIS
+0xF7	0x0169	#	LATIN SMALL LETTER U WITH TILDE
+0xF8	0x00F8	#	LATIN SMALL LETTER O WITH STROKE
+0xF9	0x0173	#	LATIN SMALL LETTER U WITH OGONEK
+0xFA	0x00FA	#	LATIN SMALL LETTER U WITH ACUTE
+0xFB	0x00FB	#	LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xFC	0x00FC	#	LATIN SMALL LETTER U WITH DIAERESIS
+0xFD	0x00FD	#	LATIN SMALL LETTER Y WITH ACUTE
+0xFE	0x00FE	#	LATIN SMALL LETTER THORN (Icelandic)
+0xFF	0x0138	#	LATIN SMALL LETTER KRA
diff --git a/Resources/8859-11.txt b/Resources/8859-11.txt
new file mode 100644
index 0000000..ab29d3d
--- /dev/null
+++ b/Resources/8859-11.txt
@@ -0,0 +1,299 @@
+#
+#	Name:             ISO/IEC 8859-11:2001 to Unicode
+#	Unicode version:  3.2
+#	Table version:    1.0
+#	Table format:     Format A
+#	Date:             2002 October 7
+#	Authors:          Ken Whistler <kenw@sybase.com>
+#
+#	Copyright (c) 2002 Unicode, Inc.  All Rights reserved.
+#
+#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+#	No claims are made as to fitness for any particular purpose.  No
+#	warranties of any kind are expressed or implied.  The recipient
+#	agrees to determine applicability of information provided.  If this
+#	file has been provided on optical media by Unicode, Inc., the sole
+#	remedy for any claim will be exchange of defective media within 90
+#	days of receipt.
+#
+#	Unicode, Inc. hereby grants the right to freely use the information
+#	supplied in this file in the creation of products supporting the
+#	Unicode Standard, and to make copies of this file in any form for
+#	internal or external distribution as long as this notice remains
+#	attached.
+#
+#	General notes:
+#
+#	This table contains the data the Unicode Consortium has on how
+#       ISO/IEC 8859-11:2001 characters map into Unicode.
+#
+#	ISO/IEC 8859-11:2001 is equivalent to TIS 620-2533 (1990) with
+#	the addition of 0xA0 NO-BREAK SPACE.
+#
+#	Format:  Three tab-separated columns
+#		 Column #1 is the ISO/IEC 8859-11 code (in hex as 0xXX)
+#		 Column #2 is the Unicode (in hex as 0xXXXX)
+#		 Column #3 the Unicode name (follows a comment sign, '#')
+#
+#	The entries are in ISO/IEC 8859-11 order.
+#
+#	Version history:
+#		2002 October 7  Created
+#
+#	Updated versions of this file may be found in:
+#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
+#
+#	For any comments or problems, please use the Unicode
+#	web contact form at:
+#		http://www.unicode.org/unicode/reporting.html
+#
+0x00	0x0000	#	NULL
+0x01	0x0001	#	START OF HEADING
+0x02	0x0002	#	START OF TEXT
+0x03	0x0003	#	END OF TEXT
+0x04	0x0004	#	END OF TRANSMISSION
+0x05	0x0005	#	ENQUIRY
+0x06	0x0006	#	ACKNOWLEDGE
+0x07	0x0007	#	BELL
+0x08	0x0008	#	BACKSPACE
+0x09	0x0009	#	HORIZONTAL TABULATION
+0x0A	0x000A	#	LINE FEED
+0x0B	0x000B	#	VERTICAL TABULATION
+0x0C	0x000C	#	FORM FEED
+0x0D	0x000D	#	CARRIAGE RETURN
+0x0E	0x000E	#	SHIFT OUT
+0x0F	0x000F	#	SHIFT IN
+0x10	0x0010	#	DATA LINK ESCAPE
+0x11	0x0011	#	DEVICE CONTROL ONE
+0x12	0x0012	#	DEVICE CONTROL TWO
+0x13	0x0013	#	DEVICE CONTROL THREE
+0x14	0x0014	#	DEVICE CONTROL FOUR
+0x15	0x0015	#	NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#	SYNCHRONOUS IDLE
+0x17	0x0017	#	END OF TRANSMISSION BLOCK
+0x18	0x0018	#	CANCEL
+0x19	0x0019	#	END OF MEDIUM
+0x1A	0x001A	#	SUBSTITUTE
+0x1B	0x001B	#	ESCAPE
+0x1C	0x001C	#	FILE SEPARATOR
+0x1D	0x001D	#	GROUP SEPARATOR
+0x1E	0x001E	#	RECORD SEPARATOR
+0x1F	0x001F	#	UNIT SEPARATOR
+0x20	0x0020	#	SPACE
+0x21	0x0021	#	EXCLAMATION MARK
+0x22	0x0022	#	QUOTATION MARK
+0x23	0x0023	#	NUMBER SIGN
+0x24	0x0024	#	DOLLAR SIGN
+0x25	0x0025	#	PERCENT SIGN
+0x26	0x0026	#	AMPERSAND
+0x27	0x0027	#	APOSTROPHE
+0x28	0x0028	#	LEFT PARENTHESIS
+0x29	0x0029	#	RIGHT PARENTHESIS
+0x2A	0x002A	#	ASTERISK
+0x2B	0x002B	#	PLUS SIGN
+0x2C	0x002C	#	COMMA
+0x2D	0x002D	#	HYPHEN-MINUS
+0x2E	0x002E	#	FULL STOP
+0x2F	0x002F	#	SOLIDUS
+0x30	0x0030	#	DIGIT ZERO
+0x31	0x0031	#	DIGIT ONE
+0x32	0x0032	#	DIGIT TWO
+0x33	0x0033	#	DIGIT THREE
+0x34	0x0034	#	DIGIT FOUR
+0x35	0x0035	#	DIGIT FIVE
+0x36	0x0036	#	DIGIT SIX
+0x37	0x0037	#	DIGIT SEVEN
+0x38	0x0038	#	DIGIT EIGHT
+0x39	0x0039	#	DIGIT NINE
+0x3A	0x003A	#	COLON
+0x3B	0x003B	#	SEMICOLON
+0x3C	0x003C	#	LESS-THAN SIGN
+0x3D	0x003D	#	EQUALS SIGN
+0x3E	0x003E	#	GREATER-THAN SIGN
+0x3F	0x003F	#	QUESTION MARK
+0x40	0x0040	#	COMMERCIAL AT
+0x41	0x0041	#	LATIN CAPITAL LETTER A
+0x42	0x0042	#	LATIN CAPITAL LETTER B
+0x43	0x0043	#	LATIN CAPITAL LETTER C
+0x44	0x0044	#	LATIN CAPITAL LETTER D
+0x45	0x0045	#	LATIN CAPITAL LETTER E
+0x46	0x0046	#	LATIN CAPITAL LETTER F
+0x47	0x0047	#	LATIN CAPITAL LETTER G
+0x48	0x0048	#	LATIN CAPITAL LETTER H
+0x49	0x0049	#	LATIN CAPITAL LETTER I
+0x4A	0x004A	#	LATIN CAPITAL LETTER J
+0x4B	0x004B	#	LATIN CAPITAL LETTER K
+0x4C	0x004C	#	LATIN CAPITAL LETTER L
+0x4D	0x004D	#	LATIN CAPITAL LETTER M
+0x4E	0x004E	#	LATIN CAPITAL LETTER N
+0x4F	0x004F	#	LATIN CAPITAL LETTER O
+0x50	0x0050	#	LATIN CAPITAL LETTER P
+0x51	0x0051	#	LATIN CAPITAL LETTER Q
+0x52	0x0052	#	LATIN CAPITAL LETTER R
+0x53	0x0053	#	LATIN CAPITAL LETTER S
+0x54	0x0054	#	LATIN CAPITAL LETTER T
+0x55	0x0055	#	LATIN CAPITAL LETTER U
+0x56	0x0056	#	LATIN CAPITAL LETTER V
+0x57	0x0057	#	LATIN CAPITAL LETTER W
+0x58	0x0058	#	LATIN CAPITAL LETTER X
+0x59	0x0059	#	LATIN CAPITAL LETTER Y
+0x5A	0x005A	#	LATIN CAPITAL LETTER Z
+0x5B	0x005B	#	LEFT SQUARE BRACKET
+0x5C	0x005C	#	REVERSE SOLIDUS
+0x5D	0x005D	#	RIGHT SQUARE BRACKET
+0x5E	0x005E	#	CIRCUMFLEX ACCENT
+0x5F	0x005F	#	LOW LINE
+0x60	0x0060	#	GRAVE ACCENT
+0x61	0x0061	#	LATIN SMALL LETTER A
+0x62	0x0062	#	LATIN SMALL LETTER B
+0x63	0x0063	#	LATIN SMALL LETTER C
+0x64	0x0064	#	LATIN SMALL LETTER D
+0x65	0x0065	#	LATIN SMALL LETTER E
+0x66	0x0066	#	LATIN SMALL LETTER F
+0x67	0x0067	#	LATIN SMALL LETTER G
+0x68	0x0068	#	LATIN SMALL LETTER H
+0x69	0x0069	#	LATIN SMALL LETTER I
+0x6A	0x006A	#	LATIN SMALL LETTER J
+0x6B	0x006B	#	LATIN SMALL LETTER K
+0x6C	0x006C	#	LATIN SMALL LETTER L
+0x6D	0x006D	#	LATIN SMALL LETTER M
+0x6E	0x006E	#	LATIN SMALL LETTER N
+0x6F	0x006F	#	LATIN SMALL LETTER O
+0x70	0x0070	#	LATIN SMALL LETTER P
+0x71	0x0071	#	LATIN SMALL LETTER Q
+0x72	0x0072	#	LATIN SMALL LETTER R
+0x73	0x0073	#	LATIN SMALL LETTER S
+0x74	0x0074	#	LATIN SMALL LETTER T
+0x75	0x0075	#	LATIN SMALL LETTER U
+0x76	0x0076	#	LATIN SMALL LETTER V
+0x77	0x0077	#	LATIN SMALL LETTER W
+0x78	0x0078	#	LATIN SMALL LETTER X
+0x79	0x0079	#	LATIN SMALL LETTER Y
+0x7A	0x007A	#	LATIN SMALL LETTER Z
+0x7B	0x007B	#	LEFT CURLY BRACKET
+0x7C	0x007C	#	VERTICAL LINE
+0x7D	0x007D	#	RIGHT CURLY BRACKET
+0x7E	0x007E	#	TILDE
+0x7F	0x007F	#	DELETE
+0x80	0x0080	#	<control>
+0x81	0x0081	#	<control>
+0x82	0x0082	#	<control>
+0x83	0x0083	#	<control>
+0x84	0x0084	#	<control>
+0x85	0x0085	#	<control>
+0x86	0x0086	#	<control>
+0x87	0x0087	#	<control>
+0x88	0x0088	#	<control>
+0x89	0x0089	#	<control>
+0x8A	0x008A	#	<control>
+0x8B	0x008B	#	<control>
+0x8C	0x008C	#	<control>
+0x8D	0x008D	#	<control>
+0x8E	0x008E	#	<control>
+0x8F	0x008F	#	<control>
+0x90	0x0090	#	<control>
+0x91	0x0091	#	<control>
+0x92	0x0092	#	<control>
+0x93	0x0093	#	<control>
+0x94	0x0094	#	<control>
+0x95	0x0095	#	<control>
+0x96	0x0096	#	<control>
+0x97	0x0097	#	<control>
+0x98	0x0098	#	<control>
+0x99	0x0099	#	<control>
+0x9A	0x009A	#	<control>
+0x9B	0x009B	#	<control>
+0x9C	0x009C	#	<control>
+0x9D	0x009D	#	<control>
+0x9E	0x009E	#	<control>
+0x9F	0x009F	#	<control>
+0xA0	0x00A0	#	NO-BREAK SPACE
+0xA1	0x0E01	#	THAI CHARACTER KO KAI
+0xA2	0x0E02	#	THAI CHARACTER KHO KHAI
+0xA3	0x0E03	#	THAI CHARACTER KHO KHUAT
+0xA4	0x0E04	#	THAI CHARACTER KHO KHWAI
+0xA5	0x0E05	#	THAI CHARACTER KHO KHON
+0xA6	0x0E06	#	THAI CHARACTER KHO RAKHANG
+0xA7	0x0E07	#	THAI CHARACTER NGO NGU
+0xA8	0x0E08	#	THAI CHARACTER CHO CHAN
+0xA9	0x0E09	#	THAI CHARACTER CHO CHING
+0xAA	0x0E0A	#	THAI CHARACTER CHO CHANG
+0xAB	0x0E0B	#	THAI CHARACTER SO SO
+0xAC	0x0E0C	#	THAI CHARACTER CHO CHOE
+0xAD	0x0E0D	#	THAI CHARACTER YO YING
+0xAE	0x0E0E	#	THAI CHARACTER DO CHADA
+0xAF	0x0E0F	#	THAI CHARACTER TO PATAK
+0xB0	0x0E10	#	THAI CHARACTER THO THAN
+0xB1	0x0E11	#	THAI CHARACTER THO NANGMONTHO
+0xB2	0x0E12	#	THAI CHARACTER THO PHUTHAO
+0xB3	0x0E13	#	THAI CHARACTER NO NEN
+0xB4	0x0E14	#	THAI CHARACTER DO DEK
+0xB5	0x0E15	#	THAI CHARACTER TO TAO
+0xB6	0x0E16	#	THAI CHARACTER THO THUNG
+0xB7	0x0E17	#	THAI CHARACTER THO THAHAN
+0xB8	0x0E18	#	THAI CHARACTER THO THONG
+0xB9	0x0E19	#	THAI CHARACTER NO NU
+0xBA	0x0E1A	#	THAI CHARACTER BO BAIMAI
+0xBB	0x0E1B	#	THAI CHARACTER PO PLA
+0xBC	0x0E1C	#	THAI CHARACTER PHO PHUNG
+0xBD	0x0E1D	#	THAI CHARACTER FO FA
+0xBE	0x0E1E	#	THAI CHARACTER PHO PHAN
+0xBF	0x0E1F	#	THAI CHARACTER FO FAN
+0xC0	0x0E20	#	THAI CHARACTER PHO SAMPHAO
+0xC1	0x0E21	#	THAI CHARACTER MO MA
+0xC2	0x0E22	#	THAI CHARACTER YO YAK
+0xC3	0x0E23	#	THAI CHARACTER RO RUA
+0xC4	0x0E24	#	THAI CHARACTER RU
+0xC5	0x0E25	#	THAI CHARACTER LO LING
+0xC6	0x0E26	#	THAI CHARACTER LU
+0xC7	0x0E27	#	THAI CHARACTER WO WAEN
+0xC8	0x0E28	#	THAI CHARACTER SO SALA
+0xC9	0x0E29	#	THAI CHARACTER SO RUSI
+0xCA	0x0E2A	#	THAI CHARACTER SO SUA
+0xCB	0x0E2B	#	THAI CHARACTER HO HIP
+0xCC	0x0E2C	#	THAI CHARACTER LO CHULA
+0xCD	0x0E2D	#	THAI CHARACTER O ANG
+0xCE	0x0E2E	#	THAI CHARACTER HO NOKHUK
+0xCF	0x0E2F	#	THAI CHARACTER PAIYANNOI
+0xD0	0x0E30	#	THAI CHARACTER SARA A
+0xD1	0x0E31	#	THAI CHARACTER MAI HAN-AKAT
+0xD2	0x0E32	#	THAI CHARACTER SARA AA
+0xD3	0x0E33	#	THAI CHARACTER SARA AM
+0xD4	0x0E34	#	THAI CHARACTER SARA I
+0xD5	0x0E35	#	THAI CHARACTER SARA II
+0xD6	0x0E36	#	THAI CHARACTER SARA UE
+0xD7	0x0E37	#	THAI CHARACTER SARA UEE
+0xD8	0x0E38	#	THAI CHARACTER SARA U
+0xD9	0x0E39	#	THAI CHARACTER SARA UU
+0xDA	0x0E3A	#	THAI CHARACTER PHINTHU
+0xDF	0x0E3F	#	THAI CURRENCY SYMBOL BAHT
+0xE0	0x0E40	#	THAI CHARACTER SARA E
+0xE1	0x0E41	#	THAI CHARACTER SARA AE
+0xE2	0x0E42	#	THAI CHARACTER SARA O
+0xE3	0x0E43	#	THAI CHARACTER SARA AI MAIMUAN
+0xE4	0x0E44	#	THAI CHARACTER SARA AI MAIMALAI
+0xE5	0x0E45	#	THAI CHARACTER LAKKHANGYAO
+0xE6	0x0E46	#	THAI CHARACTER MAIYAMOK
+0xE7	0x0E47	#	THAI CHARACTER MAITAIKHU
+0xE8	0x0E48	#	THAI CHARACTER MAI EK
+0xE9	0x0E49	#	THAI CHARACTER MAI THO
+0xEA	0x0E4A	#	THAI CHARACTER MAI TRI
+0xEB	0x0E4B	#	THAI CHARACTER MAI CHATTAWA
+0xEC	0x0E4C	#	THAI CHARACTER THANTHAKHAT
+0xED	0x0E4D	#	THAI CHARACTER NIKHAHIT
+0xEE	0x0E4E	#	THAI CHARACTER YAMAKKAN
+0xEF	0x0E4F	#	THAI CHARACTER FONGMAN
+0xF0	0x0E50	#	THAI DIGIT ZERO
+0xF1	0x0E51	#	THAI DIGIT ONE
+0xF2	0x0E52	#	THAI DIGIT TWO
+0xF3	0x0E53	#	THAI DIGIT THREE
+0xF4	0x0E54	#	THAI DIGIT FOUR
+0xF5	0x0E55	#	THAI DIGIT FIVE
+0xF6	0x0E56	#	THAI DIGIT SIX
+0xF7	0x0E57	#	THAI DIGIT SEVEN
+0xF8	0x0E58	#	THAI DIGIT EIGHT
+0xF9	0x0E59	#	THAI DIGIT NINE
+0xFA	0x0E5A	#	THAI CHARACTER ANGKHANKHU
+0xFB	0x0E5B	#	THAI CHARACTER KHOMUT
+
+
diff --git a/Resources/8859-13.txt b/Resources/8859-13.txt
new file mode 100644
index 0000000..cd11b53
--- /dev/null
+++ b/Resources/8859-13.txt
@@ -0,0 +1,299 @@
+#
+#	Name:             ISO/IEC 8859-13:1998  to Unicode
+#	Unicode version:  3.0
+#	Table version:    1.0
+#	Table format:     Format A
+#	Date:             1999 July 27
+#	Authors:          Ken Whistler <kenw@sybase.com>
+#
+#	Copyright (c) 1998 - 1999 Unicode, Inc.  All Rights reserved.
+#
+#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+#	No claims are made as to fitness for any particular purpose.  No
+#	warranties of any kind are expressed or implied.  The recipient
+#	agrees to determine applicability of information provided.  If this
+#	file has been provided on optical media by Unicode, Inc., the sole
+#	remedy for any claim will be exchange of defective media within 90
+#	days of receipt.
+#
+#	Unicode, Inc. hereby grants the right to freely use the information
+#	supplied in this file in the creation of products supporting the
+#	Unicode Standard, and to make copies of this file in any form for
+#	internal or external distribution as long as this notice remains
+#	attached.
+#
+#	General notes:
+#
+#	This table contains the data the Unicode Consortium has on how
+#       ISO/IEC 8859-13:1998 characters map into Unicode.
+#
+#	Format:  Three tab-separated columns
+#		 Column #1 is the ISO/IEC 8859-13 code (in hex as 0xXX)
+#		 Column #2 is the Unicode (in hex as 0xXXXX)
+#		 Column #3 the Unicode name (follows a comment sign, '#')
+#
+#	The entries are in ISO/IEC 8859-13 order.
+#
+#	Updated versions of this file may be found in:
+#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
+#
+#	Any comments or problems, contact <errata@unicode.org>
+#	Please note that <errata@unicode.org> is an archival address;
+#	notices will be checked, but do not expect an immediate response.
+#
+0x00	0x0000	#	NULL
+0x01	0x0001	#	START OF HEADING
+0x02	0x0002	#	START OF TEXT
+0x03	0x0003	#	END OF TEXT
+0x04	0x0004	#	END OF TRANSMISSION
+0x05	0x0005	#	ENQUIRY
+0x06	0x0006	#	ACKNOWLEDGE
+0x07	0x0007	#	BELL
+0x08	0x0008	#	BACKSPACE
+0x09	0x0009	#	HORIZONTAL TABULATION
+0x0A	0x000A	#	LINE FEED
+0x0B	0x000B	#	VERTICAL TABULATION
+0x0C	0x000C	#	FORM FEED
+0x0D	0x000D	#	CARRIAGE RETURN
+0x0E	0x000E	#	SHIFT OUT
+0x0F	0x000F	#	SHIFT IN
+0x10	0x0010	#	DATA LINK ESCAPE
+0x11	0x0011	#	DEVICE CONTROL ONE
+0x12	0x0012	#	DEVICE CONTROL TWO
+0x13	0x0013	#	DEVICE CONTROL THREE
+0x14	0x0014	#	DEVICE CONTROL FOUR
+0x15	0x0015	#	NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#	SYNCHRONOUS IDLE
+0x17	0x0017	#	END OF TRANSMISSION BLOCK
+0x18	0x0018	#	CANCEL
+0x19	0x0019	#	END OF MEDIUM
+0x1A	0x001A	#	SUBSTITUTE
+0x1B	0x001B	#	ESCAPE
+0x1C	0x001C	#	FILE SEPARATOR
+0x1D	0x001D	#	GROUP SEPARATOR
+0x1E	0x001E	#	RECORD SEPARATOR
+0x1F	0x001F	#	UNIT SEPARATOR
+0x20	0x0020	#	SPACE
+0x21	0x0021	#	EXCLAMATION MARK
+0x22	0x0022	#	QUOTATION MARK
+0x23	0x0023	#	NUMBER SIGN
+0x24	0x0024	#	DOLLAR SIGN
+0x25	0x0025	#	PERCENT SIGN
+0x26	0x0026	#	AMPERSAND
+0x27	0x0027	#	APOSTROPHE
+0x28	0x0028	#	LEFT PARENTHESIS
+0x29	0x0029	#	RIGHT PARENTHESIS
+0x2A	0x002A	#	ASTERISK
+0x2B	0x002B	#	PLUS SIGN
+0x2C	0x002C	#	COMMA
+0x2D	0x002D	#	HYPHEN-MINUS
+0x2E	0x002E	#	FULL STOP
+0x2F	0x002F	#	SOLIDUS
+0x30	0x0030	#	DIGIT ZERO
+0x31	0x0031	#	DIGIT ONE
+0x32	0x0032	#	DIGIT TWO
+0x33	0x0033	#	DIGIT THREE
+0x34	0x0034	#	DIGIT FOUR
+0x35	0x0035	#	DIGIT FIVE
+0x36	0x0036	#	DIGIT SIX
+0x37	0x0037	#	DIGIT SEVEN
+0x38	0x0038	#	DIGIT EIGHT
+0x39	0x0039	#	DIGIT NINE
+0x3A	0x003A	#	COLON
+0x3B	0x003B	#	SEMICOLON
+0x3C	0x003C	#	LESS-THAN SIGN
+0x3D	0x003D	#	EQUALS SIGN
+0x3E	0x003E	#	GREATER-THAN SIGN
+0x3F	0x003F	#	QUESTION MARK
+0x40	0x0040	#	COMMERCIAL AT
+0x41	0x0041	#	LATIN CAPITAL LETTER A
+0x42	0x0042	#	LATIN CAPITAL LETTER B
+0x43	0x0043	#	LATIN CAPITAL LETTER C
+0x44	0x0044	#	LATIN CAPITAL LETTER D
+0x45	0x0045	#	LATIN CAPITAL LETTER E
+0x46	0x0046	#	LATIN CAPITAL LETTER F
+0x47	0x0047	#	LATIN CAPITAL LETTER G
+0x48	0x0048	#	LATIN CAPITAL LETTER H
+0x49	0x0049	#	LATIN CAPITAL LETTER I
+0x4A	0x004A	#	LATIN CAPITAL LETTER J
+0x4B	0x004B	#	LATIN CAPITAL LETTER K
+0x4C	0x004C	#	LATIN CAPITAL LETTER L
+0x4D	0x004D	#	LATIN CAPITAL LETTER M
+0x4E	0x004E	#	LATIN CAPITAL LETTER N
+0x4F	0x004F	#	LATIN CAPITAL LETTER O
+0x50	0x0050	#	LATIN CAPITAL LETTER P
+0x51	0x0051	#	LATIN CAPITAL LETTER Q
+0x52	0x0052	#	LATIN CAPITAL LETTER R
+0x53	0x0053	#	LATIN CAPITAL LETTER S
+0x54	0x0054	#	LATIN CAPITAL LETTER T
+0x55	0x0055	#	LATIN CAPITAL LETTER U
+0x56	0x0056	#	LATIN CAPITAL LETTER V
+0x57	0x0057	#	LATIN CAPITAL LETTER W
+0x58	0x0058	#	LATIN CAPITAL LETTER X
+0x59	0x0059	#	LATIN CAPITAL LETTER Y
+0x5A	0x005A	#	LATIN CAPITAL LETTER Z
+0x5B	0x005B	#	LEFT SQUARE BRACKET
+0x5C	0x005C	#	REVERSE SOLIDUS
+0x5D	0x005D	#	RIGHT SQUARE BRACKET
+0x5E	0x005E	#	CIRCUMFLEX ACCENT
+0x5F	0x005F	#	LOW LINE
+0x60	0x0060	#	GRAVE ACCENT
+0x61	0x0061	#	LATIN SMALL LETTER A
+0x62	0x0062	#	LATIN SMALL LETTER B
+0x63	0x0063	#	LATIN SMALL LETTER C
+0x64	0x0064	#	LATIN SMALL LETTER D
+0x65	0x0065	#	LATIN SMALL LETTER E
+0x66	0x0066	#	LATIN SMALL LETTER F
+0x67	0x0067	#	LATIN SMALL LETTER G
+0x68	0x0068	#	LATIN SMALL LETTER H
+0x69	0x0069	#	LATIN SMALL LETTER I
+0x6A	0x006A	#	LATIN SMALL LETTER J
+0x6B	0x006B	#	LATIN SMALL LETTER K
+0x6C	0x006C	#	LATIN SMALL LETTER L
+0x6D	0x006D	#	LATIN SMALL LETTER M
+0x6E	0x006E	#	LATIN SMALL LETTER N
+0x6F	0x006F	#	LATIN SMALL LETTER O
+0x70	0x0070	#	LATIN SMALL LETTER P
+0x71	0x0071	#	LATIN SMALL LETTER Q
+0x72	0x0072	#	LATIN SMALL LETTER R
+0x73	0x0073	#	LATIN SMALL LETTER S
+0x74	0x0074	#	LATIN SMALL LETTER T
+0x75	0x0075	#	LATIN SMALL LETTER U
+0x76	0x0076	#	LATIN SMALL LETTER V
+0x77	0x0077	#	LATIN SMALL LETTER W
+0x78	0x0078	#	LATIN SMALL LETTER X
+0x79	0x0079	#	LATIN SMALL LETTER Y
+0x7A	0x007A	#	LATIN SMALL LETTER Z
+0x7B	0x007B	#	LEFT CURLY BRACKET
+0x7C	0x007C	#	VERTICAL LINE
+0x7D	0x007D	#	RIGHT CURLY BRACKET
+0x7E	0x007E	#	TILDE
+0x7F	0x007F	#	DELETE
+0x80	0x0080	#	<control>
+0x81	0x0081	#	<control>
+0x82	0x0082	#	<control>
+0x83	0x0083	#	<control>
+0x84	0x0084	#	<control>
+0x85	0x0085	#	<control>
+0x86	0x0086	#	<control>
+0x87	0x0087	#	<control>
+0x88	0x0088	#	<control>
+0x89	0x0089	#	<control>
+0x8A	0x008A	#	<control>
+0x8B	0x008B	#	<control>
+0x8C	0x008C	#	<control>
+0x8D	0x008D	#	<control>
+0x8E	0x008E	#	<control>
+0x8F	0x008F	#	<control>
+0x90	0x0090	#	<control>
+0x91	0x0091	#	<control>
+0x92	0x0092	#	<control>
+0x93	0x0093	#	<control>
+0x94	0x0094	#	<control>
+0x95	0x0095	#	<control>
+0x96	0x0096	#	<control>
+0x97	0x0097	#	<control>
+0x98	0x0098	#	<control>
+0x99	0x0099	#	<control>
+0x9A	0x009A	#	<control>
+0x9B	0x009B	#	<control>
+0x9C	0x009C	#	<control>
+0x9D	0x009D	#	<control>
+0x9E	0x009E	#	<control>
+0x9F	0x009F	#	<control>
+0xA0	0x00A0	#	NO-BREAK SPACE
+0xA1	0x201D	#	RIGHT DOUBLE QUOTATION MARK
+0xA2	0x00A2	#	CENT SIGN
+0xA3	0x00A3	#	POUND SIGN
+0xA4	0x00A4	#	CURRENCY SIGN
+0xA5	0x201E	#	DOUBLE LOW-9 QUOTATION MARK
+0xA6	0x00A6	#	BROKEN BAR
+0xA7	0x00A7	#	SECTION SIGN
+0xA8	0x00D8	#	LATIN CAPITAL LETTER O WITH STROKE
+0xA9	0x00A9	#	COPYRIGHT SIGN
+0xAA	0x0156	#	LATIN CAPITAL LETTER R WITH CEDILLA
+0xAB	0x00AB	#	LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC	0x00AC	#	NOT SIGN
+0xAD	0x00AD	#	SOFT HYPHEN
+0xAE	0x00AE	#	REGISTERED SIGN
+0xAF	0x00C6	#	LATIN CAPITAL LETTER AE
+0xB0	0x00B0	#	DEGREE SIGN
+0xB1	0x00B1	#	PLUS-MINUS SIGN
+0xB2	0x00B2	#	SUPERSCRIPT TWO
+0xB3	0x00B3	#	SUPERSCRIPT THREE
+0xB4	0x201C	#	LEFT DOUBLE QUOTATION MARK
+0xB5	0x00B5	#	MICRO SIGN
+0xB6	0x00B6	#	PILCROW SIGN
+0xB7	0x00B7	#	MIDDLE DOT
+0xB8	0x00F8	#	LATIN SMALL LETTER O WITH STROKE
+0xB9	0x00B9	#	SUPERSCRIPT ONE
+0xBA	0x0157	#	LATIN SMALL LETTER R WITH CEDILLA
+0xBB	0x00BB	#	RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC	0x00BC	#	VULGAR FRACTION ONE QUARTER
+0xBD	0x00BD	#	VULGAR FRACTION ONE HALF
+0xBE	0x00BE	#	VULGAR FRACTION THREE QUARTERS
+0xBF	0x00E6	#	LATIN SMALL LETTER AE
+0xC0	0x0104	#	LATIN CAPITAL LETTER A WITH OGONEK
+0xC1	0x012E	#	LATIN CAPITAL LETTER I WITH OGONEK
+0xC2	0x0100	#	LATIN CAPITAL LETTER A WITH MACRON
+0xC3	0x0106	#	LATIN CAPITAL LETTER C WITH ACUTE
+0xC4	0x00C4	#	LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5	0x00C5	#	LATIN CAPITAL LETTER A WITH RING ABOVE
+0xC6	0x0118	#	LATIN CAPITAL LETTER E WITH OGONEK
+0xC7	0x0112	#	LATIN CAPITAL LETTER E WITH MACRON
+0xC8	0x010C	#	LATIN CAPITAL LETTER C WITH CARON
+0xC9	0x00C9	#	LATIN CAPITAL LETTER E WITH ACUTE
+0xCA	0x0179	#	LATIN CAPITAL LETTER Z WITH ACUTE
+0xCB	0x0116	#	LATIN CAPITAL LETTER E WITH DOT ABOVE
+0xCC	0x0122	#	LATIN CAPITAL LETTER G WITH CEDILLA
+0xCD	0x0136	#	LATIN CAPITAL LETTER K WITH CEDILLA
+0xCE	0x012A	#	LATIN CAPITAL LETTER I WITH MACRON
+0xCF	0x013B	#	LATIN CAPITAL LETTER L WITH CEDILLA
+0xD0	0x0160	#	LATIN CAPITAL LETTER S WITH CARON
+0xD1	0x0143	#	LATIN CAPITAL LETTER N WITH ACUTE
+0xD2	0x0145	#	LATIN CAPITAL LETTER N WITH CEDILLA
+0xD3	0x00D3	#	LATIN CAPITAL LETTER O WITH ACUTE
+0xD4	0x014C	#	LATIN CAPITAL LETTER O WITH MACRON
+0xD5	0x00D5	#	LATIN CAPITAL LETTER O WITH TILDE
+0xD6	0x00D6	#	LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7	0x00D7	#	MULTIPLICATION SIGN
+0xD8	0x0172	#	LATIN CAPITAL LETTER U WITH OGONEK
+0xD9	0x0141	#	LATIN CAPITAL LETTER L WITH STROKE
+0xDA	0x015A	#	LATIN CAPITAL LETTER S WITH ACUTE
+0xDB	0x016A	#	LATIN CAPITAL LETTER U WITH MACRON
+0xDC	0x00DC	#	LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD	0x017B	#	LATIN CAPITAL LETTER Z WITH DOT ABOVE
+0xDE	0x017D	#	LATIN CAPITAL LETTER Z WITH CARON
+0xDF	0x00DF	#	LATIN SMALL LETTER SHARP S (German)
+0xE0	0x0105	#	LATIN SMALL LETTER A WITH OGONEK
+0xE1	0x012F	#	LATIN SMALL LETTER I WITH OGONEK
+0xE2	0x0101	#	LATIN SMALL LETTER A WITH MACRON
+0xE3	0x0107	#	LATIN SMALL LETTER C WITH ACUTE
+0xE4	0x00E4	#	LATIN SMALL LETTER A WITH DIAERESIS
+0xE5	0x00E5	#	LATIN SMALL LETTER A WITH RING ABOVE
+0xE6	0x0119	#	LATIN SMALL LETTER E WITH OGONEK
+0xE7	0x0113	#	LATIN SMALL LETTER E WITH MACRON
+0xE8	0x010D	#	LATIN SMALL LETTER C WITH CARON
+0xE9	0x00E9	#	LATIN SMALL LETTER E WITH ACUTE
+0xEA	0x017A	#	LATIN SMALL LETTER Z WITH ACUTE
+0xEB	0x0117	#	LATIN SMALL LETTER E WITH DOT ABOVE
+0xEC	0x0123	#	LATIN SMALL LETTER G WITH CEDILLA
+0xED	0x0137	#	LATIN SMALL LETTER K WITH CEDILLA
+0xEE	0x012B	#	LATIN SMALL LETTER I WITH MACRON
+0xEF	0x013C	#	LATIN SMALL LETTER L WITH CEDILLA
+0xF0	0x0161	#	LATIN SMALL LETTER S WITH CARON
+0xF1	0x0144	#	LATIN SMALL LETTER N WITH ACUTE
+0xF2	0x0146	#	LATIN SMALL LETTER N WITH CEDILLA
+0xF3	0x00F3	#	LATIN SMALL LETTER O WITH ACUTE
+0xF4	0x014D	#	LATIN SMALL LETTER O WITH MACRON
+0xF5	0x00F5	#	LATIN SMALL LETTER O WITH TILDE
+0xF6	0x00F6	#	LATIN SMALL LETTER O WITH DIAERESIS
+0xF7	0x00F7	#	DIVISION SIGN
+0xF8	0x0173	#	LATIN SMALL LETTER U WITH OGONEK
+0xF9	0x0142	#	LATIN SMALL LETTER L WITH STROKE
+0xFA	0x015B	#	LATIN SMALL LETTER S WITH ACUTE
+0xFB	0x016B	#	LATIN SMALL LETTER U WITH MACRON
+0xFC	0x00FC	#	LATIN SMALL LETTER U WITH DIAERESIS
+0xFD	0x017C	#	LATIN SMALL LETTER Z WITH DOT ABOVE
+0xFE	0x017E	#	LATIN SMALL LETTER Z WITH CARON
+0xFF	0x2019	#	RIGHT SINGLE QUOTATION MARK
diff --git a/Resources/8859-14.txt b/Resources/8859-14.txt
new file mode 100644
index 0000000..36038f4
--- /dev/null
+++ b/Resources/8859-14.txt
@@ -0,0 +1,301 @@
+#
+#	Name:             ISO/IEC 8859-14:1998 to Unicode
+#	Unicode version:  3.0
+#	Table version:    1.0
+#	Table format:     Format A
+#	Date:             1999 July 27
+#	Authors:          Markus Kuhn <mkuhn@acm.org>
+#			  Ken Whistler <kenw@sybase.com>
+#
+#	Copyright (c) 1998 - 1999 Unicode, Inc.  All Rights reserved.
+#
+#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+#	No claims are made as to fitness for any particular purpose.  No
+#	warranties of any kind are expressed or implied.  The recipient
+#	agrees to determine applicability of information provided.  If this
+#	file has been provided on optical media by Unicode, Inc., the sole
+#	remedy for any claim will be exchange of defective media within 90
+#	days of receipt.
+#
+#	Unicode, Inc. hereby grants the right to freely use the information
+#	supplied in this file in the creation of products supporting the
+#	Unicode Standard, and to make copies of this file in any form for
+#	internal or external distribution as long as this notice remains
+#	attached.
+#
+#	General notes:
+#
+#	This table contains the data the Unicode Consortium has on how
+#       ISO/IEC 8859-14:1998 characters map into Unicode.
+#
+#	Format:  Three tab-separated columns
+#		 Column #1 is the ISO/IEC 8859-14 code (in hex as 0xXX)
+#		 Column #2 is the Unicode (in hex as 0xXXXX)
+#		 Column #3 the Unicode name (follows a comment sign, '#')
+#
+#	The entries are in ISO/IEC 8859-14 order.
+#
+#	Updated versions of this file may be found in:
+#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
+#
+#	Any comments or problems, contact <errata@unicode.org>
+#	Please note that <errata@unicode.org> is an archival address;
+#	notices will be checked, but do not expect an immediate response.
+#
+0x00	0x0000	#	NULL
+0x01	0x0001	#	START OF HEADING
+0x02	0x0002	#	START OF TEXT
+0x03	0x0003	#	END OF TEXT
+0x04	0x0004	#	END OF TRANSMISSION
+0x05	0x0005	#	ENQUIRY
+0x06	0x0006	#	ACKNOWLEDGE
+0x07	0x0007	#	BELL
+0x08	0x0008	#	BACKSPACE
+0x09	0x0009	#	HORIZONTAL TABULATION
+0x0A	0x000A	#	LINE FEED
+0x0B	0x000B	#	VERTICAL TABULATION
+0x0C	0x000C	#	FORM FEED
+0x0D	0x000D	#	CARRIAGE RETURN
+0x0E	0x000E	#	SHIFT OUT
+0x0F	0x000F	#	SHIFT IN
+0x10	0x0010	#	DATA LINK ESCAPE
+0x11	0x0011	#	DEVICE CONTROL ONE
+0x12	0x0012	#	DEVICE CONTROL TWO
+0x13	0x0013	#	DEVICE CONTROL THREE
+0x14	0x0014	#	DEVICE CONTROL FOUR
+0x15	0x0015	#	NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#	SYNCHRONOUS IDLE
+0x17	0x0017	#	END OF TRANSMISSION BLOCK
+0x18	0x0018	#	CANCEL
+0x19	0x0019	#	END OF MEDIUM
+0x1A	0x001A	#	SUBSTITUTE
+0x1B	0x001B	#	ESCAPE
+0x1C	0x001C	#	FILE SEPARATOR
+0x1D	0x001D	#	GROUP SEPARATOR
+0x1E	0x001E	#	RECORD SEPARATOR
+0x1F	0x001F	#	UNIT SEPARATOR
+0x20	0x0020	#	SPACE
+0x21	0x0021	#	EXCLAMATION MARK
+0x22	0x0022	#	QUOTATION MARK
+0x23	0x0023	#	NUMBER SIGN
+0x24	0x0024	#	DOLLAR SIGN
+0x25	0x0025	#	PERCENT SIGN
+0x26	0x0026	#	AMPERSAND
+0x27	0x0027	#	APOSTROPHE
+0x28	0x0028	#	LEFT PARENTHESIS
+0x29	0x0029	#	RIGHT PARENTHESIS
+0x2A	0x002A	#	ASTERISK
+0x2B	0x002B	#	PLUS SIGN
+0x2C	0x002C	#	COMMA
+0x2D	0x002D	#	HYPHEN-MINUS
+0x2E	0x002E	#	FULL STOP
+0x2F	0x002F	#	SOLIDUS
+0x30	0x0030	#	DIGIT ZERO
+0x31	0x0031	#	DIGIT ONE
+0x32	0x0032	#	DIGIT TWO
+0x33	0x0033	#	DIGIT THREE
+0x34	0x0034	#	DIGIT FOUR
+0x35	0x0035	#	DIGIT FIVE
+0x36	0x0036	#	DIGIT SIX
+0x37	0x0037	#	DIGIT SEVEN
+0x38	0x0038	#	DIGIT EIGHT
+0x39	0x0039	#	DIGIT NINE
+0x3A	0x003A	#	COLON
+0x3B	0x003B	#	SEMICOLON
+0x3C	0x003C	#	LESS-THAN SIGN
+0x3D	0x003D	#	EQUALS SIGN
+0x3E	0x003E	#	GREATER-THAN SIGN
+0x3F	0x003F	#	QUESTION MARK
+0x40	0x0040	#	COMMERCIAL AT
+0x41	0x0041	#	LATIN CAPITAL LETTER A
+0x42	0x0042	#	LATIN CAPITAL LETTER B
+0x43	0x0043	#	LATIN CAPITAL LETTER C
+0x44	0x0044	#	LATIN CAPITAL LETTER D
+0x45	0x0045	#	LATIN CAPITAL LETTER E
+0x46	0x0046	#	LATIN CAPITAL LETTER F
+0x47	0x0047	#	LATIN CAPITAL LETTER G
+0x48	0x0048	#	LATIN CAPITAL LETTER H
+0x49	0x0049	#	LATIN CAPITAL LETTER I
+0x4A	0x004A	#	LATIN CAPITAL LETTER J
+0x4B	0x004B	#	LATIN CAPITAL LETTER K
+0x4C	0x004C	#	LATIN CAPITAL LETTER L
+0x4D	0x004D	#	LATIN CAPITAL LETTER M
+0x4E	0x004E	#	LATIN CAPITAL LETTER N
+0x4F	0x004F	#	LATIN CAPITAL LETTER O
+0x50	0x0050	#	LATIN CAPITAL LETTER P
+0x51	0x0051	#	LATIN CAPITAL LETTER Q
+0x52	0x0052	#	LATIN CAPITAL LETTER R
+0x53	0x0053	#	LATIN CAPITAL LETTER S
+0x54	0x0054	#	LATIN CAPITAL LETTER T
+0x55	0x0055	#	LATIN CAPITAL LETTER U
+0x56	0x0056	#	LATIN CAPITAL LETTER V
+0x57	0x0057	#	LATIN CAPITAL LETTER W
+0x58	0x0058	#	LATIN CAPITAL LETTER X
+0x59	0x0059	#	LATIN CAPITAL LETTER Y
+0x5A	0x005A	#	LATIN CAPITAL LETTER Z
+0x5B	0x005B	#	LEFT SQUARE BRACKET
+0x5C	0x005C	#	REVERSE SOLIDUS
+0x5D	0x005D	#	RIGHT SQUARE BRACKET
+0x5E	0x005E	#	CIRCUMFLEX ACCENT
+0x5F	0x005F	#	LOW LINE
+0x60	0x0060	#	GRAVE ACCENT
+0x61	0x0061	#	LATIN SMALL LETTER A
+0x62	0x0062	#	LATIN SMALL LETTER B
+0x63	0x0063	#	LATIN SMALL LETTER C
+0x64	0x0064	#	LATIN SMALL LETTER D
+0x65	0x0065	#	LATIN SMALL LETTER E
+0x66	0x0066	#	LATIN SMALL LETTER F
+0x67	0x0067	#	LATIN SMALL LETTER G
+0x68	0x0068	#	LATIN SMALL LETTER H
+0x69	0x0069	#	LATIN SMALL LETTER I
+0x6A	0x006A	#	LATIN SMALL LETTER J
+0x6B	0x006B	#	LATIN SMALL LETTER K
+0x6C	0x006C	#	LATIN SMALL LETTER L
+0x6D	0x006D	#	LATIN SMALL LETTER M
+0x6E	0x006E	#	LATIN SMALL LETTER N
+0x6F	0x006F	#	LATIN SMALL LETTER O
+0x70	0x0070	#	LATIN SMALL LETTER P
+0x71	0x0071	#	LATIN SMALL LETTER Q
+0x72	0x0072	#	LATIN SMALL LETTER R
+0x73	0x0073	#	LATIN SMALL LETTER S
+0x74	0x0074	#	LATIN SMALL LETTER T
+0x75	0x0075	#	LATIN SMALL LETTER U
+0x76	0x0076	#	LATIN SMALL LETTER V
+0x77	0x0077	#	LATIN SMALL LETTER W
+0x78	0x0078	#	LATIN SMALL LETTER X
+0x79	0x0079	#	LATIN SMALL LETTER Y
+0x7A	0x007A	#	LATIN SMALL LETTER Z
+0x7B	0x007B	#	LEFT CURLY BRACKET
+0x7C	0x007C	#	VERTICAL LINE
+0x7D	0x007D	#	RIGHT CURLY BRACKET
+0x7E	0x007E	#	TILDE
+0x7F	0x007F	#	DELETE
+0x80	0x0080	#	<control>
+0x81	0x0081	#	<control>
+0x82	0x0082	#	<control>
+0x83	0x0083	#	<control>
+0x84	0x0084	#	<control>
+0x85	0x0085	#	<control>
+0x86	0x0086	#	<control>
+0x87	0x0087	#	<control>
+0x88	0x0088	#	<control>
+0x89	0x0089	#	<control>
+0x8A	0x008A	#	<control>
+0x8B	0x008B	#	<control>
+0x8C	0x008C	#	<control>
+0x8D	0x008D	#	<control>
+0x8E	0x008E	#	<control>
+0x8F	0x008F	#	<control>
+0x90	0x0090	#	<control>
+0x91	0x0091	#	<control>
+0x92	0x0092	#	<control>
+0x93	0x0093	#	<control>
+0x94	0x0094	#	<control>
+0x95	0x0095	#	<control>
+0x96	0x0096	#	<control>
+0x97	0x0097	#	<control>
+0x98	0x0098	#	<control>
+0x99	0x0099	#	<control>
+0x9A	0x009A	#	<control>
+0x9B	0x009B	#	<control>
+0x9C	0x009C	#	<control>
+0x9D	0x009D	#	<control>
+0x9E	0x009E	#	<control>
+0x9F	0x009F	#	<control>
+0xA0	0x00A0	#	NO-BREAK SPACE
+0xA1	0x1E02	#	LATIN CAPITAL LETTER B WITH DOT ABOVE
+0xA2	0x1E03	#	LATIN SMALL LETTER B WITH DOT ABOVE
+0xA3	0x00A3	#	POUND SIGN
+0xA4	0x010A	#	LATIN CAPITAL LETTER C WITH DOT ABOVE
+0xA5	0x010B	#	LATIN SMALL LETTER C WITH DOT ABOVE
+0xA6	0x1E0A	#	LATIN CAPITAL LETTER D WITH DOT ABOVE
+0xA7	0x00A7	#	SECTION SIGN
+0xA8	0x1E80	#	LATIN CAPITAL LETTER W WITH GRAVE
+0xA9	0x00A9	#	COPYRIGHT SIGN
+0xAA	0x1E82	#	LATIN CAPITAL LETTER W WITH ACUTE
+0xAB	0x1E0B	#	LATIN SMALL LETTER D WITH DOT ABOVE
+0xAC	0x1EF2	#	LATIN CAPITAL LETTER Y WITH GRAVE
+0xAD	0x00AD	#	SOFT HYPHEN
+0xAE	0x00AE	#	REGISTERED SIGN
+0xAF	0x0178	#	LATIN CAPITAL LETTER Y WITH DIAERESIS
+0xB0	0x1E1E	#	LATIN CAPITAL LETTER F WITH DOT ABOVE
+0xB1	0x1E1F	#	LATIN SMALL LETTER F WITH DOT ABOVE
+0xB2	0x0120	#	LATIN CAPITAL LETTER G WITH DOT ABOVE
+0xB3	0x0121	#	LATIN SMALL LETTER G WITH DOT ABOVE
+0xB4	0x1E40	#	LATIN CAPITAL LETTER M WITH DOT ABOVE
+0xB5	0x1E41	#	LATIN SMALL LETTER M WITH DOT ABOVE
+0xB6	0x00B6	#	PILCROW SIGN
+0xB7	0x1E56	#	LATIN CAPITAL LETTER P WITH DOT ABOVE
+0xB8	0x1E81	#	LATIN SMALL LETTER W WITH GRAVE
+0xB9	0x1E57	#	LATIN SMALL LETTER P WITH DOT ABOVE
+0xBA	0x1E83	#	LATIN SMALL LETTER W WITH ACUTE
+0xBB	0x1E60	#	LATIN CAPITAL LETTER S WITH DOT ABOVE
+0xBC	0x1EF3	#	LATIN SMALL LETTER Y WITH GRAVE
+0xBD	0x1E84	#	LATIN CAPITAL LETTER W WITH DIAERESIS
+0xBE	0x1E85	#	LATIN SMALL LETTER W WITH DIAERESIS
+0xBF	0x1E61	#	LATIN SMALL LETTER S WITH DOT ABOVE
+0xC0	0x00C0	#	LATIN CAPITAL LETTER A WITH GRAVE
+0xC1	0x00C1	#	LATIN CAPITAL LETTER A WITH ACUTE
+0xC2	0x00C2	#	LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3	0x00C3	#	LATIN CAPITAL LETTER A WITH TILDE
+0xC4	0x00C4	#	LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5	0x00C5	#	LATIN CAPITAL LETTER A WITH RING ABOVE
+0xC6	0x00C6	#	LATIN CAPITAL LETTER AE
+0xC7	0x00C7	#	LATIN CAPITAL LETTER C WITH CEDILLA
+0xC8	0x00C8	#	LATIN CAPITAL LETTER E WITH GRAVE
+0xC9	0x00C9	#	LATIN CAPITAL LETTER E WITH ACUTE
+0xCA	0x00CA	#	LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xCB	0x00CB	#	LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC	0x00CC	#	LATIN CAPITAL LETTER I WITH GRAVE
+0xCD	0x00CD	#	LATIN CAPITAL LETTER I WITH ACUTE
+0xCE	0x00CE	#	LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF	0x00CF	#	LATIN CAPITAL LETTER I WITH DIAERESIS
+0xD0	0x0174	#	LATIN CAPITAL LETTER W WITH CIRCUMFLEX
+0xD1	0x00D1	#	LATIN CAPITAL LETTER N WITH TILDE
+0xD2	0x00D2	#	LATIN CAPITAL LETTER O WITH GRAVE
+0xD3	0x00D3	#	LATIN CAPITAL LETTER O WITH ACUTE
+0xD4	0x00D4	#	LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5	0x00D5	#	LATIN CAPITAL LETTER O WITH TILDE
+0xD6	0x00D6	#	LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7	0x1E6A	#	LATIN CAPITAL LETTER T WITH DOT ABOVE
+0xD8	0x00D8	#	LATIN CAPITAL LETTER O WITH STROKE
+0xD9	0x00D9	#	LATIN CAPITAL LETTER U WITH GRAVE
+0xDA	0x00DA	#	LATIN CAPITAL LETTER U WITH ACUTE
+0xDB	0x00DB	#	LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xDC	0x00DC	#	LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD	0x00DD	#	LATIN CAPITAL LETTER Y WITH ACUTE
+0xDE	0x0176	#	LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
+0xDF	0x00DF	#	LATIN SMALL LETTER SHARP S
+0xE0	0x00E0	#	LATIN SMALL LETTER A WITH GRAVE
+0xE1	0x00E1	#	LATIN SMALL LETTER A WITH ACUTE
+0xE2	0x00E2	#	LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3	0x00E3	#	LATIN SMALL LETTER A WITH TILDE
+0xE4	0x00E4	#	LATIN SMALL LETTER A WITH DIAERESIS
+0xE5	0x00E5	#	LATIN SMALL LETTER A WITH RING ABOVE
+0xE6	0x00E6	#	LATIN SMALL LETTER AE
+0xE7	0x00E7	#	LATIN SMALL LETTER C WITH CEDILLA
+0xE8	0x00E8	#	LATIN SMALL LETTER E WITH GRAVE
+0xE9	0x00E9	#	LATIN SMALL LETTER E WITH ACUTE
+0xEA	0x00EA	#	LATIN SMALL LETTER E WITH CIRCUMFLEX
+0xEB	0x00EB	#	LATIN SMALL LETTER E WITH DIAERESIS
+0xEC	0x00EC	#	LATIN SMALL LETTER I WITH GRAVE
+0xED	0x00ED	#	LATIN SMALL LETTER I WITH ACUTE
+0xEE	0x00EE	#	LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF	0x00EF	#	LATIN SMALL LETTER I WITH DIAERESIS
+0xF0	0x0175	#	LATIN SMALL LETTER W WITH CIRCUMFLEX
+0xF1	0x00F1	#	LATIN SMALL LETTER N WITH TILDE
+0xF2	0x00F2	#	LATIN SMALL LETTER O WITH GRAVE
+0xF3	0x00F3	#	LATIN SMALL LETTER O WITH ACUTE
+0xF4	0x00F4	#	LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5	0x00F5	#	LATIN SMALL LETTER O WITH TILDE
+0xF6	0x00F6	#	LATIN SMALL LETTER O WITH DIAERESIS
+0xF7	0x1E6B	#	LATIN SMALL LETTER T WITH DOT ABOVE
+0xF8	0x00F8	#	LATIN SMALL LETTER O WITH STROKE
+0xF9	0x00F9	#	LATIN SMALL LETTER U WITH GRAVE
+0xFA	0x00FA	#	LATIN SMALL LETTER U WITH ACUTE
+0xFB	0x00FB	#	LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xFC	0x00FC	#	LATIN SMALL LETTER U WITH DIAERESIS
+0xFD	0x00FD	#	LATIN SMALL LETTER Y WITH ACUTE
+0xFE	0x0177	#	LATIN SMALL LETTER Y WITH CIRCUMFLEX
+0xFF	0x00FF	#	LATIN SMALL LETTER Y WITH DIAERESIS
+
diff --git a/Resources/8859-15.txt b/Resources/8859-15.txt
new file mode 100644
index 0000000..1e31970
--- /dev/null
+++ b/Resources/8859-15.txt
@@ -0,0 +1,303 @@
+#
+#	Name:             ISO/IEC 8859-15:1999 to Unicode
+#	Unicode version:  3.0
+#	Table version:    1.0
+#	Table format:     Format A
+#	Date:             1999 July 27
+#	Authors:          Markus Kuhn <mkuhn@acm.org>
+#			  Ken Whistler <kenw@sybase.com>
+#
+#	Copyright (c) 1998 - 1999 Unicode, Inc.  All Rights reserved.
+#
+#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+#	No claims are made as to fitness for any particular purpose.  No
+#	warranties of any kind are expressed or implied.  The recipient
+#	agrees to determine applicability of information provided.  If this
+#	file has been provided on optical media by Unicode, Inc., the sole
+#	remedy for any claim will be exchange of defective media within 90
+#	days of receipt.
+#
+#	Unicode, Inc. hereby grants the right to freely use the information
+#	supplied in this file in the creation of products supporting the
+#	Unicode Standard, and to make copies of this file in any form for
+#	internal or external distribution as long as this notice remains
+#	attached.
+#
+#	General notes:
+#
+#	This table contains the data the Unicode Consortium has on how
+#       ISO/IEC 8859-15:1999 characters map into Unicode.
+#
+#	Format:  Three tab-separated columns
+#		 Column #1 is the ISO/IEC 8859-15 code (in hex as 0xXX)
+#		 Column #2 is the Unicode (in hex as 0xXXXX)
+#		 Column #3 the Unicode name (follows a comment sign, '#')
+#
+#	The entries are in ISO/IEC 8859-15 order.
+#
+#	Version history
+#
+#	Updated versions of this file may be found in:
+#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
+#
+#	Any comments or problems, contact <errata@unicode.org>
+#	Please note that <errata@unicode.org> is an archival address;
+#	notices will be checked, but do not expect an immediate response.
+#
+0x00	0x0000	#	NULL
+0x01	0x0001	#	START OF HEADING
+0x02	0x0002	#	START OF TEXT
+0x03	0x0003	#	END OF TEXT
+0x04	0x0004	#	END OF TRANSMISSION
+0x05	0x0005	#	ENQUIRY
+0x06	0x0006	#	ACKNOWLEDGE
+0x07	0x0007	#	BELL
+0x08	0x0008	#	BACKSPACE
+0x09	0x0009	#	HORIZONTAL TABULATION
+0x0A	0x000A	#	LINE FEED
+0x0B	0x000B	#	VERTICAL TABULATION
+0x0C	0x000C	#	FORM FEED
+0x0D	0x000D	#	CARRIAGE RETURN
+0x0E	0x000E	#	SHIFT OUT
+0x0F	0x000F	#	SHIFT IN
+0x10	0x0010	#	DATA LINK ESCAPE
+0x11	0x0011	#	DEVICE CONTROL ONE
+0x12	0x0012	#	DEVICE CONTROL TWO
+0x13	0x0013	#	DEVICE CONTROL THREE
+0x14	0x0014	#	DEVICE CONTROL FOUR
+0x15	0x0015	#	NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#	SYNCHRONOUS IDLE
+0x17	0x0017	#	END OF TRANSMISSION BLOCK
+0x18	0x0018	#	CANCEL
+0x19	0x0019	#	END OF MEDIUM
+0x1A	0x001A	#	SUBSTITUTE
+0x1B	0x001B	#	ESCAPE
+0x1C	0x001C	#	FILE SEPARATOR
+0x1D	0x001D	#	GROUP SEPARATOR
+0x1E	0x001E	#	RECORD SEPARATOR
+0x1F	0x001F	#	UNIT SEPARATOR
+0x20	0x0020	#	SPACE
+0x21	0x0021	#	EXCLAMATION MARK
+0x22	0x0022	#	QUOTATION MARK
+0x23	0x0023	#	NUMBER SIGN
+0x24	0x0024	#	DOLLAR SIGN
+0x25	0x0025	#	PERCENT SIGN
+0x26	0x0026	#	AMPERSAND
+0x27	0x0027	#	APOSTROPHE
+0x28	0x0028	#	LEFT PARENTHESIS
+0x29	0x0029	#	RIGHT PARENTHESIS
+0x2A	0x002A	#	ASTERISK
+0x2B	0x002B	#	PLUS SIGN
+0x2C	0x002C	#	COMMA
+0x2D	0x002D	#	HYPHEN-MINUS
+0x2E	0x002E	#	FULL STOP
+0x2F	0x002F	#	SOLIDUS
+0x30	0x0030	#	DIGIT ZERO
+0x31	0x0031	#	DIGIT ONE
+0x32	0x0032	#	DIGIT TWO
+0x33	0x0033	#	DIGIT THREE
+0x34	0x0034	#	DIGIT FOUR
+0x35	0x0035	#	DIGIT FIVE
+0x36	0x0036	#	DIGIT SIX
+0x37	0x0037	#	DIGIT SEVEN
+0x38	0x0038	#	DIGIT EIGHT
+0x39	0x0039	#	DIGIT NINE
+0x3A	0x003A	#	COLON
+0x3B	0x003B	#	SEMICOLON
+0x3C	0x003C	#	LESS-THAN SIGN
+0x3D	0x003D	#	EQUALS SIGN
+0x3E	0x003E	#	GREATER-THAN SIGN
+0x3F	0x003F	#	QUESTION MARK
+0x40	0x0040	#	COMMERCIAL AT
+0x41	0x0041	#	LATIN CAPITAL LETTER A
+0x42	0x0042	#	LATIN CAPITAL LETTER B
+0x43	0x0043	#	LATIN CAPITAL LETTER C
+0x44	0x0044	#	LATIN CAPITAL LETTER D
+0x45	0x0045	#	LATIN CAPITAL LETTER E
+0x46	0x0046	#	LATIN CAPITAL LETTER F
+0x47	0x0047	#	LATIN CAPITAL LETTER G
+0x48	0x0048	#	LATIN CAPITAL LETTER H
+0x49	0x0049	#	LATIN CAPITAL LETTER I
+0x4A	0x004A	#	LATIN CAPITAL LETTER J
+0x4B	0x004B	#	LATIN CAPITAL LETTER K
+0x4C	0x004C	#	LATIN CAPITAL LETTER L
+0x4D	0x004D	#	LATIN CAPITAL LETTER M
+0x4E	0x004E	#	LATIN CAPITAL LETTER N
+0x4F	0x004F	#	LATIN CAPITAL LETTER O
+0x50	0x0050	#	LATIN CAPITAL LETTER P
+0x51	0x0051	#	LATIN CAPITAL LETTER Q
+0x52	0x0052	#	LATIN CAPITAL LETTER R
+0x53	0x0053	#	LATIN CAPITAL LETTER S
+0x54	0x0054	#	LATIN CAPITAL LETTER T
+0x55	0x0055	#	LATIN CAPITAL LETTER U
+0x56	0x0056	#	LATIN CAPITAL LETTER V
+0x57	0x0057	#	LATIN CAPITAL LETTER W
+0x58	0x0058	#	LATIN CAPITAL LETTER X
+0x59	0x0059	#	LATIN CAPITAL LETTER Y
+0x5A	0x005A	#	LATIN CAPITAL LETTER Z
+0x5B	0x005B	#	LEFT SQUARE BRACKET
+0x5C	0x005C	#	REVERSE SOLIDUS
+0x5D	0x005D	#	RIGHT SQUARE BRACKET
+0x5E	0x005E	#	CIRCUMFLEX ACCENT
+0x5F	0x005F	#	LOW LINE
+0x60	0x0060	#	GRAVE ACCENT
+0x61	0x0061	#	LATIN SMALL LETTER A
+0x62	0x0062	#	LATIN SMALL LETTER B
+0x63	0x0063	#	LATIN SMALL LETTER C
+0x64	0x0064	#	LATIN SMALL LETTER D
+0x65	0x0065	#	LATIN SMALL LETTER E
+0x66	0x0066	#	LATIN SMALL LETTER F
+0x67	0x0067	#	LATIN SMALL LETTER G
+0x68	0x0068	#	LATIN SMALL LETTER H
+0x69	0x0069	#	LATIN SMALL LETTER I
+0x6A	0x006A	#	LATIN SMALL LETTER J
+0x6B	0x006B	#	LATIN SMALL LETTER K
+0x6C	0x006C	#	LATIN SMALL LETTER L
+0x6D	0x006D	#	LATIN SMALL LETTER M
+0x6E	0x006E	#	LATIN SMALL LETTER N
+0x6F	0x006F	#	LATIN SMALL LETTER O
+0x70	0x0070	#	LATIN SMALL LETTER P
+0x71	0x0071	#	LATIN SMALL LETTER Q
+0x72	0x0072	#	LATIN SMALL LETTER R
+0x73	0x0073	#	LATIN SMALL LETTER S
+0x74	0x0074	#	LATIN SMALL LETTER T
+0x75	0x0075	#	LATIN SMALL LETTER U
+0x76	0x0076	#	LATIN SMALL LETTER V
+0x77	0x0077	#	LATIN SMALL LETTER W
+0x78	0x0078	#	LATIN SMALL LETTER X
+0x79	0x0079	#	LATIN SMALL LETTER Y
+0x7A	0x007A	#	LATIN SMALL LETTER Z
+0x7B	0x007B	#	LEFT CURLY BRACKET
+0x7C	0x007C	#	VERTICAL LINE
+0x7D	0x007D	#	RIGHT CURLY BRACKET
+0x7E	0x007E	#	TILDE
+0x7F	0x007F	#	DELETE
+0x80	0x0080	#	<control>
+0x81	0x0081	#	<control>
+0x82	0x0082	#	<control>
+0x83	0x0083	#	<control>
+0x84	0x0084	#	<control>
+0x85	0x0085	#	<control>
+0x86	0x0086	#	<control>
+0x87	0x0087	#	<control>
+0x88	0x0088	#	<control>
+0x89	0x0089	#	<control>
+0x8A	0x008A	#	<control>
+0x8B	0x008B	#	<control>
+0x8C	0x008C	#	<control>
+0x8D	0x008D	#	<control>
+0x8E	0x008E	#	<control>
+0x8F	0x008F	#	<control>
+0x90	0x0090	#	<control>
+0x91	0x0091	#	<control>
+0x92	0x0092	#	<control>
+0x93	0x0093	#	<control>
+0x94	0x0094	#	<control>
+0x95	0x0095	#	<control>
+0x96	0x0096	#	<control>
+0x97	0x0097	#	<control>
+0x98	0x0098	#	<control>
+0x99	0x0099	#	<control>
+0x9A	0x009A	#	<control>
+0x9B	0x009B	#	<control>
+0x9C	0x009C	#	<control>
+0x9D	0x009D	#	<control>
+0x9E	0x009E	#	<control>
+0x9F	0x009F	#	<control>
+0xA0	0x00A0	#	NO-BREAK SPACE
+0xA1	0x00A1	#	INVERTED EXCLAMATION MARK
+0xA2	0x00A2	#	CENT SIGN
+0xA3	0x00A3	#	POUND SIGN
+0xA4	0x20AC	#	EURO SIGN
+0xA5	0x00A5	#	YEN SIGN
+0xA6	0x0160	#	LATIN CAPITAL LETTER S WITH CARON
+0xA7	0x00A7	#	SECTION SIGN
+0xA8	0x0161	#	LATIN SMALL LETTER S WITH CARON
+0xA9	0x00A9	#	COPYRIGHT SIGN
+0xAA	0x00AA	#	FEMININE ORDINAL INDICATOR
+0xAB	0x00AB	#	LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC	0x00AC	#	NOT SIGN
+0xAD	0x00AD	#	SOFT HYPHEN
+0xAE	0x00AE	#	REGISTERED SIGN
+0xAF	0x00AF	#	MACRON
+0xB0	0x00B0	#	DEGREE SIGN
+0xB1	0x00B1	#	PLUS-MINUS SIGN
+0xB2	0x00B2	#	SUPERSCRIPT TWO
+0xB3	0x00B3	#	SUPERSCRIPT THREE
+0xB4	0x017D	#	LATIN CAPITAL LETTER Z WITH CARON
+0xB5	0x00B5	#	MICRO SIGN
+0xB6	0x00B6	#	PILCROW SIGN
+0xB7	0x00B7	#	MIDDLE DOT
+0xB8	0x017E	#	LATIN SMALL LETTER Z WITH CARON
+0xB9	0x00B9	#	SUPERSCRIPT ONE
+0xBA	0x00BA	#	MASCULINE ORDINAL INDICATOR
+0xBB	0x00BB	#	RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC	0x0152	#	LATIN CAPITAL LIGATURE OE
+0xBD	0x0153	#	LATIN SMALL LIGATURE OE
+0xBE	0x0178	#	LATIN CAPITAL LETTER Y WITH DIAERESIS
+0xBF	0x00BF	#	INVERTED QUESTION MARK
+0xC0	0x00C0	#	LATIN CAPITAL LETTER A WITH GRAVE
+0xC1	0x00C1	#	LATIN CAPITAL LETTER A WITH ACUTE
+0xC2	0x00C2	#	LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3	0x00C3	#	LATIN CAPITAL LETTER A WITH TILDE
+0xC4	0x00C4	#	LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5	0x00C5	#	LATIN CAPITAL LETTER A WITH RING ABOVE
+0xC6	0x00C6	#	LATIN CAPITAL LETTER AE
+0xC7	0x00C7	#	LATIN CAPITAL LETTER C WITH CEDILLA
+0xC8	0x00C8	#	LATIN CAPITAL LETTER E WITH GRAVE
+0xC9	0x00C9	#	LATIN CAPITAL LETTER E WITH ACUTE
+0xCA	0x00CA	#	LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xCB	0x00CB	#	LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC	0x00CC	#	LATIN CAPITAL LETTER I WITH GRAVE
+0xCD	0x00CD	#	LATIN CAPITAL LETTER I WITH ACUTE
+0xCE	0x00CE	#	LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF	0x00CF	#	LATIN CAPITAL LETTER I WITH DIAERESIS
+0xD0	0x00D0	#	LATIN CAPITAL LETTER ETH
+0xD1	0x00D1	#	LATIN CAPITAL LETTER N WITH TILDE
+0xD2	0x00D2	#	LATIN CAPITAL LETTER O WITH GRAVE
+0xD3	0x00D3	#	LATIN CAPITAL LETTER O WITH ACUTE
+0xD4	0x00D4	#	LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5	0x00D5	#	LATIN CAPITAL LETTER O WITH TILDE
+0xD6	0x00D6	#	LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7	0x00D7	#	MULTIPLICATION SIGN
+0xD8	0x00D8	#	LATIN CAPITAL LETTER O WITH STROKE
+0xD9	0x00D9	#	LATIN CAPITAL LETTER U WITH GRAVE
+0xDA	0x00DA	#	LATIN CAPITAL LETTER U WITH ACUTE
+0xDB	0x00DB	#	LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xDC	0x00DC	#	LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD	0x00DD	#	LATIN CAPITAL LETTER Y WITH ACUTE
+0xDE	0x00DE	#	LATIN CAPITAL LETTER THORN
+0xDF	0x00DF	#	LATIN SMALL LETTER SHARP S
+0xE0	0x00E0	#	LATIN SMALL LETTER A WITH GRAVE
+0xE1	0x00E1	#	LATIN SMALL LETTER A WITH ACUTE
+0xE2	0x00E2	#	LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3	0x00E3	#	LATIN SMALL LETTER A WITH TILDE
+0xE4	0x00E4	#	LATIN SMALL LETTER A WITH DIAERESIS
+0xE5	0x00E5	#	LATIN SMALL LETTER A WITH RING ABOVE
+0xE6	0x00E6	#	LATIN SMALL LETTER AE
+0xE7	0x00E7	#	LATIN SMALL LETTER C WITH CEDILLA
+0xE8	0x00E8	#	LATIN SMALL LETTER E WITH GRAVE
+0xE9	0x00E9	#	LATIN SMALL LETTER E WITH ACUTE
+0xEA	0x00EA	#	LATIN SMALL LETTER E WITH CIRCUMFLEX
+0xEB	0x00EB	#	LATIN SMALL LETTER E WITH DIAERESIS
+0xEC	0x00EC	#	LATIN SMALL LETTER I WITH GRAVE
+0xED	0x00ED	#	LATIN SMALL LETTER I WITH ACUTE
+0xEE	0x00EE	#	LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF	0x00EF	#	LATIN SMALL LETTER I WITH DIAERESIS
+0xF0	0x00F0	#	LATIN SMALL LETTER ETH
+0xF1	0x00F1	#	LATIN SMALL LETTER N WITH TILDE
+0xF2	0x00F2	#	LATIN SMALL LETTER O WITH GRAVE
+0xF3	0x00F3	#	LATIN SMALL LETTER O WITH ACUTE
+0xF4	0x00F4	#	LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5	0x00F5	#	LATIN SMALL LETTER O WITH TILDE
+0xF6	0x00F6	#	LATIN SMALL LETTER O WITH DIAERESIS
+0xF7	0x00F7	#	DIVISION SIGN
+0xF8	0x00F8	#	LATIN SMALL LETTER O WITH STROKE
+0xF9	0x00F9	#	LATIN SMALL LETTER U WITH GRAVE
+0xFA	0x00FA	#	LATIN SMALL LETTER U WITH ACUTE
+0xFB	0x00FB	#	LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xFC	0x00FC	#	LATIN SMALL LETTER U WITH DIAERESIS
+0xFD	0x00FD	#	LATIN SMALL LETTER Y WITH ACUTE
+0xFE	0x00FE	#	LATIN SMALL LETTER THORN
+0xFF	0x00FF	#	LATIN SMALL LETTER Y WITH DIAERESIS
+
diff --git a/Resources/8859-16.txt b/Resources/8859-16.txt
new file mode 100644
index 0000000..5353d74
--- /dev/null
+++ b/Resources/8859-16.txt
@@ -0,0 +1,299 @@
+#
+#	Name:             ISO/IEC 8859-16:2001 to Unicode
+#	Unicode version:  3.0
+#	Table version:    1.0
+#	Table format:     Format A
+#	Date:             2001 July 26
+#	Authors:          Markus Kuhn <mkuhn@acm.org>
+#
+#	Copyright (c) 1999-2001 Unicode, Inc.  All Rights reserved.
+#
+#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+#	No claims are made as to fitness for any particular purpose.  No
+#	warranties of any kind are expressed or implied.  The recipient
+#	agrees to determine applicability of information provided.  If this
+#	file has been provided on optical media by Unicode, Inc., the sole
+#	remedy for any claim will be exchange of defective media within 90
+#	days of receipt.
+#
+#	Unicode, Inc. hereby grants the right to freely use the information
+#	supplied in this file in the creation of products supporting the
+#	Unicode Standard, and to make copies of this file in any form for
+#	internal or external distribution as long as this notice remains
+#	attached.
+#
+#	General notes:
+#
+#	This table contains the data the Unicode Consortium has on how
+#       ISO/IEC 8859-16:2001 characters map into Unicode.
+#
+#	Format:  Three tab-separated columns
+#		 Column #1 is the ISO/IEC 8859-16 code (in hex as 0xXX)
+#		 Column #2 is the Unicode (in hex as 0xXXXX)
+#		 Column #3 the Unicode name (follows a comment sign, '#')
+#
+#	The entries are in ISO/IEC 8859-16 order.
+#
+#	Updated versions of this file may be found in:
+#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
+#
+#	Any comments or problems, contact <errata@unicode.org>
+#	Please note that <errata@unicode.org> is an archival address;
+#	notices will be checked, but do not expect an immediate response.
+#
+0x00	0x0000	#	NULL
+0x01	0x0001	#	START OF HEADING
+0x02	0x0002	#	START OF TEXT
+0x03	0x0003	#	END OF TEXT
+0x04	0x0004	#	END OF TRANSMISSION
+0x05	0x0005	#	ENQUIRY
+0x06	0x0006	#	ACKNOWLEDGE
+0x07	0x0007	#	BELL
+0x08	0x0008	#	BACKSPACE
+0x09	0x0009	#	HORIZONTAL TABULATION
+0x0A	0x000A	#	LINE FEED
+0x0B	0x000B	#	VERTICAL TABULATION
+0x0C	0x000C	#	FORM FEED
+0x0D	0x000D	#	CARRIAGE RETURN
+0x0E	0x000E	#	SHIFT OUT
+0x0F	0x000F	#	SHIFT IN
+0x10	0x0010	#	DATA LINK ESCAPE
+0x11	0x0011	#	DEVICE CONTROL ONE
+0x12	0x0012	#	DEVICE CONTROL TWO
+0x13	0x0013	#	DEVICE CONTROL THREE
+0x14	0x0014	#	DEVICE CONTROL FOUR
+0x15	0x0015	#	NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#	SYNCHRONOUS IDLE
+0x17	0x0017	#	END OF TRANSMISSION BLOCK
+0x18	0x0018	#	CANCEL
+0x19	0x0019	#	END OF MEDIUM
+0x1A	0x001A	#	SUBSTITUTE
+0x1B	0x001B	#	ESCAPE
+0x1C	0x001C	#	FILE SEPARATOR
+0x1D	0x001D	#	GROUP SEPARATOR
+0x1E	0x001E	#	RECORD SEPARATOR
+0x1F	0x001F	#	UNIT SEPARATOR
+0x20	0x0020	#	SPACE
+0x21	0x0021	#	EXCLAMATION MARK
+0x22	0x0022	#	QUOTATION MARK
+0x23	0x0023	#	NUMBER SIGN
+0x24	0x0024	#	DOLLAR SIGN
+0x25	0x0025	#	PERCENT SIGN
+0x26	0x0026	#	AMPERSAND
+0x27	0x0027	#	APOSTROPHE
+0x28	0x0028	#	LEFT PARENTHESIS
+0x29	0x0029	#	RIGHT PARENTHESIS
+0x2A	0x002A	#	ASTERISK
+0x2B	0x002B	#	PLUS SIGN
+0x2C	0x002C	#	COMMA
+0x2D	0x002D	#	HYPHEN-MINUS
+0x2E	0x002E	#	FULL STOP
+0x2F	0x002F	#	SOLIDUS
+0x30	0x0030	#	DIGIT ZERO
+0x31	0x0031	#	DIGIT ONE
+0x32	0x0032	#	DIGIT TWO
+0x33	0x0033	#	DIGIT THREE
+0x34	0x0034	#	DIGIT FOUR
+0x35	0x0035	#	DIGIT FIVE
+0x36	0x0036	#	DIGIT SIX
+0x37	0x0037	#	DIGIT SEVEN
+0x38	0x0038	#	DIGIT EIGHT
+0x39	0x0039	#	DIGIT NINE
+0x3A	0x003A	#	COLON
+0x3B	0x003B	#	SEMICOLON
+0x3C	0x003C	#	LESS-THAN SIGN
+0x3D	0x003D	#	EQUALS SIGN
+0x3E	0x003E	#	GREATER-THAN SIGN
+0x3F	0x003F	#	QUESTION MARK
+0x40	0x0040	#	COMMERCIAL AT
+0x41	0x0041	#	LATIN CAPITAL LETTER A
+0x42	0x0042	#	LATIN CAPITAL LETTER B
+0x43	0x0043	#	LATIN CAPITAL LETTER C
+0x44	0x0044	#	LATIN CAPITAL LETTER D
+0x45	0x0045	#	LATIN CAPITAL LETTER E
+0x46	0x0046	#	LATIN CAPITAL LETTER F
+0x47	0x0047	#	LATIN CAPITAL LETTER G
+0x48	0x0048	#	LATIN CAPITAL LETTER H
+0x49	0x0049	#	LATIN CAPITAL LETTER I
+0x4A	0x004A	#	LATIN CAPITAL LETTER J
+0x4B	0x004B	#	LATIN CAPITAL LETTER K
+0x4C	0x004C	#	LATIN CAPITAL LETTER L
+0x4D	0x004D	#	LATIN CAPITAL LETTER M
+0x4E	0x004E	#	LATIN CAPITAL LETTER N
+0x4F	0x004F	#	LATIN CAPITAL LETTER O
+0x50	0x0050	#	LATIN CAPITAL LETTER P
+0x51	0x0051	#	LATIN CAPITAL LETTER Q
+0x52	0x0052	#	LATIN CAPITAL LETTER R
+0x53	0x0053	#	LATIN CAPITAL LETTER S
+0x54	0x0054	#	LATIN CAPITAL LETTER T
+0x55	0x0055	#	LATIN CAPITAL LETTER U
+0x56	0x0056	#	LATIN CAPITAL LETTER V
+0x57	0x0057	#	LATIN CAPITAL LETTER W
+0x58	0x0058	#	LATIN CAPITAL LETTER X
+0x59	0x0059	#	LATIN CAPITAL LETTER Y
+0x5A	0x005A	#	LATIN CAPITAL LETTER Z
+0x5B	0x005B	#	LEFT SQUARE BRACKET
+0x5C	0x005C	#	REVERSE SOLIDUS
+0x5D	0x005D	#	RIGHT SQUARE BRACKET
+0x5E	0x005E	#	CIRCUMFLEX ACCENT
+0x5F	0x005F	#	LOW LINE
+0x60	0x0060	#	GRAVE ACCENT
+0x61	0x0061	#	LATIN SMALL LETTER A
+0x62	0x0062	#	LATIN SMALL LETTER B
+0x63	0x0063	#	LATIN SMALL LETTER C
+0x64	0x0064	#	LATIN SMALL LETTER D
+0x65	0x0065	#	LATIN SMALL LETTER E
+0x66	0x0066	#	LATIN SMALL LETTER F
+0x67	0x0067	#	LATIN SMALL LETTER G
+0x68	0x0068	#	LATIN SMALL LETTER H
+0x69	0x0069	#	LATIN SMALL LETTER I
+0x6A	0x006A	#	LATIN SMALL LETTER J
+0x6B	0x006B	#	LATIN SMALL LETTER K
+0x6C	0x006C	#	LATIN SMALL LETTER L
+0x6D	0x006D	#	LATIN SMALL LETTER M
+0x6E	0x006E	#	LATIN SMALL LETTER N
+0x6F	0x006F	#	LATIN SMALL LETTER O
+0x70	0x0070	#	LATIN SMALL LETTER P
+0x71	0x0071	#	LATIN SMALL LETTER Q
+0x72	0x0072	#	LATIN SMALL LETTER R
+0x73	0x0073	#	LATIN SMALL LETTER S
+0x74	0x0074	#	LATIN SMALL LETTER T
+0x75	0x0075	#	LATIN SMALL LETTER U
+0x76	0x0076	#	LATIN SMALL LETTER V
+0x77	0x0077	#	LATIN SMALL LETTER W
+0x78	0x0078	#	LATIN SMALL LETTER X
+0x79	0x0079	#	LATIN SMALL LETTER Y
+0x7A	0x007A	#	LATIN SMALL LETTER Z
+0x7B	0x007B	#	LEFT CURLY BRACKET
+0x7C	0x007C	#	VERTICAL LINE
+0x7D	0x007D	#	RIGHT CURLY BRACKET
+0x7E	0x007E	#	TILDE
+0x7F	0x007F	#	DELETE
+0x80	0x0080	#	<control>
+0x81	0x0081	#	<control>
+0x82	0x0082	#	<control>
+0x83	0x0083	#	<control>
+0x84	0x0084	#	<control>
+0x85	0x0085	#	<control>
+0x86	0x0086	#	<control>
+0x87	0x0087	#	<control>
+0x88	0x0088	#	<control>
+0x89	0x0089	#	<control>
+0x8A	0x008A	#	<control>
+0x8B	0x008B	#	<control>
+0x8C	0x008C	#	<control>
+0x8D	0x008D	#	<control>
+0x8E	0x008E	#	<control>
+0x8F	0x008F	#	<control>
+0x90	0x0090	#	<control>
+0x91	0x0091	#	<control>
+0x92	0x0092	#	<control>
+0x93	0x0093	#	<control>
+0x94	0x0094	#	<control>
+0x95	0x0095	#	<control>
+0x96	0x0096	#	<control>
+0x97	0x0097	#	<control>
+0x98	0x0098	#	<control>
+0x99	0x0099	#	<control>
+0x9A	0x009A	#	<control>
+0x9B	0x009B	#	<control>
+0x9C	0x009C	#	<control>
+0x9D	0x009D	#	<control>
+0x9E	0x009E	#	<control>
+0x9F	0x009F	#	<control>
+0xA0	0x00A0	#	NO-BREAK SPACE
+0xA1	0x0104	#	LATIN CAPITAL LETTER A WITH OGONEK
+0xA2	0x0105	#	LATIN SMALL LETTER A WITH OGONEK
+0xA3	0x0141	#	LATIN CAPITAL LETTER L WITH STROKE
+0xA4	0x20AC	#	EURO SIGN
+0xA5	0x201E	#	DOUBLE LOW-9 QUOTATION MARK
+0xA6	0x0160	#	LATIN CAPITAL LETTER S WITH CARON
+0xA7	0x00A7	#	SECTION SIGN
+0xA8	0x0161	#	LATIN SMALL LETTER S WITH CARON
+0xA9	0x00A9	#	COPYRIGHT SIGN
+0xAA	0x0218	#	LATIN CAPITAL LETTER S WITH COMMA BELOW
+0xAB	0x00AB	#	LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC	0x0179	#	LATIN CAPITAL LETTER Z WITH ACUTE
+0xAD	0x00AD	#	SOFT HYPHEN
+0xAE	0x017A	#	LATIN SMALL LETTER Z WITH ACUTE
+0xAF	0x017B	#	LATIN CAPITAL LETTER Z WITH DOT ABOVE
+0xB0	0x00B0	#	DEGREE SIGN
+0xB1	0x00B1	#	PLUS-MINUS SIGN
+0xB2	0x010C	#	LATIN CAPITAL LETTER C WITH CARON
+0xB3	0x0142	#	LATIN SMALL LETTER L WITH STROKE
+0xB4	0x017D	#	LATIN CAPITAL LETTER Z WITH CARON
+0xB5	0x201D	#	RIGHT DOUBLE QUOTATION MARK
+0xB6	0x00B6	#	PILCROW SIGN
+0xB7	0x00B7	#	MIDDLE DOT
+0xB8	0x017E	#	LATIN SMALL LETTER Z WITH CARON
+0xB9	0x010D	#	LATIN SMALL LETTER C WITH CARON
+0xBA	0x0219	#	LATIN SMALL LETTER S WITH COMMA BELOW
+0xBB	0x00BB	#	RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC	0x0152	#	LATIN CAPITAL LIGATURE OE
+0xBD	0x0153	#	LATIN SMALL LIGATURE OE
+0xBE	0x0178	#	LATIN CAPITAL LETTER Y WITH DIAERESIS
+0xBF	0x017C	#	LATIN SMALL LETTER Z WITH DOT ABOVE
+0xC0	0x00C0	#	LATIN CAPITAL LETTER A WITH GRAVE
+0xC1	0x00C1	#	LATIN CAPITAL LETTER A WITH ACUTE
+0xC2	0x00C2	#	LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3	0x0102	#	LATIN CAPITAL LETTER A WITH BREVE
+0xC4	0x00C4	#	LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5	0x0106	#	LATIN CAPITAL LETTER C WITH ACUTE
+0xC6	0x00C6	#	LATIN CAPITAL LETTER AE
+0xC7	0x00C7	#	LATIN CAPITAL LETTER C WITH CEDILLA
+0xC8	0x00C8	#	LATIN CAPITAL LETTER E WITH GRAVE
+0xC9	0x00C9	#	LATIN CAPITAL LETTER E WITH ACUTE
+0xCA	0x00CA	#	LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xCB	0x00CB	#	LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC	0x00CC	#	LATIN CAPITAL LETTER I WITH GRAVE
+0xCD	0x00CD	#	LATIN CAPITAL LETTER I WITH ACUTE
+0xCE	0x00CE	#	LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF	0x00CF	#	LATIN CAPITAL LETTER I WITH DIAERESIS
+0xD0	0x0110	#	LATIN CAPITAL LETTER D WITH STROKE
+0xD1	0x0143	#	LATIN CAPITAL LETTER N WITH ACUTE
+0xD2	0x00D2	#	LATIN CAPITAL LETTER O WITH GRAVE
+0xD3	0x00D3	#	LATIN CAPITAL LETTER O WITH ACUTE
+0xD4	0x00D4	#	LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5	0x0150	#	LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+0xD6	0x00D6	#	LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7	0x015A	#	LATIN CAPITAL LETTER S WITH ACUTE
+0xD8	0x0170	#	LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+0xD9	0x00D9	#	LATIN CAPITAL LETTER U WITH GRAVE
+0xDA	0x00DA	#	LATIN CAPITAL LETTER U WITH ACUTE
+0xDB	0x00DB	#	LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xDC	0x00DC	#	LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD	0x0118	#	LATIN CAPITAL LETTER E WITH OGONEK
+0xDE	0x021A	#	LATIN CAPITAL LETTER T WITH COMMA BELOW
+0xDF	0x00DF	#	LATIN SMALL LETTER SHARP S
+0xE0	0x00E0	#	LATIN SMALL LETTER A WITH GRAVE
+0xE1	0x00E1	#	LATIN SMALL LETTER A WITH ACUTE
+0xE2	0x00E2	#	LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3	0x0103	#	LATIN SMALL LETTER A WITH BREVE
+0xE4	0x00E4	#	LATIN SMALL LETTER A WITH DIAERESIS
+0xE5	0x0107	#	LATIN SMALL LETTER C WITH ACUTE
+0xE6	0x00E6	#	LATIN SMALL LETTER AE
+0xE7	0x00E7	#	LATIN SMALL LETTER C WITH CEDILLA
+0xE8	0x00E8	#	LATIN SMALL LETTER E WITH GRAVE
+0xE9	0x00E9	#	LATIN SMALL LETTER E WITH ACUTE
+0xEA	0x00EA	#	LATIN SMALL LETTER E WITH CIRCUMFLEX
+0xEB	0x00EB	#	LATIN SMALL LETTER E WITH DIAERESIS
+0xEC	0x00EC	#	LATIN SMALL LETTER I WITH GRAVE
+0xED	0x00ED	#	LATIN SMALL LETTER I WITH ACUTE
+0xEE	0x00EE	#	LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF	0x00EF	#	LATIN SMALL LETTER I WITH DIAERESIS
+0xF0	0x0111	#	LATIN SMALL LETTER D WITH STROKE
+0xF1	0x0144	#	LATIN SMALL LETTER N WITH ACUTE
+0xF2	0x00F2	#	LATIN SMALL LETTER O WITH GRAVE
+0xF3	0x00F3	#	LATIN SMALL LETTER O WITH ACUTE
+0xF4	0x00F4	#	LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5	0x0151	#	LATIN SMALL LETTER O WITH DOUBLE ACUTE
+0xF6	0x00F6	#	LATIN SMALL LETTER O WITH DIAERESIS
+0xF7	0x015B	#	LATIN SMALL LETTER S WITH ACUTE
+0xF8	0x0171	#	LATIN SMALL LETTER U WITH DOUBLE ACUTE
+0xF9	0x00F9	#	LATIN SMALL LETTER U WITH GRAVE
+0xFA	0x00FA	#	LATIN SMALL LETTER U WITH ACUTE
+0xFB	0x00FB	#	LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xFC	0x00FC	#	LATIN SMALL LETTER U WITH DIAERESIS
+0xFD	0x0119	#	LATIN SMALL LETTER E WITH OGONEK
+0xFE	0x021B	#	LATIN SMALL LETTER T WITH COMMA BELOW
+0xFF	0x00FF	#	LATIN SMALL LETTER Y WITH DIAERESIS
diff --git a/Resources/8859-2.txt b/Resources/8859-2.txt
new file mode 100644
index 0000000..e45df25
--- /dev/null
+++ b/Resources/8859-2.txt
@@ -0,0 +1,303 @@
+#
+#	Name:             ISO 8859-2:1999 to Unicode
+#	Unicode version:  3.0
+#	Table version:    1.0
+#	Table format:     Format A
+#	Date:             1999 July 27
+#	Authors:          Ken Whistler <kenw@sybase.com>
+#
+#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
+#
+#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+#	No claims are made as to fitness for any particular purpose.  No
+#	warranties of any kind are expressed or implied.  The recipient
+#	agrees to determine applicability of information provided.  If this
+#	file has been provided on optical media by Unicode, Inc., the sole
+#	remedy for any claim will be exchange of defective media within 90
+#	days of receipt.
+#
+#	Unicode, Inc. hereby grants the right to freely use the information
+#	supplied in this file in the creation of products supporting the
+#	Unicode Standard, and to make copies of this file in any form for
+#	internal or external distribution as long as this notice remains
+#	attached.
+#
+#	General notes:
+#
+#	This table contains the data the Unicode Consortium has on how
+#       ISO/IEC 8859-2:1999 characters map into Unicode.
+#
+#	Format:  Three tab-separated columns
+#		 Column #1 is the ISO/IEC 8859-2 code (in hex as 0xXX)
+#		 Column #2 is the Unicode (in hex as 0xXXXX)
+#		 Column #3 the Unicode name (follows a comment sign, '#')
+#
+#	The entries are in ISO/IEC 8859-2 order.
+#
+#	Version history
+#	1.0 version updates 0.1 version by adding mappings for all
+#	control characters.
+#
+#	Updated versions of this file may be found in:
+#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
+#
+#	Any comments or problems, contact <errata@unicode.org>
+#	Please note that <errata@unicode.org> is an archival address;
+#	notices will be checked, but do not expect an immediate response.
+#
+0x00	0x0000	#	NULL
+0x01	0x0001	#	START OF HEADING
+0x02	0x0002	#	START OF TEXT
+0x03	0x0003	#	END OF TEXT
+0x04	0x0004	#	END OF TRANSMISSION
+0x05	0x0005	#	ENQUIRY
+0x06	0x0006	#	ACKNOWLEDGE
+0x07	0x0007	#	BELL
+0x08	0x0008	#	BACKSPACE
+0x09	0x0009	#	HORIZONTAL TABULATION
+0x0A	0x000A	#	LINE FEED
+0x0B	0x000B	#	VERTICAL TABULATION
+0x0C	0x000C	#	FORM FEED
+0x0D	0x000D	#	CARRIAGE RETURN
+0x0E	0x000E	#	SHIFT OUT
+0x0F	0x000F	#	SHIFT IN
+0x10	0x0010	#	DATA LINK ESCAPE
+0x11	0x0011	#	DEVICE CONTROL ONE
+0x12	0x0012	#	DEVICE CONTROL TWO
+0x13	0x0013	#	DEVICE CONTROL THREE
+0x14	0x0014	#	DEVICE CONTROL FOUR
+0x15	0x0015	#	NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#	SYNCHRONOUS IDLE
+0x17	0x0017	#	END OF TRANSMISSION BLOCK
+0x18	0x0018	#	CANCEL
+0x19	0x0019	#	END OF MEDIUM
+0x1A	0x001A	#	SUBSTITUTE
+0x1B	0x001B	#	ESCAPE
+0x1C	0x001C	#	FILE SEPARATOR
+0x1D	0x001D	#	GROUP SEPARATOR
+0x1E	0x001E	#	RECORD SEPARATOR
+0x1F	0x001F	#	UNIT SEPARATOR
+0x20	0x0020	#	SPACE
+0x21	0x0021	#	EXCLAMATION MARK
+0x22	0x0022	#	QUOTATION MARK
+0x23	0x0023	#	NUMBER SIGN
+0x24	0x0024	#	DOLLAR SIGN
+0x25	0x0025	#	PERCENT SIGN
+0x26	0x0026	#	AMPERSAND
+0x27	0x0027	#	APOSTROPHE
+0x28	0x0028	#	LEFT PARENTHESIS
+0x29	0x0029	#	RIGHT PARENTHESIS
+0x2A	0x002A	#	ASTERISK
+0x2B	0x002B	#	PLUS SIGN
+0x2C	0x002C	#	COMMA
+0x2D	0x002D	#	HYPHEN-MINUS
+0x2E	0x002E	#	FULL STOP
+0x2F	0x002F	#	SOLIDUS
+0x30	0x0030	#	DIGIT ZERO
+0x31	0x0031	#	DIGIT ONE
+0x32	0x0032	#	DIGIT TWO
+0x33	0x0033	#	DIGIT THREE
+0x34	0x0034	#	DIGIT FOUR
+0x35	0x0035	#	DIGIT FIVE
+0x36	0x0036	#	DIGIT SIX
+0x37	0x0037	#	DIGIT SEVEN
+0x38	0x0038	#	DIGIT EIGHT
+0x39	0x0039	#	DIGIT NINE
+0x3A	0x003A	#	COLON
+0x3B	0x003B	#	SEMICOLON
+0x3C	0x003C	#	LESS-THAN SIGN
+0x3D	0x003D	#	EQUALS SIGN
+0x3E	0x003E	#	GREATER-THAN SIGN
+0x3F	0x003F	#	QUESTION MARK
+0x40	0x0040	#	COMMERCIAL AT
+0x41	0x0041	#	LATIN CAPITAL LETTER A
+0x42	0x0042	#	LATIN CAPITAL LETTER B
+0x43	0x0043	#	LATIN CAPITAL LETTER C
+0x44	0x0044	#	LATIN CAPITAL LETTER D
+0x45	0x0045	#	LATIN CAPITAL LETTER E
+0x46	0x0046	#	LATIN CAPITAL LETTER F
+0x47	0x0047	#	LATIN CAPITAL LETTER G
+0x48	0x0048	#	LATIN CAPITAL LETTER H
+0x49	0x0049	#	LATIN CAPITAL LETTER I
+0x4A	0x004A	#	LATIN CAPITAL LETTER J
+0x4B	0x004B	#	LATIN CAPITAL LETTER K
+0x4C	0x004C	#	LATIN CAPITAL LETTER L
+0x4D	0x004D	#	LATIN CAPITAL LETTER M
+0x4E	0x004E	#	LATIN CAPITAL LETTER N
+0x4F	0x004F	#	LATIN CAPITAL LETTER O
+0x50	0x0050	#	LATIN CAPITAL LETTER P
+0x51	0x0051	#	LATIN CAPITAL LETTER Q
+0x52	0x0052	#	LATIN CAPITAL LETTER R
+0x53	0x0053	#	LATIN CAPITAL LETTER S
+0x54	0x0054	#	LATIN CAPITAL LETTER T
+0x55	0x0055	#	LATIN CAPITAL LETTER U
+0x56	0x0056	#	LATIN CAPITAL LETTER V
+0x57	0x0057	#	LATIN CAPITAL LETTER W
+0x58	0x0058	#	LATIN CAPITAL LETTER X
+0x59	0x0059	#	LATIN CAPITAL LETTER Y
+0x5A	0x005A	#	LATIN CAPITAL LETTER Z
+0x5B	0x005B	#	LEFT SQUARE BRACKET
+0x5C	0x005C	#	REVERSE SOLIDUS
+0x5D	0x005D	#	RIGHT SQUARE BRACKET
+0x5E	0x005E	#	CIRCUMFLEX ACCENT
+0x5F	0x005F	#	LOW LINE
+0x60	0x0060	#	GRAVE ACCENT
+0x61	0x0061	#	LATIN SMALL LETTER A
+0x62	0x0062	#	LATIN SMALL LETTER B
+0x63	0x0063	#	LATIN SMALL LETTER C
+0x64	0x0064	#	LATIN SMALL LETTER D
+0x65	0x0065	#	LATIN SMALL LETTER E
+0x66	0x0066	#	LATIN SMALL LETTER F
+0x67	0x0067	#	LATIN SMALL LETTER G
+0x68	0x0068	#	LATIN SMALL LETTER H
+0x69	0x0069	#	LATIN SMALL LETTER I
+0x6A	0x006A	#	LATIN SMALL LETTER J
+0x6B	0x006B	#	LATIN SMALL LETTER K
+0x6C	0x006C	#	LATIN SMALL LETTER L
+0x6D	0x006D	#	LATIN SMALL LETTER M
+0x6E	0x006E	#	LATIN SMALL LETTER N
+0x6F	0x006F	#	LATIN SMALL LETTER O
+0x70	0x0070	#	LATIN SMALL LETTER P
+0x71	0x0071	#	LATIN SMALL LETTER Q
+0x72	0x0072	#	LATIN SMALL LETTER R
+0x73	0x0073	#	LATIN SMALL LETTER S
+0x74	0x0074	#	LATIN SMALL LETTER T
+0x75	0x0075	#	LATIN SMALL LETTER U
+0x76	0x0076	#	LATIN SMALL LETTER V
+0x77	0x0077	#	LATIN SMALL LETTER W
+0x78	0x0078	#	LATIN SMALL LETTER X
+0x79	0x0079	#	LATIN SMALL LETTER Y
+0x7A	0x007A	#	LATIN SMALL LETTER Z
+0x7B	0x007B	#	LEFT CURLY BRACKET
+0x7C	0x007C	#	VERTICAL LINE
+0x7D	0x007D	#	RIGHT CURLY BRACKET
+0x7E	0x007E	#	TILDE
+0x7F	0x007F	#	DELETE
+0x80	0x0080	#	<control>
+0x81	0x0081	#	<control>
+0x82	0x0082	#	<control>
+0x83	0x0083	#	<control>
+0x84	0x0084	#	<control>
+0x85	0x0085	#	<control>
+0x86	0x0086	#	<control>
+0x87	0x0087	#	<control>
+0x88	0x0088	#	<control>
+0x89	0x0089	#	<control>
+0x8A	0x008A	#	<control>
+0x8B	0x008B	#	<control>
+0x8C	0x008C	#	<control>
+0x8D	0x008D	#	<control>
+0x8E	0x008E	#	<control>
+0x8F	0x008F	#	<control>
+0x90	0x0090	#	<control>
+0x91	0x0091	#	<control>
+0x92	0x0092	#	<control>
+0x93	0x0093	#	<control>
+0x94	0x0094	#	<control>
+0x95	0x0095	#	<control>
+0x96	0x0096	#	<control>
+0x97	0x0097	#	<control>
+0x98	0x0098	#	<control>
+0x99	0x0099	#	<control>
+0x9A	0x009A	#	<control>
+0x9B	0x009B	#	<control>
+0x9C	0x009C	#	<control>
+0x9D	0x009D	#	<control>
+0x9E	0x009E	#	<control>
+0x9F	0x009F	#	<control>
+0xA0	0x00A0	#	NO-BREAK SPACE
+0xA1	0x0104	#	LATIN CAPITAL LETTER A WITH OGONEK
+0xA2	0x02D8	#	BREVE
+0xA3	0x0141	#	LATIN CAPITAL LETTER L WITH STROKE
+0xA4	0x00A4	#	CURRENCY SIGN
+0xA5	0x013D	#	LATIN CAPITAL LETTER L WITH CARON
+0xA6	0x015A	#	LATIN CAPITAL LETTER S WITH ACUTE
+0xA7	0x00A7	#	SECTION SIGN
+0xA8	0x00A8	#	DIAERESIS
+0xA9	0x0160	#	LATIN CAPITAL LETTER S WITH CARON
+0xAA	0x015E	#	LATIN CAPITAL LETTER S WITH CEDILLA
+0xAB	0x0164	#	LATIN CAPITAL LETTER T WITH CARON
+0xAC	0x0179	#	LATIN CAPITAL LETTER Z WITH ACUTE
+0xAD	0x00AD	#	SOFT HYPHEN
+0xAE	0x017D	#	LATIN CAPITAL LETTER Z WITH CARON
+0xAF	0x017B	#	LATIN CAPITAL LETTER Z WITH DOT ABOVE
+0xB0	0x00B0	#	DEGREE SIGN
+0xB1	0x0105	#	LATIN SMALL LETTER A WITH OGONEK
+0xB2	0x02DB	#	OGONEK
+0xB3	0x0142	#	LATIN SMALL LETTER L WITH STROKE
+0xB4	0x00B4	#	ACUTE ACCENT
+0xB5	0x013E	#	LATIN SMALL LETTER L WITH CARON
+0xB6	0x015B	#	LATIN SMALL LETTER S WITH ACUTE
+0xB7	0x02C7	#	CARON
+0xB8	0x00B8	#	CEDILLA
+0xB9	0x0161	#	LATIN SMALL LETTER S WITH CARON
+0xBA	0x015F	#	LATIN SMALL LETTER S WITH CEDILLA
+0xBB	0x0165	#	LATIN SMALL LETTER T WITH CARON
+0xBC	0x017A	#	LATIN SMALL LETTER Z WITH ACUTE
+0xBD	0x02DD	#	DOUBLE ACUTE ACCENT
+0xBE	0x017E	#	LATIN SMALL LETTER Z WITH CARON
+0xBF	0x017C	#	LATIN SMALL LETTER Z WITH DOT ABOVE
+0xC0	0x0154	#	LATIN CAPITAL LETTER R WITH ACUTE
+0xC1	0x00C1	#	LATIN CAPITAL LETTER A WITH ACUTE
+0xC2	0x00C2	#	LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3	0x0102	#	LATIN CAPITAL LETTER A WITH BREVE
+0xC4	0x00C4	#	LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5	0x0139	#	LATIN CAPITAL LETTER L WITH ACUTE
+0xC6	0x0106	#	LATIN CAPITAL LETTER C WITH ACUTE
+0xC7	0x00C7	#	LATIN CAPITAL LETTER C WITH CEDILLA
+0xC8	0x010C	#	LATIN CAPITAL LETTER C WITH CARON
+0xC9	0x00C9	#	LATIN CAPITAL LETTER E WITH ACUTE
+0xCA	0x0118	#	LATIN CAPITAL LETTER E WITH OGONEK
+0xCB	0x00CB	#	LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC	0x011A	#	LATIN CAPITAL LETTER E WITH CARON
+0xCD	0x00CD	#	LATIN CAPITAL LETTER I WITH ACUTE
+0xCE	0x00CE	#	LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF	0x010E	#	LATIN CAPITAL LETTER D WITH CARON
+0xD0	0x0110	#	LATIN CAPITAL LETTER D WITH STROKE
+0xD1	0x0143	#	LATIN CAPITAL LETTER N WITH ACUTE
+0xD2	0x0147	#	LATIN CAPITAL LETTER N WITH CARON
+0xD3	0x00D3	#	LATIN CAPITAL LETTER O WITH ACUTE
+0xD4	0x00D4	#	LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5	0x0150	#	LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+0xD6	0x00D6	#	LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7	0x00D7	#	MULTIPLICATION SIGN
+0xD8	0x0158	#	LATIN CAPITAL LETTER R WITH CARON
+0xD9	0x016E	#	LATIN CAPITAL LETTER U WITH RING ABOVE
+0xDA	0x00DA	#	LATIN CAPITAL LETTER U WITH ACUTE
+0xDB	0x0170	#	LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+0xDC	0x00DC	#	LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD	0x00DD	#	LATIN CAPITAL LETTER Y WITH ACUTE
+0xDE	0x0162	#	LATIN CAPITAL LETTER T WITH CEDILLA
+0xDF	0x00DF	#	LATIN SMALL LETTER SHARP S
+0xE0	0x0155	#	LATIN SMALL LETTER R WITH ACUTE
+0xE1	0x00E1	#	LATIN SMALL LETTER A WITH ACUTE
+0xE2	0x00E2	#	LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3	0x0103	#	LATIN SMALL LETTER A WITH BREVE
+0xE4	0x00E4	#	LATIN SMALL LETTER A WITH DIAERESIS
+0xE5	0x013A	#	LATIN SMALL LETTER L WITH ACUTE
+0xE6	0x0107	#	LATIN SMALL LETTER C WITH ACUTE
+0xE7	0x00E7	#	LATIN SMALL LETTER C WITH CEDILLA
+0xE8	0x010D	#	LATIN SMALL LETTER C WITH CARON
+0xE9	0x00E9	#	LATIN SMALL LETTER E WITH ACUTE
+0xEA	0x0119	#	LATIN SMALL LETTER E WITH OGONEK
+0xEB	0x00EB	#	LATIN SMALL LETTER E WITH DIAERESIS
+0xEC	0x011B	#	LATIN SMALL LETTER E WITH CARON
+0xED	0x00ED	#	LATIN SMALL LETTER I WITH ACUTE
+0xEE	0x00EE	#	LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF	0x010F	#	LATIN SMALL LETTER D WITH CARON
+0xF0	0x0111	#	LATIN SMALL LETTER D WITH STROKE
+0xF1	0x0144	#	LATIN SMALL LETTER N WITH ACUTE
+0xF2	0x0148	#	LATIN SMALL LETTER N WITH CARON
+0xF3	0x00F3	#	LATIN SMALL LETTER O WITH ACUTE
+0xF4	0x00F4	#	LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5	0x0151	#	LATIN SMALL LETTER O WITH DOUBLE ACUTE
+0xF6	0x00F6	#	LATIN SMALL LETTER O WITH DIAERESIS
+0xF7	0x00F7	#	DIVISION SIGN
+0xF8	0x0159	#	LATIN SMALL LETTER R WITH CARON
+0xF9	0x016F	#	LATIN SMALL LETTER U WITH RING ABOVE
+0xFA	0x00FA	#	LATIN SMALL LETTER U WITH ACUTE
+0xFB	0x0171	#	LATIN SMALL LETTER U WITH DOUBLE ACUTE
+0xFC	0x00FC	#	LATIN SMALL LETTER U WITH DIAERESIS
+0xFD	0x00FD	#	LATIN SMALL LETTER Y WITH ACUTE
+0xFE	0x0163	#	LATIN SMALL LETTER T WITH CEDILLA
+0xFF	0x02D9	#	DOT ABOVE
diff --git a/Resources/8859-3.txt b/Resources/8859-3.txt
new file mode 100644
index 0000000..9b6ac69
--- /dev/null
+++ b/Resources/8859-3.txt
@@ -0,0 +1,296 @@
+#
+#	Name:             ISO/IEC 8859-3:1999 to Unicode
+#	Unicode version:  3.0
+#	Table version:    1.0
+#	Table format:     Format A
+#	Date:             1999 July 27
+#	Authors:          Ken Whistler <kenw@sybase.com>
+#
+#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
+#
+#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+#	No claims are made as to fitness for any particular purpose.  No
+#	warranties of any kind are expressed or implied.  The recipient
+#	agrees to determine applicability of information provided.  If this
+#	file has been provided on optical media by Unicode, Inc., the sole
+#	remedy for any claim will be exchange of defective media within 90
+#	days of receipt.
+#
+#	Unicode, Inc. hereby grants the right to freely use the information
+#	supplied in this file in the creation of products supporting the
+#	Unicode Standard, and to make copies of this file in any form for
+#	internal or external distribution as long as this notice remains
+#	attached.
+#
+#	General notes:
+#
+#	This table contains the data the Unicode Consortium has on how
+#       ISO/IEC 8859-3:1999 characters map into Unicode.
+#
+#	Format:  Three tab-separated columns
+#		 Column #1 is the ISO/IEC 8859-3 code (in hex as 0xXX)
+#		 Column #2 is the Unicode (in hex as 0xXXXX)
+#		 Column #3 the Unicode name (follows a comment sign, '#')
+#
+#	The entries are in ISO/IEC 8859-3 order.
+#
+#	Version history
+#	1.0 version updates 0.1 version by adding mappings for all
+#	control characters.
+#
+#	Updated versions of this file may be found in:
+#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
+#
+#	Any comments or problems, contact <errata@unicode.org>
+#	Please note that <errata@unicode.org> is an archival address;
+#	notices will be checked, but do not expect an immediate response.
+#
+0x00	0x0000	#	NULL
+0x01	0x0001	#	START OF HEADING
+0x02	0x0002	#	START OF TEXT
+0x03	0x0003	#	END OF TEXT
+0x04	0x0004	#	END OF TRANSMISSION
+0x05	0x0005	#	ENQUIRY
+0x06	0x0006	#	ACKNOWLEDGE
+0x07	0x0007	#	BELL
+0x08	0x0008	#	BACKSPACE
+0x09	0x0009	#	HORIZONTAL TABULATION
+0x0A	0x000A	#	LINE FEED
+0x0B	0x000B	#	VERTICAL TABULATION
+0x0C	0x000C	#	FORM FEED
+0x0D	0x000D	#	CARRIAGE RETURN
+0x0E	0x000E	#	SHIFT OUT
+0x0F	0x000F	#	SHIFT IN
+0x10	0x0010	#	DATA LINK ESCAPE
+0x11	0x0011	#	DEVICE CONTROL ONE
+0x12	0x0012	#	DEVICE CONTROL TWO
+0x13	0x0013	#	DEVICE CONTROL THREE
+0x14	0x0014	#	DEVICE CONTROL FOUR
+0x15	0x0015	#	NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#	SYNCHRONOUS IDLE
+0x17	0x0017	#	END OF TRANSMISSION BLOCK
+0x18	0x0018	#	CANCEL
+0x19	0x0019	#	END OF MEDIUM
+0x1A	0x001A	#	SUBSTITUTE
+0x1B	0x001B	#	ESCAPE
+0x1C	0x001C	#	FILE SEPARATOR
+0x1D	0x001D	#	GROUP SEPARATOR
+0x1E	0x001E	#	RECORD SEPARATOR
+0x1F	0x001F	#	UNIT SEPARATOR
+0x20	0x0020	#	SPACE
+0x21	0x0021	#	EXCLAMATION MARK
+0x22	0x0022	#	QUOTATION MARK
+0x23	0x0023	#	NUMBER SIGN
+0x24	0x0024	#	DOLLAR SIGN
+0x25	0x0025	#	PERCENT SIGN
+0x26	0x0026	#	AMPERSAND
+0x27	0x0027	#	APOSTROPHE
+0x28	0x0028	#	LEFT PARENTHESIS
+0x29	0x0029	#	RIGHT PARENTHESIS
+0x2A	0x002A	#	ASTERISK
+0x2B	0x002B	#	PLUS SIGN
+0x2C	0x002C	#	COMMA
+0x2D	0x002D	#	HYPHEN-MINUS
+0x2E	0x002E	#	FULL STOP
+0x2F	0x002F	#	SOLIDUS
+0x30	0x0030	#	DIGIT ZERO
+0x31	0x0031	#	DIGIT ONE
+0x32	0x0032	#	DIGIT TWO
+0x33	0x0033	#	DIGIT THREE
+0x34	0x0034	#	DIGIT FOUR
+0x35	0x0035	#	DIGIT FIVE
+0x36	0x0036	#	DIGIT SIX
+0x37	0x0037	#	DIGIT SEVEN
+0x38	0x0038	#	DIGIT EIGHT
+0x39	0x0039	#	DIGIT NINE
+0x3A	0x003A	#	COLON
+0x3B	0x003B	#	SEMICOLON
+0x3C	0x003C	#	LESS-THAN SIGN
+0x3D	0x003D	#	EQUALS SIGN
+0x3E	0x003E	#	GREATER-THAN SIGN
+0x3F	0x003F	#	QUESTION MARK
+0x40	0x0040	#	COMMERCIAL AT
+0x41	0x0041	#	LATIN CAPITAL LETTER A
+0x42	0x0042	#	LATIN CAPITAL LETTER B
+0x43	0x0043	#	LATIN CAPITAL LETTER C
+0x44	0x0044	#	LATIN CAPITAL LETTER D
+0x45	0x0045	#	LATIN CAPITAL LETTER E
+0x46	0x0046	#	LATIN CAPITAL LETTER F
+0x47	0x0047	#	LATIN CAPITAL LETTER G
+0x48	0x0048	#	LATIN CAPITAL LETTER H
+0x49	0x0049	#	LATIN CAPITAL LETTER I
+0x4A	0x004A	#	LATIN CAPITAL LETTER J
+0x4B	0x004B	#	LATIN CAPITAL LETTER K
+0x4C	0x004C	#	LATIN CAPITAL LETTER L
+0x4D	0x004D	#	LATIN CAPITAL LETTER M
+0x4E	0x004E	#	LATIN CAPITAL LETTER N
+0x4F	0x004F	#	LATIN CAPITAL LETTER O
+0x50	0x0050	#	LATIN CAPITAL LETTER P
+0x51	0x0051	#	LATIN CAPITAL LETTER Q
+0x52	0x0052	#	LATIN CAPITAL LETTER R
+0x53	0x0053	#	LATIN CAPITAL LETTER S
+0x54	0x0054	#	LATIN CAPITAL LETTER T
+0x55	0x0055	#	LATIN CAPITAL LETTER U
+0x56	0x0056	#	LATIN CAPITAL LETTER V
+0x57	0x0057	#	LATIN CAPITAL LETTER W
+0x58	0x0058	#	LATIN CAPITAL LETTER X
+0x59	0x0059	#	LATIN CAPITAL LETTER Y
+0x5A	0x005A	#	LATIN CAPITAL LETTER Z
+0x5B	0x005B	#	LEFT SQUARE BRACKET
+0x5C	0x005C	#	REVERSE SOLIDUS
+0x5D	0x005D	#	RIGHT SQUARE BRACKET
+0x5E	0x005E	#	CIRCUMFLEX ACCENT
+0x5F	0x005F	#	LOW LINE
+0x60	0x0060	#	GRAVE ACCENT
+0x61	0x0061	#	LATIN SMALL LETTER A
+0x62	0x0062	#	LATIN SMALL LETTER B
+0x63	0x0063	#	LATIN SMALL LETTER C
+0x64	0x0064	#	LATIN SMALL LETTER D
+0x65	0x0065	#	LATIN SMALL LETTER E
+0x66	0x0066	#	LATIN SMALL LETTER F
+0x67	0x0067	#	LATIN SMALL LETTER G
+0x68	0x0068	#	LATIN SMALL LETTER H
+0x69	0x0069	#	LATIN SMALL LETTER I
+0x6A	0x006A	#	LATIN SMALL LETTER J
+0x6B	0x006B	#	LATIN SMALL LETTER K
+0x6C	0x006C	#	LATIN SMALL LETTER L
+0x6D	0x006D	#	LATIN SMALL LETTER M
+0x6E	0x006E	#	LATIN SMALL LETTER N
+0x6F	0x006F	#	LATIN SMALL LETTER O
+0x70	0x0070	#	LATIN SMALL LETTER P
+0x71	0x0071	#	LATIN SMALL LETTER Q
+0x72	0x0072	#	LATIN SMALL LETTER R
+0x73	0x0073	#	LATIN SMALL LETTER S
+0x74	0x0074	#	LATIN SMALL LETTER T
+0x75	0x0075	#	LATIN SMALL LETTER U
+0x76	0x0076	#	LATIN SMALL LETTER V
+0x77	0x0077	#	LATIN SMALL LETTER W
+0x78	0x0078	#	LATIN SMALL LETTER X
+0x79	0x0079	#	LATIN SMALL LETTER Y
+0x7A	0x007A	#	LATIN SMALL LETTER Z
+0x7B	0x007B	#	LEFT CURLY BRACKET
+0x7C	0x007C	#	VERTICAL LINE
+0x7D	0x007D	#	RIGHT CURLY BRACKET
+0x7E	0x007E	#	TILDE
+0x7F	0x007F	#	DELETE
+0x80	0x0080	#	<control>
+0x81	0x0081	#	<control>
+0x82	0x0082	#	<control>
+0x83	0x0083	#	<control>
+0x84	0x0084	#	<control>
+0x85	0x0085	#	<control>
+0x86	0x0086	#	<control>
+0x87	0x0087	#	<control>
+0x88	0x0088	#	<control>
+0x89	0x0089	#	<control>
+0x8A	0x008A	#	<control>
+0x8B	0x008B	#	<control>
+0x8C	0x008C	#	<control>
+0x8D	0x008D	#	<control>
+0x8E	0x008E	#	<control>
+0x8F	0x008F	#	<control>
+0x90	0x0090	#	<control>
+0x91	0x0091	#	<control>
+0x92	0x0092	#	<control>
+0x93	0x0093	#	<control>
+0x94	0x0094	#	<control>
+0x95	0x0095	#	<control>
+0x96	0x0096	#	<control>
+0x97	0x0097	#	<control>
+0x98	0x0098	#	<control>
+0x99	0x0099	#	<control>
+0x9A	0x009A	#	<control>
+0x9B	0x009B	#	<control>
+0x9C	0x009C	#	<control>
+0x9D	0x009D	#	<control>
+0x9E	0x009E	#	<control>
+0x9F	0x009F	#	<control>
+0xA0	0x00A0	#	NO-BREAK SPACE
+0xA1	0x0126	#	LATIN CAPITAL LETTER H WITH STROKE
+0xA2	0x02D8	#	BREVE
+0xA3	0x00A3	#	POUND SIGN
+0xA4	0x00A4	#	CURRENCY SIGN
+0xA6	0x0124	#	LATIN CAPITAL LETTER H WITH CIRCUMFLEX
+0xA7	0x00A7	#	SECTION SIGN
+0xA8	0x00A8	#	DIAERESIS
+0xA9	0x0130	#	LATIN CAPITAL LETTER I WITH DOT ABOVE
+0xAA	0x015E	#	LATIN CAPITAL LETTER S WITH CEDILLA
+0xAB	0x011E	#	LATIN CAPITAL LETTER G WITH BREVE
+0xAC	0x0134	#	LATIN CAPITAL LETTER J WITH CIRCUMFLEX
+0xAD	0x00AD	#	SOFT HYPHEN
+0xAF	0x017B	#	LATIN CAPITAL LETTER Z WITH DOT ABOVE
+0xB0	0x00B0	#	DEGREE SIGN
+0xB1	0x0127	#	LATIN SMALL LETTER H WITH STROKE
+0xB2	0x00B2	#	SUPERSCRIPT TWO
+0xB3	0x00B3	#	SUPERSCRIPT THREE
+0xB4	0x00B4	#	ACUTE ACCENT
+0xB5	0x00B5	#	MICRO SIGN
+0xB6	0x0125	#	LATIN SMALL LETTER H WITH CIRCUMFLEX
+0xB7	0x00B7	#	MIDDLE DOT
+0xB8	0x00B8	#	CEDILLA
+0xB9	0x0131	#	LATIN SMALL LETTER DOTLESS I
+0xBA	0x015F	#	LATIN SMALL LETTER S WITH CEDILLA
+0xBB	0x011F	#	LATIN SMALL LETTER G WITH BREVE
+0xBC	0x0135	#	LATIN SMALL LETTER J WITH CIRCUMFLEX
+0xBD	0x00BD	#	VULGAR FRACTION ONE HALF
+0xBF	0x017C	#	LATIN SMALL LETTER Z WITH DOT ABOVE
+0xC0	0x00C0	#	LATIN CAPITAL LETTER A WITH GRAVE
+0xC1	0x00C1	#	LATIN CAPITAL LETTER A WITH ACUTE
+0xC2	0x00C2	#	LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC4	0x00C4	#	LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5	0x010A	#	LATIN CAPITAL LETTER C WITH DOT ABOVE
+0xC6	0x0108	#	LATIN CAPITAL LETTER C WITH CIRCUMFLEX
+0xC7	0x00C7	#	LATIN CAPITAL LETTER C WITH CEDILLA
+0xC8	0x00C8	#	LATIN CAPITAL LETTER E WITH GRAVE
+0xC9	0x00C9	#	LATIN CAPITAL LETTER E WITH ACUTE
+0xCA	0x00CA	#	LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xCB	0x00CB	#	LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC	0x00CC	#	LATIN CAPITAL LETTER I WITH GRAVE
+0xCD	0x00CD	#	LATIN CAPITAL LETTER I WITH ACUTE
+0xCE	0x00CE	#	LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF	0x00CF	#	LATIN CAPITAL LETTER I WITH DIAERESIS
+0xD1	0x00D1	#	LATIN CAPITAL LETTER N WITH TILDE
+0xD2	0x00D2	#	LATIN CAPITAL LETTER O WITH GRAVE
+0xD3	0x00D3	#	LATIN CAPITAL LETTER O WITH ACUTE
+0xD4	0x00D4	#	LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5	0x0120	#	LATIN CAPITAL LETTER G WITH DOT ABOVE
+0xD6	0x00D6	#	LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7	0x00D7	#	MULTIPLICATION SIGN
+0xD8	0x011C	#	LATIN CAPITAL LETTER G WITH CIRCUMFLEX
+0xD9	0x00D9	#	LATIN CAPITAL LETTER U WITH GRAVE
+0xDA	0x00DA	#	LATIN CAPITAL LETTER U WITH ACUTE
+0xDB	0x00DB	#	LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xDC	0x00DC	#	LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD	0x016C	#	LATIN CAPITAL LETTER U WITH BREVE
+0xDE	0x015C	#	LATIN CAPITAL LETTER S WITH CIRCUMFLEX
+0xDF	0x00DF	#	LATIN SMALL LETTER SHARP S
+0xE0	0x00E0	#	LATIN SMALL LETTER A WITH GRAVE
+0xE1	0x00E1	#	LATIN SMALL LETTER A WITH ACUTE
+0xE2	0x00E2	#	LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE4	0x00E4	#	LATIN SMALL LETTER A WITH DIAERESIS
+0xE5	0x010B	#	LATIN SMALL LETTER C WITH DOT ABOVE
+0xE6	0x0109	#	LATIN SMALL LETTER C WITH CIRCUMFLEX
+0xE7	0x00E7	#	LATIN SMALL LETTER C WITH CEDILLA
+0xE8	0x00E8	#	LATIN SMALL LETTER E WITH GRAVE
+0xE9	0x00E9	#	LATIN SMALL LETTER E WITH ACUTE
+0xEA	0x00EA	#	LATIN SMALL LETTER E WITH CIRCUMFLEX
+0xEB	0x00EB	#	LATIN SMALL LETTER E WITH DIAERESIS
+0xEC	0x00EC	#	LATIN SMALL LETTER I WITH GRAVE
+0xED	0x00ED	#	LATIN SMALL LETTER I WITH ACUTE
+0xEE	0x00EE	#	LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF	0x00EF	#	LATIN SMALL LETTER I WITH DIAERESIS
+0xF1	0x00F1	#	LATIN SMALL LETTER N WITH TILDE
+0xF2	0x00F2	#	LATIN SMALL LETTER O WITH GRAVE
+0xF3	0x00F3	#	LATIN SMALL LETTER O WITH ACUTE
+0xF4	0x00F4	#	LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5	0x0121	#	LATIN SMALL LETTER G WITH DOT ABOVE
+0xF6	0x00F6	#	LATIN SMALL LETTER O WITH DIAERESIS
+0xF7	0x00F7	#	DIVISION SIGN
+0xF8	0x011D	#	LATIN SMALL LETTER G WITH CIRCUMFLEX
+0xF9	0x00F9	#	LATIN SMALL LETTER U WITH GRAVE
+0xFA	0x00FA	#	LATIN SMALL LETTER U WITH ACUTE
+0xFB	0x00FB	#	LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xFC	0x00FC	#	LATIN SMALL LETTER U WITH DIAERESIS
+0xFD	0x016D	#	LATIN SMALL LETTER U WITH BREVE
+0xFE	0x015D	#	LATIN SMALL LETTER S WITH CIRCUMFLEX
+0xFF	0x02D9	#	DOT ABOVE
diff --git a/Resources/8859-4.txt b/Resources/8859-4.txt
new file mode 100644
index 0000000..662e698
--- /dev/null
+++ b/Resources/8859-4.txt
@@ -0,0 +1,303 @@
+#
+#	Name:             ISO/IEC 8859-4:1998 to Unicode
+#	Unicode version:  3.0
+#	Table version:    1.0
+#	Table format:     Format A
+#	Date:             1999 July 27
+#	Authors:          Ken Whistler <kenw@sybase.com>
+#
+#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
+#
+#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+#	No claims are made as to fitness for any particular purpose.  No
+#	warranties of any kind are expressed or implied.  The recipient
+#	agrees to determine applicability of information provided.  If this
+#	file has been provided on optical media by Unicode, Inc., the sole
+#	remedy for any claim will be exchange of defective media within 90
+#	days of receipt.
+#
+#	Unicode, Inc. hereby grants the right to freely use the information
+#	supplied in this file in the creation of products supporting the
+#	Unicode Standard, and to make copies of this file in any form for
+#	internal or external distribution as long as this notice remains
+#	attached.
+#
+#	General notes:
+#
+#	This table contains the data the Unicode Consortium has on how
+#       ISO/IEC 8859-4:1998 characters map into Unicode.
+#
+#	Format:  Three tab-separated columns
+#		 Column #1 is the ISO/IEC 8859-4 code (in hex as 0xXX)
+#		 Column #2 is the Unicode (in hex as 0xXXXX)
+#		 Column #3 the Unicode name (follows a comment sign, '#')
+#
+#	The entries are in ISO/IEC 8859-4 order.
+#
+#	Version history
+#	1.0 version updates 0.1 version by adding mappings for all
+#	control characters.
+#
+#	Updated versions of this file may be found in:
+#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
+#
+#	Any comments or problems, contact <errata@unicode.org>
+#	Please note that <errata@unicode.org> is an archival address;
+#	notices will be checked, but do not expect an immediate response.
+#
+0x00	0x0000	#	NULL
+0x01	0x0001	#	START OF HEADING
+0x02	0x0002	#	START OF TEXT
+0x03	0x0003	#	END OF TEXT
+0x04	0x0004	#	END OF TRANSMISSION
+0x05	0x0005	#	ENQUIRY
+0x06	0x0006	#	ACKNOWLEDGE
+0x07	0x0007	#	BELL
+0x08	0x0008	#	BACKSPACE
+0x09	0x0009	#	HORIZONTAL TABULATION
+0x0A	0x000A	#	LINE FEED
+0x0B	0x000B	#	VERTICAL TABULATION
+0x0C	0x000C	#	FORM FEED
+0x0D	0x000D	#	CARRIAGE RETURN
+0x0E	0x000E	#	SHIFT OUT
+0x0F	0x000F	#	SHIFT IN
+0x10	0x0010	#	DATA LINK ESCAPE
+0x11	0x0011	#	DEVICE CONTROL ONE
+0x12	0x0012	#	DEVICE CONTROL TWO
+0x13	0x0013	#	DEVICE CONTROL THREE
+0x14	0x0014	#	DEVICE CONTROL FOUR
+0x15	0x0015	#	NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#	SYNCHRONOUS IDLE
+0x17	0x0017	#	END OF TRANSMISSION BLOCK
+0x18	0x0018	#	CANCEL
+0x19	0x0019	#	END OF MEDIUM
+0x1A	0x001A	#	SUBSTITUTE
+0x1B	0x001B	#	ESCAPE
+0x1C	0x001C	#	FILE SEPARATOR
+0x1D	0x001D	#	GROUP SEPARATOR
+0x1E	0x001E	#	RECORD SEPARATOR
+0x1F	0x001F	#	UNIT SEPARATOR
+0x20	0x0020	#	SPACE
+0x21	0x0021	#	EXCLAMATION MARK
+0x22	0x0022	#	QUOTATION MARK
+0x23	0x0023	#	NUMBER SIGN
+0x24	0x0024	#	DOLLAR SIGN
+0x25	0x0025	#	PERCENT SIGN
+0x26	0x0026	#	AMPERSAND
+0x27	0x0027	#	APOSTROPHE
+0x28	0x0028	#	LEFT PARENTHESIS
+0x29	0x0029	#	RIGHT PARENTHESIS
+0x2A	0x002A	#	ASTERISK
+0x2B	0x002B	#	PLUS SIGN
+0x2C	0x002C	#	COMMA
+0x2D	0x002D	#	HYPHEN-MINUS
+0x2E	0x002E	#	FULL STOP
+0x2F	0x002F	#	SOLIDUS
+0x30	0x0030	#	DIGIT ZERO
+0x31	0x0031	#	DIGIT ONE
+0x32	0x0032	#	DIGIT TWO
+0x33	0x0033	#	DIGIT THREE
+0x34	0x0034	#	DIGIT FOUR
+0x35	0x0035	#	DIGIT FIVE
+0x36	0x0036	#	DIGIT SIX
+0x37	0x0037	#	DIGIT SEVEN
+0x38	0x0038	#	DIGIT EIGHT
+0x39	0x0039	#	DIGIT NINE
+0x3A	0x003A	#	COLON
+0x3B	0x003B	#	SEMICOLON
+0x3C	0x003C	#	LESS-THAN SIGN
+0x3D	0x003D	#	EQUALS SIGN
+0x3E	0x003E	#	GREATER-THAN SIGN
+0x3F	0x003F	#	QUESTION MARK
+0x40	0x0040	#	COMMERCIAL AT
+0x41	0x0041	#	LATIN CAPITAL LETTER A
+0x42	0x0042	#	LATIN CAPITAL LETTER B
+0x43	0x0043	#	LATIN CAPITAL LETTER C
+0x44	0x0044	#	LATIN CAPITAL LETTER D
+0x45	0x0045	#	LATIN CAPITAL LETTER E
+0x46	0x0046	#	LATIN CAPITAL LETTER F
+0x47	0x0047	#	LATIN CAPITAL LETTER G
+0x48	0x0048	#	LATIN CAPITAL LETTER H
+0x49	0x0049	#	LATIN CAPITAL LETTER I
+0x4A	0x004A	#	LATIN CAPITAL LETTER J
+0x4B	0x004B	#	LATIN CAPITAL LETTER K
+0x4C	0x004C	#	LATIN CAPITAL LETTER L
+0x4D	0x004D	#	LATIN CAPITAL LETTER M
+0x4E	0x004E	#	LATIN CAPITAL LETTER N
+0x4F	0x004F	#	LATIN CAPITAL LETTER O
+0x50	0x0050	#	LATIN CAPITAL LETTER P
+0x51	0x0051	#	LATIN CAPITAL LETTER Q
+0x52	0x0052	#	LATIN CAPITAL LETTER R
+0x53	0x0053	#	LATIN CAPITAL LETTER S
+0x54	0x0054	#	LATIN CAPITAL LETTER T
+0x55	0x0055	#	LATIN CAPITAL LETTER U
+0x56	0x0056	#	LATIN CAPITAL LETTER V
+0x57	0x0057	#	LATIN CAPITAL LETTER W
+0x58	0x0058	#	LATIN CAPITAL LETTER X
+0x59	0x0059	#	LATIN CAPITAL LETTER Y
+0x5A	0x005A	#	LATIN CAPITAL LETTER Z
+0x5B	0x005B	#	LEFT SQUARE BRACKET
+0x5C	0x005C	#	REVERSE SOLIDUS
+0x5D	0x005D	#	RIGHT SQUARE BRACKET
+0x5E	0x005E	#	CIRCUMFLEX ACCENT
+0x5F	0x005F	#	LOW LINE
+0x60	0x0060	#	GRAVE ACCENT
+0x61	0x0061	#	LATIN SMALL LETTER A
+0x62	0x0062	#	LATIN SMALL LETTER B
+0x63	0x0063	#	LATIN SMALL LETTER C
+0x64	0x0064	#	LATIN SMALL LETTER D
+0x65	0x0065	#	LATIN SMALL LETTER E
+0x66	0x0066	#	LATIN SMALL LETTER F
+0x67	0x0067	#	LATIN SMALL LETTER G
+0x68	0x0068	#	LATIN SMALL LETTER H
+0x69	0x0069	#	LATIN SMALL LETTER I
+0x6A	0x006A	#	LATIN SMALL LETTER J
+0x6B	0x006B	#	LATIN SMALL LETTER K
+0x6C	0x006C	#	LATIN SMALL LETTER L
+0x6D	0x006D	#	LATIN SMALL LETTER M
+0x6E	0x006E	#	LATIN SMALL LETTER N
+0x6F	0x006F	#	LATIN SMALL LETTER O
+0x70	0x0070	#	LATIN SMALL LETTER P
+0x71	0x0071	#	LATIN SMALL LETTER Q
+0x72	0x0072	#	LATIN SMALL LETTER R
+0x73	0x0073	#	LATIN SMALL LETTER S
+0x74	0x0074	#	LATIN SMALL LETTER T
+0x75	0x0075	#	LATIN SMALL LETTER U
+0x76	0x0076	#	LATIN SMALL LETTER V
+0x77	0x0077	#	LATIN SMALL LETTER W
+0x78	0x0078	#	LATIN SMALL LETTER X
+0x79	0x0079	#	LATIN SMALL LETTER Y
+0x7A	0x007A	#	LATIN SMALL LETTER Z
+0x7B	0x007B	#	LEFT CURLY BRACKET
+0x7C	0x007C	#	VERTICAL LINE
+0x7D	0x007D	#	RIGHT CURLY BRACKET
+0x7E	0x007E	#	TILDE
+0x7F	0x007F	#	DELETE
+0x80	0x0080	#	<control>
+0x81	0x0081	#	<control>
+0x82	0x0082	#	<control>
+0x83	0x0083	#	<control>
+0x84	0x0084	#	<control>
+0x85	0x0085	#	<control>
+0x86	0x0086	#	<control>
+0x87	0x0087	#	<control>
+0x88	0x0088	#	<control>
+0x89	0x0089	#	<control>
+0x8A	0x008A	#	<control>
+0x8B	0x008B	#	<control>
+0x8C	0x008C	#	<control>
+0x8D	0x008D	#	<control>
+0x8E	0x008E	#	<control>
+0x8F	0x008F	#	<control>
+0x90	0x0090	#	<control>
+0x91	0x0091	#	<control>
+0x92	0x0092	#	<control>
+0x93	0x0093	#	<control>
+0x94	0x0094	#	<control>
+0x95	0x0095	#	<control>
+0x96	0x0096	#	<control>
+0x97	0x0097	#	<control>
+0x98	0x0098	#	<control>
+0x99	0x0099	#	<control>
+0x9A	0x009A	#	<control>
+0x9B	0x009B	#	<control>
+0x9C	0x009C	#	<control>
+0x9D	0x009D	#	<control>
+0x9E	0x009E	#	<control>
+0x9F	0x009F	#	<control>
+0xA0	0x00A0	#	NO-BREAK SPACE
+0xA1	0x0104	#	LATIN CAPITAL LETTER A WITH OGONEK
+0xA2	0x0138	#	LATIN SMALL LETTER KRA
+0xA3	0x0156	#	LATIN CAPITAL LETTER R WITH CEDILLA
+0xA4	0x00A4	#	CURRENCY SIGN
+0xA5	0x0128	#	LATIN CAPITAL LETTER I WITH TILDE
+0xA6	0x013B	#	LATIN CAPITAL LETTER L WITH CEDILLA
+0xA7	0x00A7	#	SECTION SIGN
+0xA8	0x00A8	#	DIAERESIS
+0xA9	0x0160	#	LATIN CAPITAL LETTER S WITH CARON
+0xAA	0x0112	#	LATIN CAPITAL LETTER E WITH MACRON
+0xAB	0x0122	#	LATIN CAPITAL LETTER G WITH CEDILLA
+0xAC	0x0166	#	LATIN CAPITAL LETTER T WITH STROKE
+0xAD	0x00AD	#	SOFT HYPHEN
+0xAE	0x017D	#	LATIN CAPITAL LETTER Z WITH CARON
+0xAF	0x00AF	#	MACRON
+0xB0	0x00B0	#	DEGREE SIGN
+0xB1	0x0105	#	LATIN SMALL LETTER A WITH OGONEK
+0xB2	0x02DB	#	OGONEK
+0xB3	0x0157	#	LATIN SMALL LETTER R WITH CEDILLA
+0xB4	0x00B4	#	ACUTE ACCENT
+0xB5	0x0129	#	LATIN SMALL LETTER I WITH TILDE
+0xB6	0x013C	#	LATIN SMALL LETTER L WITH CEDILLA
+0xB7	0x02C7	#	CARON
+0xB8	0x00B8	#	CEDILLA
+0xB9	0x0161	#	LATIN SMALL LETTER S WITH CARON
+0xBA	0x0113	#	LATIN SMALL LETTER E WITH MACRON
+0xBB	0x0123	#	LATIN SMALL LETTER G WITH CEDILLA
+0xBC	0x0167	#	LATIN SMALL LETTER T WITH STROKE
+0xBD	0x014A	#	LATIN CAPITAL LETTER ENG
+0xBE	0x017E	#	LATIN SMALL LETTER Z WITH CARON
+0xBF	0x014B	#	LATIN SMALL LETTER ENG
+0xC0	0x0100	#	LATIN CAPITAL LETTER A WITH MACRON
+0xC1	0x00C1	#	LATIN CAPITAL LETTER A WITH ACUTE
+0xC2	0x00C2	#	LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3	0x00C3	#	LATIN CAPITAL LETTER A WITH TILDE
+0xC4	0x00C4	#	LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5	0x00C5	#	LATIN CAPITAL LETTER A WITH RING ABOVE
+0xC6	0x00C6	#	LATIN CAPITAL LETTER AE
+0xC7	0x012E	#	LATIN CAPITAL LETTER I WITH OGONEK
+0xC8	0x010C	#	LATIN CAPITAL LETTER C WITH CARON
+0xC9	0x00C9	#	LATIN CAPITAL LETTER E WITH ACUTE
+0xCA	0x0118	#	LATIN CAPITAL LETTER E WITH OGONEK
+0xCB	0x00CB	#	LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC	0x0116	#	LATIN CAPITAL LETTER E WITH DOT ABOVE
+0xCD	0x00CD	#	LATIN CAPITAL LETTER I WITH ACUTE
+0xCE	0x00CE	#	LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF	0x012A	#	LATIN CAPITAL LETTER I WITH MACRON
+0xD0	0x0110	#	LATIN CAPITAL LETTER D WITH STROKE
+0xD1	0x0145	#	LATIN CAPITAL LETTER N WITH CEDILLA
+0xD2	0x014C	#	LATIN CAPITAL LETTER O WITH MACRON
+0xD3	0x0136	#	LATIN CAPITAL LETTER K WITH CEDILLA
+0xD4	0x00D4	#	LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5	0x00D5	#	LATIN CAPITAL LETTER O WITH TILDE
+0xD6	0x00D6	#	LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7	0x00D7	#	MULTIPLICATION SIGN
+0xD8	0x00D8	#	LATIN CAPITAL LETTER O WITH STROKE
+0xD9	0x0172	#	LATIN CAPITAL LETTER U WITH OGONEK
+0xDA	0x00DA	#	LATIN CAPITAL LETTER U WITH ACUTE
+0xDB	0x00DB	#	LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xDC	0x00DC	#	LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD	0x0168	#	LATIN CAPITAL LETTER U WITH TILDE
+0xDE	0x016A	#	LATIN CAPITAL LETTER U WITH MACRON
+0xDF	0x00DF	#	LATIN SMALL LETTER SHARP S
+0xE0	0x0101	#	LATIN SMALL LETTER A WITH MACRON
+0xE1	0x00E1	#	LATIN SMALL LETTER A WITH ACUTE
+0xE2	0x00E2	#	LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3	0x00E3	#	LATIN SMALL LETTER A WITH TILDE
+0xE4	0x00E4	#	LATIN SMALL LETTER A WITH DIAERESIS
+0xE5	0x00E5	#	LATIN SMALL LETTER A WITH RING ABOVE
+0xE6	0x00E6	#	LATIN SMALL LETTER AE
+0xE7	0x012F	#	LATIN SMALL LETTER I WITH OGONEK
+0xE8	0x010D	#	LATIN SMALL LETTER C WITH CARON
+0xE9	0x00E9	#	LATIN SMALL LETTER E WITH ACUTE
+0xEA	0x0119	#	LATIN SMALL LETTER E WITH OGONEK
+0xEB	0x00EB	#	LATIN SMALL LETTER E WITH DIAERESIS
+0xEC	0x0117	#	LATIN SMALL LETTER E WITH DOT ABOVE
+0xED	0x00ED	#	LATIN SMALL LETTER I WITH ACUTE
+0xEE	0x00EE	#	LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF	0x012B	#	LATIN SMALL LETTER I WITH MACRON
+0xF0	0x0111	#	LATIN SMALL LETTER D WITH STROKE
+0xF1	0x0146	#	LATIN SMALL LETTER N WITH CEDILLA
+0xF2	0x014D	#	LATIN SMALL LETTER O WITH MACRON
+0xF3	0x0137	#	LATIN SMALL LETTER K WITH CEDILLA
+0xF4	0x00F4	#	LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5	0x00F5	#	LATIN SMALL LETTER O WITH TILDE
+0xF6	0x00F6	#	LATIN SMALL LETTER O WITH DIAERESIS
+0xF7	0x00F7	#	DIVISION SIGN
+0xF8	0x00F8	#	LATIN SMALL LETTER O WITH STROKE
+0xF9	0x0173	#	LATIN SMALL LETTER U WITH OGONEK
+0xFA	0x00FA	#	LATIN SMALL LETTER U WITH ACUTE
+0xFB	0x00FB	#	LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xFC	0x00FC	#	LATIN SMALL LETTER U WITH DIAERESIS
+0xFD	0x0169	#	LATIN SMALL LETTER U WITH TILDE
+0xFE	0x016B	#	LATIN SMALL LETTER U WITH MACRON
+0xFF	0x02D9	#	DOT ABOVE
diff --git a/Resources/8859-5.txt b/Resources/8859-5.txt
new file mode 100644
index 0000000..a7ed1ce
--- /dev/null
+++ b/Resources/8859-5.txt
@@ -0,0 +1,303 @@
+#
+#	Name:             ISO 8859-5:1999 to Unicode
+#	Unicode version:  3.0
+#	Table version:    1.0
+#	Table format:     Format A
+#	Date:             1999 July 27
+#	Authors:          Ken Whistler <kenw@sybase.com>
+#
+#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
+#
+#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+#	No claims are made as to fitness for any particular purpose.  No
+#	warranties of any kind are expressed or implied.  The recipient
+#	agrees to determine applicability of information provided.  If this
+#	file has been provided on optical media by Unicode, Inc., the sole
+#	remedy for any claim will be exchange of defective media within 90
+#	days of receipt.
+#
+#	Unicode, Inc. hereby grants the right to freely use the information
+#	supplied in this file in the creation of products supporting the
+#	Unicode Standard, and to make copies of this file in any form for
+#	internal or external distribution as long as this notice remains
+#	attached.
+#
+#	General notes:
+#
+#	This table contains the data the Unicode Consortium has on how
+#       ISO/IEC 8859-5:1999 characters map into Unicode.
+#
+#	Format:  Three tab-separated columns
+#		 Column #1 is the ISO/IEC 8859-5 code (in hex as 0xXX)
+#		 Column #2 is the Unicode (in hex as 0xXXXX)
+#		 Column #3 the Unicode name (follows a comment sign, '#')
+#
+#	The entries are in ISO/IEC 8859-5 order.
+#
+#	Version history
+#	1.0 version updates 0.1 version by adding mappings for all
+#	control characters.
+#
+#	Updated versions of this file may be found in:
+#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
+#
+#	Any comments or problems, contact <errata@unicode.org>
+#	Please note that <errata@unicode.org> is an archival address;
+#	notices will be checked, but do not expect an immediate response.
+#
+0x00	0x0000	#	NULL
+0x01	0x0001	#	START OF HEADING
+0x02	0x0002	#	START OF TEXT
+0x03	0x0003	#	END OF TEXT
+0x04	0x0004	#	END OF TRANSMISSION
+0x05	0x0005	#	ENQUIRY
+0x06	0x0006	#	ACKNOWLEDGE
+0x07	0x0007	#	BELL
+0x08	0x0008	#	BACKSPACE
+0x09	0x0009	#	HORIZONTAL TABULATION
+0x0A	0x000A	#	LINE FEED
+0x0B	0x000B	#	VERTICAL TABULATION
+0x0C	0x000C	#	FORM FEED
+0x0D	0x000D	#	CARRIAGE RETURN
+0x0E	0x000E	#	SHIFT OUT
+0x0F	0x000F	#	SHIFT IN
+0x10	0x0010	#	DATA LINK ESCAPE
+0x11	0x0011	#	DEVICE CONTROL ONE
+0x12	0x0012	#	DEVICE CONTROL TWO
+0x13	0x0013	#	DEVICE CONTROL THREE
+0x14	0x0014	#	DEVICE CONTROL FOUR
+0x15	0x0015	#	NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#	SYNCHRONOUS IDLE
+0x17	0x0017	#	END OF TRANSMISSION BLOCK
+0x18	0x0018	#	CANCEL
+0x19	0x0019	#	END OF MEDIUM
+0x1A	0x001A	#	SUBSTITUTE
+0x1B	0x001B	#	ESCAPE
+0x1C	0x001C	#	FILE SEPARATOR
+0x1D	0x001D	#	GROUP SEPARATOR
+0x1E	0x001E	#	RECORD SEPARATOR
+0x1F	0x001F	#	UNIT SEPARATOR
+0x20	0x0020	#	SPACE
+0x21	0x0021	#	EXCLAMATION MARK
+0x22	0x0022	#	QUOTATION MARK
+0x23	0x0023	#	NUMBER SIGN
+0x24	0x0024	#	DOLLAR SIGN
+0x25	0x0025	#	PERCENT SIGN
+0x26	0x0026	#	AMPERSAND
+0x27	0x0027	#	APOSTROPHE
+0x28	0x0028	#	LEFT PARENTHESIS
+0x29	0x0029	#	RIGHT PARENTHESIS
+0x2A	0x002A	#	ASTERISK
+0x2B	0x002B	#	PLUS SIGN
+0x2C	0x002C	#	COMMA
+0x2D	0x002D	#	HYPHEN-MINUS
+0x2E	0x002E	#	FULL STOP
+0x2F	0x002F	#	SOLIDUS
+0x30	0x0030	#	DIGIT ZERO
+0x31	0x0031	#	DIGIT ONE
+0x32	0x0032	#	DIGIT TWO
+0x33	0x0033	#	DIGIT THREE
+0x34	0x0034	#	DIGIT FOUR
+0x35	0x0035	#	DIGIT FIVE
+0x36	0x0036	#	DIGIT SIX
+0x37	0x0037	#	DIGIT SEVEN
+0x38	0x0038	#	DIGIT EIGHT
+0x39	0x0039	#	DIGIT NINE
+0x3A	0x003A	#	COLON
+0x3B	0x003B	#	SEMICOLON
+0x3C	0x003C	#	LESS-THAN SIGN
+0x3D	0x003D	#	EQUALS SIGN
+0x3E	0x003E	#	GREATER-THAN SIGN
+0x3F	0x003F	#	QUESTION MARK
+0x40	0x0040	#	COMMERCIAL AT
+0x41	0x0041	#	LATIN CAPITAL LETTER A
+0x42	0x0042	#	LATIN CAPITAL LETTER B
+0x43	0x0043	#	LATIN CAPITAL LETTER C
+0x44	0x0044	#	LATIN CAPITAL LETTER D
+0x45	0x0045	#	LATIN CAPITAL LETTER E
+0x46	0x0046	#	LATIN CAPITAL LETTER F
+0x47	0x0047	#	LATIN CAPITAL LETTER G
+0x48	0x0048	#	LATIN CAPITAL LETTER H
+0x49	0x0049	#	LATIN CAPITAL LETTER I
+0x4A	0x004A	#	LATIN CAPITAL LETTER J
+0x4B	0x004B	#	LATIN CAPITAL LETTER K
+0x4C	0x004C	#	LATIN CAPITAL LETTER L
+0x4D	0x004D	#	LATIN CAPITAL LETTER M
+0x4E	0x004E	#	LATIN CAPITAL LETTER N
+0x4F	0x004F	#	LATIN CAPITAL LETTER O
+0x50	0x0050	#	LATIN CAPITAL LETTER P
+0x51	0x0051	#	LATIN CAPITAL LETTER Q
+0x52	0x0052	#	LATIN CAPITAL LETTER R
+0x53	0x0053	#	LATIN CAPITAL LETTER S
+0x54	0x0054	#	LATIN CAPITAL LETTER T
+0x55	0x0055	#	LATIN CAPITAL LETTER U
+0x56	0x0056	#	LATIN CAPITAL LETTER V
+0x57	0x0057	#	LATIN CAPITAL LETTER W
+0x58	0x0058	#	LATIN CAPITAL LETTER X
+0x59	0x0059	#	LATIN CAPITAL LETTER Y
+0x5A	0x005A	#	LATIN CAPITAL LETTER Z
+0x5B	0x005B	#	LEFT SQUARE BRACKET
+0x5C	0x005C	#	REVERSE SOLIDUS
+0x5D	0x005D	#	RIGHT SQUARE BRACKET
+0x5E	0x005E	#	CIRCUMFLEX ACCENT
+0x5F	0x005F	#	LOW LINE
+0x60	0x0060	#	GRAVE ACCENT
+0x61	0x0061	#	LATIN SMALL LETTER A
+0x62	0x0062	#	LATIN SMALL LETTER B
+0x63	0x0063	#	LATIN SMALL LETTER C
+0x64	0x0064	#	LATIN SMALL LETTER D
+0x65	0x0065	#	LATIN SMALL LETTER E
+0x66	0x0066	#	LATIN SMALL LETTER F
+0x67	0x0067	#	LATIN SMALL LETTER G
+0x68	0x0068	#	LATIN SMALL LETTER H
+0x69	0x0069	#	LATIN SMALL LETTER I
+0x6A	0x006A	#	LATIN SMALL LETTER J
+0x6B	0x006B	#	LATIN SMALL LETTER K
+0x6C	0x006C	#	LATIN SMALL LETTER L
+0x6D	0x006D	#	LATIN SMALL LETTER M
+0x6E	0x006E	#	LATIN SMALL LETTER N
+0x6F	0x006F	#	LATIN SMALL LETTER O
+0x70	0x0070	#	LATIN SMALL LETTER P
+0x71	0x0071	#	LATIN SMALL LETTER Q
+0x72	0x0072	#	LATIN SMALL LETTER R
+0x73	0x0073	#	LATIN SMALL LETTER S
+0x74	0x0074	#	LATIN SMALL LETTER T
+0x75	0x0075	#	LATIN SMALL LETTER U
+0x76	0x0076	#	LATIN SMALL LETTER V
+0x77	0x0077	#	LATIN SMALL LETTER W
+0x78	0x0078	#	LATIN SMALL LETTER X
+0x79	0x0079	#	LATIN SMALL LETTER Y
+0x7A	0x007A	#	LATIN SMALL LETTER Z
+0x7B	0x007B	#	LEFT CURLY BRACKET
+0x7C	0x007C	#	VERTICAL LINE
+0x7D	0x007D	#	RIGHT CURLY BRACKET
+0x7E	0x007E	#	TILDE
+0x7F	0x007F	#	DELETE
+0x80	0x0080	#	<control>
+0x81	0x0081	#	<control>
+0x82	0x0082	#	<control>
+0x83	0x0083	#	<control>
+0x84	0x0084	#	<control>
+0x85	0x0085	#	<control>
+0x86	0x0086	#	<control>
+0x87	0x0087	#	<control>
+0x88	0x0088	#	<control>
+0x89	0x0089	#	<control>
+0x8A	0x008A	#	<control>
+0x8B	0x008B	#	<control>
+0x8C	0x008C	#	<control>
+0x8D	0x008D	#	<control>
+0x8E	0x008E	#	<control>
+0x8F	0x008F	#	<control>
+0x90	0x0090	#	<control>
+0x91	0x0091	#	<control>
+0x92	0x0092	#	<control>
+0x93	0x0093	#	<control>
+0x94	0x0094	#	<control>
+0x95	0x0095	#	<control>
+0x96	0x0096	#	<control>
+0x97	0x0097	#	<control>
+0x98	0x0098	#	<control>
+0x99	0x0099	#	<control>
+0x9A	0x009A	#	<control>
+0x9B	0x009B	#	<control>
+0x9C	0x009C	#	<control>
+0x9D	0x009D	#	<control>
+0x9E	0x009E	#	<control>
+0x9F	0x009F	#	<control>
+0xA0	0x00A0	#	NO-BREAK SPACE
+0xA1	0x0401	#	CYRILLIC CAPITAL LETTER IO
+0xA2	0x0402	#	CYRILLIC CAPITAL LETTER DJE
+0xA3	0x0403	#	CYRILLIC CAPITAL LETTER GJE
+0xA4	0x0404	#	CYRILLIC CAPITAL LETTER UKRAINIAN IE
+0xA5	0x0405	#	CYRILLIC CAPITAL LETTER DZE
+0xA6	0x0406	#	CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+0xA7	0x0407	#	CYRILLIC CAPITAL LETTER YI
+0xA8	0x0408	#	CYRILLIC CAPITAL LETTER JE
+0xA9	0x0409	#	CYRILLIC CAPITAL LETTER LJE
+0xAA	0x040A	#	CYRILLIC CAPITAL LETTER NJE
+0xAB	0x040B	#	CYRILLIC CAPITAL LETTER TSHE
+0xAC	0x040C	#	CYRILLIC CAPITAL LETTER KJE
+0xAD	0x00AD	#	SOFT HYPHEN
+0xAE	0x040E	#	CYRILLIC CAPITAL LETTER SHORT U
+0xAF	0x040F	#	CYRILLIC CAPITAL LETTER DZHE
+0xB0	0x0410	#	CYRILLIC CAPITAL LETTER A
+0xB1	0x0411	#	CYRILLIC CAPITAL LETTER BE
+0xB2	0x0412	#	CYRILLIC CAPITAL LETTER VE
+0xB3	0x0413	#	CYRILLIC CAPITAL LETTER GHE
+0xB4	0x0414	#	CYRILLIC CAPITAL LETTER DE
+0xB5	0x0415	#	CYRILLIC CAPITAL LETTER IE
+0xB6	0x0416	#	CYRILLIC CAPITAL LETTER ZHE
+0xB7	0x0417	#	CYRILLIC CAPITAL LETTER ZE
+0xB8	0x0418	#	CYRILLIC CAPITAL LETTER I
+0xB9	0x0419	#	CYRILLIC CAPITAL LETTER SHORT I
+0xBA	0x041A	#	CYRILLIC CAPITAL LETTER KA
+0xBB	0x041B	#	CYRILLIC CAPITAL LETTER EL
+0xBC	0x041C	#	CYRILLIC CAPITAL LETTER EM
+0xBD	0x041D	#	CYRILLIC CAPITAL LETTER EN
+0xBE	0x041E	#	CYRILLIC CAPITAL LETTER O
+0xBF	0x041F	#	CYRILLIC CAPITAL LETTER PE
+0xC0	0x0420	#	CYRILLIC CAPITAL LETTER ER
+0xC1	0x0421	#	CYRILLIC CAPITAL LETTER ES
+0xC2	0x0422	#	CYRILLIC CAPITAL LETTER TE
+0xC3	0x0423	#	CYRILLIC CAPITAL LETTER U
+0xC4	0x0424	#	CYRILLIC CAPITAL LETTER EF
+0xC5	0x0425	#	CYRILLIC CAPITAL LETTER HA
+0xC6	0x0426	#	CYRILLIC CAPITAL LETTER TSE
+0xC7	0x0427	#	CYRILLIC CAPITAL LETTER CHE
+0xC8	0x0428	#	CYRILLIC CAPITAL LETTER SHA
+0xC9	0x0429	#	CYRILLIC CAPITAL LETTER SHCHA
+0xCA	0x042A	#	CYRILLIC CAPITAL LETTER HARD SIGN
+0xCB	0x042B	#	CYRILLIC CAPITAL LETTER YERU
+0xCC	0x042C	#	CYRILLIC CAPITAL LETTER SOFT SIGN
+0xCD	0x042D	#	CYRILLIC CAPITAL LETTER E
+0xCE	0x042E	#	CYRILLIC CAPITAL LETTER YU
+0xCF	0x042F	#	CYRILLIC CAPITAL LETTER YA
+0xD0	0x0430	#	CYRILLIC SMALL LETTER A
+0xD1	0x0431	#	CYRILLIC SMALL LETTER BE
+0xD2	0x0432	#	CYRILLIC SMALL LETTER VE
+0xD3	0x0433	#	CYRILLIC SMALL LETTER GHE
+0xD4	0x0434	#	CYRILLIC SMALL LETTER DE
+0xD5	0x0435	#	CYRILLIC SMALL LETTER IE
+0xD6	0x0436	#	CYRILLIC SMALL LETTER ZHE
+0xD7	0x0437	#	CYRILLIC SMALL LETTER ZE
+0xD8	0x0438	#	CYRILLIC SMALL LETTER I
+0xD9	0x0439	#	CYRILLIC SMALL LETTER SHORT I
+0xDA	0x043A	#	CYRILLIC SMALL LETTER KA
+0xDB	0x043B	#	CYRILLIC SMALL LETTER EL
+0xDC	0x043C	#	CYRILLIC SMALL LETTER EM
+0xDD	0x043D	#	CYRILLIC SMALL LETTER EN
+0xDE	0x043E	#	CYRILLIC SMALL LETTER O
+0xDF	0x043F	#	CYRILLIC SMALL LETTER PE
+0xE0	0x0440	#	CYRILLIC SMALL LETTER ER
+0xE1	0x0441	#	CYRILLIC SMALL LETTER ES
+0xE2	0x0442	#	CYRILLIC SMALL LETTER TE
+0xE3	0x0443	#	CYRILLIC SMALL LETTER U
+0xE4	0x0444	#	CYRILLIC SMALL LETTER EF
+0xE5	0x0445	#	CYRILLIC SMALL LETTER HA
+0xE6	0x0446	#	CYRILLIC SMALL LETTER TSE
+0xE7	0x0447	#	CYRILLIC SMALL LETTER CHE
+0xE8	0x0448	#	CYRILLIC SMALL LETTER SHA
+0xE9	0x0449	#	CYRILLIC SMALL LETTER SHCHA
+0xEA	0x044A	#	CYRILLIC SMALL LETTER HARD SIGN
+0xEB	0x044B	#	CYRILLIC SMALL LETTER YERU
+0xEC	0x044C	#	CYRILLIC SMALL LETTER SOFT SIGN
+0xED	0x044D	#	CYRILLIC SMALL LETTER E
+0xEE	0x044E	#	CYRILLIC SMALL LETTER YU
+0xEF	0x044F	#	CYRILLIC SMALL LETTER YA
+0xF0	0x2116	#	NUMERO SIGN
+0xF1	0x0451	#	CYRILLIC SMALL LETTER IO
+0xF2	0x0452	#	CYRILLIC SMALL LETTER DJE
+0xF3	0x0453	#	CYRILLIC SMALL LETTER GJE
+0xF4	0x0454	#	CYRILLIC SMALL LETTER UKRAINIAN IE
+0xF5	0x0455	#	CYRILLIC SMALL LETTER DZE
+0xF6	0x0456	#	CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+0xF7	0x0457	#	CYRILLIC SMALL LETTER YI
+0xF8	0x0458	#	CYRILLIC SMALL LETTER JE
+0xF9	0x0459	#	CYRILLIC SMALL LETTER LJE
+0xFA	0x045A	#	CYRILLIC SMALL LETTER NJE
+0xFB	0x045B	#	CYRILLIC SMALL LETTER TSHE
+0xFC	0x045C	#	CYRILLIC SMALL LETTER KJE
+0xFD	0x00A7	#	SECTION SIGN
+0xFE	0x045E	#	CYRILLIC SMALL LETTER SHORT U
+0xFF	0x045F	#	CYRILLIC SMALL LETTER DZHE
diff --git a/Resources/8859-6.txt b/Resources/8859-6.txt
new file mode 100644
index 0000000..69ac7f5
--- /dev/null
+++ b/Resources/8859-6.txt
@@ -0,0 +1,260 @@
+#
+#	Name:             ISO 8859-6:1999 to Unicode
+#	Unicode version:  3.0
+#	Table version:    1.0
+#	Table format:     Format A
+#	Date:             1999 July 27
+#	Authors:          Ken Whistler <kenw@sybase.com>
+#
+#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
+#
+#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+#	No claims are made as to fitness for any particular purpose.  No
+#	warranties of any kind are expressed or implied.  The recipient
+#	agrees to determine applicability of information provided.  If this
+#	file has been provided on optical media by Unicode, Inc., the sole
+#	remedy for any claim will be exchange of defective media within 90
+#	days of receipt.
+#
+#	Unicode, Inc. hereby grants the right to freely use the information
+#	supplied in this file in the creation of products supporting the
+#	Unicode Standard, and to make copies of this file in any form for
+#	internal or external distribution as long as this notice remains
+#	attached.
+#
+#	General notes:
+#
+#	This table contains the data the Unicode Consortium has on how
+#       ISO/IEC 8859-6:1999 characters map into Unicode.
+#
+#	Format:  Three tab-separated columns
+#		 Column #1 is the ISO/IEC 8859-6 code (in hex as 0xXX)
+#		 Column #2 is the Unicode (in hex as 0xXXXX)
+#		 Column #3 the Unicode name (follows a comment sign, '#')
+#
+#	The entries are in ISO/IEC 8859-6 order.
+#
+#	Version history
+#	1.0 version updates 0.1 version by adding mappings for all
+#	control characters.
+#	0x30..0x39 remapped to the ASCII digits (U+0030..U+0039) instead
+#	of the Arabic digits (U+0660..U+0669).
+#
+#	Updated versions of this file may be found in:
+#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
+#
+#	Any comments or problems, contact <errata@unicode.org>
+#	Please note that <errata@unicode.org> is an archival address;
+#	notices will be checked, but do not expect an immediate response.
+#
+0x00	0x0000	#	NULL
+0x01	0x0001	#	START OF HEADING
+0x02	0x0002	#	START OF TEXT
+0x03	0x0003	#	END OF TEXT
+0x04	0x0004	#	END OF TRANSMISSION
+0x05	0x0005	#	ENQUIRY
+0x06	0x0006	#	ACKNOWLEDGE
+0x07	0x0007	#	BELL
+0x08	0x0008	#	BACKSPACE
+0x09	0x0009	#	HORIZONTAL TABULATION
+0x0A	0x000A	#	LINE FEED
+0x0B	0x000B	#	VERTICAL TABULATION
+0x0C	0x000C	#	FORM FEED
+0x0D	0x000D	#	CARRIAGE RETURN
+0x0E	0x000E	#	SHIFT OUT
+0x0F	0x000F	#	SHIFT IN
+0x10	0x0010	#	DATA LINK ESCAPE
+0x11	0x0011	#	DEVICE CONTROL ONE
+0x12	0x0012	#	DEVICE CONTROL TWO
+0x13	0x0013	#	DEVICE CONTROL THREE
+0x14	0x0014	#	DEVICE CONTROL FOUR
+0x15	0x0015	#	NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#	SYNCHRONOUS IDLE
+0x17	0x0017	#	END OF TRANSMISSION BLOCK
+0x18	0x0018	#	CANCEL
+0x19	0x0019	#	END OF MEDIUM
+0x1A	0x001A	#	SUBSTITUTE
+0x1B	0x001B	#	ESCAPE
+0x1C	0x001C	#	FILE SEPARATOR
+0x1D	0x001D	#	GROUP SEPARATOR
+0x1E	0x001E	#	RECORD SEPARATOR
+0x1F	0x001F	#	UNIT SEPARATOR
+0x20	0x0020	#	SPACE
+0x21	0x0021	#	EXCLAMATION MARK
+0x22	0x0022	#	QUOTATION MARK
+0x23	0x0023	#	NUMBER SIGN
+0x24	0x0024	#	DOLLAR SIGN
+0x25	0x0025	#	PERCENT SIGN
+0x26	0x0026	#	AMPERSAND
+0x27	0x0027	#	APOSTROPHE
+0x28	0x0028	#	LEFT PARENTHESIS
+0x29	0x0029	#	RIGHT PARENTHESIS
+0x2A	0x002A	#	ASTERISK
+0x2B	0x002B	#	PLUS SIGN
+0x2C	0x002C	#	COMMA
+0x2D	0x002D	#	HYPHEN-MINUS
+0x2E	0x002E	#	FULL STOP
+0x2F	0x002F	#	SOLIDUS
+0x30	0x0030	#	DIGIT ZERO
+0x31	0x0031	#	DIGIT ONE
+0x32	0x0032	#	DIGIT TWO
+0x33	0x0033	#	DIGIT THREE
+0x34	0x0034	#	DIGIT FOUR
+0x35	0x0035	#	DIGIT FIVE
+0x36	0x0036	#	DIGIT SIX
+0x37	0x0037	#	DIGIT SEVEN
+0x38	0x0038	#	DIGIT EIGHT
+0x39	0x0039	#	DIGIT NINE
+0x3A	0x003A	#	COLON
+0x3B	0x003B	#	SEMICOLON
+0x3C	0x003C	#	LESS-THAN SIGN
+0x3D	0x003D	#	EQUALS SIGN
+0x3E	0x003E	#	GREATER-THAN SIGN
+0x3F	0x003F	#	QUESTION MARK
+0x40	0x0040	#	COMMERCIAL AT
+0x41	0x0041	#	LATIN CAPITAL LETTER A
+0x42	0x0042	#	LATIN CAPITAL LETTER B
+0x43	0x0043	#	LATIN CAPITAL LETTER C
+0x44	0x0044	#	LATIN CAPITAL LETTER D
+0x45	0x0045	#	LATIN CAPITAL LETTER E
+0x46	0x0046	#	LATIN CAPITAL LETTER F
+0x47	0x0047	#	LATIN CAPITAL LETTER G
+0x48	0x0048	#	LATIN CAPITAL LETTER H
+0x49	0x0049	#	LATIN CAPITAL LETTER I
+0x4A	0x004A	#	LATIN CAPITAL LETTER J
+0x4B	0x004B	#	LATIN CAPITAL LETTER K
+0x4C	0x004C	#	LATIN CAPITAL LETTER L
+0x4D	0x004D	#	LATIN CAPITAL LETTER M
+0x4E	0x004E	#	LATIN CAPITAL LETTER N
+0x4F	0x004F	#	LATIN CAPITAL LETTER O
+0x50	0x0050	#	LATIN CAPITAL LETTER P
+0x51	0x0051	#	LATIN CAPITAL LETTER Q
+0x52	0x0052	#	LATIN CAPITAL LETTER R
+0x53	0x0053	#	LATIN CAPITAL LETTER S
+0x54	0x0054	#	LATIN CAPITAL LETTER T
+0x55	0x0055	#	LATIN CAPITAL LETTER U
+0x56	0x0056	#	LATIN CAPITAL LETTER V
+0x57	0x0057	#	LATIN CAPITAL LETTER W
+0x58	0x0058	#	LATIN CAPITAL LETTER X
+0x59	0x0059	#	LATIN CAPITAL LETTER Y
+0x5A	0x005A	#	LATIN CAPITAL LETTER Z
+0x5B	0x005B	#	LEFT SQUARE BRACKET
+0x5C	0x005C	#	REVERSE SOLIDUS
+0x5D	0x005D	#	RIGHT SQUARE BRACKET
+0x5E	0x005E	#	CIRCUMFLEX ACCENT
+0x5F	0x005F	#	LOW LINE
+0x60	0x0060	#	GRAVE ACCENT
+0x61	0x0061	#	LATIN SMALL LETTER A
+0x62	0x0062	#	LATIN SMALL LETTER B
+0x63	0x0063	#	LATIN SMALL LETTER C
+0x64	0x0064	#	LATIN SMALL LETTER D
+0x65	0x0065	#	LATIN SMALL LETTER E
+0x66	0x0066	#	LATIN SMALL LETTER F
+0x67	0x0067	#	LATIN SMALL LETTER G
+0x68	0x0068	#	LATIN SMALL LETTER H
+0x69	0x0069	#	LATIN SMALL LETTER I
+0x6A	0x006A	#	LATIN SMALL LETTER J
+0x6B	0x006B	#	LATIN SMALL LETTER K
+0x6C	0x006C	#	LATIN SMALL LETTER L
+0x6D	0x006D	#	LATIN SMALL LETTER M
+0x6E	0x006E	#	LATIN SMALL LETTER N
+0x6F	0x006F	#	LATIN SMALL LETTER O
+0x70	0x0070	#	LATIN SMALL LETTER P
+0x71	0x0071	#	LATIN SMALL LETTER Q
+0x72	0x0072	#	LATIN SMALL LETTER R
+0x73	0x0073	#	LATIN SMALL LETTER S
+0x74	0x0074	#	LATIN SMALL LETTER T
+0x75	0x0075	#	LATIN SMALL LETTER U
+0x76	0x0076	#	LATIN SMALL LETTER V
+0x77	0x0077	#	LATIN SMALL LETTER W
+0x78	0x0078	#	LATIN SMALL LETTER X
+0x79	0x0079	#	LATIN SMALL LETTER Y
+0x7A	0x007A	#	LATIN SMALL LETTER Z
+0x7B	0x007B	#	LEFT CURLY BRACKET
+0x7C	0x007C	#	VERTICAL LINE
+0x7D	0x007D	#	RIGHT CURLY BRACKET
+0x7E	0x007E	#	TILDE
+0x7F	0x007F	#	DELETE
+0x80	0x0080	#	<control>
+0x81	0x0081	#	<control>
+0x82	0x0082	#	<control>
+0x83	0x0083	#	<control>
+0x84	0x0084	#	<control>
+0x85	0x0085	#	<control>
+0x86	0x0086	#	<control>
+0x87	0x0087	#	<control>
+0x88	0x0088	#	<control>
+0x89	0x0089	#	<control>
+0x8A	0x008A	#	<control>
+0x8B	0x008B	#	<control>
+0x8C	0x008C	#	<control>
+0x8D	0x008D	#	<control>
+0x8E	0x008E	#	<control>
+0x8F	0x008F	#	<control>
+0x90	0x0090	#	<control>
+0x91	0x0091	#	<control>
+0x92	0x0092	#	<control>
+0x93	0x0093	#	<control>
+0x94	0x0094	#	<control>
+0x95	0x0095	#	<control>
+0x96	0x0096	#	<control>
+0x97	0x0097	#	<control>
+0x98	0x0098	#	<control>
+0x99	0x0099	#	<control>
+0x9A	0x009A	#	<control>
+0x9B	0x009B	#	<control>
+0x9C	0x009C	#	<control>
+0x9D	0x009D	#	<control>
+0x9E	0x009E	#	<control>
+0x9F	0x009F	#	<control>
+0xA0	0x00A0	#	NO-BREAK SPACE
+0xA4	0x00A4	#	CURRENCY SIGN
+0xAC	0x060C	#	ARABIC COMMA
+0xAD	0x00AD	#	SOFT HYPHEN
+0xBB	0x061B	#	ARABIC SEMICOLON
+0xBF	0x061F	#	ARABIC QUESTION MARK
+0xC1	0x0621	#	ARABIC LETTER HAMZA
+0xC2	0x0622	#	ARABIC LETTER ALEF WITH MADDA ABOVE
+0xC3	0x0623	#	ARABIC LETTER ALEF WITH HAMZA ABOVE
+0xC4	0x0624	#	ARABIC LETTER WAW WITH HAMZA ABOVE
+0xC5	0x0625	#	ARABIC LETTER ALEF WITH HAMZA BELOW
+0xC6	0x0626	#	ARABIC LETTER YEH WITH HAMZA ABOVE
+0xC7	0x0627	#	ARABIC LETTER ALEF
+0xC8	0x0628	#	ARABIC LETTER BEH
+0xC9	0x0629	#	ARABIC LETTER TEH MARBUTA
+0xCA	0x062A	#	ARABIC LETTER TEH
+0xCB	0x062B	#	ARABIC LETTER THEH
+0xCC	0x062C	#	ARABIC LETTER JEEM
+0xCD	0x062D	#	ARABIC LETTER HAH
+0xCE	0x062E	#	ARABIC LETTER KHAH
+0xCF	0x062F	#	ARABIC LETTER DAL
+0xD0	0x0630	#	ARABIC LETTER THAL
+0xD1	0x0631	#	ARABIC LETTER REH
+0xD2	0x0632	#	ARABIC LETTER ZAIN
+0xD3	0x0633	#	ARABIC LETTER SEEN
+0xD4	0x0634	#	ARABIC LETTER SHEEN
+0xD5	0x0635	#	ARABIC LETTER SAD
+0xD6	0x0636	#	ARABIC LETTER DAD
+0xD7	0x0637	#	ARABIC LETTER TAH
+0xD8	0x0638	#	ARABIC LETTER ZAH
+0xD9	0x0639	#	ARABIC LETTER AIN
+0xDA	0x063A	#	ARABIC LETTER GHAIN
+0xE0	0x0640	#	ARABIC TATWEEL
+0xE1	0x0641	#	ARABIC LETTER FEH
+0xE2	0x0642	#	ARABIC LETTER QAF
+0xE3	0x0643	#	ARABIC LETTER KAF
+0xE4	0x0644	#	ARABIC LETTER LAM
+0xE5	0x0645	#	ARABIC LETTER MEEM
+0xE6	0x0646	#	ARABIC LETTER NOON
+0xE7	0x0647	#	ARABIC LETTER HEH
+0xE8	0x0648	#	ARABIC LETTER WAW
+0xE9	0x0649	#	ARABIC LETTER ALEF MAKSURA
+0xEA	0x064A	#	ARABIC LETTER YEH
+0xEB	0x064B	#	ARABIC FATHATAN
+0xEC	0x064C	#	ARABIC DAMMATAN
+0xED	0x064D	#	ARABIC KASRATAN
+0xEE	0x064E	#	ARABIC FATHA
+0xEF	0x064F	#	ARABIC DAMMA
+0xF0	0x0650	#	ARABIC KASRA
+0xF1	0x0651	#	ARABIC SHADDA
+0xF2	0x0652	#	ARABIC SUKUN
diff --git a/Resources/8859-7.txt b/Resources/8859-7.txt
new file mode 100644
index 0000000..52c42d0
--- /dev/null
+++ b/Resources/8859-7.txt
@@ -0,0 +1,302 @@
+#
+#	Name:             ISO 8859-7:1987 to Unicode
+#	Unicode version:  3.0
+#	Table version:    1.0
+#	Table format:     Format A
+#	Date:             1999 July 27
+#	Authors:          Ken Whistler <kenw@sybase.com>
+#
+#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
+#
+#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+#	No claims are made as to fitness for any particular purpose.  No
+#	warranties of any kind are expressed or implied.  The recipient
+#	agrees to determine applicability of information provided.  If this
+#	file has been provided on optical media by Unicode, Inc., the sole
+#	remedy for any claim will be exchange of defective media within 90
+#	days of receipt.
+#
+#	Unicode, Inc. hereby grants the right to freely use the information
+#	supplied in this file in the creation of products supporting the
+#	Unicode Standard, and to make copies of this file in any form for
+#	internal or external distribution as long as this notice remains
+#	attached.
+#
+#	General notes:
+#
+#	This table contains the data the Unicode Consortium has on how
+#       ISO 8859-7:1987 characters map into Unicode.
+#
+#	ISO 8859-7:1987 is equivalent to ISO-IR-126, ELOT 928,
+#	and ECMA 118.
+#
+#	Format:  Three tab-separated columns
+#		 Column #1 is the ISO 8859-7 code (in hex as 0xXX)
+#		 Column #2 is the Unicode (in hex as 0xXXXX)
+#		 Column #3 the Unicode name (follows a comment sign, '#')
+#
+#	The entries are in ISO 8859-7 order.
+#
+#	Version history
+#	1.0 version updates 0.1 version by adding mappings for all
+#	control characters.
+#	Remap 0xA1 to U+2018 (instead of 0x02BD) to match text of 8859-7
+#	Remap 0xA2 to U+2019 (instead of 0x02BC) to match text of 8859-7
+#
+#	Updated versions of this file may be found in:
+#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
+#
+#	Any comments or problems, contact <errata@unicode.org>
+#	Please note that <errata@unicode.org> is an archival address;
+#	notices will be checked, but do not expect an immediate response.
+#
+0x00	0x0000	#	NULL
+0x01	0x0001	#	START OF HEADING
+0x02	0x0002	#	START OF TEXT
+0x03	0x0003	#	END OF TEXT
+0x04	0x0004	#	END OF TRANSMISSION
+0x05	0x0005	#	ENQUIRY
+0x06	0x0006	#	ACKNOWLEDGE
+0x07	0x0007	#	BELL
+0x08	0x0008	#	BACKSPACE
+0x09	0x0009	#	HORIZONTAL TABULATION
+0x0A	0x000A	#	LINE FEED
+0x0B	0x000B	#	VERTICAL TABULATION
+0x0C	0x000C	#	FORM FEED
+0x0D	0x000D	#	CARRIAGE RETURN
+0x0E	0x000E	#	SHIFT OUT
+0x0F	0x000F	#	SHIFT IN
+0x10	0x0010	#	DATA LINK ESCAPE
+0x11	0x0011	#	DEVICE CONTROL ONE
+0x12	0x0012	#	DEVICE CONTROL TWO
+0x13	0x0013	#	DEVICE CONTROL THREE
+0x14	0x0014	#	DEVICE CONTROL FOUR
+0x15	0x0015	#	NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#	SYNCHRONOUS IDLE
+0x17	0x0017	#	END OF TRANSMISSION BLOCK
+0x18	0x0018	#	CANCEL
+0x19	0x0019	#	END OF MEDIUM
+0x1A	0x001A	#	SUBSTITUTE
+0x1B	0x001B	#	ESCAPE
+0x1C	0x001C	#	FILE SEPARATOR
+0x1D	0x001D	#	GROUP SEPARATOR
+0x1E	0x001E	#	RECORD SEPARATOR
+0x1F	0x001F	#	UNIT SEPARATOR
+0x20	0x0020	#	SPACE
+0x21	0x0021	#	EXCLAMATION MARK
+0x22	0x0022	#	QUOTATION MARK
+0x23	0x0023	#	NUMBER SIGN
+0x24	0x0024	#	DOLLAR SIGN
+0x25	0x0025	#	PERCENT SIGN
+0x26	0x0026	#	AMPERSAND
+0x27	0x0027	#	APOSTROPHE
+0x28	0x0028	#	LEFT PARENTHESIS
+0x29	0x0029	#	RIGHT PARENTHESIS
+0x2A	0x002A	#	ASTERISK
+0x2B	0x002B	#	PLUS SIGN
+0x2C	0x002C	#	COMMA
+0x2D	0x002D	#	HYPHEN-MINUS
+0x2E	0x002E	#	FULL STOP
+0x2F	0x002F	#	SOLIDUS
+0x30	0x0030	#	DIGIT ZERO
+0x31	0x0031	#	DIGIT ONE
+0x32	0x0032	#	DIGIT TWO
+0x33	0x0033	#	DIGIT THREE
+0x34	0x0034	#	DIGIT FOUR
+0x35	0x0035	#	DIGIT FIVE
+0x36	0x0036	#	DIGIT SIX
+0x37	0x0037	#	DIGIT SEVEN
+0x38	0x0038	#	DIGIT EIGHT
+0x39	0x0039	#	DIGIT NINE
+0x3A	0x003A	#	COLON
+0x3B	0x003B	#	SEMICOLON
+0x3C	0x003C	#	LESS-THAN SIGN
+0x3D	0x003D	#	EQUALS SIGN
+0x3E	0x003E	#	GREATER-THAN SIGN
+0x3F	0x003F	#	QUESTION MARK
+0x40	0x0040	#	COMMERCIAL AT
+0x41	0x0041	#	LATIN CAPITAL LETTER A
+0x42	0x0042	#	LATIN CAPITAL LETTER B
+0x43	0x0043	#	LATIN CAPITAL LETTER C
+0x44	0x0044	#	LATIN CAPITAL LETTER D
+0x45	0x0045	#	LATIN CAPITAL LETTER E
+0x46	0x0046	#	LATIN CAPITAL LETTER F
+0x47	0x0047	#	LATIN CAPITAL LETTER G
+0x48	0x0048	#	LATIN CAPITAL LETTER H
+0x49	0x0049	#	LATIN CAPITAL LETTER I
+0x4A	0x004A	#	LATIN CAPITAL LETTER J
+0x4B	0x004B	#	LATIN CAPITAL LETTER K
+0x4C	0x004C	#	LATIN CAPITAL LETTER L
+0x4D	0x004D	#	LATIN CAPITAL LETTER M
+0x4E	0x004E	#	LATIN CAPITAL LETTER N
+0x4F	0x004F	#	LATIN CAPITAL LETTER O
+0x50	0x0050	#	LATIN CAPITAL LETTER P
+0x51	0x0051	#	LATIN CAPITAL LETTER Q
+0x52	0x0052	#	LATIN CAPITAL LETTER R
+0x53	0x0053	#	LATIN CAPITAL LETTER S
+0x54	0x0054	#	LATIN CAPITAL LETTER T
+0x55	0x0055	#	LATIN CAPITAL LETTER U
+0x56	0x0056	#	LATIN CAPITAL LETTER V
+0x57	0x0057	#	LATIN CAPITAL LETTER W
+0x58	0x0058	#	LATIN CAPITAL LETTER X
+0x59	0x0059	#	LATIN CAPITAL LETTER Y
+0x5A	0x005A	#	LATIN CAPITAL LETTER Z
+0x5B	0x005B	#	LEFT SQUARE BRACKET
+0x5C	0x005C	#	REVERSE SOLIDUS
+0x5D	0x005D	#	RIGHT SQUARE BRACKET
+0x5E	0x005E	#	CIRCUMFLEX ACCENT
+0x5F	0x005F	#	LOW LINE
+0x60	0x0060	#	GRAVE ACCENT
+0x61	0x0061	#	LATIN SMALL LETTER A
+0x62	0x0062	#	LATIN SMALL LETTER B
+0x63	0x0063	#	LATIN SMALL LETTER C
+0x64	0x0064	#	LATIN SMALL LETTER D
+0x65	0x0065	#	LATIN SMALL LETTER E
+0x66	0x0066	#	LATIN SMALL LETTER F
+0x67	0x0067	#	LATIN SMALL LETTER G
+0x68	0x0068	#	LATIN SMALL LETTER H
+0x69	0x0069	#	LATIN SMALL LETTER I
+0x6A	0x006A	#	LATIN SMALL LETTER J
+0x6B	0x006B	#	LATIN SMALL LETTER K
+0x6C	0x006C	#	LATIN SMALL LETTER L
+0x6D	0x006D	#	LATIN SMALL LETTER M
+0x6E	0x006E	#	LATIN SMALL LETTER N
+0x6F	0x006F	#	LATIN SMALL LETTER O
+0x70	0x0070	#	LATIN SMALL LETTER P
+0x71	0x0071	#	LATIN SMALL LETTER Q
+0x72	0x0072	#	LATIN SMALL LETTER R
+0x73	0x0073	#	LATIN SMALL LETTER S
+0x74	0x0074	#	LATIN SMALL LETTER T
+0x75	0x0075	#	LATIN SMALL LETTER U
+0x76	0x0076	#	LATIN SMALL LETTER V
+0x77	0x0077	#	LATIN SMALL LETTER W
+0x78	0x0078	#	LATIN SMALL LETTER X
+0x79	0x0079	#	LATIN SMALL LETTER Y
+0x7A	0x007A	#	LATIN SMALL LETTER Z
+0x7B	0x007B	#	LEFT CURLY BRACKET
+0x7C	0x007C	#	VERTICAL LINE
+0x7D	0x007D	#	RIGHT CURLY BRACKET
+0x7E	0x007E	#	TILDE
+0x7F	0x007F	#	DELETE
+0x80	0x0080	#	<control>
+0x81	0x0081	#	<control>
+0x82	0x0082	#	<control>
+0x83	0x0083	#	<control>
+0x84	0x0084	#	<control>
+0x85	0x0085	#	<control>
+0x86	0x0086	#	<control>
+0x87	0x0087	#	<control>
+0x88	0x0088	#	<control>
+0x89	0x0089	#	<control>
+0x8A	0x008A	#	<control>
+0x8B	0x008B	#	<control>
+0x8C	0x008C	#	<control>
+0x8D	0x008D	#	<control>
+0x8E	0x008E	#	<control>
+0x8F	0x008F	#	<control>
+0x90	0x0090	#	<control>
+0x91	0x0091	#	<control>
+0x92	0x0092	#	<control>
+0x93	0x0093	#	<control>
+0x94	0x0094	#	<control>
+0x95	0x0095	#	<control>
+0x96	0x0096	#	<control>
+0x97	0x0097	#	<control>
+0x98	0x0098	#	<control>
+0x99	0x0099	#	<control>
+0x9A	0x009A	#	<control>
+0x9B	0x009B	#	<control>
+0x9C	0x009C	#	<control>
+0x9D	0x009D	#	<control>
+0x9E	0x009E	#	<control>
+0x9F	0x009F	#	<control>
+0xA0	0x00A0	#	NO-BREAK SPACE
+0xA1	0x2018	#	LEFT SINGLE QUOTATION MARK
+0xA2	0x2019	#	RIGHT SINGLE QUOTATION MARK
+0xA3	0x00A3	#	POUND SIGN
+0xA6	0x00A6	#	BROKEN BAR
+0xA7	0x00A7	#	SECTION SIGN
+0xA8	0x00A8	#	DIAERESIS
+0xA9	0x00A9	#	COPYRIGHT SIGN
+0xAB	0x00AB	#	LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC	0x00AC	#	NOT SIGN
+0xAD	0x00AD	#	SOFT HYPHEN
+0xAF	0x2015	#	HORIZONTAL BAR
+0xB0	0x00B0	#	DEGREE SIGN
+0xB1	0x00B1	#	PLUS-MINUS SIGN
+0xB2	0x00B2	#	SUPERSCRIPT TWO
+0xB3	0x00B3	#	SUPERSCRIPT THREE
+0xB4	0x0384	#	GREEK TONOS
+0xB5	0x0385	#	GREEK DIALYTIKA TONOS
+0xB6	0x0386	#	GREEK CAPITAL LETTER ALPHA WITH TONOS
+0xB7	0x00B7	#	MIDDLE DOT
+0xB8	0x0388	#	GREEK CAPITAL LETTER EPSILON WITH TONOS
+0xB9	0x0389	#	GREEK CAPITAL LETTER ETA WITH TONOS
+0xBA	0x038A	#	GREEK CAPITAL LETTER IOTA WITH TONOS
+0xBB	0x00BB	#	RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC	0x038C	#	GREEK CAPITAL LETTER OMICRON WITH TONOS
+0xBD	0x00BD	#	VULGAR FRACTION ONE HALF
+0xBE	0x038E	#	GREEK CAPITAL LETTER UPSILON WITH TONOS
+0xBF	0x038F	#	GREEK CAPITAL LETTER OMEGA WITH TONOS
+0xC0	0x0390	#	GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+0xC1	0x0391	#	GREEK CAPITAL LETTER ALPHA
+0xC2	0x0392	#	GREEK CAPITAL LETTER BETA
+0xC3	0x0393	#	GREEK CAPITAL LETTER GAMMA
+0xC4	0x0394	#	GREEK CAPITAL LETTER DELTA
+0xC5	0x0395	#	GREEK CAPITAL LETTER EPSILON
+0xC6	0x0396	#	GREEK CAPITAL LETTER ZETA
+0xC7	0x0397	#	GREEK CAPITAL LETTER ETA
+0xC8	0x0398	#	GREEK CAPITAL LETTER THETA
+0xC9	0x0399	#	GREEK CAPITAL LETTER IOTA
+0xCA	0x039A	#	GREEK CAPITAL LETTER KAPPA
+0xCB	0x039B	#	GREEK CAPITAL LETTER LAMDA
+0xCC	0x039C	#	GREEK CAPITAL LETTER MU
+0xCD	0x039D	#	GREEK CAPITAL LETTER NU
+0xCE	0x039E	#	GREEK CAPITAL LETTER XI
+0xCF	0x039F	#	GREEK CAPITAL LETTER OMICRON
+0xD0	0x03A0	#	GREEK CAPITAL LETTER PI
+0xD1	0x03A1	#	GREEK CAPITAL LETTER RHO
+0xD3	0x03A3	#	GREEK CAPITAL LETTER SIGMA
+0xD4	0x03A4	#	GREEK CAPITAL LETTER TAU
+0xD5	0x03A5	#	GREEK CAPITAL LETTER UPSILON
+0xD6	0x03A6	#	GREEK CAPITAL LETTER PHI
+0xD7	0x03A7	#	GREEK CAPITAL LETTER CHI
+0xD8	0x03A8	#	GREEK CAPITAL LETTER PSI
+0xD9	0x03A9	#	GREEK CAPITAL LETTER OMEGA
+0xDA	0x03AA	#	GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+0xDB	0x03AB	#	GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+0xDC	0x03AC	#	GREEK SMALL LETTER ALPHA WITH TONOS
+0xDD	0x03AD	#	GREEK SMALL LETTER EPSILON WITH TONOS
+0xDE	0x03AE	#	GREEK SMALL LETTER ETA WITH TONOS
+0xDF	0x03AF	#	GREEK SMALL LETTER IOTA WITH TONOS
+0xE0	0x03B0	#	GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+0xE1	0x03B1	#	GREEK SMALL LETTER ALPHA
+0xE2	0x03B2	#	GREEK SMALL LETTER BETA
+0xE3	0x03B3	#	GREEK SMALL LETTER GAMMA
+0xE4	0x03B4	#	GREEK SMALL LETTER DELTA
+0xE5	0x03B5	#	GREEK SMALL LETTER EPSILON
+0xE6	0x03B6	#	GREEK SMALL LETTER ZETA
+0xE7	0x03B7	#	GREEK SMALL LETTER ETA
+0xE8	0x03B8	#	GREEK SMALL LETTER THETA
+0xE9	0x03B9	#	GREEK SMALL LETTER IOTA
+0xEA	0x03BA	#	GREEK SMALL LETTER KAPPA
+0xEB	0x03BB	#	GREEK SMALL LETTER LAMDA
+0xEC	0x03BC	#	GREEK SMALL LETTER MU
+0xED	0x03BD	#	GREEK SMALL LETTER NU
+0xEE	0x03BE	#	GREEK SMALL LETTER XI
+0xEF	0x03BF	#	GREEK SMALL LETTER OMICRON
+0xF0	0x03C0	#	GREEK SMALL LETTER PI
+0xF1	0x03C1	#	GREEK SMALL LETTER RHO
+0xF2	0x03C2	#	GREEK SMALL LETTER FINAL SIGMA
+0xF3	0x03C3	#	GREEK SMALL LETTER SIGMA
+0xF4	0x03C4	#	GREEK SMALL LETTER TAU
+0xF5	0x03C5	#	GREEK SMALL LETTER UPSILON
+0xF6	0x03C6	#	GREEK SMALL LETTER PHI
+0xF7	0x03C7	#	GREEK SMALL LETTER CHI
+0xF8	0x03C8	#	GREEK SMALL LETTER PSI
+0xF9	0x03C9	#	GREEK SMALL LETTER OMEGA
+0xFA	0x03CA	#	GREEK SMALL LETTER IOTA WITH DIALYTIKA
+0xFB	0x03CB	#	GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+0xFC	0x03CC	#	GREEK SMALL LETTER OMICRON WITH TONOS
+0xFD	0x03CD	#	GREEK SMALL LETTER UPSILON WITH TONOS
+0xFE	0x03CE	#	GREEK SMALL LETTER OMEGA WITH TONOS
diff --git a/Resources/8859-8.txt b/Resources/8859-8.txt
new file mode 100644
index 0000000..bc8da4c
--- /dev/null
+++ b/Resources/8859-8.txt
@@ -0,0 +1,270 @@
+#
+#	Name:             ISO/IEC 8859-8:1999 to Unicode
+#	Unicode version:  3.0
+#	Table version:    1.1
+#	Table format:     Format A
+#	Date:             2000-Jan-03
+#	Authors:          Ken Whistler <kenw@sybase.com>
+#
+#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
+#
+#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+#	No claims are made as to fitness for any particular purpose.  No
+#	warranties of any kind are expressed or implied.  The recipient
+#	agrees to determine applicability of information provided.  If this
+#	file has been provided on optical media by Unicode, Inc., the sole
+#	remedy for any claim will be exchange of defective media within 90
+#	days of receipt.
+#
+#	Unicode, Inc. hereby grants the right to freely use the information
+#	supplied in this file in the creation of products supporting the
+#	Unicode Standard, and to make copies of this file in any form for
+#	internal or external distribution as long as this notice remains
+#	attached.
+#
+#	General notes:
+#
+#	This table contains the data the Unicode Consortium has on how
+#       ISO/IEC 8859-8:1999 characters map into Unicode.
+#
+#	Format:  Three tab-separated columns
+#		 Column #1 is the ISO/IEC 8859-8 code (in hex as 0xXX)
+#		 Column #2 is the Unicode (in hex as 0xXXXX)
+#		 Column #3 the Unicode name (follows a comment sign, '#')
+#
+#	The entries are in ISO/IEC 8859-8 order.
+#
+#	Version history
+#	1.0 version updates 0.1 version by adding mappings for all
+#	control characters.
+#       1.1 version updates to the published 8859-8:1999, correcting
+#          the mapping of 0xAF and adding mappings for LRM and RLM.
+#
+#	Updated versions of this file may be found in:
+#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
+#
+#	Any comments or problems, contact <errata@unicode.org>
+#	Please note that <errata@unicode.org> is an archival address;
+#	notices will be checked, but do not expect an immediate response.
+#
+0x00	0x0000	#	NULL
+0x01	0x0001	#	START OF HEADING
+0x02	0x0002	#	START OF TEXT
+0x03	0x0003	#	END OF TEXT
+0x04	0x0004	#	END OF TRANSMISSION
+0x05	0x0005	#	ENQUIRY
+0x06	0x0006	#	ACKNOWLEDGE
+0x07	0x0007	#	BELL
+0x08	0x0008	#	BACKSPACE
+0x09	0x0009	#	HORIZONTAL TABULATION
+0x0A	0x000A	#	LINE FEED
+0x0B	0x000B	#	VERTICAL TABULATION
+0x0C	0x000C	#	FORM FEED
+0x0D	0x000D	#	CARRIAGE RETURN
+0x0E	0x000E	#	SHIFT OUT
+0x0F	0x000F	#	SHIFT IN
+0x10	0x0010	#	DATA LINK ESCAPE
+0x11	0x0011	#	DEVICE CONTROL ONE
+0x12	0x0012	#	DEVICE CONTROL TWO
+0x13	0x0013	#	DEVICE CONTROL THREE
+0x14	0x0014	#	DEVICE CONTROL FOUR
+0x15	0x0015	#	NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#	SYNCHRONOUS IDLE
+0x17	0x0017	#	END OF TRANSMISSION BLOCK
+0x18	0x0018	#	CANCEL
+0x19	0x0019	#	END OF MEDIUM
+0x1A	0x001A	#	SUBSTITUTE
+0x1B	0x001B	#	ESCAPE
+0x1C	0x001C	#	FILE SEPARATOR
+0x1D	0x001D	#	GROUP SEPARATOR
+0x1E	0x001E	#	RECORD SEPARATOR
+0x1F	0x001F	#	UNIT SEPARATOR
+0x20	0x0020	#	SPACE
+0x21	0x0021	#	EXCLAMATION MARK
+0x22	0x0022	#	QUOTATION MARK
+0x23	0x0023	#	NUMBER SIGN
+0x24	0x0024	#	DOLLAR SIGN
+0x25	0x0025	#	PERCENT SIGN
+0x26	0x0026	#	AMPERSAND
+0x27	0x0027	#	APOSTROPHE
+0x28	0x0028	#	LEFT PARENTHESIS
+0x29	0x0029	#	RIGHT PARENTHESIS
+0x2A	0x002A	#	ASTERISK
+0x2B	0x002B	#	PLUS SIGN
+0x2C	0x002C	#	COMMA
+0x2D	0x002D	#	HYPHEN-MINUS
+0x2E	0x002E	#	FULL STOP
+0x2F	0x002F	#	SOLIDUS
+0x30	0x0030	#	DIGIT ZERO
+0x31	0x0031	#	DIGIT ONE
+0x32	0x0032	#	DIGIT TWO
+0x33	0x0033	#	DIGIT THREE
+0x34	0x0034	#	DIGIT FOUR
+0x35	0x0035	#	DIGIT FIVE
+0x36	0x0036	#	DIGIT SIX
+0x37	0x0037	#	DIGIT SEVEN
+0x38	0x0038	#	DIGIT EIGHT
+0x39	0x0039	#	DIGIT NINE
+0x3A	0x003A	#	COLON
+0x3B	0x003B	#	SEMICOLON
+0x3C	0x003C	#	LESS-THAN SIGN
+0x3D	0x003D	#	EQUALS SIGN
+0x3E	0x003E	#	GREATER-THAN SIGN
+0x3F	0x003F	#	QUESTION MARK
+0x40	0x0040	#	COMMERCIAL AT
+0x41	0x0041	#	LATIN CAPITAL LETTER A
+0x42	0x0042	#	LATIN CAPITAL LETTER B
+0x43	0x0043	#	LATIN CAPITAL LETTER C
+0x44	0x0044	#	LATIN CAPITAL LETTER D
+0x45	0x0045	#	LATIN CAPITAL LETTER E
+0x46	0x0046	#	LATIN CAPITAL LETTER F
+0x47	0x0047	#	LATIN CAPITAL LETTER G
+0x48	0x0048	#	LATIN CAPITAL LETTER H
+0x49	0x0049	#	LATIN CAPITAL LETTER I
+0x4A	0x004A	#	LATIN CAPITAL LETTER J
+0x4B	0x004B	#	LATIN CAPITAL LETTER K
+0x4C	0x004C	#	LATIN CAPITAL LETTER L
+0x4D	0x004D	#	LATIN CAPITAL LETTER M
+0x4E	0x004E	#	LATIN CAPITAL LETTER N
+0x4F	0x004F	#	LATIN CAPITAL LETTER O
+0x50	0x0050	#	LATIN CAPITAL LETTER P
+0x51	0x0051	#	LATIN CAPITAL LETTER Q
+0x52	0x0052	#	LATIN CAPITAL LETTER R
+0x53	0x0053	#	LATIN CAPITAL LETTER S
+0x54	0x0054	#	LATIN CAPITAL LETTER T
+0x55	0x0055	#	LATIN CAPITAL LETTER U
+0x56	0x0056	#	LATIN CAPITAL LETTER V
+0x57	0x0057	#	LATIN CAPITAL LETTER W
+0x58	0x0058	#	LATIN CAPITAL LETTER X
+0x59	0x0059	#	LATIN CAPITAL LETTER Y
+0x5A	0x005A	#	LATIN CAPITAL LETTER Z
+0x5B	0x005B	#	LEFT SQUARE BRACKET
+0x5C	0x005C	#	REVERSE SOLIDUS
+0x5D	0x005D	#	RIGHT SQUARE BRACKET
+0x5E	0x005E	#	CIRCUMFLEX ACCENT
+0x5F	0x005F	#	LOW LINE
+0x60	0x0060	#	GRAVE ACCENT
+0x61	0x0061	#	LATIN SMALL LETTER A
+0x62	0x0062	#	LATIN SMALL LETTER B
+0x63	0x0063	#	LATIN SMALL LETTER C
+0x64	0x0064	#	LATIN SMALL LETTER D
+0x65	0x0065	#	LATIN SMALL LETTER E
+0x66	0x0066	#	LATIN SMALL LETTER F
+0x67	0x0067	#	LATIN SMALL LETTER G
+0x68	0x0068	#	LATIN SMALL LETTER H
+0x69	0x0069	#	LATIN SMALL LETTER I
+0x6A	0x006A	#	LATIN SMALL LETTER J
+0x6B	0x006B	#	LATIN SMALL LETTER K
+0x6C	0x006C	#	LATIN SMALL LETTER L
+0x6D	0x006D	#	LATIN SMALL LETTER M
+0x6E	0x006E	#	LATIN SMALL LETTER N
+0x6F	0x006F	#	LATIN SMALL LETTER O
+0x70	0x0070	#	LATIN SMALL LETTER P
+0x71	0x0071	#	LATIN SMALL LETTER Q
+0x72	0x0072	#	LATIN SMALL LETTER R
+0x73	0x0073	#	LATIN SMALL LETTER S
+0x74	0x0074	#	LATIN SMALL LETTER T
+0x75	0x0075	#	LATIN SMALL LETTER U
+0x76	0x0076	#	LATIN SMALL LETTER V
+0x77	0x0077	#	LATIN SMALL LETTER W
+0x78	0x0078	#	LATIN SMALL LETTER X
+0x79	0x0079	#	LATIN SMALL LETTER Y
+0x7A	0x007A	#	LATIN SMALL LETTER Z
+0x7B	0x007B	#	LEFT CURLY BRACKET
+0x7C	0x007C	#	VERTICAL LINE
+0x7D	0x007D	#	RIGHT CURLY BRACKET
+0x7E	0x007E	#	TILDE
+0x7F	0x007F	#	DELETE
+0x80	0x0080	#	<control>
+0x81	0x0081	#	<control>
+0x82	0x0082	#	<control>
+0x83	0x0083	#	<control>
+0x84	0x0084	#	<control>
+0x85	0x0085	#	<control>
+0x86	0x0086	#	<control>
+0x87	0x0087	#	<control>
+0x88	0x0088	#	<control>
+0x89	0x0089	#	<control>
+0x8A	0x008A	#	<control>
+0x8B	0x008B	#	<control>
+0x8C	0x008C	#	<control>
+0x8D	0x008D	#	<control>
+0x8E	0x008E	#	<control>
+0x8F	0x008F	#	<control>
+0x90	0x0090	#	<control>
+0x91	0x0091	#	<control>
+0x92	0x0092	#	<control>
+0x93	0x0093	#	<control>
+0x94	0x0094	#	<control>
+0x95	0x0095	#	<control>
+0x96	0x0096	#	<control>
+0x97	0x0097	#	<control>
+0x98	0x0098	#	<control>
+0x99	0x0099	#	<control>
+0x9A	0x009A	#	<control>
+0x9B	0x009B	#	<control>
+0x9C	0x009C	#	<control>
+0x9D	0x009D	#	<control>
+0x9E	0x009E	#	<control>
+0x9F	0x009F	#	<control>
+0xA0	0x00A0	#	NO-BREAK SPACE
+0xA2	0x00A2	#	CENT SIGN
+0xA3	0x00A3	#	POUND SIGN
+0xA4	0x00A4	#	CURRENCY SIGN
+0xA5	0x00A5	#	YEN SIGN
+0xA6	0x00A6	#	BROKEN BAR
+0xA7	0x00A7	#	SECTION SIGN
+0xA8	0x00A8	#	DIAERESIS
+0xA9	0x00A9	#	COPYRIGHT SIGN
+0xAA	0x00D7	#	MULTIPLICATION SIGN
+0xAB	0x00AB	#	LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC	0x00AC	#	NOT SIGN
+0xAD	0x00AD	#	SOFT HYPHEN
+0xAE	0x00AE	#	REGISTERED SIGN
+0xAF	0x00AF	#	MACRON
+0xB0	0x00B0	#	DEGREE SIGN
+0xB1	0x00B1	#	PLUS-MINUS SIGN
+0xB2	0x00B2	#	SUPERSCRIPT TWO
+0xB3	0x00B3	#	SUPERSCRIPT THREE
+0xB4	0x00B4	#	ACUTE ACCENT
+0xB5	0x00B5	#	MICRO SIGN
+0xB6	0x00B6	#	PILCROW SIGN
+0xB7	0x00B7	#	MIDDLE DOT
+0xB8	0x00B8	#	CEDILLA
+0xB9	0x00B9	#	SUPERSCRIPT ONE
+0xBA	0x00F7	#	DIVISION SIGN
+0xBB	0x00BB	#	RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC	0x00BC	#	VULGAR FRACTION ONE QUARTER
+0xBD	0x00BD	#	VULGAR FRACTION ONE HALF
+0xBE	0x00BE	#	VULGAR FRACTION THREE QUARTERS
+0xDF	0x2017	#	DOUBLE LOW LINE
+0xE0	0x05D0	#	HEBREW LETTER ALEF
+0xE1	0x05D1	#	HEBREW LETTER BET
+0xE2	0x05D2	#	HEBREW LETTER GIMEL
+0xE3	0x05D3	#	HEBREW LETTER DALET
+0xE4	0x05D4	#	HEBREW LETTER HE
+0xE5	0x05D5	#	HEBREW LETTER VAV
+0xE6	0x05D6	#	HEBREW LETTER ZAYIN
+0xE7	0x05D7	#	HEBREW LETTER HET
+0xE8	0x05D8	#	HEBREW LETTER TET
+0xE9	0x05D9	#	HEBREW LETTER YOD
+0xEA	0x05DA	#	HEBREW LETTER FINAL KAF
+0xEB	0x05DB	#	HEBREW LETTER KAF
+0xEC	0x05DC	#	HEBREW LETTER LAMED
+0xED	0x05DD	#	HEBREW LETTER FINAL MEM
+0xEE	0x05DE	#	HEBREW LETTER MEM
+0xEF	0x05DF	#	HEBREW LETTER FINAL NUN
+0xF0	0x05E0	#	HEBREW LETTER NUN
+0xF1	0x05E1	#	HEBREW LETTER SAMEKH
+0xF2	0x05E2	#	HEBREW LETTER AYIN
+0xF3	0x05E3	#	HEBREW LETTER FINAL PE
+0xF4	0x05E4	#	HEBREW LETTER PE
+0xF5	0x05E5	#	HEBREW LETTER FINAL TSADI
+0xF6	0x05E6	#	HEBREW LETTER TSADI
+0xF7	0x05E7	#	HEBREW LETTER QOF
+0xF8	0x05E8	#	HEBREW LETTER RESH
+0xF9	0x05E9	#	HEBREW LETTER SHIN
+0xFA	0x05EA	#	HEBREW LETTER TAV
+0xFD	0x200E	#	LEFT-TO-RIGHT MARK
+0xFE	0x200F	#	RIGHT-TO-LEFT MARK
+
diff --git a/Resources/8859-9.txt b/Resources/8859-9.txt
new file mode 100644
index 0000000..22901f1
--- /dev/null
+++ b/Resources/8859-9.txt
@@ -0,0 +1,307 @@
+#
+#	Name:             ISO/IEC 8859-9:1999 to Unicode
+#	Unicode version:  3.0
+#	Table version:    1.0
+#	Table format:     Format A
+#	Date:             1999 July 27
+#	Authors:          Ken Whistler <kenw@sybase.com>
+#
+#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
+#
+#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+#	No claims are made as to fitness for any particular purpose.  No
+#	warranties of any kind are expressed or implied.  The recipient
+#	agrees to determine applicability of information provided.  If this
+#	file has been provided on magnetic media by Unicode, Inc., the sole
+#	remedy for any claim will be exchange of defective media within 90
+#	days of receipt.
+#
+#	Unicode, Inc. hereby grants the right to freely use the information
+#	supplied in this file in the creation of products supporting the
+#	Unicode Standard, and to make copies of this file in any form for
+#	internal or external distribution as long as this notice remains
+#	attached.
+#
+#	General notes:
+#
+#	This table contains the data the Unicode Consortium has on how
+#       ISO/IEC 8859-9:1999 characters map into Unicode.
+#
+#	Format:  Three tab-separated columns
+#		 Column #1 is the ISO/IEC 8859-9 code (in hex as 0xXX)
+#		 Column #2 is the Unicode (in hex as 0xXXXX)
+#		 Column #3 the Unicode name (follows a comment sign, '#')
+#
+#	The entries are in ISO/IEC 8859-9 order.
+#
+#	ISO/IEC 8859-9 is also equivalent to ISO-IR-148.
+#
+#	Version history
+#	1.0 version updates 0.1 version by adding mappings for all
+#	control characters.
+#
+#	Updated versions of this file may be found in:
+#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
+#
+#	Any comments or problems, contact <errata@unicode.org>
+#	Please note that <errata@unicode.org> is an archival address;
+#	notices will be checked, but do not expect an immediate response.
+#
+0x00	0x0000	#	NULL
+0x01	0x0001	#	START OF HEADING
+0x02	0x0002	#	START OF TEXT
+0x03	0x0003	#	END OF TEXT
+0x04	0x0004	#	END OF TRANSMISSION
+0x05	0x0005	#	ENQUIRY
+0x06	0x0006	#	ACKNOWLEDGE
+0x07	0x0007	#	BELL
+0x08	0x0008	#	BACKSPACE
+0x09	0x0009	#	HORIZONTAL TABULATION
+0x0A	0x000A	#	LINE FEED
+0x0B	0x000B	#	VERTICAL TABULATION
+0x0C	0x000C	#	FORM FEED
+0x0D	0x000D	#	CARRIAGE RETURN
+0x0E	0x000E	#	SHIFT OUT
+0x0F	0x000F	#	SHIFT IN
+0x10	0x0010	#	DATA LINK ESCAPE
+0x11	0x0011	#	DEVICE CONTROL ONE
+0x12	0x0012	#	DEVICE CONTROL TWO
+0x13	0x0013	#	DEVICE CONTROL THREE
+0x14	0x0014	#	DEVICE CONTROL FOUR
+0x15	0x0015	#	NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#	SYNCHRONOUS IDLE
+0x17	0x0017	#	END OF TRANSMISSION BLOCK
+0x18	0x0018	#	CANCEL
+0x19	0x0019	#	END OF MEDIUM
+0x1A	0x001A	#	SUBSTITUTE
+0x1B	0x001B	#	ESCAPE
+0x1C	0x001C	#	FILE SEPARATOR
+0x1D	0x001D	#	GROUP SEPARATOR
+0x1E	0x001E	#	RECORD SEPARATOR
+0x1F	0x001F	#	UNIT SEPARATOR
+0x20	0x0020	#	SPACE
+0x21	0x0021	#	EXCLAMATION MARK
+0x22	0x0022	#	QUOTATION MARK
+0x23	0x0023	#	NUMBER SIGN
+0x24	0x0024	#	DOLLAR SIGN
+0x25	0x0025	#	PERCENT SIGN
+0x26	0x0026	#	AMPERSAND
+0x27	0x0027	#	APOSTROPHE
+0x28	0x0028	#	LEFT PARENTHESIS
+0x29	0x0029	#	RIGHT PARENTHESIS
+0x2A	0x002A	#	ASTERISK
+0x2B	0x002B	#	PLUS SIGN
+0x2C	0x002C	#	COMMA
+0x2D	0x002D	#	HYPHEN-MINUS
+0x2E	0x002E	#	FULL STOP
+0x2F	0x002F	#	SOLIDUS
+0x30	0x0030	#	DIGIT ZERO
+0x31	0x0031	#	DIGIT ONE
+0x32	0x0032	#	DIGIT TWO
+0x33	0x0033	#	DIGIT THREE
+0x34	0x0034	#	DIGIT FOUR
+0x35	0x0035	#	DIGIT FIVE
+0x36	0x0036	#	DIGIT SIX
+0x37	0x0037	#	DIGIT SEVEN
+0x38	0x0038	#	DIGIT EIGHT
+0x39	0x0039	#	DIGIT NINE
+0x3A	0x003A	#	COLON
+0x3B	0x003B	#	SEMICOLON
+0x3C	0x003C	#	LESS-THAN SIGN
+0x3D	0x003D	#	EQUALS SIGN
+0x3E	0x003E	#	GREATER-THAN SIGN
+0x3F	0x003F	#	QUESTION MARK
+0x40	0x0040	#	COMMERCIAL AT
+0x41	0x0041	#	LATIN CAPITAL LETTER A
+0x42	0x0042	#	LATIN CAPITAL LETTER B
+0x43	0x0043	#	LATIN CAPITAL LETTER C
+0x44	0x0044	#	LATIN CAPITAL LETTER D
+0x45	0x0045	#	LATIN CAPITAL LETTER E
+0x46	0x0046	#	LATIN CAPITAL LETTER F
+0x47	0x0047	#	LATIN CAPITAL LETTER G
+0x48	0x0048	#	LATIN CAPITAL LETTER H
+0x49	0x0049	#	LATIN CAPITAL LETTER I
+0x4A	0x004A	#	LATIN CAPITAL LETTER J
+0x4B	0x004B	#	LATIN CAPITAL LETTER K
+0x4C	0x004C	#	LATIN CAPITAL LETTER L
+0x4D	0x004D	#	LATIN CAPITAL LETTER M
+0x4E	0x004E	#	LATIN CAPITAL LETTER N
+0x4F	0x004F	#	LATIN CAPITAL LETTER O
+0x50	0x0050	#	LATIN CAPITAL LETTER P
+0x51	0x0051	#	LATIN CAPITAL LETTER Q
+0x52	0x0052	#	LATIN CAPITAL LETTER R
+0x53	0x0053	#	LATIN CAPITAL LETTER S
+0x54	0x0054	#	LATIN CAPITAL LETTER T
+0x55	0x0055	#	LATIN CAPITAL LETTER U
+0x56	0x0056	#	LATIN CAPITAL LETTER V
+0x57	0x0057	#	LATIN CAPITAL LETTER W
+0x58	0x0058	#	LATIN CAPITAL LETTER X
+0x59	0x0059	#	LATIN CAPITAL LETTER Y
+0x5A	0x005A	#	LATIN CAPITAL LETTER Z
+0x5B	0x005B	#	LEFT SQUARE BRACKET
+0x5C	0x005C	#	REVERSE SOLIDUS
+0x5D	0x005D	#	RIGHT SQUARE BRACKET
+0x5E	0x005E	#	CIRCUMFLEX ACCENT
+0x5F	0x005F	#	LOW LINE
+0x60	0x0060	#	GRAVE ACCENT
+0x61	0x0061	#	LATIN SMALL LETTER A
+0x62	0x0062	#	LATIN SMALL LETTER B
+0x63	0x0063	#	LATIN SMALL LETTER C
+0x64	0x0064	#	LATIN SMALL LETTER D
+0x65	0x0065	#	LATIN SMALL LETTER E
+0x66	0x0066	#	LATIN SMALL LETTER F
+0x67	0x0067	#	LATIN SMALL LETTER G
+0x68	0x0068	#	LATIN SMALL LETTER H
+0x69	0x0069	#	LATIN SMALL LETTER I
+0x6A	0x006A	#	LATIN SMALL LETTER J
+0x6B	0x006B	#	LATIN SMALL LETTER K
+0x6C	0x006C	#	LATIN SMALL LETTER L
+0x6D	0x006D	#	LATIN SMALL LETTER M
+0x6E	0x006E	#	LATIN SMALL LETTER N
+0x6F	0x006F	#	LATIN SMALL LETTER O
+0x70	0x0070	#	LATIN SMALL LETTER P
+0x71	0x0071	#	LATIN SMALL LETTER Q
+0x72	0x0072	#	LATIN SMALL LETTER R
+0x73	0x0073	#	LATIN SMALL LETTER S
+0x74	0x0074	#	LATIN SMALL LETTER T
+0x75	0x0075	#	LATIN SMALL LETTER U
+0x76	0x0076	#	LATIN SMALL LETTER V
+0x77	0x0077	#	LATIN SMALL LETTER W
+0x78	0x0078	#	LATIN SMALL LETTER X
+0x79	0x0079	#	LATIN SMALL LETTER Y
+0x7A	0x007A	#	LATIN SMALL LETTER Z
+0x7B	0x007B	#	LEFT CURLY BRACKET
+0x7C	0x007C	#	VERTICAL LINE
+0x7D	0x007D	#	RIGHT CURLY BRACKET
+0x7E	0x007E	#	TILDE
+0x7F	0x007F	#	DELETE
+0x80	0x0080	#	<control>
+0x81	0x0081	#	<control>
+0x82	0x0082	#	<control>
+0x83	0x0083	#	<control>
+0x84	0x0084	#	<control>
+0x85	0x0085	#	<control>
+0x86	0x0086	#	<control>
+0x87	0x0087	#	<control>
+0x88	0x0088	#	<control>
+0x89	0x0089	#	<control>
+0x8A	0x008A	#	<control>
+0x8B	0x008B	#	<control>
+0x8C	0x008C	#	<control>
+0x8D	0x008D	#	<control>
+0x8E	0x008E	#	<control>
+0x8F	0x008F	#	<control>
+0x90	0x0090	#	<control>
+0x91	0x0091	#	<control>
+0x92	0x0092	#	<control>
+0x93	0x0093	#	<control>
+0x94	0x0094	#	<control>
+0x95	0x0095	#	<control>
+0x96	0x0096	#	<control>
+0x97	0x0097	#	<control>
+0x98	0x0098	#	<control>
+0x99	0x0099	#	<control>
+0x9A	0x009A	#	<control>
+0x9B	0x009B	#	<control>
+0x9C	0x009C	#	<control>
+0x9D	0x009D	#	<control>
+0x9E	0x009E	#	<control>
+0x9F	0x009F	#	<control>
+0xA0	0x00A0	#	NO-BREAK SPACE
+0xA1	0x00A1	#	INVERTED EXCLAMATION MARK
+0xA2	0x00A2	#	CENT SIGN
+0xA3	0x00A3	#	POUND SIGN
+0xA4	0x00A4	#	CURRENCY SIGN
+0xA5	0x00A5	#	YEN SIGN
+0xA6	0x00A6	#	BROKEN BAR
+0xA7	0x00A7	#	SECTION SIGN
+0xA8	0x00A8	#	DIAERESIS
+0xA9	0x00A9	#	COPYRIGHT SIGN
+0xAA	0x00AA	#	FEMININE ORDINAL INDICATOR
+0xAB	0x00AB	#	LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC	0x00AC	#	NOT SIGN
+0xAD	0x00AD	#	SOFT HYPHEN
+0xAE	0x00AE	#	REGISTERED SIGN
+0xAF	0x00AF	#	MACRON
+0xB0	0x00B0	#	DEGREE SIGN
+0xB1	0x00B1	#	PLUS-MINUS SIGN
+0xB2	0x00B2	#	SUPERSCRIPT TWO
+0xB3	0x00B3	#	SUPERSCRIPT THREE
+0xB4	0x00B4	#	ACUTE ACCENT
+0xB5	0x00B5	#	MICRO SIGN
+0xB6	0x00B6	#	PILCROW SIGN
+0xB7	0x00B7	#	MIDDLE DOT
+0xB8	0x00B8	#	CEDILLA
+0xB9	0x00B9	#	SUPERSCRIPT ONE
+0xBA	0x00BA	#	MASCULINE ORDINAL INDICATOR
+0xBB	0x00BB	#	RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC	0x00BC	#	VULGAR FRACTION ONE QUARTER
+0xBD	0x00BD	#	VULGAR FRACTION ONE HALF
+0xBE	0x00BE	#	VULGAR FRACTION THREE QUARTERS
+0xBF	0x00BF	#	INVERTED QUESTION MARK
+0xC0	0x00C0	#	LATIN CAPITAL LETTER A WITH GRAVE
+0xC1	0x00C1	#	LATIN CAPITAL LETTER A WITH ACUTE
+0xC2	0x00C2	#	LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3	0x00C3	#	LATIN CAPITAL LETTER A WITH TILDE
+0xC4	0x00C4	#	LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5	0x00C5	#	LATIN CAPITAL LETTER A WITH RING ABOVE
+0xC6	0x00C6	#	LATIN CAPITAL LETTER AE
+0xC7	0x00C7	#	LATIN CAPITAL LETTER C WITH CEDILLA
+0xC8	0x00C8	#	LATIN CAPITAL LETTER E WITH GRAVE
+0xC9	0x00C9	#	LATIN CAPITAL LETTER E WITH ACUTE
+0xCA	0x00CA	#	LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xCB	0x00CB	#	LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC	0x00CC	#	LATIN CAPITAL LETTER I WITH GRAVE
+0xCD	0x00CD	#	LATIN CAPITAL LETTER I WITH ACUTE
+0xCE	0x00CE	#	LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF	0x00CF	#	LATIN CAPITAL LETTER I WITH DIAERESIS
+0xD0	0x011E	#	LATIN CAPITAL LETTER G WITH BREVE
+0xD1	0x00D1	#	LATIN CAPITAL LETTER N WITH TILDE
+0xD2	0x00D2	#	LATIN CAPITAL LETTER O WITH GRAVE
+0xD3	0x00D3	#	LATIN CAPITAL LETTER O WITH ACUTE
+0xD4	0x00D4	#	LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5	0x00D5	#	LATIN CAPITAL LETTER O WITH TILDE
+0xD6	0x00D6	#	LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7	0x00D7	#	MULTIPLICATION SIGN
+0xD8	0x00D8	#	LATIN CAPITAL LETTER O WITH STROKE
+0xD9	0x00D9	#	LATIN CAPITAL LETTER U WITH GRAVE
+0xDA	0x00DA	#	LATIN CAPITAL LETTER U WITH ACUTE
+0xDB	0x00DB	#	LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xDC	0x00DC	#	LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD	0x0130	#	LATIN CAPITAL LETTER I WITH DOT ABOVE
+0xDE	0x015E	#	LATIN CAPITAL LETTER S WITH CEDILLA
+0xDF	0x00DF	#	LATIN SMALL LETTER SHARP S
+0xE0	0x00E0	#	LATIN SMALL LETTER A WITH GRAVE
+0xE1	0x00E1	#	LATIN SMALL LETTER A WITH ACUTE
+0xE2	0x00E2	#	LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3	0x00E3	#	LATIN SMALL LETTER A WITH TILDE
+0xE4	0x00E4	#	LATIN SMALL LETTER A WITH DIAERESIS
+0xE5	0x00E5	#	LATIN SMALL LETTER A WITH RING ABOVE
+0xE6	0x00E6	#	LATIN SMALL LETTER AE
+0xE7	0x00E7	#	LATIN SMALL LETTER C WITH CEDILLA
+0xE8	0x00E8	#	LATIN SMALL LETTER E WITH GRAVE
+0xE9	0x00E9	#	LATIN SMALL LETTER E WITH ACUTE
+0xEA	0x00EA	#	LATIN SMALL LETTER E WITH CIRCUMFLEX
+0xEB	0x00EB	#	LATIN SMALL LETTER E WITH DIAERESIS
+0xEC	0x00EC	#	LATIN SMALL LETTER I WITH GRAVE
+0xED	0x00ED	#	LATIN SMALL LETTER I WITH ACUTE
+0xEE	0x00EE	#	LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF	0x00EF	#	LATIN SMALL LETTER I WITH DIAERESIS
+0xF0	0x011F	#	LATIN SMALL LETTER G WITH BREVE
+0xF1	0x00F1	#	LATIN SMALL LETTER N WITH TILDE
+0xF2	0x00F2	#	LATIN SMALL LETTER O WITH GRAVE
+0xF3	0x00F3	#	LATIN SMALL LETTER O WITH ACUTE
+0xF4	0x00F4	#	LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5	0x00F5	#	LATIN SMALL LETTER O WITH TILDE
+0xF6	0x00F6	#	LATIN SMALL LETTER O WITH DIAERESIS
+0xF7	0x00F7	#	DIVISION SIGN
+0xF8	0x00F8	#	LATIN SMALL LETTER O WITH STROKE
+0xF9	0x00F9	#	LATIN SMALL LETTER U WITH GRAVE
+0xFA	0x00FA	#	LATIN SMALL LETTER U WITH ACUTE
+0xFB	0x00FB	#	LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xFC	0x00FC	#	LATIN SMALL LETTER U WITH DIAERESIS
+0xFD	0x0131	#	LATIN SMALL LETTER DOTLESS I
+0xFE	0x015F	#	LATIN SMALL LETTER S WITH CEDILLA
+0xFF	0x00FF	#	LATIN SMALL LETTER Y WITH DIAERESIS
+
+
diff --git a/Resources/Default b/Resources/Default
new file mode 100644
index 0000000..c16f39a
--- /dev/null
+++ b/Resources/Default
@@ -0,0 +1,81 @@
+# Default fontnames translation table
+# uses only fonts present in the RISC OS 3 ROMs
+#
+# MS-Word fontname,	Italic,	Bold,	Acorn fontname,		Special
+Arial,			0,	0,	Homerton.Medium,	0
+Arial,			0,	1,	Homerton.Bold,		0
+Arial,			1,	0,	Homerton.Medium.Oblique,0
+Arial,			1,	1,	Homerton.Bold.Oblique,	0
+Arial Black,		0,	0,	Homerton.Medium,	0
+Arial Black,		0,	1,	Homerton.Bold,		0
+Arial Black,		1,	0,	Homerton.Medium.Oblique,0
+Arial Black,		1,	1,	Homerton.Bold.Oblique,	0
+Arial CE,		0,	0,	Homerton.Medium,	0
+Arial CE,		0,	1,	Homerton.Bold,		0
+Arial CE,		1,	0,	Homerton.Medium.Oblique,0
+Arial CE,		1,	1,	Homerton.Bold.Oblique,	0
+Arial Narrow,		0,	0,	Homerton.Medium,	0
+Arial Narrow,		0,	1,	Homerton.Bold,		0
+Arial Narrow,		1,	0,	Homerton.Medium.Oblique,0
+Arial Narrow,		1,	1,	Homerton.Bold.Oblique,	0
+Comic Sans MS,		0,	0,	Homerton.Medium,	0
+Comic Sans MS,		0,	1,	Homerton.Bold,		0
+Comic Sans MS,		1,	0,	Homerton.Medium.Oblique,0
+Comic Sans MS,		1,	1,	Homerton.Bold.Oblique,	0
+Courier,		0,	0,	Corpus.Medium,		0
+Courier,		0,	1,	Corpus.Bold,		0
+Courier,		1,	0,	Corpus.Medium.Oblique,	0
+Courier,		1,	1,	Corpus.Bold.Oblique,	0
+Courier New,		0,	0,	Corpus.Medium,		0
+Courier New,		0,	1,	Corpus.Bold,		0
+Courier New,		1,	0,	Corpus.Medium.Oblique,	0
+Courier New,		1,	1,	Corpus.Bold.Oblique,	0
+Fixedsys,		0,	0,	Corpus.Medium,		0
+Fixedsys,		0,	1,	Corpus.Bold,		0
+Fixedsys,		1,	0,	Corpus.Medium.Oblique,	0
+Fixedsys,		1,	1,	Corpus.Bold.Oblique,	0
+Helvetica,		0,	0,	Homerton.Medium,	0
+Helvetica,		0,	1,	Homerton.Bold,		0
+Helvetica,		1,	0,	Homerton.Medium.Oblique,0
+Helvetica,		1,	1,	Homerton.Bold.Oblique,	0
+Helvetica-Narrow,	0,	0,	Homerton.Medium,	0
+Helvetica-Narrow,	0,	1,	Homerton.Bold,		0
+Helvetica-Narrow,	1,	0,	Homerton.Medium.Oblique,0
+Helvetica-Narrow,	1,	1,	Homerton.Bold.Oblique,	0
+Lucida Console,		0,	0,	Corpus.Medium,		0
+Lucida Console,		0,	1,	Corpus.Bold,		0
+Lucida Console,		1,	0,	Corpus.Medium.Oblique,	0
+Lucida Console,		1,	1,	Corpus.Bold.Oblique,	0
+Monotype.com,		0,	0,	Corpus.Medium,		0
+Monotype.com,		0,	1,	Corpus.Bold,		0
+Monotype.com,		1,	0,	Corpus.Medium.Oblique,	0
+Monotype.com,		1,	1,	Corpus.Bold.Oblique,	0
+MS Sans Serif,		0,	0,	Homerton.Medium,	0
+MS Sans Serif,		0,	1,	Homerton.Bold,		0
+MS Sans Serif,		1,	0,	Homerton.Medium.Oblique,0
+MS Sans Serif,		1,	1,	Homerton.Bold.Oblique,	0
+Swiss,			0,	0,	Homerton.Medium,	0
+Swiss,			0,	1,	Homerton.Bold,		0
+Swiss,			1,	0,	Homerton.Medium.Oblique,0
+Swiss,			1,	1,	Homerton.Bold.Oblique,	0
+Tahoma,			0,	0,	Homerton.Medium,	0
+Tahoma,			0,	1,	Homerton.Bold,		0
+Tahoma,			1,	0,	Homerton.Medium.Oblique,0
+Tahoma,			1,	1,	Homerton.Bold.Oblique,	0
+Trebuchet MS,		0,	0,	Homerton.Medium,	0
+Trebuchet MS,		0,	1,	Homerton.Bold,		0
+Trebuchet MS,		1,	0,	Homerton.Medium.Oblique,0
+Trebuchet MS,		1,	1,	Homerton.Bold.Oblique,	0
+Verdana,		0,	0,	Homerton.Medium,	0
+Verdana,		0,	1,	Homerton.Bold,		0
+Verdana,		1,	0,	Homerton.Medium.Oblique,0
+Verdana,		1,	1,	Homerton.Bold.Oblique,	0
+Univers,		0,	0,	Homerton.Medium,	0
+Univers,		0,	1,	Homerton.Bold,		0
+Univers,		1,	0,	Homerton.Medium.Oblique,0
+Univers,		1,	1,	Homerton.Bold.Oblique,	0
+# All the other fonts
+*,			0,	0,	Trinity.Medium,		0
+*,			0,	1,	Trinity.Bold,		0
+*,			1,	0,	Trinity.Medium.Italic,	0
+*,			1,	1,	Trinity.Bold.Italic,	0
diff --git a/Resources/Example b/Resources/Example
new file mode 100644
index 0000000..43d2ee2
--- /dev/null
+++ b/Resources/Example
@@ -0,0 +1,80 @@
+# An example of a fontnames translation table
+#
+# MS-Word fontname,	Italic,	Bold,	Acorn fontname,		Special
+Arial,			0,	0,	Homerton.Medium,	0
+Arial,			0,	1,	Homerton.Bold,		0
+Arial,			1,	0,	Homerton.Medium.Oblique,0
+Arial,			1,	1,	Homerton.Bold.Oblique,	0
+Arial Black,		0,	0,	Homerton.Medium,	0
+Arial Black,		0,	1,	Homerton.Bold,		0
+Arial Black,		1,	0,	Homerton.Medium.Oblique,0
+Arial Black,		1,	1,	Homerton.Bold.Oblique,	0
+AvantGarde,		0,	0,	Clare.Medium,		0
+AvantGarde,		0,	1,	Clare.Demi,		0
+AvantGarde,		1,	0,	Clare.Medium.Oblique,	0
+AvantGarde,		1,	1,	Clare.Demi.Oblique,	0
+Bookman,		0,	0,	Robinson.Light,		0
+Bookman,		0,	1,	Robinson.Demi,		0
+Bookman,		1,	0,	Robinson.Light.Italic,	0
+Bookman,		1,	1,	Robinson.Demi.Italic,	0
+Bookman Old Style,	0,	0,	Robinson.Light,		0
+Bookman Old Style,	0,	1,	Robinson.Demi,		0
+Bookman Old Style,	1,	0,	Robinson.Light.Italic,	0
+Bookman Old Style,	1,	1,	Robinson.Demi.Italic,	0
+Courier,		0,	0,	Corpus.Medium,		0
+Courier,		0,	1,	Corpus.Bold,		0
+Courier,		1,	0,	Corpus.Medium.Oblique,	0
+Courier,		1,	1,	Corpus.Bold.Oblique,	0
+Courier New,		0,	0,	Corpus.Medium,		0
+Courier New,		0,	1,	Corpus.Bold,		0
+Courier New,		1,	0,	Corpus.Medium.Oblique,	0
+Courier New,		1,	1,	Corpus.Bold.Oblique,	0
+Fixedsys,		0,	0,	Corpus.Medium,		0
+Fixedsys,		0,	1,	Corpus.Bold,		0
+Fixedsys,		1,	0,	Corpus.Medium.Oblique,	0
+Fixedsys,		1,	1,	Corpus.Bold.Oblique,	0
+Helvetica,		0,	0,	Homerton.Medium,	0
+Helvetica,		0,	1,	Homerton.Bold,		0
+Helvetica,		1,	0,	Homerton.Medium.Oblique,0
+Helvetica,		1,	1,	Homerton.Bold.Oblique,	0
+Lucida Console,		0,	0,	Corpus.Medium,		0
+Lucida Console,		0,	1,	Corpus.Bold,		0
+Lucida Console,		1,	0,	Corpus.Medium.Oblique,	0
+Lucida Console,		1,	1,	Corpus.Bold.Oblique,	0
+Palatino,		0,	0,	Pembroke.Medium,	0
+Palatino,		0,	1,	Pembroke.Bold,		0
+Palatino,		1,	0,	Pembroke.Medium.Italic,	0
+Palatino,		1,	1,	Pembroke.Bold.Italic,	0
+Swiss,			0,	0,	Homerton.Medium,	0
+Swiss,			0,	1,	Homerton.Bold,		0
+Swiss,			1,	0,	Homerton.Medium.Oblique,0
+Swiss,			1,	1,	Homerton.Bold.Oblique,	0
+Symbol,			0,	0,	Sidney,			1
+Symbol,			0,	1,	Sidney,			1
+Symbol,			1,	0,	Sidney,			1
+Symbol,			1,	1,	Sidney,			1
+Times,			0,	0,	Trinity.Medium,		0
+Times,			0,	1,	Trinity.Bold,		0
+Times,			1,	0,	Trinity.Medium.Italic,	0
+Times,			1,	1,	Trinity.Bold.Italic,	0
+Times New Roman,	0,	0,	Trinity.Medium,		0
+Times New Roman,	0,	1,	Trinity.Bold,		0
+Times New Roman,	1,	0,	Trinity.Medium.Italic,	0
+Times New Roman,	1,	1,	Trinity.Bold.Italic,	0
+Times Roman,		0,	0,	Trinity.Medium,		0
+Times Roman,		0,	1,	Trinity.Bold,		0
+Times Roman,		1,	0,	Trinity.Medium.Italic,	0
+Times Roman,		1,	1,	Trinity.Bold.Italic,	0
+Univers,		0,	0,	Homerton.Medium,	0
+Univers,		0,	1,	Homerton.Bold,		0
+Univers,		1,	0,	Homerton.Medium.Oblique,0
+Univers,		1,	1,	Homerton.Bold.Oblique,	0
+ZapfDingbats,		0,	0,	Selwyn,			2
+ZapfDingbats,		0,	1,	Selwyn,			2
+ZapfDingbats,		1,	0,	Selwyn,			2
+ZapfDingbats,		1,	1,	Selwyn,			2
+# All the other fonts
+*,			0,	0,	Trinity.Medium,		0
+*,			0,	1,	Trinity.Bold,		0
+*,			1,	0,	Trinity.Medium.Italic,	0
+*,			1,	1,	Trinity.Bold.Italic,	0
diff --git a/Resources/MacCyrillic.txt b/Resources/MacCyrillic.txt
new file mode 100644
index 0000000..3e1dd1e
--- /dev/null
+++ b/Resources/MacCyrillic.txt
@@ -0,0 +1,344 @@
+#=======================================================================
+#   File name:  CYRILLIC.TXT
+#
+#   Contents:   Map (external version) from Mac OS Cyrillic
+#               character set to Unicode 2.1 through Unicode 3.2
+#
+#   Copyright:  (c) 1995-2002 by Apple Computer, Inc., all rights
+#               reserved.
+#
+#   Contact:    charsets@apple.com
+#
+#   Changes:
+#
+#      b3,c1 2002-Dec-19    Update URLs, notes. Matches internal
+#                           utom<b2>.
+#       b02  1999-Sep-22    Encoding changed for Mac OS 9.0 to merge
+#                           with Mac OS Ukrainian and support EURO SIGN;
+#                           Change mappings for 0xA2, 0xB6, and 0xFF.
+#                           Update contact e-mail address. Matches
+#                           internal utom<b2>, ufrm<b2>, and Text
+#                           Encoding Converter version 1.5.
+#       n05  1998-Feb-05    Update header comments to new format; no
+#                           mapping changes.  Matches internal utom<n3>,
+#                           ufrm<n13>, and Text Encoding Converter
+#                           version 1.3.
+#       n03  1995-Apr-15    First version (after fixing some typos).
+#                           Matches internal ufrm<n5>.
+#
+# Standard header:
+# ----------------
+#
+#   Apple, the Apple logo, and Macintosh are trademarks of Apple
+#   Computer, Inc., registered in the United States and other countries.
+#   Unicode is a trademark of Unicode Inc. For the sake of brevity,
+#   throughout this document, "Macintosh" can be used to refer to
+#   Macintosh computers and "Unicode" can be used to refer to the
+#   Unicode standard.
+#
+#   Apple makes no warranty or representation, either express or
+#   implied, with respect to these tables, their quality, accuracy, or
+#   fitness for a particular purpose. In no event will Apple be liable
+#   for direct, indirect, special, incidental, or consequential damages 
+#   resulting from any defect or inaccuracy in this document or the
+#   accompanying tables.
+#
+#   These mapping tables and character lists are subject to change.
+#   The latest tables should be available from the following:
+#
+#   <http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/>
+#
+#   For general information about Mac OS encodings and these mapping
+#   tables, see the file "README.TXT".
+#
+# Format:
+# -------
+#
+#   Three tab-separated columns;
+#   '#' begins a comment which continues to the end of the line.
+#     Column #1 is the Mac OS Cyrillic code (in hex as 0xNN)
+#     Column #2 is the corresponding Unicode (in hex as 0xNNNN)
+#     Column #3 is a comment containing the Unicode name
+#
+#   The entries are in Mac OS Cyrillic code order.
+#
+#   Control character mappings are not shown in this table, following
+#   the conventions of the standard UTC mapping tables. However, the
+#   Mac OS Cyrillic character set uses the standard control characters
+#   at 0x00-0x1F and 0x7F.
+#
+# Notes on Mac OS Cyrillic:
+# -------------------------
+#
+#   This is the "Euro sign" version of Mac Cyrillic for Mac OS 9.0 and
+#   later. Before Mac OS 9.0, there were two separate Slavic Cyrillic
+#   encodings:
+#
+#   1. The Cyrillic currency sign variant (used for localized Russian
+#      and Bulgarian systems), which had the following:
+#	    0xA2  U+00A2 CENT SIGN
+#	    0xB6  U+2202 PARTIAL DIFFERENTIAL
+#	    0xFF  U+00A4 CURRENCY SIGN
+#
+#   2. The Ukrainian currency sign variant (used for localized Ukrainian
+#      systems and the pre-9.0 Cyrillic Language Kit), which had the
+#      following:
+#	    0xA2  U+0490 CYRILLIC CAPITAL LETTER GHE WITH UPTURN
+#	    0xB6  U+0491 CYRILLIC SMALL LETTER GHE WITH UPTURN
+#	    0xFF  U+00A4 CURRENCY SIGN
+#
+#   This new Cyrillic Euro sign version is based on the old Ukrainian
+#   currency sign variant, with 0xFF changed to be EURO SIGN.
+#
+#   The Mac OS Cyrillic encoding includes the Cyrillic letter repertoire
+#   of ISO 8859-5 (although not at the same code points). This covers
+#   most of the Slavic languages written in Cyrillic script.
+#
+#   The Mac OS Cyrillic encoding also includes a number of characters
+#   needed for the Mac OS user interface and localization (e.g.
+#   ellipsis, bullet, copyright sign). All of the characters in Mac OS
+#   Cyrillic that are also in the Mac OS Roman encoding are at the
+#   same code point in both; this improves application compatibility.
+#
+#   Note: There is a common Ukrainian glyph variation in which the glyph
+#   for CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I may or may not
+#   have a dot above.
+#
+# Unicode mapping issues and notes:
+# ---------------------------------
+#
+# Details of mapping changes in each version:
+# -------------------------------------------
+#
+#   Changes from version n05 to version b02:
+#
+#   - Encoding changed for Mac OS 9.0 to merge with Mac OS Ukrainian and
+#   support EURO SIGN. 0xA2 changed from U+00A2 to U+0490; 0xB6 changed
+#   from U+2202 to U+0491; 0xFF changed from U+00A4 to U+20AC.
+#
+##################
+
+0x20	0x0020	# SPACE
+0x21	0x0021	# EXCLAMATION MARK
+0x22	0x0022	# QUOTATION MARK
+0x23	0x0023	# NUMBER SIGN
+0x24	0x0024	# DOLLAR SIGN
+0x25	0x0025	# PERCENT SIGN
+0x26	0x0026	# AMPERSAND
+0x27	0x0027	# APOSTROPHE
+0x28	0x0028	# LEFT PARENTHESIS
+0x29	0x0029	# RIGHT PARENTHESIS
+0x2A	0x002A	# ASTERISK
+0x2B	0x002B	# PLUS SIGN
+0x2C	0x002C	# COMMA
+0x2D	0x002D	# HYPHEN-MINUS
+0x2E	0x002E	# FULL STOP
+0x2F	0x002F	# SOLIDUS
+0x30	0x0030	# DIGIT ZERO
+0x31	0x0031	# DIGIT ONE
+0x32	0x0032	# DIGIT TWO
+0x33	0x0033	# DIGIT THREE
+0x34	0x0034	# DIGIT FOUR
+0x35	0x0035	# DIGIT FIVE
+0x36	0x0036	# DIGIT SIX
+0x37	0x0037	# DIGIT SEVEN
+0x38	0x0038	# DIGIT EIGHT
+0x39	0x0039	# DIGIT NINE
+0x3A	0x003A	# COLON
+0x3B	0x003B	# SEMICOLON
+0x3C	0x003C	# LESS-THAN SIGN
+0x3D	0x003D	# EQUALS SIGN
+0x3E	0x003E	# GREATER-THAN SIGN
+0x3F	0x003F	# QUESTION MARK
+0x40	0x0040	# COMMERCIAL AT
+0x41	0x0041	# LATIN CAPITAL LETTER A
+0x42	0x0042	# LATIN CAPITAL LETTER B
+0x43	0x0043	# LATIN CAPITAL LETTER C
+0x44	0x0044	# LATIN CAPITAL LETTER D
+0x45	0x0045	# LATIN CAPITAL LETTER E
+0x46	0x0046	# LATIN CAPITAL LETTER F
+0x47	0x0047	# LATIN CAPITAL LETTER G
+0x48	0x0048	# LATIN CAPITAL LETTER H
+0x49	0x0049	# LATIN CAPITAL LETTER I
+0x4A	0x004A	# LATIN CAPITAL LETTER J
+0x4B	0x004B	# LATIN CAPITAL LETTER K
+0x4C	0x004C	# LATIN CAPITAL LETTER L
+0x4D	0x004D	# LATIN CAPITAL LETTER M
+0x4E	0x004E	# LATIN CAPITAL LETTER N
+0x4F	0x004F	# LATIN CAPITAL LETTER O
+0x50	0x0050	# LATIN CAPITAL LETTER P
+0x51	0x0051	# LATIN CAPITAL LETTER Q
+0x52	0x0052	# LATIN CAPITAL LETTER R
+0x53	0x0053	# LATIN CAPITAL LETTER S
+0x54	0x0054	# LATIN CAPITAL LETTER T
+0x55	0x0055	# LATIN CAPITAL LETTER U
+0x56	0x0056	# LATIN CAPITAL LETTER V
+0x57	0x0057	# LATIN CAPITAL LETTER W
+0x58	0x0058	# LATIN CAPITAL LETTER X
+0x59	0x0059	# LATIN CAPITAL LETTER Y
+0x5A	0x005A	# LATIN CAPITAL LETTER Z
+0x5B	0x005B	# LEFT SQUARE BRACKET
+0x5C	0x005C	# REVERSE SOLIDUS
+0x5D	0x005D	# RIGHT SQUARE BRACKET
+0x5E	0x005E	# CIRCUMFLEX ACCENT
+0x5F	0x005F	# LOW LINE
+0x60	0x0060	# GRAVE ACCENT
+0x61	0x0061	# LATIN SMALL LETTER A
+0x62	0x0062	# LATIN SMALL LETTER B
+0x63	0x0063	# LATIN SMALL LETTER C
+0x64	0x0064	# LATIN SMALL LETTER D
+0x65	0x0065	# LATIN SMALL LETTER E
+0x66	0x0066	# LATIN SMALL LETTER F
+0x67	0x0067	# LATIN SMALL LETTER G
+0x68	0x0068	# LATIN SMALL LETTER H
+0x69	0x0069	# LATIN SMALL LETTER I
+0x6A	0x006A	# LATIN SMALL LETTER J
+0x6B	0x006B	# LATIN SMALL LETTER K
+0x6C	0x006C	# LATIN SMALL LETTER L
+0x6D	0x006D	# LATIN SMALL LETTER M
+0x6E	0x006E	# LATIN SMALL LETTER N
+0x6F	0x006F	# LATIN SMALL LETTER O
+0x70	0x0070	# LATIN SMALL LETTER P
+0x71	0x0071	# LATIN SMALL LETTER Q
+0x72	0x0072	# LATIN SMALL LETTER R
+0x73	0x0073	# LATIN SMALL LETTER S
+0x74	0x0074	# LATIN SMALL LETTER T
+0x75	0x0075	# LATIN SMALL LETTER U
+0x76	0x0076	# LATIN SMALL LETTER V
+0x77	0x0077	# LATIN SMALL LETTER W
+0x78	0x0078	# LATIN SMALL LETTER X
+0x79	0x0079	# LATIN SMALL LETTER Y
+0x7A	0x007A	# LATIN SMALL LETTER Z
+0x7B	0x007B	# LEFT CURLY BRACKET
+0x7C	0x007C	# VERTICAL LINE
+0x7D	0x007D	# RIGHT CURLY BRACKET
+0x7E	0x007E	# TILDE
+#
+0x80	0x0410	# CYRILLIC CAPITAL LETTER A
+0x81	0x0411	# CYRILLIC CAPITAL LETTER BE
+0x82	0x0412	# CYRILLIC CAPITAL LETTER VE
+0x83	0x0413	# CYRILLIC CAPITAL LETTER GHE
+0x84	0x0414	# CYRILLIC CAPITAL LETTER DE
+0x85	0x0415	# CYRILLIC CAPITAL LETTER IE
+0x86	0x0416	# CYRILLIC CAPITAL LETTER ZHE
+0x87	0x0417	# CYRILLIC CAPITAL LETTER ZE
+0x88	0x0418	# CYRILLIC CAPITAL LETTER I
+0x89	0x0419	# CYRILLIC CAPITAL LETTER SHORT I
+0x8A	0x041A	# CYRILLIC CAPITAL LETTER KA
+0x8B	0x041B	# CYRILLIC CAPITAL LETTER EL
+0x8C	0x041C	# CYRILLIC CAPITAL LETTER EM
+0x8D	0x041D	# CYRILLIC CAPITAL LETTER EN
+0x8E	0x041E	# CYRILLIC CAPITAL LETTER O
+0x8F	0x041F	# CYRILLIC CAPITAL LETTER PE
+0x90	0x0420	# CYRILLIC CAPITAL LETTER ER
+0x91	0x0421	# CYRILLIC CAPITAL LETTER ES
+0x92	0x0422	# CYRILLIC CAPITAL LETTER TE
+0x93	0x0423	# CYRILLIC CAPITAL LETTER U
+0x94	0x0424	# CYRILLIC CAPITAL LETTER EF
+0x95	0x0425	# CYRILLIC CAPITAL LETTER HA
+0x96	0x0426	# CYRILLIC CAPITAL LETTER TSE
+0x97	0x0427	# CYRILLIC CAPITAL LETTER CHE
+0x98	0x0428	# CYRILLIC CAPITAL LETTER SHA
+0x99	0x0429	# CYRILLIC CAPITAL LETTER SHCHA
+0x9A	0x042A	# CYRILLIC CAPITAL LETTER HARD SIGN
+0x9B	0x042B	# CYRILLIC CAPITAL LETTER YERU
+0x9C	0x042C	# CYRILLIC CAPITAL LETTER SOFT SIGN
+0x9D	0x042D	# CYRILLIC CAPITAL LETTER E
+0x9E	0x042E	# CYRILLIC CAPITAL LETTER YU
+0x9F	0x042F	# CYRILLIC CAPITAL LETTER YA
+0xA0	0x2020	# DAGGER
+0xA1	0x00B0	# DEGREE SIGN
+0xA2	0x0490	# CYRILLIC CAPITAL LETTER GHE WITH UPTURN
+0xA3	0x00A3	# POUND SIGN
+0xA4	0x00A7	# SECTION SIGN
+0xA5	0x2022	# BULLET
+0xA6	0x00B6	# PILCROW SIGN
+0xA7	0x0406	# CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+0xA8	0x00AE	# REGISTERED SIGN
+0xA9	0x00A9	# COPYRIGHT SIGN
+0xAA	0x2122	# TRADE MARK SIGN
+0xAB	0x0402	# CYRILLIC CAPITAL LETTER DJE
+0xAC	0x0452	# CYRILLIC SMALL LETTER DJE
+0xAD	0x2260	# NOT EQUAL TO
+0xAE	0x0403	# CYRILLIC CAPITAL LETTER GJE
+0xAF	0x0453	# CYRILLIC SMALL LETTER GJE
+0xB0	0x221E	# INFINITY
+0xB1	0x00B1	# PLUS-MINUS SIGN
+0xB2	0x2264	# LESS-THAN OR EQUAL TO
+0xB3	0x2265	# GREATER-THAN OR EQUAL TO
+0xB4	0x0456	# CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+0xB5	0x00B5	# MICRO SIGN
+0xB6	0x0491	# CYRILLIC SMALL LETTER GHE WITH UPTURN
+0xB7	0x0408	# CYRILLIC CAPITAL LETTER JE
+0xB8	0x0404	# CYRILLIC CAPITAL LETTER UKRAINIAN IE
+0xB9	0x0454	# CYRILLIC SMALL LETTER UKRAINIAN IE
+0xBA	0x0407	# CYRILLIC CAPITAL LETTER YI
+0xBB	0x0457	# CYRILLIC SMALL LETTER YI
+0xBC	0x0409	# CYRILLIC CAPITAL LETTER LJE
+0xBD	0x0459	# CYRILLIC SMALL LETTER LJE
+0xBE	0x040A	# CYRILLIC CAPITAL LETTER NJE
+0xBF	0x045A	# CYRILLIC SMALL LETTER NJE
+0xC0	0x0458	# CYRILLIC SMALL LETTER JE
+0xC1	0x0405	# CYRILLIC CAPITAL LETTER DZE
+0xC2	0x00AC	# NOT SIGN
+0xC3	0x221A	# SQUARE ROOT
+0xC4	0x0192	# LATIN SMALL LETTER F WITH HOOK
+0xC5	0x2248	# ALMOST EQUAL TO
+0xC6	0x2206	# INCREMENT
+0xC7	0x00AB	# LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xC8	0x00BB	# RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xC9	0x2026	# HORIZONTAL ELLIPSIS
+0xCA	0x00A0	# NO-BREAK SPACE
+0xCB	0x040B	# CYRILLIC CAPITAL LETTER TSHE
+0xCC	0x045B	# CYRILLIC SMALL LETTER TSHE
+0xCD	0x040C	# CYRILLIC CAPITAL LETTER KJE
+0xCE	0x045C	# CYRILLIC SMALL LETTER KJE
+0xCF	0x0455	# CYRILLIC SMALL LETTER DZE
+0xD0	0x2013	# EN DASH
+0xD1	0x2014	# EM DASH
+0xD2	0x201C	# LEFT DOUBLE QUOTATION MARK
+0xD3	0x201D	# RIGHT DOUBLE QUOTATION MARK
+0xD4	0x2018	# LEFT SINGLE QUOTATION MARK
+0xD5	0x2019	# RIGHT SINGLE QUOTATION MARK
+0xD6	0x00F7	# DIVISION SIGN
+0xD7	0x201E	# DOUBLE LOW-9 QUOTATION MARK
+0xD8	0x040E	# CYRILLIC CAPITAL LETTER SHORT U
+0xD9	0x045E	# CYRILLIC SMALL LETTER SHORT U
+0xDA	0x040F	# CYRILLIC CAPITAL LETTER DZHE
+0xDB	0x045F	# CYRILLIC SMALL LETTER DZHE
+0xDC	0x2116	# NUMERO SIGN
+0xDD	0x0401	# CYRILLIC CAPITAL LETTER IO
+0xDE	0x0451	# CYRILLIC SMALL LETTER IO
+0xDF	0x044F	# CYRILLIC SMALL LETTER YA
+0xE0	0x0430	# CYRILLIC SMALL LETTER A
+0xE1	0x0431	# CYRILLIC SMALL LETTER BE
+0xE2	0x0432	# CYRILLIC SMALL LETTER VE
+0xE3	0x0433	# CYRILLIC SMALL LETTER GHE
+0xE4	0x0434	# CYRILLIC SMALL LETTER DE
+0xE5	0x0435	# CYRILLIC SMALL LETTER IE
+0xE6	0x0436	# CYRILLIC SMALL LETTER ZHE
+0xE7	0x0437	# CYRILLIC SMALL LETTER ZE
+0xE8	0x0438	# CYRILLIC SMALL LETTER I
+0xE9	0x0439	# CYRILLIC SMALL LETTER SHORT I
+0xEA	0x043A	# CYRILLIC SMALL LETTER KA
+0xEB	0x043B	# CYRILLIC SMALL LETTER EL
+0xEC	0x043C	# CYRILLIC SMALL LETTER EM
+0xED	0x043D	# CYRILLIC SMALL LETTER EN
+0xEE	0x043E	# CYRILLIC SMALL LETTER O
+0xEF	0x043F	# CYRILLIC SMALL LETTER PE
+0xF0	0x0440	# CYRILLIC SMALL LETTER ER
+0xF1	0x0441	# CYRILLIC SMALL LETTER ES
+0xF2	0x0442	# CYRILLIC SMALL LETTER TE
+0xF3	0x0443	# CYRILLIC SMALL LETTER U
+0xF4	0x0444	# CYRILLIC SMALL LETTER EF
+0xF5	0x0445	# CYRILLIC SMALL LETTER HA
+0xF6	0x0446	# CYRILLIC SMALL LETTER TSE
+0xF7	0x0447	# CYRILLIC SMALL LETTER CHE
+0xF8	0x0448	# CYRILLIC SMALL LETTER SHA
+0xF9	0x0449	# CYRILLIC SMALL LETTER SHCHA
+0xFA	0x044A	# CYRILLIC SMALL LETTER HARD SIGN
+0xFB	0x044B	# CYRILLIC SMALL LETTER YERU
+0xFC	0x044C	# CYRILLIC SMALL LETTER SOFT SIGN
+0xFD	0x044D	# CYRILLIC SMALL LETTER E
+0xFE	0x044E	# CYRILLIC SMALL LETTER YU
+0xFF	0x20AC	# EURO SIGN
diff --git a/Resources/MacRoman.txt b/Resources/MacRoman.txt
new file mode 100644
index 0000000..b2b6723
--- /dev/null
+++ b/Resources/MacRoman.txt
@@ -0,0 +1,362 @@
+#=======================================================================
+#   File name:  ROMAN.TXT
+#
+#   Contents:   Map (external version) from Mac OS Roman
+#               character set to Unicode 2.1 through Unicode 3.2
+#
+#   Copyright:  (c) 1994-2002 by Apple Computer, Inc., all rights
+#               reserved.
+#
+#   Contact:    charsets@apple.com
+#
+#   Changes:
+#
+#      b4,c1 2002-Dec-19    Update URLs, notes. Matches internal
+#                           utom<b5>.
+#       b03  1999-Sep-22    Update contact e-mail address. Matches
+#                           internal utom<b4>, ufrm<b3>, and Text
+#                           Encoding Converter version 1.5.
+#       b02  1998-Aug-18    Encoding changed for Mac OS 8.5; change
+#                           mapping of 0xDB from CURRENCY SIGN to
+#                           EURO SIGN. Matches internal utom<b3>,
+#                           ufrm<b3>.
+#       n08  1998-Feb-05    Minor update to header comments
+#       n06  1997-Dec-14    Add warning about future changes to 0xDB
+#                           from CURRENCY SIGN to EURO SIGN. Clarify
+#                           some header information
+#       n04  1997-Dec-01    Update to match internal utom<n3>, ufrm<n22>:
+#                           Change standard mapping for 0xBD from U+2126
+#                           to its canonical decomposition, U+03A9.
+#       n03  1995-Apr-15    First version (after fixing some typos).
+#                           Matches internal ufrm<n9>.
+#
+# Standard header:
+# ----------------
+#
+#   Apple, the Apple logo, and Macintosh are trademarks of Apple
+#   Computer, Inc., registered in the United States and other countries.
+#   Unicode is a trademark of Unicode Inc. For the sake of brevity,
+#   throughout this document, "Macintosh" can be used to refer to
+#   Macintosh computers and "Unicode" can be used to refer to the
+#   Unicode standard.
+#
+#   Apple makes no warranty or representation, either express or
+#   implied, with respect to these tables, their quality, accuracy, or
+#   fitness for a particular purpose. In no event will Apple be liable
+#   for direct, indirect, special, incidental, or consequential damages 
+#   resulting from any defect or inaccuracy in this document or the
+#   accompanying tables.
+#
+#   These mapping tables and character lists are subject to change.
+#   The latest tables should be available from the following:
+#
+#   <http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/>
+#
+#   For general information about Mac OS encodings and these mapping
+#   tables, see the file "README.TXT".
+#
+# Format:
+# -------
+#
+#   Three tab-separated columns;
+#   '#' begins a comment which continues to the end of the line.
+#     Column #1 is the Mac OS Roman code (in hex as 0xNN)
+#     Column #2 is the corresponding Unicode (in hex as 0xNNNN)
+#     Column #3 is a comment containing the Unicode name
+#
+#   The entries are in Mac OS Roman code order.
+#
+#   One of these mappings requires the use of a corporate character.
+#   See the file "CORPCHAR.TXT" and notes below.
+#
+#   Control character mappings are not shown in this table, following
+#   the conventions of the standard UTC mapping tables. However, the
+#   Mac OS Roman character set uses the standard control characters at
+#   0x00-0x1F and 0x7F.
+#
+# Notes on Mac OS Roman:
+# ----------------------
+#
+#   This character set is used for at least the following Mac OS
+#   localizations: U.S., British, Canadian French, French, Swiss
+#   French, German, Swiss German, Italian, Swiss Italian, Dutch,
+#   Swedish, Norwegian, Danish, Finnish, Spanish, Catalan,
+#   Portuguese, Brazilian, and the default International system.
+#
+#   Variants of Mac OS Roman are used for Croatian, Icelandic,
+#   Turkish, Romanian, and other encodings. Separate mapping tables
+#   are available for these encodings.
+#
+#   Before Mac OS 8.5, code point 0xDB was CURRENCY SIGN, and was
+#   mapped to U+00A4. In Mac OS 8.5 and later versions, code point
+#   0xDB is changed to EURO SIGN and maps to U+20AC; the standard
+#   Apple fonts are updated for Mac OS 8.5 to reflect this. There is
+#   a "currency sign" variant of the Mac OS Roman encoding that still
+#   maps 0xDB to U+00A4; this can be used for older fonts.
+#
+#   Before Mac OS 8.5, the ROM bitmap versions of the fonts Chicago,
+#   New York, Geneva, and Monaco did not implement the full Mac OS
+#   Roman character set; they only supported character codes up to
+#   0xD8. The TrueType versions of these fonts have always implemented
+#   the full character set, as with the bitmap and TrueType versions
+#   of the other standard Roman fonts.
+#
+#   In all Mac OS encodings, fonts such as Chicago which are used
+#   as "system" fonts (for menus, dialogs, etc.) have four glyphs
+#   at code points 0x11-0x14 for transient use by the Menu Manager.
+#   These glyphs are not intended as characters for use in normal
+#   text, and the associated code points are not generally
+#   interpreted as associated with these glyphs; they are usually
+#   interpreted (if at all) as the control codes DC1-DC4.
+#
+# Unicode mapping issues and notes:
+# ---------------------------------
+#
+#   The following corporate zone Unicode character is used in this
+#   mapping:
+#
+#     0xF8FF  Apple logo
+#
+#   NOTE: The graphic image associated with the Apple logo character
+#   is not authorized for use without permission of Apple, and
+#   unauthorized use might constitute trademark infringement.
+#
+# Details of mapping changes in each version:
+# -------------------------------------------
+#
+#   Changes from version n08 to version b02:
+#
+#   - Encoding changed for Mac OS 8.5; change mapping of 0xDB from
+#   CURRENCY SIGN (U+00A4) to EURO SIGN (U+20AC).
+#
+#   Changes from version n03 to version n04:
+#
+#   - Change mapping of 0xBD from U+2126 to its canonical
+#     decomposition, U+03A9.
+#
+##################
+
+0x20	0x0020	# SPACE
+0x21	0x0021	# EXCLAMATION MARK
+0x22	0x0022	# QUOTATION MARK
+0x23	0x0023	# NUMBER SIGN
+0x24	0x0024	# DOLLAR SIGN
+0x25	0x0025	# PERCENT SIGN
+0x26	0x0026	# AMPERSAND
+0x27	0x0027	# APOSTROPHE
+0x28	0x0028	# LEFT PARENTHESIS
+0x29	0x0029	# RIGHT PARENTHESIS
+0x2A	0x002A	# ASTERISK
+0x2B	0x002B	# PLUS SIGN
+0x2C	0x002C	# COMMA
+0x2D	0x002D	# HYPHEN-MINUS
+0x2E	0x002E	# FULL STOP
+0x2F	0x002F	# SOLIDUS
+0x30	0x0030	# DIGIT ZERO
+0x31	0x0031	# DIGIT ONE
+0x32	0x0032	# DIGIT TWO
+0x33	0x0033	# DIGIT THREE
+0x34	0x0034	# DIGIT FOUR
+0x35	0x0035	# DIGIT FIVE
+0x36	0x0036	# DIGIT SIX
+0x37	0x0037	# DIGIT SEVEN
+0x38	0x0038	# DIGIT EIGHT
+0x39	0x0039	# DIGIT NINE
+0x3A	0x003A	# COLON
+0x3B	0x003B	# SEMICOLON
+0x3C	0x003C	# LESS-THAN SIGN
+0x3D	0x003D	# EQUALS SIGN
+0x3E	0x003E	# GREATER-THAN SIGN
+0x3F	0x003F	# QUESTION MARK
+0x40	0x0040	# COMMERCIAL AT
+0x41	0x0041	# LATIN CAPITAL LETTER A
+0x42	0x0042	# LATIN CAPITAL LETTER B
+0x43	0x0043	# LATIN CAPITAL LETTER C
+0x44	0x0044	# LATIN CAPITAL LETTER D
+0x45	0x0045	# LATIN CAPITAL LETTER E
+0x46	0x0046	# LATIN CAPITAL LETTER F
+0x47	0x0047	# LATIN CAPITAL LETTER G
+0x48	0x0048	# LATIN CAPITAL LETTER H
+0x49	0x0049	# LATIN CAPITAL LETTER I
+0x4A	0x004A	# LATIN CAPITAL LETTER J
+0x4B	0x004B	# LATIN CAPITAL LETTER K
+0x4C	0x004C	# LATIN CAPITAL LETTER L
+0x4D	0x004D	# LATIN CAPITAL LETTER M
+0x4E	0x004E	# LATIN CAPITAL LETTER N
+0x4F	0x004F	# LATIN CAPITAL LETTER O
+0x50	0x0050	# LATIN CAPITAL LETTER P
+0x51	0x0051	# LATIN CAPITAL LETTER Q
+0x52	0x0052	# LATIN CAPITAL LETTER R
+0x53	0x0053	# LATIN CAPITAL LETTER S
+0x54	0x0054	# LATIN CAPITAL LETTER T
+0x55	0x0055	# LATIN CAPITAL LETTER U
+0x56	0x0056	# LATIN CAPITAL LETTER V
+0x57	0x0057	# LATIN CAPITAL LETTER W
+0x58	0x0058	# LATIN CAPITAL LETTER X
+0x59	0x0059	# LATIN CAPITAL LETTER Y
+0x5A	0x005A	# LATIN CAPITAL LETTER Z
+0x5B	0x005B	# LEFT SQUARE BRACKET
+0x5C	0x005C	# REVERSE SOLIDUS
+0x5D	0x005D	# RIGHT SQUARE BRACKET
+0x5E	0x005E	# CIRCUMFLEX ACCENT
+0x5F	0x005F	# LOW LINE
+0x60	0x0060	# GRAVE ACCENT
+0x61	0x0061	# LATIN SMALL LETTER A
+0x62	0x0062	# LATIN SMALL LETTER B
+0x63	0x0063	# LATIN SMALL LETTER C
+0x64	0x0064	# LATIN SMALL LETTER D
+0x65	0x0065	# LATIN SMALL LETTER E
+0x66	0x0066	# LATIN SMALL LETTER F
+0x67	0x0067	# LATIN SMALL LETTER G
+0x68	0x0068	# LATIN SMALL LETTER H
+0x69	0x0069	# LATIN SMALL LETTER I
+0x6A	0x006A	# LATIN SMALL LETTER J
+0x6B	0x006B	# LATIN SMALL LETTER K
+0x6C	0x006C	# LATIN SMALL LETTER L
+0x6D	0x006D	# LATIN SMALL LETTER M
+0x6E	0x006E	# LATIN SMALL LETTER N
+0x6F	0x006F	# LATIN SMALL LETTER O
+0x70	0x0070	# LATIN SMALL LETTER P
+0x71	0x0071	# LATIN SMALL LETTER Q
+0x72	0x0072	# LATIN SMALL LETTER R
+0x73	0x0073	# LATIN SMALL LETTER S
+0x74	0x0074	# LATIN SMALL LETTER T
+0x75	0x0075	# LATIN SMALL LETTER U
+0x76	0x0076	# LATIN SMALL LETTER V
+0x77	0x0077	# LATIN SMALL LETTER W
+0x78	0x0078	# LATIN SMALL LETTER X
+0x79	0x0079	# LATIN SMALL LETTER Y
+0x7A	0x007A	# LATIN SMALL LETTER Z
+0x7B	0x007B	# LEFT CURLY BRACKET
+0x7C	0x007C	# VERTICAL LINE
+0x7D	0x007D	# RIGHT CURLY BRACKET
+0x7E	0x007E	# TILDE
+#
+0x80	0x00C4	# LATIN CAPITAL LETTER A WITH DIAERESIS
+0x81	0x00C5	# LATIN CAPITAL LETTER A WITH RING ABOVE
+0x82	0x00C7	# LATIN CAPITAL LETTER C WITH CEDILLA
+0x83	0x00C9	# LATIN CAPITAL LETTER E WITH ACUTE
+0x84	0x00D1	# LATIN CAPITAL LETTER N WITH TILDE
+0x85	0x00D6	# LATIN CAPITAL LETTER O WITH DIAERESIS
+0x86	0x00DC	# LATIN CAPITAL LETTER U WITH DIAERESIS
+0x87	0x00E1	# LATIN SMALL LETTER A WITH ACUTE
+0x88	0x00E0	# LATIN SMALL LETTER A WITH GRAVE
+0x89	0x00E2	# LATIN SMALL LETTER A WITH CIRCUMFLEX
+0x8A	0x00E4	# LATIN SMALL LETTER A WITH DIAERESIS
+0x8B	0x00E3	# LATIN SMALL LETTER A WITH TILDE
+0x8C	0x00E5	# LATIN SMALL LETTER A WITH RING ABOVE
+0x8D	0x00E7	# LATIN SMALL LETTER C WITH CEDILLA
+0x8E	0x00E9	# LATIN SMALL LETTER E WITH ACUTE
+0x8F	0x00E8	# LATIN SMALL LETTER E WITH GRAVE
+0x90	0x00EA	# LATIN SMALL LETTER E WITH CIRCUMFLEX
+0x91	0x00EB	# LATIN SMALL LETTER E WITH DIAERESIS
+0x92	0x00ED	# LATIN SMALL LETTER I WITH ACUTE
+0x93	0x00EC	# LATIN SMALL LETTER I WITH GRAVE
+0x94	0x00EE	# LATIN SMALL LETTER I WITH CIRCUMFLEX
+0x95	0x00EF	# LATIN SMALL LETTER I WITH DIAERESIS
+0x96	0x00F1	# LATIN SMALL LETTER N WITH TILDE
+0x97	0x00F3	# LATIN SMALL LETTER O WITH ACUTE
+0x98	0x00F2	# LATIN SMALL LETTER O WITH GRAVE
+0x99	0x00F4	# LATIN SMALL LETTER O WITH CIRCUMFLEX
+0x9A	0x00F6	# LATIN SMALL LETTER O WITH DIAERESIS
+0x9B	0x00F5	# LATIN SMALL LETTER O WITH TILDE
+0x9C	0x00FA	# LATIN SMALL LETTER U WITH ACUTE
+0x9D	0x00F9	# LATIN SMALL LETTER U WITH GRAVE
+0x9E	0x00FB	# LATIN SMALL LETTER U WITH CIRCUMFLEX
+0x9F	0x00FC	# LATIN SMALL LETTER U WITH DIAERESIS
+0xA0	0x2020	# DAGGER
+0xA1	0x00B0	# DEGREE SIGN
+0xA2	0x00A2	# CENT SIGN
+0xA3	0x00A3	# POUND SIGN
+0xA4	0x00A7	# SECTION SIGN
+0xA5	0x2022	# BULLET
+0xA6	0x00B6	# PILCROW SIGN
+0xA7	0x00DF	# LATIN SMALL LETTER SHARP S
+0xA8	0x00AE	# REGISTERED SIGN
+0xA9	0x00A9	# COPYRIGHT SIGN
+0xAA	0x2122	# TRADE MARK SIGN
+0xAB	0x00B4	# ACUTE ACCENT
+0xAC	0x00A8	# DIAERESIS
+0xAD	0x2260	# NOT EQUAL TO
+0xAE	0x00C6	# LATIN CAPITAL LETTER AE
+0xAF	0x00D8	# LATIN CAPITAL LETTER O WITH STROKE
+0xB0	0x221E	# INFINITY
+0xB1	0x00B1	# PLUS-MINUS SIGN
+0xB2	0x2264	# LESS-THAN OR EQUAL TO
+0xB3	0x2265	# GREATER-THAN OR EQUAL TO
+0xB4	0x00A5	# YEN SIGN
+0xB5	0x00B5	# MICRO SIGN
+0xB6	0x2202	# PARTIAL DIFFERENTIAL
+0xB7	0x2211	# N-ARY SUMMATION
+0xB8	0x220F	# N-ARY PRODUCT
+0xB9	0x03C0	# GREEK SMALL LETTER PI
+0xBA	0x222B	# INTEGRAL
+0xBB	0x00AA	# FEMININE ORDINAL INDICATOR
+0xBC	0x00BA	# MASCULINE ORDINAL INDICATOR
+0xBD	0x03A9	# GREEK CAPITAL LETTER OMEGA
+0xBE	0x00E6	# LATIN SMALL LETTER AE
+0xBF	0x00F8	# LATIN SMALL LETTER O WITH STROKE
+0xC0	0x00BF	# INVERTED QUESTION MARK
+0xC1	0x00A1	# INVERTED EXCLAMATION MARK
+0xC2	0x00AC	# NOT SIGN
+0xC3	0x221A	# SQUARE ROOT
+0xC4	0x0192	# LATIN SMALL LETTER F WITH HOOK
+0xC5	0x2248	# ALMOST EQUAL TO
+0xC6	0x2206	# INCREMENT
+0xC7	0x00AB	# LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xC8	0x00BB	# RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xC9	0x2026	# HORIZONTAL ELLIPSIS
+0xCA	0x00A0	# NO-BREAK SPACE
+0xCB	0x00C0	# LATIN CAPITAL LETTER A WITH GRAVE
+0xCC	0x00C3	# LATIN CAPITAL LETTER A WITH TILDE
+0xCD	0x00D5	# LATIN CAPITAL LETTER O WITH TILDE
+0xCE	0x0152	# LATIN CAPITAL LIGATURE OE
+0xCF	0x0153	# LATIN SMALL LIGATURE OE
+0xD0	0x2013	# EN DASH
+0xD1	0x2014	# EM DASH
+0xD2	0x201C	# LEFT DOUBLE QUOTATION MARK
+0xD3	0x201D	# RIGHT DOUBLE QUOTATION MARK
+0xD4	0x2018	# LEFT SINGLE QUOTATION MARK
+0xD5	0x2019	# RIGHT SINGLE QUOTATION MARK
+0xD6	0x00F7	# DIVISION SIGN
+0xD7	0x25CA	# LOZENGE
+0xD8	0x00FF	# LATIN SMALL LETTER Y WITH DIAERESIS
+0xD9	0x0178	# LATIN CAPITAL LETTER Y WITH DIAERESIS
+0xDA	0x2044	# FRACTION SLASH
+0xDB	0x20AC	# EURO SIGN
+0xDC	0x2039	# SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+0xDD	0x203A	# SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+0xDE	0xFB01	# LATIN SMALL LIGATURE FI
+0xDF	0xFB02	# LATIN SMALL LIGATURE FL
+0xE0	0x2021	# DOUBLE DAGGER
+0xE1	0x00B7	# MIDDLE DOT
+0xE2	0x201A	# SINGLE LOW-9 QUOTATION MARK
+0xE3	0x201E	# DOUBLE LOW-9 QUOTATION MARK
+0xE4	0x2030	# PER MILLE SIGN
+0xE5	0x00C2	# LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xE6	0x00CA	# LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xE7	0x00C1	# LATIN CAPITAL LETTER A WITH ACUTE
+0xE8	0x00CB	# LATIN CAPITAL LETTER E WITH DIAERESIS
+0xE9	0x00C8	# LATIN CAPITAL LETTER E WITH GRAVE
+0xEA	0x00CD	# LATIN CAPITAL LETTER I WITH ACUTE
+0xEB	0x00CE	# LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xEC	0x00CF	# LATIN CAPITAL LETTER I WITH DIAERESIS
+0xED	0x00CC	# LATIN CAPITAL LETTER I WITH GRAVE
+0xEE	0x00D3	# LATIN CAPITAL LETTER O WITH ACUTE
+0xEF	0x00D4	# LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xF0	0xF8FF	# Apple logo
+0xF1	0x00D2	# LATIN CAPITAL LETTER O WITH GRAVE
+0xF2	0x00DA	# LATIN CAPITAL LETTER U WITH ACUTE
+0xF3	0x00DB	# LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xF4	0x00D9	# LATIN CAPITAL LETTER U WITH GRAVE
+0xF5	0x0131	# LATIN SMALL LETTER DOTLESS I
+0xF6	0x02C6	# MODIFIER LETTER CIRCUMFLEX ACCENT
+0xF7	0x02DC	# SMALL TILDE
+0xF8	0x00AF	# MACRON
+0xF9	0x02D8	# BREVE
+0xFA	0x02D9	# DOT ABOVE
+0xFB	0x02DA	# RING ABOVE
+0xFC	0x00B8	# CEDILLA
+0xFD	0x02DD	# DOUBLE ACUTE ACCENT
+0xFE	0x02DB	# OGONEK
+0xFF	0x02C7	# CARON
diff --git a/Resources/UTF-8.txt b/Resources/UTF-8.txt
new file mode 100644
index 0000000..46431f9
--- /dev/null
+++ b/Resources/UTF-8.txt
@@ -0,0 +1,3 @@
+# UTF-8 to Unicode
+# This file is a dummy.
+# The conversion is done algorithmicly, not by a table look-up.
diff --git a/Resources/Unicode01 b/Resources/Unicode01
new file mode 100644
index 0000000..7e62eca
--- /dev/null
+++ b/Resources/Unicode01
@@ -0,0 +1,306 @@
+#
+#	Name:             ISO/IEC 8859-1:1998 to Unicode
+#	Unicode version:  3.0
+#	Table version:    1.0
+#	Table format:     Format A
+#	Date:             1999 July 27
+#	Authors:          Ken Whistler <kenw@sybase.com>
+#
+#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
+#
+#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+#	No claims are made as to fitness for any particular purpose.  No
+#	warranties of any kind are expressed or implied.  The recipient
+#	agrees to determine applicability of information provided.  If this
+#	file has been provided on optical media by Unicode, Inc., the sole
+#	remedy for any claim will be exchange of defective media within 90
+#	days of receipt.
+#
+#	Unicode, Inc. hereby grants the right to freely use the information
+#	supplied in this file in the creation of products supporting the
+#	Unicode Standard, and to make copies of this file in any form for
+#	internal or external distribution as long as this notice remains
+#	attached.
+#
+#	General notes:
+#
+#	This table contains the data the Unicode Consortium has on how
+#       ISO/IEC 8859-1:1998 characters map into Unicode.
+#
+#	Format:  Three tab-separated columns
+#		 Column #1 is the ISO/IEC 8859-1 code (in hex as 0xXX)
+#		 Column #2 is the Unicode (in hex as 0xXXXX)
+#		 Column #3 the Unicode name (follows a comment sign, '#')
+#
+#	The entries are in ISO/IEC 8859-1 order.
+#
+#	Version history
+#	1.0 version updates 0.1 version by adding mappings for all
+#	control characters.
+#
+#	Updated versions of this file may be found in:
+#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
+#
+#	Any comments or problems, contact <errata@unicode.org>
+#	Please note that <errata@unicode.org> is an archival address;
+#	notices will be checked, but do not expect an immediate response.
+#
+#RISC OS
+# This file was changed to match RISC OS specific characters (0x80 - 0x9f)
+#RISC OS
+0x00	0x0000	#	NULL
+0x01	0x0001	#	START OF HEADING
+0x02	0x0002	#	START OF TEXT
+0x03	0x0003	#	END OF TEXT
+0x04	0x0004	#	END OF TRANSMISSION
+0x05	0x0005	#	ENQUIRY
+0x06	0x0006	#	ACKNOWLEDGE
+0x07	0x0007	#	BELL
+0x08	0x0008	#	BACKSPACE
+0x09	0x0009	#	HORIZONTAL TABULATION
+0x0A	0x000A	#	LINE FEED
+0x0B	0x000B	#	VERTICAL TABULATION
+0x0C	0x000C	#	FORM FEED
+0x0D	0x000D	#	CARRIAGE RETURN
+0x0E	0x000E	#	SHIFT OUT
+0x0F	0x000F	#	SHIFT IN
+0x10	0x0010	#	DATA LINK ESCAPE
+0x11	0x0011	#	DEVICE CONTROL ONE
+0x12	0x0012	#	DEVICE CONTROL TWO
+0x13	0x0013	#	DEVICE CONTROL THREE
+0x14	0x0014	#	DEVICE CONTROL FOUR
+0x15	0x0015	#	NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#	SYNCHRONOUS IDLE
+0x17	0x0017	#	END OF TRANSMISSION BLOCK
+0x18	0x0018	#	CANCEL
+0x19	0x0019	#	END OF MEDIUM
+0x1A	0x001A	#	SUBSTITUTE
+0x1B	0x001B	#	ESCAPE
+0x1C	0x001C	#	FILE SEPARATOR
+0x1D	0x001D	#	GROUP SEPARATOR
+0x1E	0x001E	#	RECORD SEPARATOR
+0x1F	0x001F	#	UNIT SEPARATOR
+0x20	0x0020	#	SPACE
+0x21	0x0021	#	EXCLAMATION MARK
+0x22	0x0022	#	QUOTATION MARK
+0x23	0x0023	#	NUMBER SIGN
+0x24	0x0024	#	DOLLAR SIGN
+0x25	0x0025	#	PERCENT SIGN
+0x26	0x0026	#	AMPERSAND
+0x27	0x0027	#	APOSTROPHE
+0x28	0x0028	#	LEFT PARENTHESIS
+0x29	0x0029	#	RIGHT PARENTHESIS
+0x2A	0x002A	#	ASTERISK
+0x2B	0x002B	#	PLUS SIGN
+0x2C	0x002C	#	COMMA
+0x2D	0x002D	#	HYPHEN-MINUS
+0x2E	0x002E	#	FULL STOP
+0x2F	0x002F	#	SOLIDUS
+0x30	0x0030	#	DIGIT ZERO
+0x31	0x0031	#	DIGIT ONE
+0x32	0x0032	#	DIGIT TWO
+0x33	0x0033	#	DIGIT THREE
+0x34	0x0034	#	DIGIT FOUR
+0x35	0x0035	#	DIGIT FIVE
+0x36	0x0036	#	DIGIT SIX
+0x37	0x0037	#	DIGIT SEVEN
+0x38	0x0038	#	DIGIT EIGHT
+0x39	0x0039	#	DIGIT NINE
+0x3A	0x003A	#	COLON
+0x3B	0x003B	#	SEMICOLON
+0x3C	0x003C	#	LESS-THAN SIGN
+0x3D	0x003D	#	EQUALS SIGN
+0x3E	0x003E	#	GREATER-THAN SIGN
+0x3F	0x003F	#	QUESTION MARK
+0x40	0x0040	#	COMMERCIAL AT
+0x41	0x0041	#	LATIN CAPITAL LETTER A
+0x42	0x0042	#	LATIN CAPITAL LETTER B
+0x43	0x0043	#	LATIN CAPITAL LETTER C
+0x44	0x0044	#	LATIN CAPITAL LETTER D
+0x45	0x0045	#	LATIN CAPITAL LETTER E
+0x46	0x0046	#	LATIN CAPITAL LETTER F
+0x47	0x0047	#	LATIN CAPITAL LETTER G
+0x48	0x0048	#	LATIN CAPITAL LETTER H
+0x49	0x0049	#	LATIN CAPITAL LETTER I
+0x4A	0x004A	#	LATIN CAPITAL LETTER J
+0x4B	0x004B	#	LATIN CAPITAL LETTER K
+0x4C	0x004C	#	LATIN CAPITAL LETTER L
+0x4D	0x004D	#	LATIN CAPITAL LETTER M
+0x4E	0x004E	#	LATIN CAPITAL LETTER N
+0x4F	0x004F	#	LATIN CAPITAL LETTER O
+0x50	0x0050	#	LATIN CAPITAL LETTER P
+0x51	0x0051	#	LATIN CAPITAL LETTER Q
+0x52	0x0052	#	LATIN CAPITAL LETTER R
+0x53	0x0053	#	LATIN CAPITAL LETTER S
+0x54	0x0054	#	LATIN CAPITAL LETTER T
+0x55	0x0055	#	LATIN CAPITAL LETTER U
+0x56	0x0056	#	LATIN CAPITAL LETTER V
+0x57	0x0057	#	LATIN CAPITAL LETTER W
+0x58	0x0058	#	LATIN CAPITAL LETTER X
+0x59	0x0059	#	LATIN CAPITAL LETTER Y
+0x5A	0x005A	#	LATIN CAPITAL LETTER Z
+0x5B	0x005B	#	LEFT SQUARE BRACKET
+0x5C	0x005C	#	REVERSE SOLIDUS
+0x5D	0x005D	#	RIGHT SQUARE BRACKET
+0x5E	0x005E	#	CIRCUMFLEX ACCENT
+0x5F	0x005F	#	LOW LINE
+0x60	0x0060	#	GRAVE ACCENT
+0x61	0x0061	#	LATIN SMALL LETTER A
+0x62	0x0062	#	LATIN SMALL LETTER B
+0x63	0x0063	#	LATIN SMALL LETTER C
+0x64	0x0064	#	LATIN SMALL LETTER D
+0x65	0x0065	#	LATIN SMALL LETTER E
+0x66	0x0066	#	LATIN SMALL LETTER F
+0x67	0x0067	#	LATIN SMALL LETTER G
+0x68	0x0068	#	LATIN SMALL LETTER H
+0x69	0x0069	#	LATIN SMALL LETTER I
+0x6A	0x006A	#	LATIN SMALL LETTER J
+0x6B	0x006B	#	LATIN SMALL LETTER K
+0x6C	0x006C	#	LATIN SMALL LETTER L
+0x6D	0x006D	#	LATIN SMALL LETTER M
+0x6E	0x006E	#	LATIN SMALL LETTER N
+0x6F	0x006F	#	LATIN SMALL LETTER O
+0x70	0x0070	#	LATIN SMALL LETTER P
+0x71	0x0071	#	LATIN SMALL LETTER Q
+0x72	0x0072	#	LATIN SMALL LETTER R
+0x73	0x0073	#	LATIN SMALL LETTER S
+0x74	0x0074	#	LATIN SMALL LETTER T
+0x75	0x0075	#	LATIN SMALL LETTER U
+0x76	0x0076	#	LATIN SMALL LETTER V
+0x77	0x0077	#	LATIN SMALL LETTER W
+0x78	0x0078	#	LATIN SMALL LETTER X
+0x79	0x0079	#	LATIN SMALL LETTER Y
+0x7A	0x007A	#	LATIN SMALL LETTER Z
+0x7B	0x007B	#	LEFT CURLY BRACKET
+0x7C	0x007C	#	VERTICAL LINE
+0x7D	0x007D	#	RIGHT CURLY BRACKET
+0x7E	0x007E	#	TILDE
+0x7F	0x007F	#	DELETE
+0x80	0x0080	#	<control>
+0x81	0x0174	#	CAPITAL W CIRCUMFLEX ACCENT
+0x82	0x0175	#	SMALL W CIRCUMFLEX ACCENT
+0x83	0x0083	#	<control>
+0x84	0x0084	#	<control>
+0x85	0x0176	#	CAPITAL Y CIRCUMFLEX ACCENT
+0x86	0x0177	#	SMALL Y CIRCUMFLEX ACCENT
+0x87	0x0087	#	<control>
+0x88	0x0088	#	<control>
+0x89	0x0089	#	<control>
+0x8A	0x008A	#	<control>
+0x8B	0x008B	#	<control>
+0x8C	0x2026	#	ELLIPSIS
+0x8D	0x2122	#	TRADEMARK
+0x8E	0x2030	#	PER MILLE SIGN
+0x8F	0x2022	#	BULLET
+0x90	0x2018	#	LEFT SINGLE QUOTE
+0x91	0x2019	#	RIGHT SINGLE QUOTE
+0x92	0x2039	#	LEFT SINGLE QUOTATION MARK
+0x93	0x203A	#	RIGHT SINGLE QUOTATION MARK
+0x94	0x201C	#	OPENING DOUBLE QUOTE
+0x95	0x201D	#	CLOSING DOUBLE QUOTE
+0x96	0x201E	#	LOW DOUBLE QUOTE
+0x97	0x2013	#	EN DASH
+0x98	0x2014	#	EM_DASH
+0x99	0x2011	#	NON BREAKING HYPHEN
+0x9A	0x0152	#	LATIN CAPITAL LIGATURE OE
+0x9B	0x0153	#	LATIN SMALL LIGATURE OE
+0x9C	0x2020	#	DAGGER
+0x9D	0x2021	#	DOUBLE DAGGER
+0x9E	0xFB01	#	Fi
+0x9F	0xFB02	#	Fl
+0xA0	0x00A0	#	NO-BREAK SPACE
+0xA1	0x00A1	#	INVERTED EXCLAMATION MARK
+0xA2	0x00A2	#	CENT SIGN
+0xA3	0x00A3	#	POUND SIGN
+0xA4	0x00A4	#	CURRENCY SIGN
+0xA5	0x00A5	#	YEN SIGN
+0xA6	0x00A6	#	BROKEN BAR
+0xA7	0x00A7	#	SECTION SIGN
+0xA8	0x00A8	#	DIAERESIS
+0xA9	0x00A9	#	COPYRIGHT SIGN
+0xAA	0x00AA	#	FEMININE ORDINAL INDICATOR
+0xAB	0x00AB	#	LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC	0x00AC	#	NOT SIGN
+0xAD	0x00AD	#	SOFT HYPHEN
+0xAE	0x00AE	#	REGISTERED SIGN
+0xAF	0x00AF	#	MACRON
+0xB0	0x00B0	#	DEGREE SIGN
+0xB1	0x00B1	#	PLUS-MINUS SIGN
+0xB2	0x00B2	#	SUPERSCRIPT TWO
+0xB3	0x00B3	#	SUPERSCRIPT THREE
+0xB4	0x00B4	#	ACUTE ACCENT
+0xB5	0x00B5	#	MICRO SIGN
+0xB6	0x00B6	#	PILCROW SIGN
+0xB7	0x00B7	#	MIDDLE DOT
+0xB8	0x00B8	#	CEDILLA
+0xB9	0x00B9	#	SUPERSCRIPT ONE
+0xBA	0x00BA	#	MASCULINE ORDINAL INDICATOR
+0xBB	0x00BB	#	RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC	0x00BC	#	VULGAR FRACTION ONE QUARTER
+0xBD	0x00BD	#	VULGAR FRACTION ONE HALF
+0xBE	0x00BE	#	VULGAR FRACTION THREE QUARTERS
+0xBF	0x00BF	#	INVERTED QUESTION MARK
+0xC0	0x00C0	#	LATIN CAPITAL LETTER A WITH GRAVE
+0xC1	0x00C1	#	LATIN CAPITAL LETTER A WITH ACUTE
+0xC2	0x00C2	#	LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3	0x00C3	#	LATIN CAPITAL LETTER A WITH TILDE
+0xC4	0x00C4	#	LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5	0x00C5	#	LATIN CAPITAL LETTER A WITH RING ABOVE
+0xC6	0x00C6	#	LATIN CAPITAL LETTER AE
+0xC7	0x00C7	#	LATIN CAPITAL LETTER C WITH CEDILLA
+0xC8	0x00C8	#	LATIN CAPITAL LETTER E WITH GRAVE
+0xC9	0x00C9	#	LATIN CAPITAL LETTER E WITH ACUTE
+0xCA	0x00CA	#	LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xCB	0x00CB	#	LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC	0x00CC	#	LATIN CAPITAL LETTER I WITH GRAVE
+0xCD	0x00CD	#	LATIN CAPITAL LETTER I WITH ACUTE
+0xCE	0x00CE	#	LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF	0x00CF	#	LATIN CAPITAL LETTER I WITH DIAERESIS
+0xD0	0x00D0	#	LATIN CAPITAL LETTER ETH (Icelandic)
+0xD1	0x00D1	#	LATIN CAPITAL LETTER N WITH TILDE
+0xD2	0x00D2	#	LATIN CAPITAL LETTER O WITH GRAVE
+0xD3	0x00D3	#	LATIN CAPITAL LETTER O WITH ACUTE
+0xD4	0x00D4	#	LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5	0x00D5	#	LATIN CAPITAL LETTER O WITH TILDE
+0xD6	0x00D6	#	LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7	0x00D7	#	MULTIPLICATION SIGN
+0xD8	0x00D8	#	LATIN CAPITAL LETTER O WITH STROKE
+0xD9	0x00D9	#	LATIN CAPITAL LETTER U WITH GRAVE
+0xDA	0x00DA	#	LATIN CAPITAL LETTER U WITH ACUTE
+0xDB	0x00DB	#	LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xDC	0x00DC	#	LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD	0x00DD	#	LATIN CAPITAL LETTER Y WITH ACUTE
+0xDE	0x00DE	#	LATIN CAPITAL LETTER THORN (Icelandic)
+0xDF	0x00DF	#	LATIN SMALL LETTER SHARP S (German)
+0xE0	0x00E0	#	LATIN SMALL LETTER A WITH GRAVE
+0xE1	0x00E1	#	LATIN SMALL LETTER A WITH ACUTE
+0xE2	0x00E2	#	LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3	0x00E3	#	LATIN SMALL LETTER A WITH TILDE
+0xE4	0x00E4	#	LATIN SMALL LETTER A WITH DIAERESIS
+0xE5	0x00E5	#	LATIN SMALL LETTER A WITH RING ABOVE
+0xE6	0x00E6	#	LATIN SMALL LETTER AE
+0xE7	0x00E7	#	LATIN SMALL LETTER C WITH CEDILLA
+0xE8	0x00E8	#	LATIN SMALL LETTER E WITH GRAVE
+0xE9	0x00E9	#	LATIN SMALL LETTER E WITH ACUTE
+0xEA	0x00EA	#	LATIN SMALL LETTER E WITH CIRCUMFLEX
+0xEB	0x00EB	#	LATIN SMALL LETTER E WITH DIAERESIS
+0xEC	0x00EC	#	LATIN SMALL LETTER I WITH GRAVE
+0xED	0x00ED	#	LATIN SMALL LETTER I WITH ACUTE
+0xEE	0x00EE	#	LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF	0x00EF	#	LATIN SMALL LETTER I WITH DIAERESIS
+0xF0	0x00F0	#	LATIN SMALL LETTER ETH (Icelandic)
+0xF1	0x00F1	#	LATIN SMALL LETTER N WITH TILDE
+0xF2	0x00F2	#	LATIN SMALL LETTER O WITH GRAVE
+0xF3	0x00F3	#	LATIN SMALL LETTER O WITH ACUTE
+0xF4	0x00F4	#	LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5	0x00F5	#	LATIN SMALL LETTER O WITH TILDE
+0xF6	0x00F6	#	LATIN SMALL LETTER O WITH DIAERESIS
+0xF7	0x00F7	#	DIVISION SIGN
+0xF8	0x00F8	#	LATIN SMALL LETTER O WITH STROKE
+0xF9	0x00F9	#	LATIN SMALL LETTER U WITH GRAVE
+0xFA	0x00FA	#	LATIN SMALL LETTER U WITH ACUTE
+0xFB	0x00FB	#	LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xFC	0x00FC	#	LATIN SMALL LETTER U WITH DIAERESIS
+0xFD	0x00FD	#	LATIN SMALL LETTER Y WITH ACUTE
+0xFE	0x00FE	#	LATIN SMALL LETTER THORN (Icelandic)
+0xFF	0x00FF	#	LATIN SMALL LETTER Y WITH DIAERESIS
diff --git a/Resources/Unicode15 b/Resources/Unicode15
new file mode 100644
index 0000000..5051a3d
--- /dev/null
+++ b/Resources/Unicode15
@@ -0,0 +1,305 @@
+#
+#	Name:             ISO/IEC 8859-15:1999 to Unicode
+#	Unicode version:  3.0
+#	Table version:    1.0
+#	Table format:     Format A
+#	Date:             1999 July 27
+#	Authors:          Markus Kuhn <mkuhn@acm.org>
+#			  Ken Whistler <kenw@sybase.com>
+#
+#	Copyright (c) 1998 - 1999 Unicode, Inc.  All Rights reserved.
+#
+#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+#	No claims are made as to fitness for any particular purpose.  No
+#	warranties of any kind are expressed or implied.  The recipient
+#	agrees to determine applicability of information provided.  If this
+#	file has been provided on optical media by Unicode, Inc., the sole
+#	remedy for any claim will be exchange of defective media within 90
+#	days of receipt.
+#
+#	Unicode, Inc. hereby grants the right to freely use the information
+#	supplied in this file in the creation of products supporting the
+#	Unicode Standard, and to make copies of this file in any form for
+#	internal or external distribution as long as this notice remains
+#	attached.
+#
+#	General notes:
+#
+#	This table contains the data the Unicode Consortium has on how
+#       ISO/IEC 8859-15:1999 characters map into Unicode.
+#
+#	Format:  Three tab-separated columns
+#		 Column #1 is the ISO/IEC 8859-15 code (in hex as 0xXX)
+#		 Column #2 is the Unicode (in hex as 0xXXXX)
+#		 Column #3 the Unicode name (follows a comment sign, '#')
+#
+#	The entries are in ISO/IEC 8859-15 order.
+#
+#	Version history
+#
+#	Updated versions of this file may be found in:
+#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
+#
+#	Any comments or problems, contact <errata@unicode.org>
+#	Please note that <errata@unicode.org> is an archival address;
+#	notices will be checked, but do not expect an immediate response.
+#
+#RISC OS
+# This file was changed to match RISC OS specific characters (0x80 - 0x9f)
+#RISC OS
+0x00	0x0000	#	NULL
+0x01	0x0001	#	START OF HEADING
+0x02	0x0002	#	START OF TEXT
+0x03	0x0003	#	END OF TEXT
+0x04	0x0004	#	END OF TRANSMISSION
+0x05	0x0005	#	ENQUIRY
+0x06	0x0006	#	ACKNOWLEDGE
+0x07	0x0007	#	BELL
+0x08	0x0008	#	BACKSPACE
+0x09	0x0009	#	HORIZONTAL TABULATION
+0x0A	0x000A	#	LINE FEED
+0x0B	0x000B	#	VERTICAL TABULATION
+0x0C	0x000C	#	FORM FEED
+0x0D	0x000D	#	CARRIAGE RETURN
+0x0E	0x000E	#	SHIFT OUT
+0x0F	0x000F	#	SHIFT IN
+0x10	0x0010	#	DATA LINK ESCAPE
+0x11	0x0011	#	DEVICE CONTROL ONE
+0x12	0x0012	#	DEVICE CONTROL TWO
+0x13	0x0013	#	DEVICE CONTROL THREE
+0x14	0x0014	#	DEVICE CONTROL FOUR
+0x15	0x0015	#	NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#	SYNCHRONOUS IDLE
+0x17	0x0017	#	END OF TRANSMISSION BLOCK
+0x18	0x0018	#	CANCEL
+0x19	0x0019	#	END OF MEDIUM
+0x1A	0x001A	#	SUBSTITUTE
+0x1B	0x001B	#	ESCAPE
+0x1C	0x001C	#	FILE SEPARATOR
+0x1D	0x001D	#	GROUP SEPARATOR
+0x1E	0x001E	#	RECORD SEPARATOR
+0x1F	0x001F	#	UNIT SEPARATOR
+0x20	0x0020	#	SPACE
+0x21	0x0021	#	EXCLAMATION MARK
+0x22	0x0022	#	QUOTATION MARK
+0x23	0x0023	#	NUMBER SIGN
+0x24	0x0024	#	DOLLAR SIGN
+0x25	0x0025	#	PERCENT SIGN
+0x26	0x0026	#	AMPERSAND
+0x27	0x0027	#	APOSTROPHE
+0x28	0x0028	#	LEFT PARENTHESIS
+0x29	0x0029	#	RIGHT PARENTHESIS
+0x2A	0x002A	#	ASTERISK
+0x2B	0x002B	#	PLUS SIGN
+0x2C	0x002C	#	COMMA
+0x2D	0x002D	#	HYPHEN-MINUS
+0x2E	0x002E	#	FULL STOP
+0x2F	0x002F	#	SOLIDUS
+0x30	0x0030	#	DIGIT ZERO
+0x31	0x0031	#	DIGIT ONE
+0x32	0x0032	#	DIGIT TWO
+0x33	0x0033	#	DIGIT THREE
+0x34	0x0034	#	DIGIT FOUR
+0x35	0x0035	#	DIGIT FIVE
+0x36	0x0036	#	DIGIT SIX
+0x37	0x0037	#	DIGIT SEVEN
+0x38	0x0038	#	DIGIT EIGHT
+0x39	0x0039	#	DIGIT NINE
+0x3A	0x003A	#	COLON
+0x3B	0x003B	#	SEMICOLON
+0x3C	0x003C	#	LESS-THAN SIGN
+0x3D	0x003D	#	EQUALS SIGN
+0x3E	0x003E	#	GREATER-THAN SIGN
+0x3F	0x003F	#	QUESTION MARK
+0x40	0x0040	#	COMMERCIAL AT
+0x41	0x0041	#	LATIN CAPITAL LETTER A
+0x42	0x0042	#	LATIN CAPITAL LETTER B
+0x43	0x0043	#	LATIN CAPITAL LETTER C
+0x44	0x0044	#	LATIN CAPITAL LETTER D
+0x45	0x0045	#	LATIN CAPITAL LETTER E
+0x46	0x0046	#	LATIN CAPITAL LETTER F
+0x47	0x0047	#	LATIN CAPITAL LETTER G
+0x48	0x0048	#	LATIN CAPITAL LETTER H
+0x49	0x0049	#	LATIN CAPITAL LETTER I
+0x4A	0x004A	#	LATIN CAPITAL LETTER J
+0x4B	0x004B	#	LATIN CAPITAL LETTER K
+0x4C	0x004C	#	LATIN CAPITAL LETTER L
+0x4D	0x004D	#	LATIN CAPITAL LETTER M
+0x4E	0x004E	#	LATIN CAPITAL LETTER N
+0x4F	0x004F	#	LATIN CAPITAL LETTER O
+0x50	0x0050	#	LATIN CAPITAL LETTER P
+0x51	0x0051	#	LATIN CAPITAL LETTER Q
+0x52	0x0052	#	LATIN CAPITAL LETTER R
+0x53	0x0053	#	LATIN CAPITAL LETTER S
+0x54	0x0054	#	LATIN CAPITAL LETTER T
+0x55	0x0055	#	LATIN CAPITAL LETTER U
+0x56	0x0056	#	LATIN CAPITAL LETTER V
+0x57	0x0057	#	LATIN CAPITAL LETTER W
+0x58	0x0058	#	LATIN CAPITAL LETTER X
+0x59	0x0059	#	LATIN CAPITAL LETTER Y
+0x5A	0x005A	#	LATIN CAPITAL LETTER Z
+0x5B	0x005B	#	LEFT SQUARE BRACKET
+0x5C	0x005C	#	REVERSE SOLIDUS
+0x5D	0x005D	#	RIGHT SQUARE BRACKET
+0x5E	0x005E	#	CIRCUMFLEX ACCENT
+0x5F	0x005F	#	LOW LINE
+0x60	0x0060	#	GRAVE ACCENT
+0x61	0x0061	#	LATIN SMALL LETTER A
+0x62	0x0062	#	LATIN SMALL LETTER B
+0x63	0x0063	#	LATIN SMALL LETTER C
+0x64	0x0064	#	LATIN SMALL LETTER D
+0x65	0x0065	#	LATIN SMALL LETTER E
+0x66	0x0066	#	LATIN SMALL LETTER F
+0x67	0x0067	#	LATIN SMALL LETTER G
+0x68	0x0068	#	LATIN SMALL LETTER H
+0x69	0x0069	#	LATIN SMALL LETTER I
+0x6A	0x006A	#	LATIN SMALL LETTER J
+0x6B	0x006B	#	LATIN SMALL LETTER K
+0x6C	0x006C	#	LATIN SMALL LETTER L
+0x6D	0x006D	#	LATIN SMALL LETTER M
+0x6E	0x006E	#	LATIN SMALL LETTER N
+0x6F	0x006F	#	LATIN SMALL LETTER O
+0x70	0x0070	#	LATIN SMALL LETTER P
+0x71	0x0071	#	LATIN SMALL LETTER Q
+0x72	0x0072	#	LATIN SMALL LETTER R
+0x73	0x0073	#	LATIN SMALL LETTER S
+0x74	0x0074	#	LATIN SMALL LETTER T
+0x75	0x0075	#	LATIN SMALL LETTER U
+0x76	0x0076	#	LATIN SMALL LETTER V
+0x77	0x0077	#	LATIN SMALL LETTER W
+0x78	0x0078	#	LATIN SMALL LETTER X
+0x79	0x0079	#	LATIN SMALL LETTER Y
+0x7A	0x007A	#	LATIN SMALL LETTER Z
+0x7B	0x007B	#	LEFT CURLY BRACKET
+0x7C	0x007C	#	VERTICAL LINE
+0x7D	0x007D	#	RIGHT CURLY BRACKET
+0x7E	0x007E	#	TILDE
+0x7F	0x007F	#	DELETE
+0x80	0x0080	#	<control>
+0x81	0x0174	#	CAPITAL W CIRCUMFLEX ACCENT
+0x82	0x0175	#	SMALL W CIRCUMFLEX ACCENT
+0x83	0x0083	#	<control>
+0x84	0x0084	#	<control>
+0x85	0x0176	#	CAPITAL Y CIRCUMFLEX ACCENT
+0x86	0x0177	#	SMALL Y CIRCUMFLEX ACCENT
+0x87	0x0087	#	<control>
+0x88	0x0088	#	<control>
+0x89	0x0089	#	<control>
+0x8A	0x008A	#	<control>
+0x8B	0x008B	#	<control>
+0x8C	0x2026	#	ELLIPSIS
+0x8D	0x2122	#	TRADEMARK
+0x8E	0x2030	#	PER MILLE SIGN
+0x8F	0x2022	#	BULLET
+0x90	0x2018	#	LEFT SINGLE QUOTE
+0x91	0x2019	#	RIGHT SINGLE QUOTE
+0x92	0x2039	#	LEFT SINGLE QUOTATION MARK
+0x93	0x203A	#	RIGHT SINGLE QUOTATION MARK
+0x94	0x201C	#	OPENING DOUBLE QUOTE
+0x95	0x201D	#	CLOSING DOUBLE QUOTE
+0x96	0x201E	#	LOW DOUBLE QUOTE
+0x97	0x2013	#	EN DASH
+0x98	0x2014	#	EM_DASH
+0x99	0x2011	#	NON BREAKING HYPHEN
+0x9A	0x009A	#	<control>
+0x9B	0x009B	#	<control>
+0x9C	0x2020	#	DAGGER
+0x9D	0x2021	#	DOUBLE DAGGER
+0x9E	0xFB01	#	Fi
+0x9F	0xFB02	#	Fl
+0xA0	0x00A0	#	NO-BREAK SPACE
+0xA1	0x00A1	#	INVERTED EXCLAMATION MARK
+0xA2	0x00A2	#	CENT SIGN
+0xA3	0x00A3	#	POUND SIGN
+0xA4	0x20AC	#	EURO SIGN
+0xA5	0x00A5	#	YEN SIGN
+0xA6	0x0160	#	LATIN CAPITAL LETTER S WITH CARON
+0xA7	0x00A7	#	SECTION SIGN
+0xA8	0x0161	#	LATIN SMALL LETTER S WITH CARON
+0xA9	0x00A9	#	COPYRIGHT SIGN
+0xAA	0x00AA	#	FEMININE ORDINAL INDICATOR
+0xAB	0x00AB	#	LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC	0x00AC	#	NOT SIGN
+0xAD	0x00AD	#	SOFT HYPHEN
+0xAE	0x00AE	#	REGISTERED SIGN
+0xAF	0x00AF	#	MACRON
+0xB0	0x00B0	#	DEGREE SIGN
+0xB1	0x00B1	#	PLUS-MINUS SIGN
+0xB2	0x00B2	#	SUPERSCRIPT TWO
+0xB3	0x00B3	#	SUPERSCRIPT THREE
+0xB4	0x017D	#	LATIN CAPITAL LETTER Z WITH CARON
+0xB5	0x00B5	#	MICRO SIGN
+0xB6	0x00B6	#	PILCROW SIGN
+0xB7	0x00B7	#	MIDDLE DOT
+0xB8	0x017E	#	LATIN SMALL LETTER Z WITH CARON
+0xB9	0x00B9	#	SUPERSCRIPT ONE
+0xBA	0x00BA	#	MASCULINE ORDINAL INDICATOR
+0xBB	0x00BB	#	RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC	0x0152	#	LATIN CAPITAL LIGATURE OE
+0xBD	0x0153	#	LATIN SMALL LIGATURE OE
+0xBE	0x0178	#	LATIN CAPITAL LETTER Y WITH DIAERESIS
+0xBF	0x00BF	#	INVERTED QUESTION MARK
+0xC0	0x00C0	#	LATIN CAPITAL LETTER A WITH GRAVE
+0xC1	0x00C1	#	LATIN CAPITAL LETTER A WITH ACUTE
+0xC2	0x00C2	#	LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3	0x00C3	#	LATIN CAPITAL LETTER A WITH TILDE
+0xC4	0x00C4	#	LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5	0x00C5	#	LATIN CAPITAL LETTER A WITH RING ABOVE
+0xC6	0x00C6	#	LATIN CAPITAL LETTER AE
+0xC7	0x00C7	#	LATIN CAPITAL LETTER C WITH CEDILLA
+0xC8	0x00C8	#	LATIN CAPITAL LETTER E WITH GRAVE
+0xC9	0x00C9	#	LATIN CAPITAL LETTER E WITH ACUTE
+0xCA	0x00CA	#	LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xCB	0x00CB	#	LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC	0x00CC	#	LATIN CAPITAL LETTER I WITH GRAVE
+0xCD	0x00CD	#	LATIN CAPITAL LETTER I WITH ACUTE
+0xCE	0x00CE	#	LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF	0x00CF	#	LATIN CAPITAL LETTER I WITH DIAERESIS
+0xD0	0x00D0	#	LATIN CAPITAL LETTER ETH
+0xD1	0x00D1	#	LATIN CAPITAL LETTER N WITH TILDE
+0xD2	0x00D2	#	LATIN CAPITAL LETTER O WITH GRAVE
+0xD3	0x00D3	#	LATIN CAPITAL LETTER O WITH ACUTE
+0xD4	0x00D4	#	LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5	0x00D5	#	LATIN CAPITAL LETTER O WITH TILDE
+0xD6	0x00D6	#	LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7	0x00D7	#	MULTIPLICATION SIGN
+0xD8	0x00D8	#	LATIN CAPITAL LETTER O WITH STROKE
+0xD9	0x00D9	#	LATIN CAPITAL LETTER U WITH GRAVE
+0xDA	0x00DA	#	LATIN CAPITAL LETTER U WITH ACUTE
+0xDB	0x00DB	#	LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xDC	0x00DC	#	LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD	0x00DD	#	LATIN CAPITAL LETTER Y WITH ACUTE
+0xDE	0x00DE	#	LATIN CAPITAL LETTER THORN
+0xDF	0x00DF	#	LATIN SMALL LETTER SHARP S
+0xE0	0x00E0	#	LATIN SMALL LETTER A WITH GRAVE
+0xE1	0x00E1	#	LATIN SMALL LETTER A WITH ACUTE
+0xE2	0x00E2	#	LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3	0x00E3	#	LATIN SMALL LETTER A WITH TILDE
+0xE4	0x00E4	#	LATIN SMALL LETTER A WITH DIAERESIS
+0xE5	0x00E5	#	LATIN SMALL LETTER A WITH RING ABOVE
+0xE6	0x00E6	#	LATIN SMALL LETTER AE
+0xE7	0x00E7	#	LATIN SMALL LETTER C WITH CEDILLA
+0xE8	0x00E8	#	LATIN SMALL LETTER E WITH GRAVE
+0xE9	0x00E9	#	LATIN SMALL LETTER E WITH ACUTE
+0xEA	0x00EA	#	LATIN SMALL LETTER E WITH CIRCUMFLEX
+0xEB	0x00EB	#	LATIN SMALL LETTER E WITH DIAERESIS
+0xEC	0x00EC	#	LATIN SMALL LETTER I WITH GRAVE
+0xED	0x00ED	#	LATIN SMALL LETTER I WITH ACUTE
+0xEE	0x00EE	#	LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF	0x00EF	#	LATIN SMALL LETTER I WITH DIAERESIS
+0xF0	0x00F0	#	LATIN SMALL LETTER ETH
+0xF1	0x00F1	#	LATIN SMALL LETTER N WITH TILDE
+0xF2	0x00F2	#	LATIN SMALL LETTER O WITH GRAVE
+0xF3	0x00F3	#	LATIN SMALL LETTER O WITH ACUTE
+0xF4	0x00F4	#	LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5	0x00F5	#	LATIN SMALL LETTER O WITH TILDE
+0xF6	0x00F6	#	LATIN SMALL LETTER O WITH DIAERESIS
+0xF7	0x00F7	#	DIVISION SIGN
+0xF8	0x00F8	#	LATIN SMALL LETTER O WITH STROKE
+0xF9	0x00F9	#	LATIN SMALL LETTER U WITH GRAVE
+0xFA	0x00FA	#	LATIN SMALL LETTER U WITH ACUTE
+0xFB	0x00FB	#	LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xFC	0x00FC	#	LATIN SMALL LETTER U WITH DIAERESIS
+0xFD	0x00FD	#	LATIN SMALL LETTER Y WITH ACUTE
+0xFE	0x00FE	#	LATIN SMALL LETTER THORN
+0xFF	0x00FF	#	LATIN SMALL LETTER Y WITH DIAERESIS
diff --git a/Resources/cp1250.txt b/Resources/cp1250.txt
new file mode 100644
index 0000000..aa27ca3
--- /dev/null
+++ b/Resources/cp1250.txt
@@ -0,0 +1,274 @@
+#
+#    Name:     cp1250 to Unicode table
+#    Unicode version: 2.0
+#    Table version: 2.01
+#    Table format:  Format A
+#    Date:          04/15/98
+#
+#    Contact:       cpxlate@microsoft.com
+#
+#    General notes: none
+#
+#    Format: Three tab-separated columns
+#        Column #1 is the cp1250 code (in hex)
+#        Column #2 is the Unicode (in hex as 0xXXXX)
+#        Column #3 is the Unicode name (follows a comment sign, '#')
+#
+#    The entries are in cp1250 order
+#
+0x00	0x0000	#NULL
+0x01	0x0001	#START OF HEADING
+0x02	0x0002	#START OF TEXT
+0x03	0x0003	#END OF TEXT
+0x04	0x0004	#END OF TRANSMISSION
+0x05	0x0005	#ENQUIRY
+0x06	0x0006	#ACKNOWLEDGE
+0x07	0x0007	#BELL
+0x08	0x0008	#BACKSPACE
+0x09	0x0009	#HORIZONTAL TABULATION
+0x0A	0x000A	#LINE FEED
+0x0B	0x000B	#VERTICAL TABULATION
+0x0C	0x000C	#FORM FEED
+0x0D	0x000D	#CARRIAGE RETURN
+0x0E	0x000E	#SHIFT OUT
+0x0F	0x000F	#SHIFT IN
+0x10	0x0010	#DATA LINK ESCAPE
+0x11	0x0011	#DEVICE CONTROL ONE
+0x12	0x0012	#DEVICE CONTROL TWO
+0x13	0x0013	#DEVICE CONTROL THREE
+0x14	0x0014	#DEVICE CONTROL FOUR
+0x15	0x0015	#NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#SYNCHRONOUS IDLE
+0x17	0x0017	#END OF TRANSMISSION BLOCK
+0x18	0x0018	#CANCEL
+0x19	0x0019	#END OF MEDIUM
+0x1A	0x001A	#SUBSTITUTE
+0x1B	0x001B	#ESCAPE
+0x1C	0x001C	#FILE SEPARATOR
+0x1D	0x001D	#GROUP SEPARATOR
+0x1E	0x001E	#RECORD SEPARATOR
+0x1F	0x001F	#UNIT SEPARATOR
+0x20	0x0020	#SPACE
+0x21	0x0021	#EXCLAMATION MARK
+0x22	0x0022	#QUOTATION MARK
+0x23	0x0023	#NUMBER SIGN
+0x24	0x0024	#DOLLAR SIGN
+0x25	0x0025	#PERCENT SIGN
+0x26	0x0026	#AMPERSAND
+0x27	0x0027	#APOSTROPHE
+0x28	0x0028	#LEFT PARENTHESIS
+0x29	0x0029	#RIGHT PARENTHESIS
+0x2A	0x002A	#ASTERISK
+0x2B	0x002B	#PLUS SIGN
+0x2C	0x002C	#COMMA
+0x2D	0x002D	#HYPHEN-MINUS
+0x2E	0x002E	#FULL STOP
+0x2F	0x002F	#SOLIDUS
+0x30	0x0030	#DIGIT ZERO
+0x31	0x0031	#DIGIT ONE
+0x32	0x0032	#DIGIT TWO
+0x33	0x0033	#DIGIT THREE
+0x34	0x0034	#DIGIT FOUR
+0x35	0x0035	#DIGIT FIVE
+0x36	0x0036	#DIGIT SIX
+0x37	0x0037	#DIGIT SEVEN
+0x38	0x0038	#DIGIT EIGHT
+0x39	0x0039	#DIGIT NINE
+0x3A	0x003A	#COLON
+0x3B	0x003B	#SEMICOLON
+0x3C	0x003C	#LESS-THAN SIGN
+0x3D	0x003D	#EQUALS SIGN
+0x3E	0x003E	#GREATER-THAN SIGN
+0x3F	0x003F	#QUESTION MARK
+0x40	0x0040	#COMMERCIAL AT
+0x41	0x0041	#LATIN CAPITAL LETTER A
+0x42	0x0042	#LATIN CAPITAL LETTER B
+0x43	0x0043	#LATIN CAPITAL LETTER C
+0x44	0x0044	#LATIN CAPITAL LETTER D
+0x45	0x0045	#LATIN CAPITAL LETTER E
+0x46	0x0046	#LATIN CAPITAL LETTER F
+0x47	0x0047	#LATIN CAPITAL LETTER G
+0x48	0x0048	#LATIN CAPITAL LETTER H
+0x49	0x0049	#LATIN CAPITAL LETTER I
+0x4A	0x004A	#LATIN CAPITAL LETTER J
+0x4B	0x004B	#LATIN CAPITAL LETTER K
+0x4C	0x004C	#LATIN CAPITAL LETTER L
+0x4D	0x004D	#LATIN CAPITAL LETTER M
+0x4E	0x004E	#LATIN CAPITAL LETTER N
+0x4F	0x004F	#LATIN CAPITAL LETTER O
+0x50	0x0050	#LATIN CAPITAL LETTER P
+0x51	0x0051	#LATIN CAPITAL LETTER Q
+0x52	0x0052	#LATIN CAPITAL LETTER R
+0x53	0x0053	#LATIN CAPITAL LETTER S
+0x54	0x0054	#LATIN CAPITAL LETTER T
+0x55	0x0055	#LATIN CAPITAL LETTER U
+0x56	0x0056	#LATIN CAPITAL LETTER V
+0x57	0x0057	#LATIN CAPITAL LETTER W
+0x58	0x0058	#LATIN CAPITAL LETTER X
+0x59	0x0059	#LATIN CAPITAL LETTER Y
+0x5A	0x005A	#LATIN CAPITAL LETTER Z
+0x5B	0x005B	#LEFT SQUARE BRACKET
+0x5C	0x005C	#REVERSE SOLIDUS
+0x5D	0x005D	#RIGHT SQUARE BRACKET
+0x5E	0x005E	#CIRCUMFLEX ACCENT
+0x5F	0x005F	#LOW LINE
+0x60	0x0060	#GRAVE ACCENT
+0x61	0x0061	#LATIN SMALL LETTER A
+0x62	0x0062	#LATIN SMALL LETTER B
+0x63	0x0063	#LATIN SMALL LETTER C
+0x64	0x0064	#LATIN SMALL LETTER D
+0x65	0x0065	#LATIN SMALL LETTER E
+0x66	0x0066	#LATIN SMALL LETTER F
+0x67	0x0067	#LATIN SMALL LETTER G
+0x68	0x0068	#LATIN SMALL LETTER H
+0x69	0x0069	#LATIN SMALL LETTER I
+0x6A	0x006A	#LATIN SMALL LETTER J
+0x6B	0x006B	#LATIN SMALL LETTER K
+0x6C	0x006C	#LATIN SMALL LETTER L
+0x6D	0x006D	#LATIN SMALL LETTER M
+0x6E	0x006E	#LATIN SMALL LETTER N
+0x6F	0x006F	#LATIN SMALL LETTER O
+0x70	0x0070	#LATIN SMALL LETTER P
+0x71	0x0071	#LATIN SMALL LETTER Q
+0x72	0x0072	#LATIN SMALL LETTER R
+0x73	0x0073	#LATIN SMALL LETTER S
+0x74	0x0074	#LATIN SMALL LETTER T
+0x75	0x0075	#LATIN SMALL LETTER U
+0x76	0x0076	#LATIN SMALL LETTER V
+0x77	0x0077	#LATIN SMALL LETTER W
+0x78	0x0078	#LATIN SMALL LETTER X
+0x79	0x0079	#LATIN SMALL LETTER Y
+0x7A	0x007A	#LATIN SMALL LETTER Z
+0x7B	0x007B	#LEFT CURLY BRACKET
+0x7C	0x007C	#VERTICAL LINE
+0x7D	0x007D	#RIGHT CURLY BRACKET
+0x7E	0x007E	#TILDE
+0x7F	0x007F	#DELETE
+0x80	0x20AC	#EURO SIGN
+0x81	      	#UNDEFINED
+0x82	0x201A	#SINGLE LOW-9 QUOTATION MARK
+0x83	      	#UNDEFINED
+0x84	0x201E	#DOUBLE LOW-9 QUOTATION MARK
+0x85	0x2026	#HORIZONTAL ELLIPSIS
+0x86	0x2020	#DAGGER
+0x87	0x2021	#DOUBLE DAGGER
+0x88	      	#UNDEFINED
+0x89	0x2030	#PER MILLE SIGN
+0x8A	0x0160	#LATIN CAPITAL LETTER S WITH CARON
+0x8B	0x2039	#SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+0x8C	0x015A	#LATIN CAPITAL LETTER S WITH ACUTE
+0x8D	0x0164	#LATIN CAPITAL LETTER T WITH CARON
+0x8E	0x017D	#LATIN CAPITAL LETTER Z WITH CARON
+0x8F	0x0179	#LATIN CAPITAL LETTER Z WITH ACUTE
+0x90	      	#UNDEFINED
+0x91	0x2018	#LEFT SINGLE QUOTATION MARK
+0x92	0x2019	#RIGHT SINGLE QUOTATION MARK
+0x93	0x201C	#LEFT DOUBLE QUOTATION MARK
+0x94	0x201D	#RIGHT DOUBLE QUOTATION MARK
+0x95	0x2022	#BULLET
+0x96	0x2013	#EN DASH
+0x97	0x2014	#EM DASH
+0x98	      	#UNDEFINED
+0x99	0x2122	#TRADE MARK SIGN
+0x9A	0x0161	#LATIN SMALL LETTER S WITH CARON
+0x9B	0x203A	#SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+0x9C	0x015B	#LATIN SMALL LETTER S WITH ACUTE
+0x9D	0x0165	#LATIN SMALL LETTER T WITH CARON
+0x9E	0x017E	#LATIN SMALL LETTER Z WITH CARON
+0x9F	0x017A	#LATIN SMALL LETTER Z WITH ACUTE
+0xA0	0x00A0	#NO-BREAK SPACE
+0xA1	0x02C7	#CARON
+0xA2	0x02D8	#BREVE
+0xA3	0x0141	#LATIN CAPITAL LETTER L WITH STROKE
+0xA4	0x00A4	#CURRENCY SIGN
+0xA5	0x0104	#LATIN CAPITAL LETTER A WITH OGONEK
+0xA6	0x00A6	#BROKEN BAR
+0xA7	0x00A7	#SECTION SIGN
+0xA8	0x00A8	#DIAERESIS
+0xA9	0x00A9	#COPYRIGHT SIGN
+0xAA	0x015E	#LATIN CAPITAL LETTER S WITH CEDILLA
+0xAB	0x00AB	#LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC	0x00AC	#NOT SIGN
+0xAD	0x00AD	#SOFT HYPHEN
+0xAE	0x00AE	#REGISTERED SIGN
+0xAF	0x017B	#LATIN CAPITAL LETTER Z WITH DOT ABOVE
+0xB0	0x00B0	#DEGREE SIGN
+0xB1	0x00B1	#PLUS-MINUS SIGN
+0xB2	0x02DB	#OGONEK
+0xB3	0x0142	#LATIN SMALL LETTER L WITH STROKE
+0xB4	0x00B4	#ACUTE ACCENT
+0xB5	0x00B5	#MICRO SIGN
+0xB6	0x00B6	#PILCROW SIGN
+0xB7	0x00B7	#MIDDLE DOT
+0xB8	0x00B8	#CEDILLA
+0xB9	0x0105	#LATIN SMALL LETTER A WITH OGONEK
+0xBA	0x015F	#LATIN SMALL LETTER S WITH CEDILLA
+0xBB	0x00BB	#RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC	0x013D	#LATIN CAPITAL LETTER L WITH CARON
+0xBD	0x02DD	#DOUBLE ACUTE ACCENT
+0xBE	0x013E	#LATIN SMALL LETTER L WITH CARON
+0xBF	0x017C	#LATIN SMALL LETTER Z WITH DOT ABOVE
+0xC0	0x0154	#LATIN CAPITAL LETTER R WITH ACUTE
+0xC1	0x00C1	#LATIN CAPITAL LETTER A WITH ACUTE
+0xC2	0x00C2	#LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3	0x0102	#LATIN CAPITAL LETTER A WITH BREVE
+0xC4	0x00C4	#LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5	0x0139	#LATIN CAPITAL LETTER L WITH ACUTE
+0xC6	0x0106	#LATIN CAPITAL LETTER C WITH ACUTE
+0xC7	0x00C7	#LATIN CAPITAL LETTER C WITH CEDILLA
+0xC8	0x010C	#LATIN CAPITAL LETTER C WITH CARON
+0xC9	0x00C9	#LATIN CAPITAL LETTER E WITH ACUTE
+0xCA	0x0118	#LATIN CAPITAL LETTER E WITH OGONEK
+0xCB	0x00CB	#LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC	0x011A	#LATIN CAPITAL LETTER E WITH CARON
+0xCD	0x00CD	#LATIN CAPITAL LETTER I WITH ACUTE
+0xCE	0x00CE	#LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF	0x010E	#LATIN CAPITAL LETTER D WITH CARON
+0xD0	0x0110	#LATIN CAPITAL LETTER D WITH STROKE
+0xD1	0x0143	#LATIN CAPITAL LETTER N WITH ACUTE
+0xD2	0x0147	#LATIN CAPITAL LETTER N WITH CARON
+0xD3	0x00D3	#LATIN CAPITAL LETTER O WITH ACUTE
+0xD4	0x00D4	#LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5	0x0150	#LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+0xD6	0x00D6	#LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7	0x00D7	#MULTIPLICATION SIGN
+0xD8	0x0158	#LATIN CAPITAL LETTER R WITH CARON
+0xD9	0x016E	#LATIN CAPITAL LETTER U WITH RING ABOVE
+0xDA	0x00DA	#LATIN CAPITAL LETTER U WITH ACUTE
+0xDB	0x0170	#LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+0xDC	0x00DC	#LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD	0x00DD	#LATIN CAPITAL LETTER Y WITH ACUTE
+0xDE	0x0162	#LATIN CAPITAL LETTER T WITH CEDILLA
+0xDF	0x00DF	#LATIN SMALL LETTER SHARP S
+0xE0	0x0155	#LATIN SMALL LETTER R WITH ACUTE
+0xE1	0x00E1	#LATIN SMALL LETTER A WITH ACUTE
+0xE2	0x00E2	#LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3	0x0103	#LATIN SMALL LETTER A WITH BREVE
+0xE4	0x00E4	#LATIN SMALL LETTER A WITH DIAERESIS
+0xE5	0x013A	#LATIN SMALL LETTER L WITH ACUTE
+0xE6	0x0107	#LATIN SMALL LETTER C WITH ACUTE
+0xE7	0x00E7	#LATIN SMALL LETTER C WITH CEDILLA
+0xE8	0x010D	#LATIN SMALL LETTER C WITH CARON
+0xE9	0x00E9	#LATIN SMALL LETTER E WITH ACUTE
+0xEA	0x0119	#LATIN SMALL LETTER E WITH OGONEK
+0xEB	0x00EB	#LATIN SMALL LETTER E WITH DIAERESIS
+0xEC	0x011B	#LATIN SMALL LETTER E WITH CARON
+0xED	0x00ED	#LATIN SMALL LETTER I WITH ACUTE
+0xEE	0x00EE	#LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF	0x010F	#LATIN SMALL LETTER D WITH CARON
+0xF0	0x0111	#LATIN SMALL LETTER D WITH STROKE
+0xF1	0x0144	#LATIN SMALL LETTER N WITH ACUTE
+0xF2	0x0148	#LATIN SMALL LETTER N WITH CARON
+0xF3	0x00F3	#LATIN SMALL LETTER O WITH ACUTE
+0xF4	0x00F4	#LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5	0x0151	#LATIN SMALL LETTER O WITH DOUBLE ACUTE
+0xF6	0x00F6	#LATIN SMALL LETTER O WITH DIAERESIS
+0xF7	0x00F7	#DIVISION SIGN
+0xF8	0x0159	#LATIN SMALL LETTER R WITH CARON
+0xF9	0x016F	#LATIN SMALL LETTER U WITH RING ABOVE
+0xFA	0x00FA	#LATIN SMALL LETTER U WITH ACUTE
+0xFB	0x0171	#LATIN SMALL LETTER U WITH DOUBLE ACUTE
+0xFC	0x00FC	#LATIN SMALL LETTER U WITH DIAERESIS
+0xFD	0x00FD	#LATIN SMALL LETTER Y WITH ACUTE
+0xFE	0x0163	#LATIN SMALL LETTER T WITH CEDILLA
+0xFF	0x02D9	#DOT ABOVE
diff --git a/Resources/cp1251.txt b/Resources/cp1251.txt
new file mode 100644
index 0000000..f6876e6
--- /dev/null
+++ b/Resources/cp1251.txt
@@ -0,0 +1,274 @@
+#
+#    Name:     cp1251 to Unicode table
+#    Unicode version: 2.0
+#    Table version: 2.01
+#    Table format:  Format A
+#    Date:          04/15/98
+#
+#    Contact:       cpxlate@microsoft.com
+#
+#    General notes: none
+#
+#    Format: Three tab-separated columns
+#        Column #1 is the cp1251 code (in hex)
+#        Column #2 is the Unicode (in hex as 0xXXXX)
+#        Column #3 is the Unicode name (follows a comment sign, '#')
+#
+#    The entries are in cp1251 order
+#
+0x00	0x0000	#NULL
+0x01	0x0001	#START OF HEADING
+0x02	0x0002	#START OF TEXT
+0x03	0x0003	#END OF TEXT
+0x04	0x0004	#END OF TRANSMISSION
+0x05	0x0005	#ENQUIRY
+0x06	0x0006	#ACKNOWLEDGE
+0x07	0x0007	#BELL
+0x08	0x0008	#BACKSPACE
+0x09	0x0009	#HORIZONTAL TABULATION
+0x0A	0x000A	#LINE FEED
+0x0B	0x000B	#VERTICAL TABULATION
+0x0C	0x000C	#FORM FEED
+0x0D	0x000D	#CARRIAGE RETURN
+0x0E	0x000E	#SHIFT OUT
+0x0F	0x000F	#SHIFT IN
+0x10	0x0010	#DATA LINK ESCAPE
+0x11	0x0011	#DEVICE CONTROL ONE
+0x12	0x0012	#DEVICE CONTROL TWO
+0x13	0x0013	#DEVICE CONTROL THREE
+0x14	0x0014	#DEVICE CONTROL FOUR
+0x15	0x0015	#NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#SYNCHRONOUS IDLE
+0x17	0x0017	#END OF TRANSMISSION BLOCK
+0x18	0x0018	#CANCEL
+0x19	0x0019	#END OF MEDIUM
+0x1A	0x001A	#SUBSTITUTE
+0x1B	0x001B	#ESCAPE
+0x1C	0x001C	#FILE SEPARATOR
+0x1D	0x001D	#GROUP SEPARATOR
+0x1E	0x001E	#RECORD SEPARATOR
+0x1F	0x001F	#UNIT SEPARATOR
+0x20	0x0020	#SPACE
+0x21	0x0021	#EXCLAMATION MARK
+0x22	0x0022	#QUOTATION MARK
+0x23	0x0023	#NUMBER SIGN
+0x24	0x0024	#DOLLAR SIGN
+0x25	0x0025	#PERCENT SIGN
+0x26	0x0026	#AMPERSAND
+0x27	0x0027	#APOSTROPHE
+0x28	0x0028	#LEFT PARENTHESIS
+0x29	0x0029	#RIGHT PARENTHESIS
+0x2A	0x002A	#ASTERISK
+0x2B	0x002B	#PLUS SIGN
+0x2C	0x002C	#COMMA
+0x2D	0x002D	#HYPHEN-MINUS
+0x2E	0x002E	#FULL STOP
+0x2F	0x002F	#SOLIDUS
+0x30	0x0030	#DIGIT ZERO
+0x31	0x0031	#DIGIT ONE
+0x32	0x0032	#DIGIT TWO
+0x33	0x0033	#DIGIT THREE
+0x34	0x0034	#DIGIT FOUR
+0x35	0x0035	#DIGIT FIVE
+0x36	0x0036	#DIGIT SIX
+0x37	0x0037	#DIGIT SEVEN
+0x38	0x0038	#DIGIT EIGHT
+0x39	0x0039	#DIGIT NINE
+0x3A	0x003A	#COLON
+0x3B	0x003B	#SEMICOLON
+0x3C	0x003C	#LESS-THAN SIGN
+0x3D	0x003D	#EQUALS SIGN
+0x3E	0x003E	#GREATER-THAN SIGN
+0x3F	0x003F	#QUESTION MARK
+0x40	0x0040	#COMMERCIAL AT
+0x41	0x0041	#LATIN CAPITAL LETTER A
+0x42	0x0042	#LATIN CAPITAL LETTER B
+0x43	0x0043	#LATIN CAPITAL LETTER C
+0x44	0x0044	#LATIN CAPITAL LETTER D
+0x45	0x0045	#LATIN CAPITAL LETTER E
+0x46	0x0046	#LATIN CAPITAL LETTER F
+0x47	0x0047	#LATIN CAPITAL LETTER G
+0x48	0x0048	#LATIN CAPITAL LETTER H
+0x49	0x0049	#LATIN CAPITAL LETTER I
+0x4A	0x004A	#LATIN CAPITAL LETTER J
+0x4B	0x004B	#LATIN CAPITAL LETTER K
+0x4C	0x004C	#LATIN CAPITAL LETTER L
+0x4D	0x004D	#LATIN CAPITAL LETTER M
+0x4E	0x004E	#LATIN CAPITAL LETTER N
+0x4F	0x004F	#LATIN CAPITAL LETTER O
+0x50	0x0050	#LATIN CAPITAL LETTER P
+0x51	0x0051	#LATIN CAPITAL LETTER Q
+0x52	0x0052	#LATIN CAPITAL LETTER R
+0x53	0x0053	#LATIN CAPITAL LETTER S
+0x54	0x0054	#LATIN CAPITAL LETTER T
+0x55	0x0055	#LATIN CAPITAL LETTER U
+0x56	0x0056	#LATIN CAPITAL LETTER V
+0x57	0x0057	#LATIN CAPITAL LETTER W
+0x58	0x0058	#LATIN CAPITAL LETTER X
+0x59	0x0059	#LATIN CAPITAL LETTER Y
+0x5A	0x005A	#LATIN CAPITAL LETTER Z
+0x5B	0x005B	#LEFT SQUARE BRACKET
+0x5C	0x005C	#REVERSE SOLIDUS
+0x5D	0x005D	#RIGHT SQUARE BRACKET
+0x5E	0x005E	#CIRCUMFLEX ACCENT
+0x5F	0x005F	#LOW LINE
+0x60	0x0060	#GRAVE ACCENT
+0x61	0x0061	#LATIN SMALL LETTER A
+0x62	0x0062	#LATIN SMALL LETTER B
+0x63	0x0063	#LATIN SMALL LETTER C
+0x64	0x0064	#LATIN SMALL LETTER D
+0x65	0x0065	#LATIN SMALL LETTER E
+0x66	0x0066	#LATIN SMALL LETTER F
+0x67	0x0067	#LATIN SMALL LETTER G
+0x68	0x0068	#LATIN SMALL LETTER H
+0x69	0x0069	#LATIN SMALL LETTER I
+0x6A	0x006A	#LATIN SMALL LETTER J
+0x6B	0x006B	#LATIN SMALL LETTER K
+0x6C	0x006C	#LATIN SMALL LETTER L
+0x6D	0x006D	#LATIN SMALL LETTER M
+0x6E	0x006E	#LATIN SMALL LETTER N
+0x6F	0x006F	#LATIN SMALL LETTER O
+0x70	0x0070	#LATIN SMALL LETTER P
+0x71	0x0071	#LATIN SMALL LETTER Q
+0x72	0x0072	#LATIN SMALL LETTER R
+0x73	0x0073	#LATIN SMALL LETTER S
+0x74	0x0074	#LATIN SMALL LETTER T
+0x75	0x0075	#LATIN SMALL LETTER U
+0x76	0x0076	#LATIN SMALL LETTER V
+0x77	0x0077	#LATIN SMALL LETTER W
+0x78	0x0078	#LATIN SMALL LETTER X
+0x79	0x0079	#LATIN SMALL LETTER Y
+0x7A	0x007A	#LATIN SMALL LETTER Z
+0x7B	0x007B	#LEFT CURLY BRACKET
+0x7C	0x007C	#VERTICAL LINE
+0x7D	0x007D	#RIGHT CURLY BRACKET
+0x7E	0x007E	#TILDE
+0x7F	0x007F	#DELETE
+0x80	0x0402	#CYRILLIC CAPITAL LETTER DJE
+0x81	0x0403	#CYRILLIC CAPITAL LETTER GJE
+0x82	0x201A	#SINGLE LOW-9 QUOTATION MARK
+0x83	0x0453	#CYRILLIC SMALL LETTER GJE
+0x84	0x201E	#DOUBLE LOW-9 QUOTATION MARK
+0x85	0x2026	#HORIZONTAL ELLIPSIS
+0x86	0x2020	#DAGGER
+0x87	0x2021	#DOUBLE DAGGER
+0x88	0x20AC	#EURO SIGN
+0x89	0x2030	#PER MILLE SIGN
+0x8A	0x0409	#CYRILLIC CAPITAL LETTER LJE
+0x8B	0x2039	#SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+0x8C	0x040A	#CYRILLIC CAPITAL LETTER NJE
+0x8D	0x040C	#CYRILLIC CAPITAL LETTER KJE
+0x8E	0x040B	#CYRILLIC CAPITAL LETTER TSHE
+0x8F	0x040F	#CYRILLIC CAPITAL LETTER DZHE
+0x90	0x0452	#CYRILLIC SMALL LETTER DJE
+0x91	0x2018	#LEFT SINGLE QUOTATION MARK
+0x92	0x2019	#RIGHT SINGLE QUOTATION MARK
+0x93	0x201C	#LEFT DOUBLE QUOTATION MARK
+0x94	0x201D	#RIGHT DOUBLE QUOTATION MARK
+0x95	0x2022	#BULLET
+0x96	0x2013	#EN DASH
+0x97	0x2014	#EM DASH
+0x98	      	#UNDEFINED
+0x99	0x2122	#TRADE MARK SIGN
+0x9A	0x0459	#CYRILLIC SMALL LETTER LJE
+0x9B	0x203A	#SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+0x9C	0x045A	#CYRILLIC SMALL LETTER NJE
+0x9D	0x045C	#CYRILLIC SMALL LETTER KJE
+0x9E	0x045B	#CYRILLIC SMALL LETTER TSHE
+0x9F	0x045F	#CYRILLIC SMALL LETTER DZHE
+0xA0	0x00A0	#NO-BREAK SPACE
+0xA1	0x040E	#CYRILLIC CAPITAL LETTER SHORT U
+0xA2	0x045E	#CYRILLIC SMALL LETTER SHORT U
+0xA3	0x0408	#CYRILLIC CAPITAL LETTER JE
+0xA4	0x00A4	#CURRENCY SIGN
+0xA5	0x0490	#CYRILLIC CAPITAL LETTER GHE WITH UPTURN
+0xA6	0x00A6	#BROKEN BAR
+0xA7	0x00A7	#SECTION SIGN
+0xA8	0x0401	#CYRILLIC CAPITAL LETTER IO
+0xA9	0x00A9	#COPYRIGHT SIGN
+0xAA	0x0404	#CYRILLIC CAPITAL LETTER UKRAINIAN IE
+0xAB	0x00AB	#LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC	0x00AC	#NOT SIGN
+0xAD	0x00AD	#SOFT HYPHEN
+0xAE	0x00AE	#REGISTERED SIGN
+0xAF	0x0407	#CYRILLIC CAPITAL LETTER YI
+0xB0	0x00B0	#DEGREE SIGN
+0xB1	0x00B1	#PLUS-MINUS SIGN
+0xB2	0x0406	#CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+0xB3	0x0456	#CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+0xB4	0x0491	#CYRILLIC SMALL LETTER GHE WITH UPTURN
+0xB5	0x00B5	#MICRO SIGN
+0xB6	0x00B6	#PILCROW SIGN
+0xB7	0x00B7	#MIDDLE DOT
+0xB8	0x0451	#CYRILLIC SMALL LETTER IO
+0xB9	0x2116	#NUMERO SIGN
+0xBA	0x0454	#CYRILLIC SMALL LETTER UKRAINIAN IE
+0xBB	0x00BB	#RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC	0x0458	#CYRILLIC SMALL LETTER JE
+0xBD	0x0405	#CYRILLIC CAPITAL LETTER DZE
+0xBE	0x0455	#CYRILLIC SMALL LETTER DZE
+0xBF	0x0457	#CYRILLIC SMALL LETTER YI
+0xC0	0x0410	#CYRILLIC CAPITAL LETTER A
+0xC1	0x0411	#CYRILLIC CAPITAL LETTER BE
+0xC2	0x0412	#CYRILLIC CAPITAL LETTER VE
+0xC3	0x0413	#CYRILLIC CAPITAL LETTER GHE
+0xC4	0x0414	#CYRILLIC CAPITAL LETTER DE
+0xC5	0x0415	#CYRILLIC CAPITAL LETTER IE
+0xC6	0x0416	#CYRILLIC CAPITAL LETTER ZHE
+0xC7	0x0417	#CYRILLIC CAPITAL LETTER ZE
+0xC8	0x0418	#CYRILLIC CAPITAL LETTER I
+0xC9	0x0419	#CYRILLIC CAPITAL LETTER SHORT I
+0xCA	0x041A	#CYRILLIC CAPITAL LETTER KA
+0xCB	0x041B	#CYRILLIC CAPITAL LETTER EL
+0xCC	0x041C	#CYRILLIC CAPITAL LETTER EM
+0xCD	0x041D	#CYRILLIC CAPITAL LETTER EN
+0xCE	0x041E	#CYRILLIC CAPITAL LETTER O
+0xCF	0x041F	#CYRILLIC CAPITAL LETTER PE
+0xD0	0x0420	#CYRILLIC CAPITAL LETTER ER
+0xD1	0x0421	#CYRILLIC CAPITAL LETTER ES
+0xD2	0x0422	#CYRILLIC CAPITAL LETTER TE
+0xD3	0x0423	#CYRILLIC CAPITAL LETTER U
+0xD4	0x0424	#CYRILLIC CAPITAL LETTER EF
+0xD5	0x0425	#CYRILLIC CAPITAL LETTER HA
+0xD6	0x0426	#CYRILLIC CAPITAL LETTER TSE
+0xD7	0x0427	#CYRILLIC CAPITAL LETTER CHE
+0xD8	0x0428	#CYRILLIC CAPITAL LETTER SHA
+0xD9	0x0429	#CYRILLIC CAPITAL LETTER SHCHA
+0xDA	0x042A	#CYRILLIC CAPITAL LETTER HARD SIGN
+0xDB	0x042B	#CYRILLIC CAPITAL LETTER YERU
+0xDC	0x042C	#CYRILLIC CAPITAL LETTER SOFT SIGN
+0xDD	0x042D	#CYRILLIC CAPITAL LETTER E
+0xDE	0x042E	#CYRILLIC CAPITAL LETTER YU
+0xDF	0x042F	#CYRILLIC CAPITAL LETTER YA
+0xE0	0x0430	#CYRILLIC SMALL LETTER A
+0xE1	0x0431	#CYRILLIC SMALL LETTER BE
+0xE2	0x0432	#CYRILLIC SMALL LETTER VE
+0xE3	0x0433	#CYRILLIC SMALL LETTER GHE
+0xE4	0x0434	#CYRILLIC SMALL LETTER DE
+0xE5	0x0435	#CYRILLIC SMALL LETTER IE
+0xE6	0x0436	#CYRILLIC SMALL LETTER ZHE
+0xE7	0x0437	#CYRILLIC SMALL LETTER ZE
+0xE8	0x0438	#CYRILLIC SMALL LETTER I
+0xE9	0x0439	#CYRILLIC SMALL LETTER SHORT I
+0xEA	0x043A	#CYRILLIC SMALL LETTER KA
+0xEB	0x043B	#CYRILLIC SMALL LETTER EL
+0xEC	0x043C	#CYRILLIC SMALL LETTER EM
+0xED	0x043D	#CYRILLIC SMALL LETTER EN
+0xEE	0x043E	#CYRILLIC SMALL LETTER O
+0xEF	0x043F	#CYRILLIC SMALL LETTER PE
+0xF0	0x0440	#CYRILLIC SMALL LETTER ER
+0xF1	0x0441	#CYRILLIC SMALL LETTER ES
+0xF2	0x0442	#CYRILLIC SMALL LETTER TE
+0xF3	0x0443	#CYRILLIC SMALL LETTER U
+0xF4	0x0444	#CYRILLIC SMALL LETTER EF
+0xF5	0x0445	#CYRILLIC SMALL LETTER HA
+0xF6	0x0446	#CYRILLIC SMALL LETTER TSE
+0xF7	0x0447	#CYRILLIC SMALL LETTER CHE
+0xF8	0x0448	#CYRILLIC SMALL LETTER SHA
+0xF9	0x0449	#CYRILLIC SMALL LETTER SHCHA
+0xFA	0x044A	#CYRILLIC SMALL LETTER HARD SIGN
+0xFB	0x044B	#CYRILLIC SMALL LETTER YERU
+0xFC	0x044C	#CYRILLIC SMALL LETTER SOFT SIGN
+0xFD	0x044D	#CYRILLIC SMALL LETTER E
+0xFE	0x044E	#CYRILLIC SMALL LETTER YU
+0xFF	0x044F	#CYRILLIC SMALL LETTER YA
diff --git a/Resources/cp1252.txt b/Resources/cp1252.txt
new file mode 100644
index 0000000..970002d
--- /dev/null
+++ b/Resources/cp1252.txt
@@ -0,0 +1,274 @@
+#
+#    Name:     cp1252 to Unicode table
+#    Unicode version: 2.0
+#    Table version: 2.01
+#    Table format:  Format A
+#    Date:          04/15/98
+#
+#    Contact:       cpxlate@microsoft.com
+#
+#    General notes: none
+#
+#    Format: Three tab-separated columns
+#        Column #1 is the cp1252 code (in hex)
+#        Column #2 is the Unicode (in hex as 0xXXXX)
+#        Column #3 is the Unicode name (follows a comment sign, '#')
+#
+#    The entries are in cp1252 order
+#
+0x00	0x0000	#NULL
+0x01	0x0001	#START OF HEADING
+0x02	0x0002	#START OF TEXT
+0x03	0x0003	#END OF TEXT
+0x04	0x0004	#END OF TRANSMISSION
+0x05	0x0005	#ENQUIRY
+0x06	0x0006	#ACKNOWLEDGE
+0x07	0x0007	#BELL
+0x08	0x0008	#BACKSPACE
+0x09	0x0009	#HORIZONTAL TABULATION
+0x0A	0x000A	#LINE FEED
+0x0B	0x000B	#VERTICAL TABULATION
+0x0C	0x000C	#FORM FEED
+0x0D	0x000D	#CARRIAGE RETURN
+0x0E	0x000E	#SHIFT OUT
+0x0F	0x000F	#SHIFT IN
+0x10	0x0010	#DATA LINK ESCAPE
+0x11	0x0011	#DEVICE CONTROL ONE
+0x12	0x0012	#DEVICE CONTROL TWO
+0x13	0x0013	#DEVICE CONTROL THREE
+0x14	0x0014	#DEVICE CONTROL FOUR
+0x15	0x0015	#NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#SYNCHRONOUS IDLE
+0x17	0x0017	#END OF TRANSMISSION BLOCK
+0x18	0x0018	#CANCEL
+0x19	0x0019	#END OF MEDIUM
+0x1A	0x001A	#SUBSTITUTE
+0x1B	0x001B	#ESCAPE
+0x1C	0x001C	#FILE SEPARATOR
+0x1D	0x001D	#GROUP SEPARATOR
+0x1E	0x001E	#RECORD SEPARATOR
+0x1F	0x001F	#UNIT SEPARATOR
+0x20	0x0020	#SPACE
+0x21	0x0021	#EXCLAMATION MARK
+0x22	0x0022	#QUOTATION MARK
+0x23	0x0023	#NUMBER SIGN
+0x24	0x0024	#DOLLAR SIGN
+0x25	0x0025	#PERCENT SIGN
+0x26	0x0026	#AMPERSAND
+0x27	0x0027	#APOSTROPHE
+0x28	0x0028	#LEFT PARENTHESIS
+0x29	0x0029	#RIGHT PARENTHESIS
+0x2A	0x002A	#ASTERISK
+0x2B	0x002B	#PLUS SIGN
+0x2C	0x002C	#COMMA
+0x2D	0x002D	#HYPHEN-MINUS
+0x2E	0x002E	#FULL STOP
+0x2F	0x002F	#SOLIDUS
+0x30	0x0030	#DIGIT ZERO
+0x31	0x0031	#DIGIT ONE
+0x32	0x0032	#DIGIT TWO
+0x33	0x0033	#DIGIT THREE
+0x34	0x0034	#DIGIT FOUR
+0x35	0x0035	#DIGIT FIVE
+0x36	0x0036	#DIGIT SIX
+0x37	0x0037	#DIGIT SEVEN
+0x38	0x0038	#DIGIT EIGHT
+0x39	0x0039	#DIGIT NINE
+0x3A	0x003A	#COLON
+0x3B	0x003B	#SEMICOLON
+0x3C	0x003C	#LESS-THAN SIGN
+0x3D	0x003D	#EQUALS SIGN
+0x3E	0x003E	#GREATER-THAN SIGN
+0x3F	0x003F	#QUESTION MARK
+0x40	0x0040	#COMMERCIAL AT
+0x41	0x0041	#LATIN CAPITAL LETTER A
+0x42	0x0042	#LATIN CAPITAL LETTER B
+0x43	0x0043	#LATIN CAPITAL LETTER C
+0x44	0x0044	#LATIN CAPITAL LETTER D
+0x45	0x0045	#LATIN CAPITAL LETTER E
+0x46	0x0046	#LATIN CAPITAL LETTER F
+0x47	0x0047	#LATIN CAPITAL LETTER G
+0x48	0x0048	#LATIN CAPITAL LETTER H
+0x49	0x0049	#LATIN CAPITAL LETTER I
+0x4A	0x004A	#LATIN CAPITAL LETTER J
+0x4B	0x004B	#LATIN CAPITAL LETTER K
+0x4C	0x004C	#LATIN CAPITAL LETTER L
+0x4D	0x004D	#LATIN CAPITAL LETTER M
+0x4E	0x004E	#LATIN CAPITAL LETTER N
+0x4F	0x004F	#LATIN CAPITAL LETTER O
+0x50	0x0050	#LATIN CAPITAL LETTER P
+0x51	0x0051	#LATIN CAPITAL LETTER Q
+0x52	0x0052	#LATIN CAPITAL LETTER R
+0x53	0x0053	#LATIN CAPITAL LETTER S
+0x54	0x0054	#LATIN CAPITAL LETTER T
+0x55	0x0055	#LATIN CAPITAL LETTER U
+0x56	0x0056	#LATIN CAPITAL LETTER V
+0x57	0x0057	#LATIN CAPITAL LETTER W
+0x58	0x0058	#LATIN CAPITAL LETTER X
+0x59	0x0059	#LATIN CAPITAL LETTER Y
+0x5A	0x005A	#LATIN CAPITAL LETTER Z
+0x5B	0x005B	#LEFT SQUARE BRACKET
+0x5C	0x005C	#REVERSE SOLIDUS
+0x5D	0x005D	#RIGHT SQUARE BRACKET
+0x5E	0x005E	#CIRCUMFLEX ACCENT
+0x5F	0x005F	#LOW LINE
+0x60	0x0060	#GRAVE ACCENT
+0x61	0x0061	#LATIN SMALL LETTER A
+0x62	0x0062	#LATIN SMALL LETTER B
+0x63	0x0063	#LATIN SMALL LETTER C
+0x64	0x0064	#LATIN SMALL LETTER D
+0x65	0x0065	#LATIN SMALL LETTER E
+0x66	0x0066	#LATIN SMALL LETTER F
+0x67	0x0067	#LATIN SMALL LETTER G
+0x68	0x0068	#LATIN SMALL LETTER H
+0x69	0x0069	#LATIN SMALL LETTER I
+0x6A	0x006A	#LATIN SMALL LETTER J
+0x6B	0x006B	#LATIN SMALL LETTER K
+0x6C	0x006C	#LATIN SMALL LETTER L
+0x6D	0x006D	#LATIN SMALL LETTER M
+0x6E	0x006E	#LATIN SMALL LETTER N
+0x6F	0x006F	#LATIN SMALL LETTER O
+0x70	0x0070	#LATIN SMALL LETTER P
+0x71	0x0071	#LATIN SMALL LETTER Q
+0x72	0x0072	#LATIN SMALL LETTER R
+0x73	0x0073	#LATIN SMALL LETTER S
+0x74	0x0074	#LATIN SMALL LETTER T
+0x75	0x0075	#LATIN SMALL LETTER U
+0x76	0x0076	#LATIN SMALL LETTER V
+0x77	0x0077	#LATIN SMALL LETTER W
+0x78	0x0078	#LATIN SMALL LETTER X
+0x79	0x0079	#LATIN SMALL LETTER Y
+0x7A	0x007A	#LATIN SMALL LETTER Z
+0x7B	0x007B	#LEFT CURLY BRACKET
+0x7C	0x007C	#VERTICAL LINE
+0x7D	0x007D	#RIGHT CURLY BRACKET
+0x7E	0x007E	#TILDE
+0x7F	0x007F	#DELETE
+0x80	0x20AC	#EURO SIGN
+0x81	      	#UNDEFINED
+0x82	0x201A	#SINGLE LOW-9 QUOTATION MARK
+0x83	0x0192	#LATIN SMALL LETTER F WITH HOOK
+0x84	0x201E	#DOUBLE LOW-9 QUOTATION MARK
+0x85	0x2026	#HORIZONTAL ELLIPSIS
+0x86	0x2020	#DAGGER
+0x87	0x2021	#DOUBLE DAGGER
+0x88	0x02C6	#MODIFIER LETTER CIRCUMFLEX ACCENT
+0x89	0x2030	#PER MILLE SIGN
+0x8A	0x0160	#LATIN CAPITAL LETTER S WITH CARON
+0x8B	0x2039	#SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+0x8C	0x0152	#LATIN CAPITAL LIGATURE OE
+0x8D	      	#UNDEFINED
+0x8E	0x017D	#LATIN CAPITAL LETTER Z WITH CARON
+0x8F	      	#UNDEFINED
+0x90	      	#UNDEFINED
+0x91	0x2018	#LEFT SINGLE QUOTATION MARK
+0x92	0x2019	#RIGHT SINGLE QUOTATION MARK
+0x93	0x201C	#LEFT DOUBLE QUOTATION MARK
+0x94	0x201D	#RIGHT DOUBLE QUOTATION MARK
+0x95	0x2022	#BULLET
+0x96	0x2013	#EN DASH
+0x97	0x2014	#EM DASH
+0x98	0x02DC	#SMALL TILDE
+0x99	0x2122	#TRADE MARK SIGN
+0x9A	0x0161	#LATIN SMALL LETTER S WITH CARON
+0x9B	0x203A	#SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+0x9C	0x0153	#LATIN SMALL LIGATURE OE
+0x9D	      	#UNDEFINED
+0x9E	0x017E	#LATIN SMALL LETTER Z WITH CARON
+0x9F	0x0178	#LATIN CAPITAL LETTER Y WITH DIAERESIS
+0xA0	0x00A0	#NO-BREAK SPACE
+0xA1	0x00A1	#INVERTED EXCLAMATION MARK
+0xA2	0x00A2	#CENT SIGN
+0xA3	0x00A3	#POUND SIGN
+0xA4	0x00A4	#CURRENCY SIGN
+0xA5	0x00A5	#YEN SIGN
+0xA6	0x00A6	#BROKEN BAR
+0xA7	0x00A7	#SECTION SIGN
+0xA8	0x00A8	#DIAERESIS
+0xA9	0x00A9	#COPYRIGHT SIGN
+0xAA	0x00AA	#FEMININE ORDINAL INDICATOR
+0xAB	0x00AB	#LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC	0x00AC	#NOT SIGN
+0xAD	0x00AD	#SOFT HYPHEN
+0xAE	0x00AE	#REGISTERED SIGN
+0xAF	0x00AF	#MACRON
+0xB0	0x00B0	#DEGREE SIGN
+0xB1	0x00B1	#PLUS-MINUS SIGN
+0xB2	0x00B2	#SUPERSCRIPT TWO
+0xB3	0x00B3	#SUPERSCRIPT THREE
+0xB4	0x00B4	#ACUTE ACCENT
+0xB5	0x00B5	#MICRO SIGN
+0xB6	0x00B6	#PILCROW SIGN
+0xB7	0x00B7	#MIDDLE DOT
+0xB8	0x00B8	#CEDILLA
+0xB9	0x00B9	#SUPERSCRIPT ONE
+0xBA	0x00BA	#MASCULINE ORDINAL INDICATOR
+0xBB	0x00BB	#RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC	0x00BC	#VULGAR FRACTION ONE QUARTER
+0xBD	0x00BD	#VULGAR FRACTION ONE HALF
+0xBE	0x00BE	#VULGAR FRACTION THREE QUARTERS
+0xBF	0x00BF	#INVERTED QUESTION MARK
+0xC0	0x00C0	#LATIN CAPITAL LETTER A WITH GRAVE
+0xC1	0x00C1	#LATIN CAPITAL LETTER A WITH ACUTE
+0xC2	0x00C2	#LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3	0x00C3	#LATIN CAPITAL LETTER A WITH TILDE
+0xC4	0x00C4	#LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5	0x00C5	#LATIN CAPITAL LETTER A WITH RING ABOVE
+0xC6	0x00C6	#LATIN CAPITAL LETTER AE
+0xC7	0x00C7	#LATIN CAPITAL LETTER C WITH CEDILLA
+0xC8	0x00C8	#LATIN CAPITAL LETTER E WITH GRAVE
+0xC9	0x00C9	#LATIN CAPITAL LETTER E WITH ACUTE
+0xCA	0x00CA	#LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xCB	0x00CB	#LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC	0x00CC	#LATIN CAPITAL LETTER I WITH GRAVE
+0xCD	0x00CD	#LATIN CAPITAL LETTER I WITH ACUTE
+0xCE	0x00CE	#LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF	0x00CF	#LATIN CAPITAL LETTER I WITH DIAERESIS
+0xD0	0x00D0	#LATIN CAPITAL LETTER ETH
+0xD1	0x00D1	#LATIN CAPITAL LETTER N WITH TILDE
+0xD2	0x00D2	#LATIN CAPITAL LETTER O WITH GRAVE
+0xD3	0x00D3	#LATIN CAPITAL LETTER O WITH ACUTE
+0xD4	0x00D4	#LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5	0x00D5	#LATIN CAPITAL LETTER O WITH TILDE
+0xD6	0x00D6	#LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7	0x00D7	#MULTIPLICATION SIGN
+0xD8	0x00D8	#LATIN CAPITAL LETTER O WITH STROKE
+0xD9	0x00D9	#LATIN CAPITAL LETTER U WITH GRAVE
+0xDA	0x00DA	#LATIN CAPITAL LETTER U WITH ACUTE
+0xDB	0x00DB	#LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xDC	0x00DC	#LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD	0x00DD	#LATIN CAPITAL LETTER Y WITH ACUTE
+0xDE	0x00DE	#LATIN CAPITAL LETTER THORN
+0xDF	0x00DF	#LATIN SMALL LETTER SHARP S
+0xE0	0x00E0	#LATIN SMALL LETTER A WITH GRAVE
+0xE1	0x00E1	#LATIN SMALL LETTER A WITH ACUTE
+0xE2	0x00E2	#LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3	0x00E3	#LATIN SMALL LETTER A WITH TILDE
+0xE4	0x00E4	#LATIN SMALL LETTER A WITH DIAERESIS
+0xE5	0x00E5	#LATIN SMALL LETTER A WITH RING ABOVE
+0xE6	0x00E6	#LATIN SMALL LETTER AE
+0xE7	0x00E7	#LATIN SMALL LETTER C WITH CEDILLA
+0xE8	0x00E8	#LATIN SMALL LETTER E WITH GRAVE
+0xE9	0x00E9	#LATIN SMALL LETTER E WITH ACUTE
+0xEA	0x00EA	#LATIN SMALL LETTER E WITH CIRCUMFLEX
+0xEB	0x00EB	#LATIN SMALL LETTER E WITH DIAERESIS
+0xEC	0x00EC	#LATIN SMALL LETTER I WITH GRAVE
+0xED	0x00ED	#LATIN SMALL LETTER I WITH ACUTE
+0xEE	0x00EE	#LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF	0x00EF	#LATIN SMALL LETTER I WITH DIAERESIS
+0xF0	0x00F0	#LATIN SMALL LETTER ETH
+0xF1	0x00F1	#LATIN SMALL LETTER N WITH TILDE
+0xF2	0x00F2	#LATIN SMALL LETTER O WITH GRAVE
+0xF3	0x00F3	#LATIN SMALL LETTER O WITH ACUTE
+0xF4	0x00F4	#LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5	0x00F5	#LATIN SMALL LETTER O WITH TILDE
+0xF6	0x00F6	#LATIN SMALL LETTER O WITH DIAERESIS
+0xF7	0x00F7	#DIVISION SIGN
+0xF8	0x00F8	#LATIN SMALL LETTER O WITH STROKE
+0xF9	0x00F9	#LATIN SMALL LETTER U WITH GRAVE
+0xFA	0x00FA	#LATIN SMALL LETTER U WITH ACUTE
+0xFB	0x00FB	#LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xFC	0x00FC	#LATIN SMALL LETTER U WITH DIAERESIS
+0xFD	0x00FD	#LATIN SMALL LETTER Y WITH ACUTE
+0xFE	0x00FE	#LATIN SMALL LETTER THORN
+0xFF	0x00FF	#LATIN SMALL LETTER Y WITH DIAERESIS
diff --git a/Resources/cp437.txt b/Resources/cp437.txt
new file mode 100644
index 0000000..ae38e17
--- /dev/null
+++ b/Resources/cp437.txt
@@ -0,0 +1,273 @@
+#
+#    Name:     cp437_DOSLatinUS to Unicode table
+#    Unicode version: 2.0
+#    Table version: 2.00
+#    Table format:  Format A
+#    Date:          04/24/96
+#    Authors:       Lori Brownell <loribr@microsoft.com>
+#                   K.D. Chang    <a-kchang@microsoft.com>
+#    General notes: none
+#
+#    Format: Three tab-separated columns
+#        Column #1 is the cp437_DOSLatinUS code (in hex)
+#        Column #2 is the Unicode (in hex as 0xXXXX)
+#        Column #3 is the Unicode name (follows a comment sign, '#')
+#
+#    The entries are in cp437_DOSLatinUS order
+#
+0x00	0x0000	#NULL
+0x01	0x0001	#START OF HEADING
+0x02	0x0002	#START OF TEXT
+0x03	0x0003	#END OF TEXT
+0x04	0x0004	#END OF TRANSMISSION
+0x05	0x0005	#ENQUIRY
+0x06	0x0006	#ACKNOWLEDGE
+0x07	0x0007	#BELL
+0x08	0x0008	#BACKSPACE
+0x09	0x0009	#HORIZONTAL TABULATION
+0x0a	0x000a	#LINE FEED
+0x0b	0x000b	#VERTICAL TABULATION
+0x0c	0x000c	#FORM FEED
+0x0d	0x000d	#CARRIAGE RETURN
+0x0e	0x000e	#SHIFT OUT
+0x0f	0x000f	#SHIFT IN
+0x10	0x0010	#DATA LINK ESCAPE
+0x11	0x0011	#DEVICE CONTROL ONE
+0x12	0x0012	#DEVICE CONTROL TWO
+0x13	0x0013	#DEVICE CONTROL THREE
+0x14	0x0014	#DEVICE CONTROL FOUR
+0x15	0x0015	#NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#SYNCHRONOUS IDLE
+0x17	0x0017	#END OF TRANSMISSION BLOCK
+0x18	0x0018	#CANCEL
+0x19	0x0019	#END OF MEDIUM
+0x1a	0x001a	#SUBSTITUTE
+0x1b	0x001b	#ESCAPE
+0x1c	0x001c	#FILE SEPARATOR
+0x1d	0x001d	#GROUP SEPARATOR
+0x1e	0x001e	#RECORD SEPARATOR
+0x1f	0x001f	#UNIT SEPARATOR
+0x20	0x0020	#SPACE
+0x21	0x0021	#EXCLAMATION MARK
+0x22	0x0022	#QUOTATION MARK
+0x23	0x0023	#NUMBER SIGN
+0x24	0x0024	#DOLLAR SIGN
+0x25	0x0025	#PERCENT SIGN
+0x26	0x0026	#AMPERSAND
+0x27	0x0027	#APOSTROPHE
+0x28	0x0028	#LEFT PARENTHESIS
+0x29	0x0029	#RIGHT PARENTHESIS
+0x2a	0x002a	#ASTERISK
+0x2b	0x002b	#PLUS SIGN
+0x2c	0x002c	#COMMA
+0x2d	0x002d	#HYPHEN-MINUS
+0x2e	0x002e	#FULL STOP
+0x2f	0x002f	#SOLIDUS
+0x30	0x0030	#DIGIT ZERO
+0x31	0x0031	#DIGIT ONE
+0x32	0x0032	#DIGIT TWO
+0x33	0x0033	#DIGIT THREE
+0x34	0x0034	#DIGIT FOUR
+0x35	0x0035	#DIGIT FIVE
+0x36	0x0036	#DIGIT SIX
+0x37	0x0037	#DIGIT SEVEN
+0x38	0x0038	#DIGIT EIGHT
+0x39	0x0039	#DIGIT NINE
+0x3a	0x003a	#COLON
+0x3b	0x003b	#SEMICOLON
+0x3c	0x003c	#LESS-THAN SIGN
+0x3d	0x003d	#EQUALS SIGN
+0x3e	0x003e	#GREATER-THAN SIGN
+0x3f	0x003f	#QUESTION MARK
+0x40	0x0040	#COMMERCIAL AT
+0x41	0x0041	#LATIN CAPITAL LETTER A
+0x42	0x0042	#LATIN CAPITAL LETTER B
+0x43	0x0043	#LATIN CAPITAL LETTER C
+0x44	0x0044	#LATIN CAPITAL LETTER D
+0x45	0x0045	#LATIN CAPITAL LETTER E
+0x46	0x0046	#LATIN CAPITAL LETTER F
+0x47	0x0047	#LATIN CAPITAL LETTER G
+0x48	0x0048	#LATIN CAPITAL LETTER H
+0x49	0x0049	#LATIN CAPITAL LETTER I
+0x4a	0x004a	#LATIN CAPITAL LETTER J
+0x4b	0x004b	#LATIN CAPITAL LETTER K
+0x4c	0x004c	#LATIN CAPITAL LETTER L
+0x4d	0x004d	#LATIN CAPITAL LETTER M
+0x4e	0x004e	#LATIN CAPITAL LETTER N
+0x4f	0x004f	#LATIN CAPITAL LETTER O
+0x50	0x0050	#LATIN CAPITAL LETTER P
+0x51	0x0051	#LATIN CAPITAL LETTER Q
+0x52	0x0052	#LATIN CAPITAL LETTER R
+0x53	0x0053	#LATIN CAPITAL LETTER S
+0x54	0x0054	#LATIN CAPITAL LETTER T
+0x55	0x0055	#LATIN CAPITAL LETTER U
+0x56	0x0056	#LATIN CAPITAL LETTER V
+0x57	0x0057	#LATIN CAPITAL LETTER W
+0x58	0x0058	#LATIN CAPITAL LETTER X
+0x59	0x0059	#LATIN CAPITAL LETTER Y
+0x5a	0x005a	#LATIN CAPITAL LETTER Z
+0x5b	0x005b	#LEFT SQUARE BRACKET
+0x5c	0x005c	#REVERSE SOLIDUS
+0x5d	0x005d	#RIGHT SQUARE BRACKET
+0x5e	0x005e	#CIRCUMFLEX ACCENT
+0x5f	0x005f	#LOW LINE
+0x60	0x0060	#GRAVE ACCENT
+0x61	0x0061	#LATIN SMALL LETTER A
+0x62	0x0062	#LATIN SMALL LETTER B
+0x63	0x0063	#LATIN SMALL LETTER C
+0x64	0x0064	#LATIN SMALL LETTER D
+0x65	0x0065	#LATIN SMALL LETTER E
+0x66	0x0066	#LATIN SMALL LETTER F
+0x67	0x0067	#LATIN SMALL LETTER G
+0x68	0x0068	#LATIN SMALL LETTER H
+0x69	0x0069	#LATIN SMALL LETTER I
+0x6a	0x006a	#LATIN SMALL LETTER J
+0x6b	0x006b	#LATIN SMALL LETTER K
+0x6c	0x006c	#LATIN SMALL LETTER L
+0x6d	0x006d	#LATIN SMALL LETTER M
+0x6e	0x006e	#LATIN SMALL LETTER N
+0x6f	0x006f	#LATIN SMALL LETTER O
+0x70	0x0070	#LATIN SMALL LETTER P
+0x71	0x0071	#LATIN SMALL LETTER Q
+0x72	0x0072	#LATIN SMALL LETTER R
+0x73	0x0073	#LATIN SMALL LETTER S
+0x74	0x0074	#LATIN SMALL LETTER T
+0x75	0x0075	#LATIN SMALL LETTER U
+0x76	0x0076	#LATIN SMALL LETTER V
+0x77	0x0077	#LATIN SMALL LETTER W
+0x78	0x0078	#LATIN SMALL LETTER X
+0x79	0x0079	#LATIN SMALL LETTER Y
+0x7a	0x007a	#LATIN SMALL LETTER Z
+0x7b	0x007b	#LEFT CURLY BRACKET
+0x7c	0x007c	#VERTICAL LINE
+0x7d	0x007d	#RIGHT CURLY BRACKET
+0x7e	0x007e	#TILDE
+0x7f	0x007f	#DELETE
+0x80	0x00c7	#LATIN CAPITAL LETTER C WITH CEDILLA
+0x81	0x00fc	#LATIN SMALL LETTER U WITH DIAERESIS
+0x82	0x00e9	#LATIN SMALL LETTER E WITH ACUTE
+0x83	0x00e2	#LATIN SMALL LETTER A WITH CIRCUMFLEX
+0x84	0x00e4	#LATIN SMALL LETTER A WITH DIAERESIS
+0x85	0x00e0	#LATIN SMALL LETTER A WITH GRAVE
+0x86	0x00e5	#LATIN SMALL LETTER A WITH RING ABOVE
+0x87	0x00e7	#LATIN SMALL LETTER C WITH CEDILLA
+0x88	0x00ea	#LATIN SMALL LETTER E WITH CIRCUMFLEX
+0x89	0x00eb	#LATIN SMALL LETTER E WITH DIAERESIS
+0x8a	0x00e8	#LATIN SMALL LETTER E WITH GRAVE
+0x8b	0x00ef	#LATIN SMALL LETTER I WITH DIAERESIS
+0x8c	0x00ee	#LATIN SMALL LETTER I WITH CIRCUMFLEX
+0x8d	0x00ec	#LATIN SMALL LETTER I WITH GRAVE
+0x8e	0x00c4	#LATIN CAPITAL LETTER A WITH DIAERESIS
+0x8f	0x00c5	#LATIN CAPITAL LETTER A WITH RING ABOVE
+0x90	0x00c9	#LATIN CAPITAL LETTER E WITH ACUTE
+0x91	0x00e6	#LATIN SMALL LIGATURE AE
+0x92	0x00c6	#LATIN CAPITAL LIGATURE AE
+0x93	0x00f4	#LATIN SMALL LETTER O WITH CIRCUMFLEX
+0x94	0x00f6	#LATIN SMALL LETTER O WITH DIAERESIS
+0x95	0x00f2	#LATIN SMALL LETTER O WITH GRAVE
+0x96	0x00fb	#LATIN SMALL LETTER U WITH CIRCUMFLEX
+0x97	0x00f9	#LATIN SMALL LETTER U WITH GRAVE
+0x98	0x00ff	#LATIN SMALL LETTER Y WITH DIAERESIS
+0x99	0x00d6	#LATIN CAPITAL LETTER O WITH DIAERESIS
+0x9a	0x00dc	#LATIN CAPITAL LETTER U WITH DIAERESIS
+0x9b	0x00a2	#CENT SIGN
+0x9c	0x00a3	#POUND SIGN
+0x9d	0x00a5	#YEN SIGN
+0x9e	0x20a7	#PESETA SIGN
+0x9f	0x0192	#LATIN SMALL LETTER F WITH HOOK
+0xa0	0x00e1	#LATIN SMALL LETTER A WITH ACUTE
+0xa1	0x00ed	#LATIN SMALL LETTER I WITH ACUTE
+0xa2	0x00f3	#LATIN SMALL LETTER O WITH ACUTE
+0xa3	0x00fa	#LATIN SMALL LETTER U WITH ACUTE
+0xa4	0x00f1	#LATIN SMALL LETTER N WITH TILDE
+0xa5	0x00d1	#LATIN CAPITAL LETTER N WITH TILDE
+0xa6	0x00aa	#FEMININE ORDINAL INDICATOR
+0xa7	0x00ba	#MASCULINE ORDINAL INDICATOR
+0xa8	0x00bf	#INVERTED QUESTION MARK
+0xa9	0x2310	#REVERSED NOT SIGN
+0xaa	0x00ac	#NOT SIGN
+0xab	0x00bd	#VULGAR FRACTION ONE HALF
+0xac	0x00bc	#VULGAR FRACTION ONE QUARTER
+0xad	0x00a1	#INVERTED EXCLAMATION MARK
+0xae	0x00ab	#LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xaf	0x00bb	#RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xb0	0x2591	#LIGHT SHADE
+0xb1	0x2592	#MEDIUM SHADE
+0xb2	0x2593	#DARK SHADE
+0xb3	0x2502	#BOX DRAWINGS LIGHT VERTICAL
+0xb4	0x2524	#BOX DRAWINGS LIGHT VERTICAL AND LEFT
+0xb5	0x2561	#BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+0xb6	0x2562	#BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+0xb7	0x2556	#BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+0xb8	0x2555	#BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+0xb9	0x2563	#BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+0xba	0x2551	#BOX DRAWINGS DOUBLE VERTICAL
+0xbb	0x2557	#BOX DRAWINGS DOUBLE DOWN AND LEFT
+0xbc	0x255d	#BOX DRAWINGS DOUBLE UP AND LEFT
+0xbd	0x255c	#BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+0xbe	0x255b	#BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+0xbf	0x2510	#BOX DRAWINGS LIGHT DOWN AND LEFT
+0xc0	0x2514	#BOX DRAWINGS LIGHT UP AND RIGHT
+0xc1	0x2534	#BOX DRAWINGS LIGHT UP AND HORIZONTAL
+0xc2	0x252c	#BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+0xc3	0x251c	#BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+0xc4	0x2500	#BOX DRAWINGS LIGHT HORIZONTAL
+0xc5	0x253c	#BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+0xc6	0x255e	#BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+0xc7	0x255f	#BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+0xc8	0x255a	#BOX DRAWINGS DOUBLE UP AND RIGHT
+0xc9	0x2554	#BOX DRAWINGS DOUBLE DOWN AND RIGHT
+0xca	0x2569	#BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+0xcb	0x2566	#BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+0xcc	0x2560	#BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+0xcd	0x2550	#BOX DRAWINGS DOUBLE HORIZONTAL
+0xce	0x256c	#BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+0xcf	0x2567	#BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+0xd0	0x2568	#BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+0xd1	0x2564	#BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+0xd2	0x2565	#BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+0xd3	0x2559	#BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+0xd4	0x2558	#BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+0xd5	0x2552	#BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+0xd6	0x2553	#BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+0xd7	0x256b	#BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+0xd8	0x256a	#BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+0xd9	0x2518	#BOX DRAWINGS LIGHT UP AND LEFT
+0xda	0x250c	#BOX DRAWINGS LIGHT DOWN AND RIGHT
+0xdb	0x2588	#FULL BLOCK
+0xdc	0x2584	#LOWER HALF BLOCK
+0xdd	0x258c	#LEFT HALF BLOCK
+0xde	0x2590	#RIGHT HALF BLOCK
+0xdf	0x2580	#UPPER HALF BLOCK
+0xe0	0x03b1	#GREEK SMALL LETTER ALPHA
+0xe1	0x00df	#LATIN SMALL LETTER SHARP S
+0xe2	0x0393	#GREEK CAPITAL LETTER GAMMA
+0xe3	0x03c0	#GREEK SMALL LETTER PI
+0xe4	0x03a3	#GREEK CAPITAL LETTER SIGMA
+0xe5	0x03c3	#GREEK SMALL LETTER SIGMA
+0xe6	0x00b5	#MICRO SIGN
+0xe7	0x03c4	#GREEK SMALL LETTER TAU
+0xe8	0x03a6	#GREEK CAPITAL LETTER PHI
+0xe9	0x0398	#GREEK CAPITAL LETTER THETA
+0xea	0x03a9	#GREEK CAPITAL LETTER OMEGA
+0xeb	0x03b4	#GREEK SMALL LETTER DELTA
+0xec	0x221e	#INFINITY
+0xed	0x03c6	#GREEK SMALL LETTER PHI
+0xee	0x03b5	#GREEK SMALL LETTER EPSILON
+0xef	0x2229	#INTERSECTION
+0xf0	0x2261	#IDENTICAL TO
+0xf1	0x00b1	#PLUS-MINUS SIGN
+0xf2	0x2265	#GREATER-THAN OR EQUAL TO
+0xf3	0x2264	#LESS-THAN OR EQUAL TO
+0xf4	0x2320	#TOP HALF INTEGRAL
+0xf5	0x2321	#BOTTOM HALF INTEGRAL
+0xf6	0x00f7	#DIVISION SIGN
+0xf7	0x2248	#ALMOST EQUAL TO
+0xf8	0x00b0	#DEGREE SIGN
+0xf9	0x2219	#BULLET OPERATOR
+0xfa	0x00b7	#MIDDLE DOT
+0xfb	0x221a	#SQUARE ROOT
+0xfc	0x207f	#SUPERSCRIPT LATIN SMALL LETTER N
+0xfd	0x00b2	#SUPERSCRIPT TWO
+0xfe	0x25a0	#BLACK SQUARE
+0xff	0x00a0	#NO-BREAK SPACE
diff --git a/Resources/cp850.txt b/Resources/cp850.txt
new file mode 100644
index 0000000..590b1af
--- /dev/null
+++ b/Resources/cp850.txt
@@ -0,0 +1,273 @@
+#
+#    Name:     cp850_DOSLatin1 to Unicode table
+#    Unicode version: 2.0
+#    Table version: 2.00
+#    Table format:  Format A
+#    Date:          04/24/96
+#    Authors:       Lori Brownell <loribr@microsoft.com>
+#                   K.D. Chang    <a-kchang@microsoft.com>
+#    General notes: none
+#
+#    Format: Three tab-separated columns
+#        Column #1 is the cp850_DOSLatin1 code (in hex)
+#        Column #2 is the Unicode (in hex as 0xXXXX)
+#        Column #3 is the Unicode name (follows a comment sign, '#')
+#
+#    The entries are in cp850_DOSLatin1 order
+#
+0x00	0x0000	#NULL
+0x01	0x0001	#START OF HEADING
+0x02	0x0002	#START OF TEXT
+0x03	0x0003	#END OF TEXT
+0x04	0x0004	#END OF TRANSMISSION
+0x05	0x0005	#ENQUIRY
+0x06	0x0006	#ACKNOWLEDGE
+0x07	0x0007	#BELL
+0x08	0x0008	#BACKSPACE
+0x09	0x0009	#HORIZONTAL TABULATION
+0x0a	0x000a	#LINE FEED
+0x0b	0x000b	#VERTICAL TABULATION
+0x0c	0x000c	#FORM FEED
+0x0d	0x000d	#CARRIAGE RETURN
+0x0e	0x000e	#SHIFT OUT
+0x0f	0x000f	#SHIFT IN
+0x10	0x0010	#DATA LINK ESCAPE
+0x11	0x0011	#DEVICE CONTROL ONE
+0x12	0x0012	#DEVICE CONTROL TWO
+0x13	0x0013	#DEVICE CONTROL THREE
+0x14	0x0014	#DEVICE CONTROL FOUR
+0x15	0x0015	#NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#SYNCHRONOUS IDLE
+0x17	0x0017	#END OF TRANSMISSION BLOCK
+0x18	0x0018	#CANCEL
+0x19	0x0019	#END OF MEDIUM
+0x1a	0x001a	#SUBSTITUTE
+0x1b	0x001b	#ESCAPE
+0x1c	0x001c	#FILE SEPARATOR
+0x1d	0x001d	#GROUP SEPARATOR
+0x1e	0x001e	#RECORD SEPARATOR
+0x1f	0x001f	#UNIT SEPARATOR
+0x20	0x0020	#SPACE
+0x21	0x0021	#EXCLAMATION MARK
+0x22	0x0022	#QUOTATION MARK
+0x23	0x0023	#NUMBER SIGN
+0x24	0x0024	#DOLLAR SIGN
+0x25	0x0025	#PERCENT SIGN
+0x26	0x0026	#AMPERSAND
+0x27	0x0027	#APOSTROPHE
+0x28	0x0028	#LEFT PARENTHESIS
+0x29	0x0029	#RIGHT PARENTHESIS
+0x2a	0x002a	#ASTERISK
+0x2b	0x002b	#PLUS SIGN
+0x2c	0x002c	#COMMA
+0x2d	0x002d	#HYPHEN-MINUS
+0x2e	0x002e	#FULL STOP
+0x2f	0x002f	#SOLIDUS
+0x30	0x0030	#DIGIT ZERO
+0x31	0x0031	#DIGIT ONE
+0x32	0x0032	#DIGIT TWO
+0x33	0x0033	#DIGIT THREE
+0x34	0x0034	#DIGIT FOUR
+0x35	0x0035	#DIGIT FIVE
+0x36	0x0036	#DIGIT SIX
+0x37	0x0037	#DIGIT SEVEN
+0x38	0x0038	#DIGIT EIGHT
+0x39	0x0039	#DIGIT NINE
+0x3a	0x003a	#COLON
+0x3b	0x003b	#SEMICOLON
+0x3c	0x003c	#LESS-THAN SIGN
+0x3d	0x003d	#EQUALS SIGN
+0x3e	0x003e	#GREATER-THAN SIGN
+0x3f	0x003f	#QUESTION MARK
+0x40	0x0040	#COMMERCIAL AT
+0x41	0x0041	#LATIN CAPITAL LETTER A
+0x42	0x0042	#LATIN CAPITAL LETTER B
+0x43	0x0043	#LATIN CAPITAL LETTER C
+0x44	0x0044	#LATIN CAPITAL LETTER D
+0x45	0x0045	#LATIN CAPITAL LETTER E
+0x46	0x0046	#LATIN CAPITAL LETTER F
+0x47	0x0047	#LATIN CAPITAL LETTER G
+0x48	0x0048	#LATIN CAPITAL LETTER H
+0x49	0x0049	#LATIN CAPITAL LETTER I
+0x4a	0x004a	#LATIN CAPITAL LETTER J
+0x4b	0x004b	#LATIN CAPITAL LETTER K
+0x4c	0x004c	#LATIN CAPITAL LETTER L
+0x4d	0x004d	#LATIN CAPITAL LETTER M
+0x4e	0x004e	#LATIN CAPITAL LETTER N
+0x4f	0x004f	#LATIN CAPITAL LETTER O
+0x50	0x0050	#LATIN CAPITAL LETTER P
+0x51	0x0051	#LATIN CAPITAL LETTER Q
+0x52	0x0052	#LATIN CAPITAL LETTER R
+0x53	0x0053	#LATIN CAPITAL LETTER S
+0x54	0x0054	#LATIN CAPITAL LETTER T
+0x55	0x0055	#LATIN CAPITAL LETTER U
+0x56	0x0056	#LATIN CAPITAL LETTER V
+0x57	0x0057	#LATIN CAPITAL LETTER W
+0x58	0x0058	#LATIN CAPITAL LETTER X
+0x59	0x0059	#LATIN CAPITAL LETTER Y
+0x5a	0x005a	#LATIN CAPITAL LETTER Z
+0x5b	0x005b	#LEFT SQUARE BRACKET
+0x5c	0x005c	#REVERSE SOLIDUS
+0x5d	0x005d	#RIGHT SQUARE BRACKET
+0x5e	0x005e	#CIRCUMFLEX ACCENT
+0x5f	0x005f	#LOW LINE
+0x60	0x0060	#GRAVE ACCENT
+0x61	0x0061	#LATIN SMALL LETTER A
+0x62	0x0062	#LATIN SMALL LETTER B
+0x63	0x0063	#LATIN SMALL LETTER C
+0x64	0x0064	#LATIN SMALL LETTER D
+0x65	0x0065	#LATIN SMALL LETTER E
+0x66	0x0066	#LATIN SMALL LETTER F
+0x67	0x0067	#LATIN SMALL LETTER G
+0x68	0x0068	#LATIN SMALL LETTER H
+0x69	0x0069	#LATIN SMALL LETTER I
+0x6a	0x006a	#LATIN SMALL LETTER J
+0x6b	0x006b	#LATIN SMALL LETTER K
+0x6c	0x006c	#LATIN SMALL LETTER L
+0x6d	0x006d	#LATIN SMALL LETTER M
+0x6e	0x006e	#LATIN SMALL LETTER N
+0x6f	0x006f	#LATIN SMALL LETTER O
+0x70	0x0070	#LATIN SMALL LETTER P
+0x71	0x0071	#LATIN SMALL LETTER Q
+0x72	0x0072	#LATIN SMALL LETTER R
+0x73	0x0073	#LATIN SMALL LETTER S
+0x74	0x0074	#LATIN SMALL LETTER T
+0x75	0x0075	#LATIN SMALL LETTER U
+0x76	0x0076	#LATIN SMALL LETTER V
+0x77	0x0077	#LATIN SMALL LETTER W
+0x78	0x0078	#LATIN SMALL LETTER X
+0x79	0x0079	#LATIN SMALL LETTER Y
+0x7a	0x007a	#LATIN SMALL LETTER Z
+0x7b	0x007b	#LEFT CURLY BRACKET
+0x7c	0x007c	#VERTICAL LINE
+0x7d	0x007d	#RIGHT CURLY BRACKET
+0x7e	0x007e	#TILDE
+0x7f	0x007f	#DELETE
+0x80	0x00c7	#LATIN CAPITAL LETTER C WITH CEDILLA
+0x81	0x00fc	#LATIN SMALL LETTER U WITH DIAERESIS
+0x82	0x00e9	#LATIN SMALL LETTER E WITH ACUTE
+0x83	0x00e2	#LATIN SMALL LETTER A WITH CIRCUMFLEX
+0x84	0x00e4	#LATIN SMALL LETTER A WITH DIAERESIS
+0x85	0x00e0	#LATIN SMALL LETTER A WITH GRAVE
+0x86	0x00e5	#LATIN SMALL LETTER A WITH RING ABOVE
+0x87	0x00e7	#LATIN SMALL LETTER C WITH CEDILLA
+0x88	0x00ea	#LATIN SMALL LETTER E WITH CIRCUMFLEX
+0x89	0x00eb	#LATIN SMALL LETTER E WITH DIAERESIS
+0x8a	0x00e8	#LATIN SMALL LETTER E WITH GRAVE
+0x8b	0x00ef	#LATIN SMALL LETTER I WITH DIAERESIS
+0x8c	0x00ee	#LATIN SMALL LETTER I WITH CIRCUMFLEX
+0x8d	0x00ec	#LATIN SMALL LETTER I WITH GRAVE
+0x8e	0x00c4	#LATIN CAPITAL LETTER A WITH DIAERESIS
+0x8f	0x00c5	#LATIN CAPITAL LETTER A WITH RING ABOVE
+0x90	0x00c9	#LATIN CAPITAL LETTER E WITH ACUTE
+0x91	0x00e6	#LATIN SMALL LIGATURE AE
+0x92	0x00c6	#LATIN CAPITAL LIGATURE AE
+0x93	0x00f4	#LATIN SMALL LETTER O WITH CIRCUMFLEX
+0x94	0x00f6	#LATIN SMALL LETTER O WITH DIAERESIS
+0x95	0x00f2	#LATIN SMALL LETTER O WITH GRAVE
+0x96	0x00fb	#LATIN SMALL LETTER U WITH CIRCUMFLEX
+0x97	0x00f9	#LATIN SMALL LETTER U WITH GRAVE
+0x98	0x00ff	#LATIN SMALL LETTER Y WITH DIAERESIS
+0x99	0x00d6	#LATIN CAPITAL LETTER O WITH DIAERESIS
+0x9a	0x00dc	#LATIN CAPITAL LETTER U WITH DIAERESIS
+0x9b	0x00f8	#LATIN SMALL LETTER O WITH STROKE
+0x9c	0x00a3	#POUND SIGN
+0x9d	0x00d8	#LATIN CAPITAL LETTER O WITH STROKE
+0x9e	0x00d7	#MULTIPLICATION SIGN
+0x9f	0x0192	#LATIN SMALL LETTER F WITH HOOK
+0xa0	0x00e1	#LATIN SMALL LETTER A WITH ACUTE
+0xa1	0x00ed	#LATIN SMALL LETTER I WITH ACUTE
+0xa2	0x00f3	#LATIN SMALL LETTER O WITH ACUTE
+0xa3	0x00fa	#LATIN SMALL LETTER U WITH ACUTE
+0xa4	0x00f1	#LATIN SMALL LETTER N WITH TILDE
+0xa5	0x00d1	#LATIN CAPITAL LETTER N WITH TILDE
+0xa6	0x00aa	#FEMININE ORDINAL INDICATOR
+0xa7	0x00ba	#MASCULINE ORDINAL INDICATOR
+0xa8	0x00bf	#INVERTED QUESTION MARK
+0xa9	0x00ae	#REGISTERED SIGN
+0xaa	0x00ac	#NOT SIGN
+0xab	0x00bd	#VULGAR FRACTION ONE HALF
+0xac	0x00bc	#VULGAR FRACTION ONE QUARTER
+0xad	0x00a1	#INVERTED EXCLAMATION MARK
+0xae	0x00ab	#LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xaf	0x00bb	#RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xb0	0x2591	#LIGHT SHADE
+0xb1	0x2592	#MEDIUM SHADE
+0xb2	0x2593	#DARK SHADE
+0xb3	0x2502	#BOX DRAWINGS LIGHT VERTICAL
+0xb4	0x2524	#BOX DRAWINGS LIGHT VERTICAL AND LEFT
+0xb5	0x00c1	#LATIN CAPITAL LETTER A WITH ACUTE
+0xb6	0x00c2	#LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xb7	0x00c0	#LATIN CAPITAL LETTER A WITH GRAVE
+0xb8	0x00a9	#COPYRIGHT SIGN
+0xb9	0x2563	#BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+0xba	0x2551	#BOX DRAWINGS DOUBLE VERTICAL
+0xbb	0x2557	#BOX DRAWINGS DOUBLE DOWN AND LEFT
+0xbc	0x255d	#BOX DRAWINGS DOUBLE UP AND LEFT
+0xbd	0x00a2	#CENT SIGN
+0xbe	0x00a5	#YEN SIGN
+0xbf	0x2510	#BOX DRAWINGS LIGHT DOWN AND LEFT
+0xc0	0x2514	#BOX DRAWINGS LIGHT UP AND RIGHT
+0xc1	0x2534	#BOX DRAWINGS LIGHT UP AND HORIZONTAL
+0xc2	0x252c	#BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+0xc3	0x251c	#BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+0xc4	0x2500	#BOX DRAWINGS LIGHT HORIZONTAL
+0xc5	0x253c	#BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+0xc6	0x00e3	#LATIN SMALL LETTER A WITH TILDE
+0xc7	0x00c3	#LATIN CAPITAL LETTER A WITH TILDE
+0xc8	0x255a	#BOX DRAWINGS DOUBLE UP AND RIGHT
+0xc9	0x2554	#BOX DRAWINGS DOUBLE DOWN AND RIGHT
+0xca	0x2569	#BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+0xcb	0x2566	#BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+0xcc	0x2560	#BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+0xcd	0x2550	#BOX DRAWINGS DOUBLE HORIZONTAL
+0xce	0x256c	#BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+0xcf	0x00a4	#CURRENCY SIGN
+0xd0	0x00f0	#LATIN SMALL LETTER ETH
+0xd1	0x00d0	#LATIN CAPITAL LETTER ETH
+0xd2	0x00ca	#LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xd3	0x00cb	#LATIN CAPITAL LETTER E WITH DIAERESIS
+0xd4	0x00c8	#LATIN CAPITAL LETTER E WITH GRAVE
+0xd5	0x0131	#LATIN SMALL LETTER DOTLESS I
+0xd6	0x00cd	#LATIN CAPITAL LETTER I WITH ACUTE
+0xd7	0x00ce	#LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xd8	0x00cf	#LATIN CAPITAL LETTER I WITH DIAERESIS
+0xd9	0x2518	#BOX DRAWINGS LIGHT UP AND LEFT
+0xda	0x250c	#BOX DRAWINGS LIGHT DOWN AND RIGHT
+0xdb	0x2588	#FULL BLOCK
+0xdc	0x2584	#LOWER HALF BLOCK
+0xdd	0x00a6	#BROKEN BAR
+0xde	0x00cc	#LATIN CAPITAL LETTER I WITH GRAVE
+0xdf	0x2580	#UPPER HALF BLOCK
+0xe0	0x00d3	#LATIN CAPITAL LETTER O WITH ACUTE
+0xe1	0x00df	#LATIN SMALL LETTER SHARP S
+0xe2	0x00d4	#LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xe3	0x00d2	#LATIN CAPITAL LETTER O WITH GRAVE
+0xe4	0x00f5	#LATIN SMALL LETTER O WITH TILDE
+0xe5	0x00d5	#LATIN CAPITAL LETTER O WITH TILDE
+0xe6	0x00b5	#MICRO SIGN
+0xe7	0x00fe	#LATIN SMALL LETTER THORN
+0xe8	0x00de	#LATIN CAPITAL LETTER THORN
+0xe9	0x00da	#LATIN CAPITAL LETTER U WITH ACUTE
+0xea	0x00db	#LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xeb	0x00d9	#LATIN CAPITAL LETTER U WITH GRAVE
+0xec	0x00fd	#LATIN SMALL LETTER Y WITH ACUTE
+0xed	0x00dd	#LATIN CAPITAL LETTER Y WITH ACUTE
+0xee	0x00af	#MACRON
+0xef	0x00b4	#ACUTE ACCENT
+0xf0	0x00ad	#SOFT HYPHEN
+0xf1	0x00b1	#PLUS-MINUS SIGN
+0xf2	0x2017	#DOUBLE LOW LINE
+0xf3	0x00be	#VULGAR FRACTION THREE QUARTERS
+0xf4	0x00b6	#PILCROW SIGN
+0xf5	0x00a7	#SECTION SIGN
+0xf6	0x00f7	#DIVISION SIGN
+0xf7	0x00b8	#CEDILLA
+0xf8	0x00b0	#DEGREE SIGN
+0xf9	0x00a8	#DIAERESIS
+0xfa	0x00b7	#MIDDLE DOT
+0xfb	0x00b9	#SUPERSCRIPT ONE
+0xfc	0x00b3	#SUPERSCRIPT THREE
+0xfd	0x00b2	#SUPERSCRIPT TWO
+0xfe	0x25a0	#BLACK SQUARE
+0xff	0x00a0	#NO-BREAK SPACE
diff --git a/Resources/cp852.txt b/Resources/cp852.txt
new file mode 100644
index 0000000..2f2daba
--- /dev/null
+++ b/Resources/cp852.txt
@@ -0,0 +1,273 @@
+#
+#    Name:     cp852_DOSLatin2 to Unicode table
+#    Unicode version: 2.0
+#    Table version: 2.00
+#    Table format:  Format A
+#    Date:          04/24/96
+#    Authors:       Lori Brownell <loribr@microsoft.com>
+#                   K.D. Chang    <a-kchang@microsoft.com>
+#    General notes: none
+#
+#    Format: Three tab-separated columns
+#        Column #1 is the cp852_DOSLatin2 code (in hex)
+#        Column #2 is the Unicode (in hex as 0xXXXX)
+#        Column #3 is the Unicode name (follows a comment sign, '#')
+#
+#    The entries are in cp852_DOSLatin2 order
+#
+0x00	0x0000	#NULL
+0x01	0x0001	#START OF HEADING
+0x02	0x0002	#START OF TEXT
+0x03	0x0003	#END OF TEXT
+0x04	0x0004	#END OF TRANSMISSION
+0x05	0x0005	#ENQUIRY
+0x06	0x0006	#ACKNOWLEDGE
+0x07	0x0007	#BELL
+0x08	0x0008	#BACKSPACE
+0x09	0x0009	#HORIZONTAL TABULATION
+0x0a	0x000a	#LINE FEED
+0x0b	0x000b	#VERTICAL TABULATION
+0x0c	0x000c	#FORM FEED
+0x0d	0x000d	#CARRIAGE RETURN
+0x0e	0x000e	#SHIFT OUT
+0x0f	0x000f	#SHIFT IN
+0x10	0x0010	#DATA LINK ESCAPE
+0x11	0x0011	#DEVICE CONTROL ONE
+0x12	0x0012	#DEVICE CONTROL TWO
+0x13	0x0013	#DEVICE CONTROL THREE
+0x14	0x0014	#DEVICE CONTROL FOUR
+0x15	0x0015	#NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#SYNCHRONOUS IDLE
+0x17	0x0017	#END OF TRANSMISSION BLOCK
+0x18	0x0018	#CANCEL
+0x19	0x0019	#END OF MEDIUM
+0x1a	0x001a	#SUBSTITUTE
+0x1b	0x001b	#ESCAPE
+0x1c	0x001c	#FILE SEPARATOR
+0x1d	0x001d	#GROUP SEPARATOR
+0x1e	0x001e	#RECORD SEPARATOR
+0x1f	0x001f	#UNIT SEPARATOR
+0x20	0x0020	#SPACE
+0x21	0x0021	#EXCLAMATION MARK
+0x22	0x0022	#QUOTATION MARK
+0x23	0x0023	#NUMBER SIGN
+0x24	0x0024	#DOLLAR SIGN
+0x25	0x0025	#PERCENT SIGN
+0x26	0x0026	#AMPERSAND
+0x27	0x0027	#APOSTROPHE
+0x28	0x0028	#LEFT PARENTHESIS
+0x29	0x0029	#RIGHT PARENTHESIS
+0x2a	0x002a	#ASTERISK
+0x2b	0x002b	#PLUS SIGN
+0x2c	0x002c	#COMMA
+0x2d	0x002d	#HYPHEN-MINUS
+0x2e	0x002e	#FULL STOP
+0x2f	0x002f	#SOLIDUS
+0x30	0x0030	#DIGIT ZERO
+0x31	0x0031	#DIGIT ONE
+0x32	0x0032	#DIGIT TWO
+0x33	0x0033	#DIGIT THREE
+0x34	0x0034	#DIGIT FOUR
+0x35	0x0035	#DIGIT FIVE
+0x36	0x0036	#DIGIT SIX
+0x37	0x0037	#DIGIT SEVEN
+0x38	0x0038	#DIGIT EIGHT
+0x39	0x0039	#DIGIT NINE
+0x3a	0x003a	#COLON
+0x3b	0x003b	#SEMICOLON
+0x3c	0x003c	#LESS-THAN SIGN
+0x3d	0x003d	#EQUALS SIGN
+0x3e	0x003e	#GREATER-THAN SIGN
+0x3f	0x003f	#QUESTION MARK
+0x40	0x0040	#COMMERCIAL AT
+0x41	0x0041	#LATIN CAPITAL LETTER A
+0x42	0x0042	#LATIN CAPITAL LETTER B
+0x43	0x0043	#LATIN CAPITAL LETTER C
+0x44	0x0044	#LATIN CAPITAL LETTER D
+0x45	0x0045	#LATIN CAPITAL LETTER E
+0x46	0x0046	#LATIN CAPITAL LETTER F
+0x47	0x0047	#LATIN CAPITAL LETTER G
+0x48	0x0048	#LATIN CAPITAL LETTER H
+0x49	0x0049	#LATIN CAPITAL LETTER I
+0x4a	0x004a	#LATIN CAPITAL LETTER J
+0x4b	0x004b	#LATIN CAPITAL LETTER K
+0x4c	0x004c	#LATIN CAPITAL LETTER L
+0x4d	0x004d	#LATIN CAPITAL LETTER M
+0x4e	0x004e	#LATIN CAPITAL LETTER N
+0x4f	0x004f	#LATIN CAPITAL LETTER O
+0x50	0x0050	#LATIN CAPITAL LETTER P
+0x51	0x0051	#LATIN CAPITAL LETTER Q
+0x52	0x0052	#LATIN CAPITAL LETTER R
+0x53	0x0053	#LATIN CAPITAL LETTER S
+0x54	0x0054	#LATIN CAPITAL LETTER T
+0x55	0x0055	#LATIN CAPITAL LETTER U
+0x56	0x0056	#LATIN CAPITAL LETTER V
+0x57	0x0057	#LATIN CAPITAL LETTER W
+0x58	0x0058	#LATIN CAPITAL LETTER X
+0x59	0x0059	#LATIN CAPITAL LETTER Y
+0x5a	0x005a	#LATIN CAPITAL LETTER Z
+0x5b	0x005b	#LEFT SQUARE BRACKET
+0x5c	0x005c	#REVERSE SOLIDUS
+0x5d	0x005d	#RIGHT SQUARE BRACKET
+0x5e	0x005e	#CIRCUMFLEX ACCENT
+0x5f	0x005f	#LOW LINE
+0x60	0x0060	#GRAVE ACCENT
+0x61	0x0061	#LATIN SMALL LETTER A
+0x62	0x0062	#LATIN SMALL LETTER B
+0x63	0x0063	#LATIN SMALL LETTER C
+0x64	0x0064	#LATIN SMALL LETTER D
+0x65	0x0065	#LATIN SMALL LETTER E
+0x66	0x0066	#LATIN SMALL LETTER F
+0x67	0x0067	#LATIN SMALL LETTER G
+0x68	0x0068	#LATIN SMALL LETTER H
+0x69	0x0069	#LATIN SMALL LETTER I
+0x6a	0x006a	#LATIN SMALL LETTER J
+0x6b	0x006b	#LATIN SMALL LETTER K
+0x6c	0x006c	#LATIN SMALL LETTER L
+0x6d	0x006d	#LATIN SMALL LETTER M
+0x6e	0x006e	#LATIN SMALL LETTER N
+0x6f	0x006f	#LATIN SMALL LETTER O
+0x70	0x0070	#LATIN SMALL LETTER P
+0x71	0x0071	#LATIN SMALL LETTER Q
+0x72	0x0072	#LATIN SMALL LETTER R
+0x73	0x0073	#LATIN SMALL LETTER S
+0x74	0x0074	#LATIN SMALL LETTER T
+0x75	0x0075	#LATIN SMALL LETTER U
+0x76	0x0076	#LATIN SMALL LETTER V
+0x77	0x0077	#LATIN SMALL LETTER W
+0x78	0x0078	#LATIN SMALL LETTER X
+0x79	0x0079	#LATIN SMALL LETTER Y
+0x7a	0x007a	#LATIN SMALL LETTER Z
+0x7b	0x007b	#LEFT CURLY BRACKET
+0x7c	0x007c	#VERTICAL LINE
+0x7d	0x007d	#RIGHT CURLY BRACKET
+0x7e	0x007e	#TILDE
+0x7f	0x007f	#DELETE
+0x80	0x00c7	#LATIN CAPITAL LETTER C WITH CEDILLA
+0x81	0x00fc	#LATIN SMALL LETTER U WITH DIAERESIS
+0x82	0x00e9	#LATIN SMALL LETTER E WITH ACUTE
+0x83	0x00e2	#LATIN SMALL LETTER A WITH CIRCUMFLEX
+0x84	0x00e4	#LATIN SMALL LETTER A WITH DIAERESIS
+0x85	0x016f	#LATIN SMALL LETTER U WITH RING ABOVE
+0x86	0x0107	#LATIN SMALL LETTER C WITH ACUTE
+0x87	0x00e7	#LATIN SMALL LETTER C WITH CEDILLA
+0x88	0x0142	#LATIN SMALL LETTER L WITH STROKE
+0x89	0x00eb	#LATIN SMALL LETTER E WITH DIAERESIS
+0x8a	0x0150	#LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+0x8b	0x0151	#LATIN SMALL LETTER O WITH DOUBLE ACUTE
+0x8c	0x00ee	#LATIN SMALL LETTER I WITH CIRCUMFLEX
+0x8d	0x0179	#LATIN CAPITAL LETTER Z WITH ACUTE
+0x8e	0x00c4	#LATIN CAPITAL LETTER A WITH DIAERESIS
+0x8f	0x0106	#LATIN CAPITAL LETTER C WITH ACUTE
+0x90	0x00c9	#LATIN CAPITAL LETTER E WITH ACUTE
+0x91	0x0139	#LATIN CAPITAL LETTER L WITH ACUTE
+0x92	0x013a	#LATIN SMALL LETTER L WITH ACUTE
+0x93	0x00f4	#LATIN SMALL LETTER O WITH CIRCUMFLEX
+0x94	0x00f6	#LATIN SMALL LETTER O WITH DIAERESIS
+0x95	0x013d	#LATIN CAPITAL LETTER L WITH CARON
+0x96	0x013e	#LATIN SMALL LETTER L WITH CARON
+0x97	0x015a	#LATIN CAPITAL LETTER S WITH ACUTE
+0x98	0x015b	#LATIN SMALL LETTER S WITH ACUTE
+0x99	0x00d6	#LATIN CAPITAL LETTER O WITH DIAERESIS
+0x9a	0x00dc	#LATIN CAPITAL LETTER U WITH DIAERESIS
+0x9b	0x0164	#LATIN CAPITAL LETTER T WITH CARON
+0x9c	0x0165	#LATIN SMALL LETTER T WITH CARON
+0x9d	0x0141	#LATIN CAPITAL LETTER L WITH STROKE
+0x9e	0x00d7	#MULTIPLICATION SIGN
+0x9f	0x010d	#LATIN SMALL LETTER C WITH CARON
+0xa0	0x00e1	#LATIN SMALL LETTER A WITH ACUTE
+0xa1	0x00ed	#LATIN SMALL LETTER I WITH ACUTE
+0xa2	0x00f3	#LATIN SMALL LETTER O WITH ACUTE
+0xa3	0x00fa	#LATIN SMALL LETTER U WITH ACUTE
+0xa4	0x0104	#LATIN CAPITAL LETTER A WITH OGONEK
+0xa5	0x0105	#LATIN SMALL LETTER A WITH OGONEK
+0xa6	0x017d	#LATIN CAPITAL LETTER Z WITH CARON
+0xa7	0x017e	#LATIN SMALL LETTER Z WITH CARON
+0xa8	0x0118	#LATIN CAPITAL LETTER E WITH OGONEK
+0xa9	0x0119	#LATIN SMALL LETTER E WITH OGONEK
+0xaa	0x00ac	#NOT SIGN
+0xab	0x017a	#LATIN SMALL LETTER Z WITH ACUTE
+0xac	0x010c	#LATIN CAPITAL LETTER C WITH CARON
+0xad	0x015f	#LATIN SMALL LETTER S WITH CEDILLA
+0xae	0x00ab	#LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xaf	0x00bb	#RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xb0	0x2591	#LIGHT SHADE
+0xb1	0x2592	#MEDIUM SHADE
+0xb2	0x2593	#DARK SHADE
+0xb3	0x2502	#BOX DRAWINGS LIGHT VERTICAL
+0xb4	0x2524	#BOX DRAWINGS LIGHT VERTICAL AND LEFT
+0xb5	0x00c1	#LATIN CAPITAL LETTER A WITH ACUTE
+0xb6	0x00c2	#LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xb7	0x011a	#LATIN CAPITAL LETTER E WITH CARON
+0xb8	0x015e	#LATIN CAPITAL LETTER S WITH CEDILLA
+0xb9	0x2563	#BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+0xba	0x2551	#BOX DRAWINGS DOUBLE VERTICAL
+0xbb	0x2557	#BOX DRAWINGS DOUBLE DOWN AND LEFT
+0xbc	0x255d	#BOX DRAWINGS DOUBLE UP AND LEFT
+0xbd	0x017b	#LATIN CAPITAL LETTER Z WITH DOT ABOVE
+0xbe	0x017c	#LATIN SMALL LETTER Z WITH DOT ABOVE
+0xbf	0x2510	#BOX DRAWINGS LIGHT DOWN AND LEFT
+0xc0	0x2514	#BOX DRAWINGS LIGHT UP AND RIGHT
+0xc1	0x2534	#BOX DRAWINGS LIGHT UP AND HORIZONTAL
+0xc2	0x252c	#BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+0xc3	0x251c	#BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+0xc4	0x2500	#BOX DRAWINGS LIGHT HORIZONTAL
+0xc5	0x253c	#BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+0xc6	0x0102	#LATIN CAPITAL LETTER A WITH BREVE
+0xc7	0x0103	#LATIN SMALL LETTER A WITH BREVE
+0xc8	0x255a	#BOX DRAWINGS DOUBLE UP AND RIGHT
+0xc9	0x2554	#BOX DRAWINGS DOUBLE DOWN AND RIGHT
+0xca	0x2569	#BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+0xcb	0x2566	#BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+0xcc	0x2560	#BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+0xcd	0x2550	#BOX DRAWINGS DOUBLE HORIZONTAL
+0xce	0x256c	#BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+0xcf	0x00a4	#CURRENCY SIGN
+0xd0	0x0111	#LATIN SMALL LETTER D WITH STROKE
+0xd1	0x0110	#LATIN CAPITAL LETTER D WITH STROKE
+0xd2	0x010e	#LATIN CAPITAL LETTER D WITH CARON
+0xd3	0x00cb	#LATIN CAPITAL LETTER E WITH DIAERESIS
+0xd4	0x010f	#LATIN SMALL LETTER D WITH CARON
+0xd5	0x0147	#LATIN CAPITAL LETTER N WITH CARON
+0xd6	0x00cd	#LATIN CAPITAL LETTER I WITH ACUTE
+0xd7	0x00ce	#LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xd8	0x011b	#LATIN SMALL LETTER E WITH CARON
+0xd9	0x2518	#BOX DRAWINGS LIGHT UP AND LEFT
+0xda	0x250c	#BOX DRAWINGS LIGHT DOWN AND RIGHT
+0xdb	0x2588	#FULL BLOCK
+0xdc	0x2584	#LOWER HALF BLOCK
+0xdd	0x0162	#LATIN CAPITAL LETTER T WITH CEDILLA
+0xde	0x016e	#LATIN CAPITAL LETTER U WITH RING ABOVE
+0xdf	0x2580	#UPPER HALF BLOCK
+0xe0	0x00d3	#LATIN CAPITAL LETTER O WITH ACUTE
+0xe1	0x00df	#LATIN SMALL LETTER SHARP S
+0xe2	0x00d4	#LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xe3	0x0143	#LATIN CAPITAL LETTER N WITH ACUTE
+0xe4	0x0144	#LATIN SMALL LETTER N WITH ACUTE
+0xe5	0x0148	#LATIN SMALL LETTER N WITH CARON
+0xe6	0x0160	#LATIN CAPITAL LETTER S WITH CARON
+0xe7	0x0161	#LATIN SMALL LETTER S WITH CARON
+0xe8	0x0154	#LATIN CAPITAL LETTER R WITH ACUTE
+0xe9	0x00da	#LATIN CAPITAL LETTER U WITH ACUTE
+0xea	0x0155	#LATIN SMALL LETTER R WITH ACUTE
+0xeb	0x0170	#LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+0xec	0x00fd	#LATIN SMALL LETTER Y WITH ACUTE
+0xed	0x00dd	#LATIN CAPITAL LETTER Y WITH ACUTE
+0xee	0x0163	#LATIN SMALL LETTER T WITH CEDILLA
+0xef	0x00b4	#ACUTE ACCENT
+0xf0	0x00ad	#SOFT HYPHEN
+0xf1	0x02dd	#DOUBLE ACUTE ACCENT
+0xf2	0x02db	#OGONEK
+0xf3	0x02c7	#CARON
+0xf4	0x02d8	#BREVE
+0xf5	0x00a7	#SECTION SIGN
+0xf6	0x00f7	#DIVISION SIGN
+0xf7	0x00b8	#CEDILLA
+0xf8	0x00b0	#DEGREE SIGN
+0xf9	0x00a8	#DIAERESIS
+0xfa	0x02d9	#DOT ABOVE
+0xfb	0x0171	#LATIN SMALL LETTER U WITH DOUBLE ACUTE
+0xfc	0x0158	#LATIN CAPITAL LETTER R WITH CARON
+0xfd	0x0159	#LATIN SMALL LETTER R WITH CARON
+0xfe	0x25a0	#BLACK SQUARE
+0xff	0x00a0	#NO-BREAK SPACE
diff --git a/Resources/cp862.txt b/Resources/cp862.txt
new file mode 100644
index 0000000..e2a4f47
--- /dev/null
+++ b/Resources/cp862.txt
@@ -0,0 +1,273 @@
+#
+#    Name:     cp862_DOSHebrew to Unicode table
+#    Unicode version: 2.0
+#    Table version: 2.00
+#    Table format:  Format A
+#    Date:          04/24/96
+#    Authors:       Lori Brownell <loribr@microsoft.com>
+#                   K.D. Chang    <a-kchang@microsoft.com>
+#    General notes: none
+#
+#    Format: Three tab-separated columns
+#        Column #1 is the cp862_DOSHebrew code (in hex)
+#        Column #2 is the Unicode (in hex as 0xXXXX)
+#        Column #3 is the Unicode name (follows a comment sign, '#')
+#
+#    The entries are in cp862_DOSHebrew order
+#
+0x00	0x0000	#NULL
+0x01	0x0001	#START OF HEADING
+0x02	0x0002	#START OF TEXT
+0x03	0x0003	#END OF TEXT
+0x04	0x0004	#END OF TRANSMISSION
+0x05	0x0005	#ENQUIRY
+0x06	0x0006	#ACKNOWLEDGE
+0x07	0x0007	#BELL
+0x08	0x0008	#BACKSPACE
+0x09	0x0009	#HORIZONTAL TABULATION
+0x0a	0x000a	#LINE FEED
+0x0b	0x000b	#VERTICAL TABULATION
+0x0c	0x000c	#FORM FEED
+0x0d	0x000d	#CARRIAGE RETURN
+0x0e	0x000e	#SHIFT OUT
+0x0f	0x000f	#SHIFT IN
+0x10	0x0010	#DATA LINK ESCAPE
+0x11	0x0011	#DEVICE CONTROL ONE
+0x12	0x0012	#DEVICE CONTROL TWO
+0x13	0x0013	#DEVICE CONTROL THREE
+0x14	0x0014	#DEVICE CONTROL FOUR
+0x15	0x0015	#NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#SYNCHRONOUS IDLE
+0x17	0x0017	#END OF TRANSMISSION BLOCK
+0x18	0x0018	#CANCEL
+0x19	0x0019	#END OF MEDIUM
+0x1a	0x001a	#SUBSTITUTE
+0x1b	0x001b	#ESCAPE
+0x1c	0x001c	#FILE SEPARATOR
+0x1d	0x001d	#GROUP SEPARATOR
+0x1e	0x001e	#RECORD SEPARATOR
+0x1f	0x001f	#UNIT SEPARATOR
+0x20	0x0020	#SPACE
+0x21	0x0021	#EXCLAMATION MARK
+0x22	0x0022	#QUOTATION MARK
+0x23	0x0023	#NUMBER SIGN
+0x24	0x0024	#DOLLAR SIGN
+0x25	0x0025	#PERCENT SIGN
+0x26	0x0026	#AMPERSAND
+0x27	0x0027	#APOSTROPHE
+0x28	0x0028	#LEFT PARENTHESIS
+0x29	0x0029	#RIGHT PARENTHESIS
+0x2a	0x002a	#ASTERISK
+0x2b	0x002b	#PLUS SIGN
+0x2c	0x002c	#COMMA
+0x2d	0x002d	#HYPHEN-MINUS
+0x2e	0x002e	#FULL STOP
+0x2f	0x002f	#SOLIDUS
+0x30	0x0030	#DIGIT ZERO
+0x31	0x0031	#DIGIT ONE
+0x32	0x0032	#DIGIT TWO
+0x33	0x0033	#DIGIT THREE
+0x34	0x0034	#DIGIT FOUR
+0x35	0x0035	#DIGIT FIVE
+0x36	0x0036	#DIGIT SIX
+0x37	0x0037	#DIGIT SEVEN
+0x38	0x0038	#DIGIT EIGHT
+0x39	0x0039	#DIGIT NINE
+0x3a	0x003a	#COLON
+0x3b	0x003b	#SEMICOLON
+0x3c	0x003c	#LESS-THAN SIGN
+0x3d	0x003d	#EQUALS SIGN
+0x3e	0x003e	#GREATER-THAN SIGN
+0x3f	0x003f	#QUESTION MARK
+0x40	0x0040	#COMMERCIAL AT
+0x41	0x0041	#LATIN CAPITAL LETTER A
+0x42	0x0042	#LATIN CAPITAL LETTER B
+0x43	0x0043	#LATIN CAPITAL LETTER C
+0x44	0x0044	#LATIN CAPITAL LETTER D
+0x45	0x0045	#LATIN CAPITAL LETTER E
+0x46	0x0046	#LATIN CAPITAL LETTER F
+0x47	0x0047	#LATIN CAPITAL LETTER G
+0x48	0x0048	#LATIN CAPITAL LETTER H
+0x49	0x0049	#LATIN CAPITAL LETTER I
+0x4a	0x004a	#LATIN CAPITAL LETTER J
+0x4b	0x004b	#LATIN CAPITAL LETTER K
+0x4c	0x004c	#LATIN CAPITAL LETTER L
+0x4d	0x004d	#LATIN CAPITAL LETTER M
+0x4e	0x004e	#LATIN CAPITAL LETTER N
+0x4f	0x004f	#LATIN CAPITAL LETTER O
+0x50	0x0050	#LATIN CAPITAL LETTER P
+0x51	0x0051	#LATIN CAPITAL LETTER Q
+0x52	0x0052	#LATIN CAPITAL LETTER R
+0x53	0x0053	#LATIN CAPITAL LETTER S
+0x54	0x0054	#LATIN CAPITAL LETTER T
+0x55	0x0055	#LATIN CAPITAL LETTER U
+0x56	0x0056	#LATIN CAPITAL LETTER V
+0x57	0x0057	#LATIN CAPITAL LETTER W
+0x58	0x0058	#LATIN CAPITAL LETTER X
+0x59	0x0059	#LATIN CAPITAL LETTER Y
+0x5a	0x005a	#LATIN CAPITAL LETTER Z
+0x5b	0x005b	#LEFT SQUARE BRACKET
+0x5c	0x005c	#REVERSE SOLIDUS
+0x5d	0x005d	#RIGHT SQUARE BRACKET
+0x5e	0x005e	#CIRCUMFLEX ACCENT
+0x5f	0x005f	#LOW LINE
+0x60	0x0060	#GRAVE ACCENT
+0x61	0x0061	#LATIN SMALL LETTER A
+0x62	0x0062	#LATIN SMALL LETTER B
+0x63	0x0063	#LATIN SMALL LETTER C
+0x64	0x0064	#LATIN SMALL LETTER D
+0x65	0x0065	#LATIN SMALL LETTER E
+0x66	0x0066	#LATIN SMALL LETTER F
+0x67	0x0067	#LATIN SMALL LETTER G
+0x68	0x0068	#LATIN SMALL LETTER H
+0x69	0x0069	#LATIN SMALL LETTER I
+0x6a	0x006a	#LATIN SMALL LETTER J
+0x6b	0x006b	#LATIN SMALL LETTER K
+0x6c	0x006c	#LATIN SMALL LETTER L
+0x6d	0x006d	#LATIN SMALL LETTER M
+0x6e	0x006e	#LATIN SMALL LETTER N
+0x6f	0x006f	#LATIN SMALL LETTER O
+0x70	0x0070	#LATIN SMALL LETTER P
+0x71	0x0071	#LATIN SMALL LETTER Q
+0x72	0x0072	#LATIN SMALL LETTER R
+0x73	0x0073	#LATIN SMALL LETTER S
+0x74	0x0074	#LATIN SMALL LETTER T
+0x75	0x0075	#LATIN SMALL LETTER U
+0x76	0x0076	#LATIN SMALL LETTER V
+0x77	0x0077	#LATIN SMALL LETTER W
+0x78	0x0078	#LATIN SMALL LETTER X
+0x79	0x0079	#LATIN SMALL LETTER Y
+0x7a	0x007a	#LATIN SMALL LETTER Z
+0x7b	0x007b	#LEFT CURLY BRACKET
+0x7c	0x007c	#VERTICAL LINE
+0x7d	0x007d	#RIGHT CURLY BRACKET
+0x7e	0x007e	#TILDE
+0x7f	0x007f	#DELETE
+0x80	0x05d0	#HEBREW LETTER ALEF
+0x81	0x05d1	#HEBREW LETTER BET
+0x82	0x05d2	#HEBREW LETTER GIMEL
+0x83	0x05d3	#HEBREW LETTER DALET
+0x84	0x05d4	#HEBREW LETTER HE
+0x85	0x05d5	#HEBREW LETTER VAV
+0x86	0x05d6	#HEBREW LETTER ZAYIN
+0x87	0x05d7	#HEBREW LETTER HET
+0x88	0x05d8	#HEBREW LETTER TET
+0x89	0x05d9	#HEBREW LETTER YOD
+0x8a	0x05da	#HEBREW LETTER FINAL KAF
+0x8b	0x05db	#HEBREW LETTER KAF
+0x8c	0x05dc	#HEBREW LETTER LAMED
+0x8d	0x05dd	#HEBREW LETTER FINAL MEM
+0x8e	0x05de	#HEBREW LETTER MEM
+0x8f	0x05df	#HEBREW LETTER FINAL NUN
+0x90	0x05e0	#HEBREW LETTER NUN
+0x91	0x05e1	#HEBREW LETTER SAMEKH
+0x92	0x05e2	#HEBREW LETTER AYIN
+0x93	0x05e3	#HEBREW LETTER FINAL PE
+0x94	0x05e4	#HEBREW LETTER PE
+0x95	0x05e5	#HEBREW LETTER FINAL TSADI
+0x96	0x05e6	#HEBREW LETTER TSADI
+0x97	0x05e7	#HEBREW LETTER QOF
+0x98	0x05e8	#HEBREW LETTER RESH
+0x99	0x05e9	#HEBREW LETTER SHIN
+0x9a	0x05ea	#HEBREW LETTER TAV
+0x9b	0x00a2	#CENT SIGN
+0x9c	0x00a3	#POUND SIGN
+0x9d	0x00a5	#YEN SIGN
+0x9e	0x20a7	#PESETA SIGN
+0x9f	0x0192	#LATIN SMALL LETTER F WITH HOOK
+0xa0	0x00e1	#LATIN SMALL LETTER A WITH ACUTE
+0xa1	0x00ed	#LATIN SMALL LETTER I WITH ACUTE
+0xa2	0x00f3	#LATIN SMALL LETTER O WITH ACUTE
+0xa3	0x00fa	#LATIN SMALL LETTER U WITH ACUTE
+0xa4	0x00f1	#LATIN SMALL LETTER N WITH TILDE
+0xa5	0x00d1	#LATIN CAPITAL LETTER N WITH TILDE
+0xa6	0x00aa	#FEMININE ORDINAL INDICATOR
+0xa7	0x00ba	#MASCULINE ORDINAL INDICATOR
+0xa8	0x00bf	#INVERTED QUESTION MARK
+0xa9	0x2310	#REVERSED NOT SIGN
+0xaa	0x00ac	#NOT SIGN
+0xab	0x00bd	#VULGAR FRACTION ONE HALF
+0xac	0x00bc	#VULGAR FRACTION ONE QUARTER
+0xad	0x00a1	#INVERTED EXCLAMATION MARK
+0xae	0x00ab	#LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xaf	0x00bb	#RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xb0	0x2591	#LIGHT SHADE
+0xb1	0x2592	#MEDIUM SHADE
+0xb2	0x2593	#DARK SHADE
+0xb3	0x2502	#BOX DRAWINGS LIGHT VERTICAL
+0xb4	0x2524	#BOX DRAWINGS LIGHT VERTICAL AND LEFT
+0xb5	0x2561	#BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+0xb6	0x2562	#BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+0xb7	0x2556	#BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+0xb8	0x2555	#BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+0xb9	0x2563	#BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+0xba	0x2551	#BOX DRAWINGS DOUBLE VERTICAL
+0xbb	0x2557	#BOX DRAWINGS DOUBLE DOWN AND LEFT
+0xbc	0x255d	#BOX DRAWINGS DOUBLE UP AND LEFT
+0xbd	0x255c	#BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+0xbe	0x255b	#BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+0xbf	0x2510	#BOX DRAWINGS LIGHT DOWN AND LEFT
+0xc0	0x2514	#BOX DRAWINGS LIGHT UP AND RIGHT
+0xc1	0x2534	#BOX DRAWINGS LIGHT UP AND HORIZONTAL
+0xc2	0x252c	#BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+0xc3	0x251c	#BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+0xc4	0x2500	#BOX DRAWINGS LIGHT HORIZONTAL
+0xc5	0x253c	#BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+0xc6	0x255e	#BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+0xc7	0x255f	#BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+0xc8	0x255a	#BOX DRAWINGS DOUBLE UP AND RIGHT
+0xc9	0x2554	#BOX DRAWINGS DOUBLE DOWN AND RIGHT
+0xca	0x2569	#BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+0xcb	0x2566	#BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+0xcc	0x2560	#BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+0xcd	0x2550	#BOX DRAWINGS DOUBLE HORIZONTAL
+0xce	0x256c	#BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+0xcf	0x2567	#BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+0xd0	0x2568	#BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+0xd1	0x2564	#BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+0xd2	0x2565	#BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+0xd3	0x2559	#BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+0xd4	0x2558	#BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+0xd5	0x2552	#BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+0xd6	0x2553	#BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+0xd7	0x256b	#BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+0xd8	0x256a	#BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+0xd9	0x2518	#BOX DRAWINGS LIGHT UP AND LEFT
+0xda	0x250c	#BOX DRAWINGS LIGHT DOWN AND RIGHT
+0xdb	0x2588	#FULL BLOCK
+0xdc	0x2584	#LOWER HALF BLOCK
+0xdd	0x258c	#LEFT HALF BLOCK
+0xde	0x2590	#RIGHT HALF BLOCK
+0xdf	0x2580	#UPPER HALF BLOCK
+0xe0	0x03b1	#GREEK SMALL LETTER ALPHA
+0xe1	0x00df	#LATIN SMALL LETTER SHARP S (GERMAN)
+0xe2	0x0393	#GREEK CAPITAL LETTER GAMMA
+0xe3	0x03c0	#GREEK SMALL LETTER PI
+0xe4	0x03a3	#GREEK CAPITAL LETTER SIGMA
+0xe5	0x03c3	#GREEK SMALL LETTER SIGMA
+0xe6	0x00b5	#MICRO SIGN
+0xe7	0x03c4	#GREEK SMALL LETTER TAU
+0xe8	0x03a6	#GREEK CAPITAL LETTER PHI
+0xe9	0x0398	#GREEK CAPITAL LETTER THETA
+0xea	0x03a9	#GREEK CAPITAL LETTER OMEGA
+0xeb	0x03b4	#GREEK SMALL LETTER DELTA
+0xec	0x221e	#INFINITY
+0xed	0x03c6	#GREEK SMALL LETTER PHI
+0xee	0x03b5	#GREEK SMALL LETTER EPSILON
+0xef	0x2229	#INTERSECTION
+0xf0	0x2261	#IDENTICAL TO
+0xf1	0x00b1	#PLUS-MINUS SIGN
+0xf2	0x2265	#GREATER-THAN OR EQUAL TO
+0xf3	0x2264	#LESS-THAN OR EQUAL TO
+0xf4	0x2320	#TOP HALF INTEGRAL
+0xf5	0x2321	#BOTTOM HALF INTEGRAL
+0xf6	0x00f7	#DIVISION SIGN
+0xf7	0x2248	#ALMOST EQUAL TO
+0xf8	0x00b0	#DEGREE SIGN
+0xf9	0x2219	#BULLET OPERATOR
+0xfa	0x00b7	#MIDDLE DOT
+0xfb	0x221a	#SQUARE ROOT
+0xfc	0x207f	#SUPERSCRIPT LATIN SMALL LETTER N
+0xfd	0x00b2	#SUPERSCRIPT TWO
+0xfe	0x25a0	#BLACK SQUARE
+0xff	0x00a0	#NO-BREAK SPACE
diff --git a/Resources/cp864.txt b/Resources/cp864.txt
new file mode 100644
index 0000000..b20aba5
--- /dev/null
+++ b/Resources/cp864.txt
@@ -0,0 +1,273 @@
+#
+#    Name:     cp864_DOSArabic to Unicode table
+#    Unicode version: 2.0
+#    Table version: 2.00
+#    Table format:  Format A
+#    Date:          04/24/96
+#    Authors:       Lori Brownell <loribr@microsoft.com>
+#                   K.D. Chang    <a-kchang@microsoft.com>
+#    General notes: none
+#
+#    Format: Three tab-separated columns
+#        Column #1 is the cp864_DOSArabic code (in hex)
+#        Column #2 is the Unicode (in hex as 0xXXXX)
+#        Column #3 is the Unicode name (follows a comment sign, '#')
+#
+#    The entries are in cp864_DOSArabic order
+#
+0x00	0x0000	#NULL
+0x01	0x0001	#START OF HEADING
+0x02	0x0002	#START OF TEXT
+0x03	0x0003	#END OF TEXT
+0x04	0x0004	#END OF TRANSMISSION
+0x05	0x0005	#ENQUIRY
+0x06	0x0006	#ACKNOWLEDGE
+0x07	0x0007	#BELL
+0x08	0x0008	#BACKSPACE
+0x09	0x0009	#HORIZONTAL TABULATION
+0x0a	0x000a	#LINE FEED
+0x0b	0x000b	#VERTICAL TABULATION
+0x0c	0x000c	#FORM FEED
+0x0d	0x000d	#CARRIAGE RETURN
+0x0e	0x000e	#SHIFT OUT
+0x0f	0x000f	#SHIFT IN
+0x10	0x0010	#DATA LINK ESCAPE
+0x11	0x0011	#DEVICE CONTROL ONE
+0x12	0x0012	#DEVICE CONTROL TWO
+0x13	0x0013	#DEVICE CONTROL THREE
+0x14	0x0014	#DEVICE CONTROL FOUR
+0x15	0x0015	#NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#SYNCHRONOUS IDLE
+0x17	0x0017	#END OF TRANSMISSION BLOCK
+0x18	0x0018	#CANCEL
+0x19	0x0019	#END OF MEDIUM
+0x1a	0x001a	#SUBSTITUTE
+0x1b	0x001b	#ESCAPE
+0x1c	0x001c	#FILE SEPARATOR
+0x1d	0x001d	#GROUP SEPARATOR
+0x1e	0x001e	#RECORD SEPARATOR
+0x1f	0x001f	#UNIT SEPARATOR
+0x20	0x0020	#SPACE
+0x21	0x0021	#EXCLAMATION MARK
+0x22	0x0022	#QUOTATION MARK
+0x23	0x0023	#NUMBER SIGN
+0x24	0x0024	#DOLLAR SIGN
+0x25	0x066a	#ARABIC PERCENT SIGN
+0x26	0x0026	#AMPERSAND
+0x27	0x0027	#APOSTROPHE
+0x28	0x0028	#LEFT PARENTHESIS
+0x29	0x0029	#RIGHT PARENTHESIS
+0x2a	0x002a	#ASTERISK
+0x2b	0x002b	#PLUS SIGN
+0x2c	0x002c	#COMMA
+0x2d	0x002d	#HYPHEN-MINUS
+0x2e	0x002e	#FULL STOP
+0x2f	0x002f	#SOLIDUS
+0x30	0x0030	#DIGIT ZERO
+0x31	0x0031	#DIGIT ONE
+0x32	0x0032	#DIGIT TWO
+0x33	0x0033	#DIGIT THREE
+0x34	0x0034	#DIGIT FOUR
+0x35	0x0035	#DIGIT FIVE
+0x36	0x0036	#DIGIT SIX
+0x37	0x0037	#DIGIT SEVEN
+0x38	0x0038	#DIGIT EIGHT
+0x39	0x0039	#DIGIT NINE
+0x3a	0x003a	#COLON
+0x3b	0x003b	#SEMICOLON
+0x3c	0x003c	#LESS-THAN SIGN
+0x3d	0x003d	#EQUALS SIGN
+0x3e	0x003e	#GREATER-THAN SIGN
+0x3f	0x003f	#QUESTION MARK
+0x40	0x0040	#COMMERCIAL AT
+0x41	0x0041	#LATIN CAPITAL LETTER A
+0x42	0x0042	#LATIN CAPITAL LETTER B
+0x43	0x0043	#LATIN CAPITAL LETTER C
+0x44	0x0044	#LATIN CAPITAL LETTER D
+0x45	0x0045	#LATIN CAPITAL LETTER E
+0x46	0x0046	#LATIN CAPITAL LETTER F
+0x47	0x0047	#LATIN CAPITAL LETTER G
+0x48	0x0048	#LATIN CAPITAL LETTER H
+0x49	0x0049	#LATIN CAPITAL LETTER I
+0x4a	0x004a	#LATIN CAPITAL LETTER J
+0x4b	0x004b	#LATIN CAPITAL LETTER K
+0x4c	0x004c	#LATIN CAPITAL LETTER L
+0x4d	0x004d	#LATIN CAPITAL LETTER M
+0x4e	0x004e	#LATIN CAPITAL LETTER N
+0x4f	0x004f	#LATIN CAPITAL LETTER O
+0x50	0x0050	#LATIN CAPITAL LETTER P
+0x51	0x0051	#LATIN CAPITAL LETTER Q
+0x52	0x0052	#LATIN CAPITAL LETTER R
+0x53	0x0053	#LATIN CAPITAL LETTER S
+0x54	0x0054	#LATIN CAPITAL LETTER T
+0x55	0x0055	#LATIN CAPITAL LETTER U
+0x56	0x0056	#LATIN CAPITAL LETTER V
+0x57	0x0057	#LATIN CAPITAL LETTER W
+0x58	0x0058	#LATIN CAPITAL LETTER X
+0x59	0x0059	#LATIN CAPITAL LETTER Y
+0x5a	0x005a	#LATIN CAPITAL LETTER Z
+0x5b	0x005b	#LEFT SQUARE BRACKET
+0x5c	0x005c	#REVERSE SOLIDUS
+0x5d	0x005d	#RIGHT SQUARE BRACKET
+0x5e	0x005e	#CIRCUMFLEX ACCENT
+0x5f	0x005f	#LOW LINE
+0x60	0x0060	#GRAVE ACCENT
+0x61	0x0061	#LATIN SMALL LETTER A
+0x62	0x0062	#LATIN SMALL LETTER B
+0x63	0x0063	#LATIN SMALL LETTER C
+0x64	0x0064	#LATIN SMALL LETTER D
+0x65	0x0065	#LATIN SMALL LETTER E
+0x66	0x0066	#LATIN SMALL LETTER F
+0x67	0x0067	#LATIN SMALL LETTER G
+0x68	0x0068	#LATIN SMALL LETTER H
+0x69	0x0069	#LATIN SMALL LETTER I
+0x6a	0x006a	#LATIN SMALL LETTER J
+0x6b	0x006b	#LATIN SMALL LETTER K
+0x6c	0x006c	#LATIN SMALL LETTER L
+0x6d	0x006d	#LATIN SMALL LETTER M
+0x6e	0x006e	#LATIN SMALL LETTER N
+0x6f	0x006f	#LATIN SMALL LETTER O
+0x70	0x0070	#LATIN SMALL LETTER P
+0x71	0x0071	#LATIN SMALL LETTER Q
+0x72	0x0072	#LATIN SMALL LETTER R
+0x73	0x0073	#LATIN SMALL LETTER S
+0x74	0x0074	#LATIN SMALL LETTER T
+0x75	0x0075	#LATIN SMALL LETTER U
+0x76	0x0076	#LATIN SMALL LETTER V
+0x77	0x0077	#LATIN SMALL LETTER W
+0x78	0x0078	#LATIN SMALL LETTER X
+0x79	0x0079	#LATIN SMALL LETTER Y
+0x7a	0x007a	#LATIN SMALL LETTER Z
+0x7b	0x007b	#LEFT CURLY BRACKET
+0x7c	0x007c	#VERTICAL LINE
+0x7d	0x007d	#RIGHT CURLY BRACKET
+0x7e	0x007e	#TILDE
+0x7f	0x007f	#DELETE
+0x80	0x00b0	#DEGREE SIGN
+0x81	0x00b7	#MIDDLE DOT
+0x82	0x2219	#BULLET OPERATOR
+0x83	0x221a	#SQUARE ROOT
+0x84	0x2592	#MEDIUM SHADE
+0x85	0x2500	#FORMS LIGHT HORIZONTAL
+0x86	0x2502	#FORMS LIGHT VERTICAL
+0x87	0x253c	#FORMS LIGHT VERTICAL AND HORIZONTAL
+0x88	0x2524	#FORMS LIGHT VERTICAL AND LEFT
+0x89	0x252c	#FORMS LIGHT DOWN AND HORIZONTAL
+0x8a	0x251c	#FORMS LIGHT VERTICAL AND RIGHT
+0x8b	0x2534	#FORMS LIGHT UP AND HORIZONTAL
+0x8c	0x2510	#FORMS LIGHT DOWN AND LEFT
+0x8d	0x250c	#FORMS LIGHT DOWN AND RIGHT
+0x8e	0x2514	#FORMS LIGHT UP AND RIGHT
+0x8f	0x2518	#FORMS LIGHT UP AND LEFT
+0x90	0x03b2	#GREEK SMALL BETA
+0x91	0x221e	#INFINITY
+0x92	0x03c6	#GREEK SMALL PHI
+0x93	0x00b1	#PLUS-OR-MINUS SIGN
+0x94	0x00bd	#FRACTION 1/2
+0x95	0x00bc	#FRACTION 1/4
+0x96	0x2248	#ALMOST EQUAL TO
+0x97	0x00ab	#LEFT POINTING GUILLEMET
+0x98	0x00bb	#RIGHT POINTING GUILLEMET
+0x99	0xfef7	#ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM
+0x9a	0xfef8	#ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM
+0x9b		#UNDEFINED
+0x9c		#UNDEFINED
+0x9d	0xfefb	#ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM
+0x9e	0xfefc	#ARABIC LIGATURE LAM WITH ALEF FINAL FORM
+0x9f		#UNDEFINED
+0xa0	0x00a0	#NON-BREAKING SPACE
+0xa1	0x00ad	#SOFT HYPHEN
+0xa2	0xfe82	#ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM
+0xa3	0x00a3	#POUND SIGN
+0xa4	0x00a4	#CURRENCY SIGN
+0xa5	0xfe84	#ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM
+0xa6		#UNDEFINED
+0xa7		#UNDEFINED
+0xa8	0xfe8e	#ARABIC LETTER ALEF FINAL FORM
+0xa9	0xfe8f	#ARABIC LETTER BEH ISOLATED FORM
+0xaa	0xfe95	#ARABIC LETTER TEH ISOLATED FORM
+0xab	0xfe99	#ARABIC LETTER THEH ISOLATED FORM
+0xac	0x060c	#ARABIC COMMA
+0xad	0xfe9d	#ARABIC LETTER JEEM ISOLATED FORM
+0xae	0xfea1	#ARABIC LETTER HAH ISOLATED FORM
+0xaf	0xfea5	#ARABIC LETTER KHAH ISOLATED FORM
+0xb0	0x0660	#ARABIC-INDIC DIGIT ZERO
+0xb1	0x0661	#ARABIC-INDIC DIGIT ONE
+0xb2	0x0662	#ARABIC-INDIC DIGIT TWO
+0xb3	0x0663	#ARABIC-INDIC DIGIT THREE
+0xb4	0x0664	#ARABIC-INDIC DIGIT FOUR
+0xb5	0x0665	#ARABIC-INDIC DIGIT FIVE
+0xb6	0x0666	#ARABIC-INDIC DIGIT SIX
+0xb7	0x0667	#ARABIC-INDIC DIGIT SEVEN
+0xb8	0x0668	#ARABIC-INDIC DIGIT EIGHT
+0xb9	0x0669	#ARABIC-INDIC DIGIT NINE
+0xba	0xfed1	#ARABIC LETTER FEH ISOLATED FORM
+0xbb	0x061b	#ARABIC SEMICOLON
+0xbc	0xfeb1	#ARABIC LETTER SEEN ISOLATED FORM
+0xbd	0xfeb5	#ARABIC LETTER SHEEN ISOLATED FORM
+0xbe	0xfeb9	#ARABIC LETTER SAD ISOLATED FORM
+0xbf	0x061f	#ARABIC QUESTION MARK
+0xc0	0x00a2	#CENT SIGN
+0xc1	0xfe80	#ARABIC LETTER HAMZA ISOLATED FORM
+0xc2	0xfe81	#ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM
+0xc3	0xfe83	#ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM
+0xc4	0xfe85	#ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM
+0xc5	0xfeca	#ARABIC LETTER AIN FINAL FORM
+0xc6	0xfe8b	#ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM
+0xc7	0xfe8d	#ARABIC LETTER ALEF ISOLATED FORM
+0xc8	0xfe91	#ARABIC LETTER BEH INITIAL FORM
+0xc9	0xfe93	#ARABIC LETTER TEH MARBUTA ISOLATED FORM
+0xca	0xfe97	#ARABIC LETTER TEH INITIAL FORM
+0xcb	0xfe9b	#ARABIC LETTER THEH INITIAL FORM
+0xcc	0xfe9f	#ARABIC LETTER JEEM INITIAL FORM
+0xcd	0xfea3	#ARABIC LETTER HAH INITIAL FORM
+0xce	0xfea7	#ARABIC LETTER KHAH INITIAL FORM
+0xcf	0xfea9	#ARABIC LETTER DAL ISOLATED FORM
+0xd0	0xfeab	#ARABIC LETTER THAL ISOLATED FORM
+0xd1	0xfead	#ARABIC LETTER REH ISOLATED FORM
+0xd2	0xfeaf	#ARABIC LETTER ZAIN ISOLATED FORM
+0xd3	0xfeb3	#ARABIC LETTER SEEN INITIAL FORM
+0xd4	0xfeb7	#ARABIC LETTER SHEEN INITIAL FORM
+0xd5	0xfebb	#ARABIC LETTER SAD INITIAL FORM
+0xd6	0xfebf	#ARABIC LETTER DAD INITIAL FORM
+0xd7	0xfec1	#ARABIC LETTER TAH ISOLATED FORM
+0xd8	0xfec5	#ARABIC LETTER ZAH ISOLATED FORM
+0xd9	0xfecb	#ARABIC LETTER AIN INITIAL FORM
+0xda	0xfecf	#ARABIC LETTER GHAIN INITIAL FORM
+0xdb	0x00a6	#BROKEN VERTICAL BAR
+0xdc	0x00ac	#NOT SIGN
+0xdd	0x00f7	#DIVISION SIGN
+0xde	0x00d7	#MULTIPLICATION SIGN
+0xdf	0xfec9	#ARABIC LETTER AIN ISOLATED FORM
+0xe0	0x0640	#ARABIC TATWEEL
+0xe1	0xfed3	#ARABIC LETTER FEH INITIAL FORM
+0xe2	0xfed7	#ARABIC LETTER QAF INITIAL FORM
+0xe3	0xfedb	#ARABIC LETTER KAF INITIAL FORM
+0xe4	0xfedf	#ARABIC LETTER LAM INITIAL FORM
+0xe5	0xfee3	#ARABIC LETTER MEEM INITIAL FORM
+0xe6	0xfee7	#ARABIC LETTER NOON INITIAL FORM
+0xe7	0xfeeb	#ARABIC LETTER HEH INITIAL FORM
+0xe8	0xfeed	#ARABIC LETTER WAW ISOLATED FORM
+0xe9	0xfeef	#ARABIC LETTER ALEF MAKSURA ISOLATED FORM
+0xea	0xfef3	#ARABIC LETTER YEH INITIAL FORM
+0xeb	0xfebd	#ARABIC LETTER DAD ISOLATED FORM
+0xec	0xfecc	#ARABIC LETTER AIN MEDIAL FORM
+0xed	0xfece	#ARABIC LETTER GHAIN FINAL FORM
+0xee	0xfecd	#ARABIC LETTER GHAIN ISOLATED FORM
+0xef	0xfee1	#ARABIC LETTER MEEM ISOLATED FORM
+0xf0	0xfe7d	#ARABIC SHADDA MEDIAL FORM
+0xf1	0x0651	#ARABIC SHADDAH
+0xf2	0xfee5	#ARABIC LETTER NOON ISOLATED FORM
+0xf3	0xfee9	#ARABIC LETTER HEH ISOLATED FORM
+0xf4	0xfeec	#ARABIC LETTER HEH MEDIAL FORM
+0xf5	0xfef0	#ARABIC LETTER ALEF MAKSURA FINAL FORM
+0xf6	0xfef2	#ARABIC LETTER YEH FINAL FORM
+0xf7	0xfed0	#ARABIC LETTER GHAIN MEDIAL FORM
+0xf8	0xfed5	#ARABIC LETTER QAF ISOLATED FORM
+0xf9	0xfef5	#ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM
+0xfa	0xfef6	#ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM
+0xfb	0xfedd	#ARABIC LETTER LAM ISOLATED FORM
+0xfc	0xfed9	#ARABIC LETTER KAF ISOLATED FORM
+0xfd	0xfef1	#ARABIC LETTER YEH ISOLATED FORM
+0xfe	0x25a0	#BLACK SQUARE
+0xff		#UNDEFINED
diff --git a/Resources/cp866.txt b/Resources/cp866.txt
new file mode 100644
index 0000000..94e03b0
--- /dev/null
+++ b/Resources/cp866.txt
@@ -0,0 +1,273 @@
+#
+#    Name:     cp866_DOSCyrillicRussian to Unicode table
+#    Unicode version: 2.0
+#    Table version: 2.00
+#    Table format:  Format A
+#    Date:          04/24/96
+#    Authors:       Lori Brownell <loribr@microsoft.com>
+#                   K.D. Chang    <a-kchang@microsoft.com>
+#    General notes: none
+#
+#    Format: Three tab-separated columns
+#        Column #1 is the cp866_DOSCyrillicRussian code (in hex)
+#        Column #2 is the Unicode (in hex as 0xXXXX)
+#        Column #3 is the Unicode name (follows a comment sign, '#')
+#
+#    The entries are in cp866_DOSCyrillicRussian order
+#
+0x00	0x0000	#NULL
+0x01	0x0001	#START OF HEADING
+0x02	0x0002	#START OF TEXT
+0x03	0x0003	#END OF TEXT
+0x04	0x0004	#END OF TRANSMISSION
+0x05	0x0005	#ENQUIRY
+0x06	0x0006	#ACKNOWLEDGE
+0x07	0x0007	#BELL
+0x08	0x0008	#BACKSPACE
+0x09	0x0009	#HORIZONTAL TABULATION
+0x0a	0x000a	#LINE FEED
+0x0b	0x000b	#VERTICAL TABULATION
+0x0c	0x000c	#FORM FEED
+0x0d	0x000d	#CARRIAGE RETURN
+0x0e	0x000e	#SHIFT OUT
+0x0f	0x000f	#SHIFT IN
+0x10	0x0010	#DATA LINK ESCAPE
+0x11	0x0011	#DEVICE CONTROL ONE
+0x12	0x0012	#DEVICE CONTROL TWO
+0x13	0x0013	#DEVICE CONTROL THREE
+0x14	0x0014	#DEVICE CONTROL FOUR
+0x15	0x0015	#NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#SYNCHRONOUS IDLE
+0x17	0x0017	#END OF TRANSMISSION BLOCK
+0x18	0x0018	#CANCEL
+0x19	0x0019	#END OF MEDIUM
+0x1a	0x001a	#SUBSTITUTE
+0x1b	0x001b	#ESCAPE
+0x1c	0x001c	#FILE SEPARATOR
+0x1d	0x001d	#GROUP SEPARATOR
+0x1e	0x001e	#RECORD SEPARATOR
+0x1f	0x001f	#UNIT SEPARATOR
+0x20	0x0020	#SPACE
+0x21	0x0021	#EXCLAMATION MARK
+0x22	0x0022	#QUOTATION MARK
+0x23	0x0023	#NUMBER SIGN
+0x24	0x0024	#DOLLAR SIGN
+0x25	0x0025	#PERCENT SIGN
+0x26	0x0026	#AMPERSAND
+0x27	0x0027	#APOSTROPHE
+0x28	0x0028	#LEFT PARENTHESIS
+0x29	0x0029	#RIGHT PARENTHESIS
+0x2a	0x002a	#ASTERISK
+0x2b	0x002b	#PLUS SIGN
+0x2c	0x002c	#COMMA
+0x2d	0x002d	#HYPHEN-MINUS
+0x2e	0x002e	#FULL STOP
+0x2f	0x002f	#SOLIDUS
+0x30	0x0030	#DIGIT ZERO
+0x31	0x0031	#DIGIT ONE
+0x32	0x0032	#DIGIT TWO
+0x33	0x0033	#DIGIT THREE
+0x34	0x0034	#DIGIT FOUR
+0x35	0x0035	#DIGIT FIVE
+0x36	0x0036	#DIGIT SIX
+0x37	0x0037	#DIGIT SEVEN
+0x38	0x0038	#DIGIT EIGHT
+0x39	0x0039	#DIGIT NINE
+0x3a	0x003a	#COLON
+0x3b	0x003b	#SEMICOLON
+0x3c	0x003c	#LESS-THAN SIGN
+0x3d	0x003d	#EQUALS SIGN
+0x3e	0x003e	#GREATER-THAN SIGN
+0x3f	0x003f	#QUESTION MARK
+0x40	0x0040	#COMMERCIAL AT
+0x41	0x0041	#LATIN CAPITAL LETTER A
+0x42	0x0042	#LATIN CAPITAL LETTER B
+0x43	0x0043	#LATIN CAPITAL LETTER C
+0x44	0x0044	#LATIN CAPITAL LETTER D
+0x45	0x0045	#LATIN CAPITAL LETTER E
+0x46	0x0046	#LATIN CAPITAL LETTER F
+0x47	0x0047	#LATIN CAPITAL LETTER G
+0x48	0x0048	#LATIN CAPITAL LETTER H
+0x49	0x0049	#LATIN CAPITAL LETTER I
+0x4a	0x004a	#LATIN CAPITAL LETTER J
+0x4b	0x004b	#LATIN CAPITAL LETTER K
+0x4c	0x004c	#LATIN CAPITAL LETTER L
+0x4d	0x004d	#LATIN CAPITAL LETTER M
+0x4e	0x004e	#LATIN CAPITAL LETTER N
+0x4f	0x004f	#LATIN CAPITAL LETTER O
+0x50	0x0050	#LATIN CAPITAL LETTER P
+0x51	0x0051	#LATIN CAPITAL LETTER Q
+0x52	0x0052	#LATIN CAPITAL LETTER R
+0x53	0x0053	#LATIN CAPITAL LETTER S
+0x54	0x0054	#LATIN CAPITAL LETTER T
+0x55	0x0055	#LATIN CAPITAL LETTER U
+0x56	0x0056	#LATIN CAPITAL LETTER V
+0x57	0x0057	#LATIN CAPITAL LETTER W
+0x58	0x0058	#LATIN CAPITAL LETTER X
+0x59	0x0059	#LATIN CAPITAL LETTER Y
+0x5a	0x005a	#LATIN CAPITAL LETTER Z
+0x5b	0x005b	#LEFT SQUARE BRACKET
+0x5c	0x005c	#REVERSE SOLIDUS
+0x5d	0x005d	#RIGHT SQUARE BRACKET
+0x5e	0x005e	#CIRCUMFLEX ACCENT
+0x5f	0x005f	#LOW LINE
+0x60	0x0060	#GRAVE ACCENT
+0x61	0x0061	#LATIN SMALL LETTER A
+0x62	0x0062	#LATIN SMALL LETTER B
+0x63	0x0063	#LATIN SMALL LETTER C
+0x64	0x0064	#LATIN SMALL LETTER D
+0x65	0x0065	#LATIN SMALL LETTER E
+0x66	0x0066	#LATIN SMALL LETTER F
+0x67	0x0067	#LATIN SMALL LETTER G
+0x68	0x0068	#LATIN SMALL LETTER H
+0x69	0x0069	#LATIN SMALL LETTER I
+0x6a	0x006a	#LATIN SMALL LETTER J
+0x6b	0x006b	#LATIN SMALL LETTER K
+0x6c	0x006c	#LATIN SMALL LETTER L
+0x6d	0x006d	#LATIN SMALL LETTER M
+0x6e	0x006e	#LATIN SMALL LETTER N
+0x6f	0x006f	#LATIN SMALL LETTER O
+0x70	0x0070	#LATIN SMALL LETTER P
+0x71	0x0071	#LATIN SMALL LETTER Q
+0x72	0x0072	#LATIN SMALL LETTER R
+0x73	0x0073	#LATIN SMALL LETTER S
+0x74	0x0074	#LATIN SMALL LETTER T
+0x75	0x0075	#LATIN SMALL LETTER U
+0x76	0x0076	#LATIN SMALL LETTER V
+0x77	0x0077	#LATIN SMALL LETTER W
+0x78	0x0078	#LATIN SMALL LETTER X
+0x79	0x0079	#LATIN SMALL LETTER Y
+0x7a	0x007a	#LATIN SMALL LETTER Z
+0x7b	0x007b	#LEFT CURLY BRACKET
+0x7c	0x007c	#VERTICAL LINE
+0x7d	0x007d	#RIGHT CURLY BRACKET
+0x7e	0x007e	#TILDE
+0x7f	0x007f	#DELETE
+0x80	0x0410	#CYRILLIC CAPITAL LETTER A
+0x81	0x0411	#CYRILLIC CAPITAL LETTER BE
+0x82	0x0412	#CYRILLIC CAPITAL LETTER VE
+0x83	0x0413	#CYRILLIC CAPITAL LETTER GHE
+0x84	0x0414	#CYRILLIC CAPITAL LETTER DE
+0x85	0x0415	#CYRILLIC CAPITAL LETTER IE
+0x86	0x0416	#CYRILLIC CAPITAL LETTER ZHE
+0x87	0x0417	#CYRILLIC CAPITAL LETTER ZE
+0x88	0x0418	#CYRILLIC CAPITAL LETTER I
+0x89	0x0419	#CYRILLIC CAPITAL LETTER SHORT I
+0x8a	0x041a	#CYRILLIC CAPITAL LETTER KA
+0x8b	0x041b	#CYRILLIC CAPITAL LETTER EL
+0x8c	0x041c	#CYRILLIC CAPITAL LETTER EM
+0x8d	0x041d	#CYRILLIC CAPITAL LETTER EN
+0x8e	0x041e	#CYRILLIC CAPITAL LETTER O
+0x8f	0x041f	#CYRILLIC CAPITAL LETTER PE
+0x90	0x0420	#CYRILLIC CAPITAL LETTER ER
+0x91	0x0421	#CYRILLIC CAPITAL LETTER ES
+0x92	0x0422	#CYRILLIC CAPITAL LETTER TE
+0x93	0x0423	#CYRILLIC CAPITAL LETTER U
+0x94	0x0424	#CYRILLIC CAPITAL LETTER EF
+0x95	0x0425	#CYRILLIC CAPITAL LETTER HA
+0x96	0x0426	#CYRILLIC CAPITAL LETTER TSE
+0x97	0x0427	#CYRILLIC CAPITAL LETTER CHE
+0x98	0x0428	#CYRILLIC CAPITAL LETTER SHA
+0x99	0x0429	#CYRILLIC CAPITAL LETTER SHCHA
+0x9a	0x042a	#CYRILLIC CAPITAL LETTER HARD SIGN
+0x9b	0x042b	#CYRILLIC CAPITAL LETTER YERU
+0x9c	0x042c	#CYRILLIC CAPITAL LETTER SOFT SIGN
+0x9d	0x042d	#CYRILLIC CAPITAL LETTER E
+0x9e	0x042e	#CYRILLIC CAPITAL LETTER YU
+0x9f	0x042f	#CYRILLIC CAPITAL LETTER YA
+0xa0	0x0430	#CYRILLIC SMALL LETTER A
+0xa1	0x0431	#CYRILLIC SMALL LETTER BE
+0xa2	0x0432	#CYRILLIC SMALL LETTER VE
+0xa3	0x0433	#CYRILLIC SMALL LETTER GHE
+0xa4	0x0434	#CYRILLIC SMALL LETTER DE
+0xa5	0x0435	#CYRILLIC SMALL LETTER IE
+0xa6	0x0436	#CYRILLIC SMALL LETTER ZHE
+0xa7	0x0437	#CYRILLIC SMALL LETTER ZE
+0xa8	0x0438	#CYRILLIC SMALL LETTER I
+0xa9	0x0439	#CYRILLIC SMALL LETTER SHORT I
+0xaa	0x043a	#CYRILLIC SMALL LETTER KA
+0xab	0x043b	#CYRILLIC SMALL LETTER EL
+0xac	0x043c	#CYRILLIC SMALL LETTER EM
+0xad	0x043d	#CYRILLIC SMALL LETTER EN
+0xae	0x043e	#CYRILLIC SMALL LETTER O
+0xaf	0x043f	#CYRILLIC SMALL LETTER PE
+0xb0	0x2591	#LIGHT SHADE
+0xb1	0x2592	#MEDIUM SHADE
+0xb2	0x2593	#DARK SHADE
+0xb3	0x2502	#BOX DRAWINGS LIGHT VERTICAL
+0xb4	0x2524	#BOX DRAWINGS LIGHT VERTICAL AND LEFT
+0xb5	0x2561	#BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+0xb6	0x2562	#BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+0xb7	0x2556	#BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+0xb8	0x2555	#BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+0xb9	0x2563	#BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+0xba	0x2551	#BOX DRAWINGS DOUBLE VERTICAL
+0xbb	0x2557	#BOX DRAWINGS DOUBLE DOWN AND LEFT
+0xbc	0x255d	#BOX DRAWINGS DOUBLE UP AND LEFT
+0xbd	0x255c	#BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+0xbe	0x255b	#BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+0xbf	0x2510	#BOX DRAWINGS LIGHT DOWN AND LEFT
+0xc0	0x2514	#BOX DRAWINGS LIGHT UP AND RIGHT
+0xc1	0x2534	#BOX DRAWINGS LIGHT UP AND HORIZONTAL
+0xc2	0x252c	#BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+0xc3	0x251c	#BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+0xc4	0x2500	#BOX DRAWINGS LIGHT HORIZONTAL
+0xc5	0x253c	#BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+0xc6	0x255e	#BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+0xc7	0x255f	#BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+0xc8	0x255a	#BOX DRAWINGS DOUBLE UP AND RIGHT
+0xc9	0x2554	#BOX DRAWINGS DOUBLE DOWN AND RIGHT
+0xca	0x2569	#BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+0xcb	0x2566	#BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+0xcc	0x2560	#BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+0xcd	0x2550	#BOX DRAWINGS DOUBLE HORIZONTAL
+0xce	0x256c	#BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+0xcf	0x2567	#BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+0xd0	0x2568	#BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+0xd1	0x2564	#BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+0xd2	0x2565	#BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+0xd3	0x2559	#BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+0xd4	0x2558	#BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+0xd5	0x2552	#BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+0xd6	0x2553	#BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+0xd7	0x256b	#BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+0xd8	0x256a	#BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+0xd9	0x2518	#BOX DRAWINGS LIGHT UP AND LEFT
+0xda	0x250c	#BOX DRAWINGS LIGHT DOWN AND RIGHT
+0xdb	0x2588	#FULL BLOCK
+0xdc	0x2584	#LOWER HALF BLOCK
+0xdd	0x258c	#LEFT HALF BLOCK
+0xde	0x2590	#RIGHT HALF BLOCK
+0xdf	0x2580	#UPPER HALF BLOCK
+0xe0	0x0440	#CYRILLIC SMALL LETTER ER
+0xe1	0x0441	#CYRILLIC SMALL LETTER ES
+0xe2	0x0442	#CYRILLIC SMALL LETTER TE
+0xe3	0x0443	#CYRILLIC SMALL LETTER U
+0xe4	0x0444	#CYRILLIC SMALL LETTER EF
+0xe5	0x0445	#CYRILLIC SMALL LETTER HA
+0xe6	0x0446	#CYRILLIC SMALL LETTER TSE
+0xe7	0x0447	#CYRILLIC SMALL LETTER CHE
+0xe8	0x0448	#CYRILLIC SMALL LETTER SHA
+0xe9	0x0449	#CYRILLIC SMALL LETTER SHCHA
+0xea	0x044a	#CYRILLIC SMALL LETTER HARD SIGN
+0xeb	0x044b	#CYRILLIC SMALL LETTER YERU
+0xec	0x044c	#CYRILLIC SMALL LETTER SOFT SIGN
+0xed	0x044d	#CYRILLIC SMALL LETTER E
+0xee	0x044e	#CYRILLIC SMALL LETTER YU
+0xef	0x044f	#CYRILLIC SMALL LETTER YA
+0xf0	0x0401	#CYRILLIC CAPITAL LETTER IO
+0xf1	0x0451	#CYRILLIC SMALL LETTER IO
+0xf2	0x0404	#CYRILLIC CAPITAL LETTER UKRAINIAN IE
+0xf3	0x0454	#CYRILLIC SMALL LETTER UKRAINIAN IE
+0xf4	0x0407	#CYRILLIC CAPITAL LETTER YI
+0xf5	0x0457	#CYRILLIC SMALL LETTER YI
+0xf6	0x040e	#CYRILLIC CAPITAL LETTER SHORT U
+0xf7	0x045e	#CYRILLIC SMALL LETTER SHORT U
+0xf8	0x00b0	#DEGREE SIGN
+0xf9	0x2219	#BULLET OPERATOR
+0xfa	0x00b7	#MIDDLE DOT
+0xfb	0x221a	#SQUARE ROOT
+0xfc	0x2116	#NUMERO SIGN
+0xfd	0x00a4	#CURRENCY SIGN
+0xfe	0x25a0	#BLACK SQUARE
+0xff	0x00a0	#NO-BREAK SPACE
diff --git a/Resources/fontnames b/Resources/fontnames
new file mode 100644
index 0000000..bb710d2
--- /dev/null
+++ b/Resources/fontnames
@@ -0,0 +1,117 @@
+# Default fontnames translation table
+# uses only Standard PostScript (TM) fonts
+#
+# MS-Word fontname,	Italic,	Bold,	PostScript fontname,	Special
+Arial,			0,	0,	Helvetica,		0
+Arial,			0,	1,	Helvetica-Bold,		0
+Arial,			1,	0,	Helvetica-Oblique,	0
+Arial,			1,	1,	Helvetica-BoldOblique,	0
+Arial Black,		0,	0,	Helvetica,		0
+Arial Black,		0,	1,	Helvetica-Bold,		0
+Arial Black,		1,	0,	Helvetica-Oblique,	0
+Arial Black,		1,	1,	Helvetica-BoldOblique,	0
+Arial CE,		0,	0,	Helvetica,		0
+Arial CE,		0,	1,	Helvetica-Bold,		0
+Arial CE,		1,	0,	Helvetica-Oblique,	0
+Arial CE,		1,	1,	Helvetica-BoldOblique,	0
+Arial Narrow,		0,	0,	Helvetica-Narrow,	0
+Arial Narrow,		0,	1,	Helvetica-Narrow-Bold,	0
+Arial Narrow,		1,	0,	Helvetica-Narrow-Oblique,	0
+Arial Narrow,		1,	1,	Helvetica-Narrow-BoldOblique,	0
+AvantGarde,		0,	0,	AvantGarde-Book,	0
+AvantGarde,		0,	1,	AvantGarde-Demi,	0
+AvantGarde,		1,	0,	AvantGarde-BookOblique,	0
+AvantGarde,		1,	1,	AvantGarde-DemiOblique,	0
+Bookman Old Style,	0,	0,	Bookman-Light,		0
+Bookman Old Style,	0,	1,	Bookman-Demi,		0
+Bookman Old Style,	1,	0,	Bookman-LightItalic,	0
+Bookman Old Style,	1,	1,	Bookman-DemiItalic,	0
+Century Schoolbook,	0,	0,	NewCenturySchlbk-Roman,	0
+Century Schoolbook,	0,	1,	NewCenturySchlbk-Bold,	0
+Century Schoolbook,	1,	0,	NewCenturySchlbk-Italic,	0
+Century Schoolbook,	1,	1,	NewCenturySchlbk-BoldItalic,	0
+CG Omega,		0,	0,	Helvetica,		0
+CG Omega,		0,	1,	Helvetica-Bold,		0
+CG Omega,		1,	0,	Helvetica-Oblique,	0
+CG Omega,		1,	1,	Helvetica-BoldOblique,	0
+Comic Sans MS,		0,	0,	Helvetica,		0
+Comic Sans MS,		0,	1,	Helvetica-Bold,		0
+Comic Sans MS,		1,	0,	Helvetica-Oblique,	0
+Comic Sans MS,		1,	1,	Helvetica-BoldOblique,	0
+Courier,		0,	0,	Courier,		0
+Courier,		0,	1,	Courier-Bold,		0
+Courier,		1,	0,	Courier-Oblique,	0
+Courier,		1,	1,	Courier-BoldOblique,	0
+Courier New,		0,	0,	Courier,		0
+Courier New,		0,	1,	Courier-Bold,		0
+Courier New,		1,	0,	Courier-Oblique,	0
+Courier New,		1,	1,	Courier-BoldOblique,	0
+Fixedsys,		0,	0,	Courier,		0
+Fixedsys,		0,	1,	Courier-Bold,		0
+Fixedsys,		1,	0,	Courier-Oblique,	0
+Fixedsys,		1,	1,	Courier-BoldOblique,	0
+Helvetica,		0,	0,	Helvetica,		0
+Helvetica,		0,	1,	Helvetica-Bold,		0
+Helvetica,		1,	0,	Helvetica-Oblique,	0
+Helvetica,		1,	1,	Helvetica-BoldOblique,	0
+Helvetica-Narrow,	0,	0,	Helvetica-Narrow,	0
+Helvetica-Narrow,	0,	1,	Helvetica-Narrow-Bold,	0
+Helvetica-Narrow,	1,	0,	Helvetica-Narrow-Oblique,	0
+Helvetica-Narrow,	1,	1,	Helvetica-Narrow-BoldOblique,	0
+ITC Bookman,		0,	0,	Bookman-Light,		0
+ITC Bookman,		0,	1,	Bookman-Demi,		0
+ITC Bookman,		1,	0,	Bookman-LightItalic,	0
+ITC Bookman,		1,	1,	Bookman-DemiItalic,	0
+Lucida Console,		0,	0,	Courier,		0
+Lucida Console,		0,	1,	Courier-Bold,		0
+Lucida Console,		1,	0,	Courier-Oblique,	0
+Lucida Console,		1,	1,	Courier-BoldOblique,	0
+Lucida Sans Typewriter,	0,	0,	Courier,		0
+Lucida Sans Typewriter,	0,	1,	Courier-Bold,		0
+Lucida Sans Typewriter,	1,	0,	Courier-Oblique,	0
+Lucida Sans Typewriter,	1,	1,	Courier-BoldOblique,	0
+Monotype.com,		0,	0,	Courier,		0
+Monotype.com,		0,	1,	Courier-Bold,		0
+Monotype.com,		1,	0,	Courier-Oblique,	0
+Monotype.com,		1,	1,	Courier-BoldOblique,	0
+MS Sans Serif,		0,	0,	Helvetica,		0
+MS Sans Serif,		0,	1,	Helvetica-Bold,		0
+MS Sans Serif,		1,	0,	Helvetica-Oblique,	0
+MS Sans Serif,		1,	1,	Helvetica-BoldOblique,	0
+New Century Schlbk,	0,	0,	NewCenturySchlbk-Roman,	0
+New Century Schlbk,	0,	1,	NewCenturySchlbk-Bold,	0
+New Century Schlbk,	1,	0,	NewCenturySchlbk-Italic,	0
+New Century Schlbk,	1,	1,	NewCenturySchlbk-BoldItalic,	0
+NewCenturySchlbk,	0,	0,	NewCenturySchlbk-Roman,	0
+NewCenturySchlbk,	0,	1,	NewCenturySchlbk-Bold,	0
+NewCenturySchlbk,	1,	0,	NewCenturySchlbk-Italic,	0
+NewCenturySchlbk,	1,	1,	NewCenturySchlbk-BoldItalic,	0
+Palatino,		0,	0,	Palatino-Roman,		0
+Palatino,		0,	1,	Palatino-Bold,		0
+Palatino,		1,	0,	Palatino-Italic,	0
+Palatino,		1,	1,	Palatino-BoldItalic,	0
+Swiss,			0,	0,	Helvetica,		0
+Swiss,			0,	1,	Helvetica-Bold,		0
+Swiss,			1,	0,	Helvetica-Oblique,	0
+Swiss,			1,	1,	Helvetica-BoldOblique,	0
+Tahoma,			0,	0,	Helvetica,		0
+Tahoma,			0,	1,	Helvetica-Bold,		0
+Tahoma,			1,	0,	Helvetica-Oblique,	0
+Tahoma,			1,	1,	Helvetica-BoldOblique,	0
+Trebuchet MS,		0,	0,	Helvetica,		0
+Trebuchet MS,		0,	1,	Helvetica-Bold,		0
+Trebuchet MS,		1,	0,	Helvetica-Oblique,	0
+Trebuchet MS,		1,	1,	Helvetica-BoldOblique,	0
+Univers,		0,	0,	Helvetica,		0
+Univers,		0,	1,	Helvetica-Bold,		0
+Univers,		1,	0,	Helvetica-Oblique,	0
+Univers,		1,	1,	Helvetica-BoldOblique,	0
+Verdana,		0,	0,	Helvetica,		0
+Verdana,		0,	1,	Helvetica-Bold,		0
+Verdana,		1,	0,	Helvetica-Oblique,	0
+Verdana,		1,	1,	Helvetica-BoldOblique,	0
+# All the other fonts
+*,			0,	0,	Times-Roman,		0
+*,			0,	1,	Times-Bold,		0
+*,			1,	0,	Times-Italic,		0
+*,			1,	1,	Times-BoldItalic,	0
diff --git a/Resources/fontnames.russian b/Resources/fontnames.russian
new file mode 100644
index 0000000..fb21c56
--- /dev/null
+++ b/Resources/fontnames.russian
@@ -0,0 +1,43 @@
+# Default fontnames translation table
+# for Cyrillic
+#
+# by: Dmitry Chernyak <cdl@inkasbank.ru>
+#
+# MS-Word fontname,	Italic,	Bold,	PostScript fontname,	Special
+Arial,			0,	0,	ArialCyrMT,		0
+Arial,			0,	1,	ArialCyrMT-Bold,	0
+Arial,			1,	0,	ArialCyrMT-Italic,	0
+Arial,			1,	1,	ArialCyrMT-BoldItalic,	0
+Courier,		0,	0,	CourierCyrPS,		0
+Courier,		0,	1,	CourierCyrPS-Bold,	0
+Courier,		1,	0,	CourierCyrPS-Inclined,	0
+Courier,		1,	1,	CourierCyrPS-BoldInclined,	0
+Courier New,		0,	0,	CourierCyrPS,		0
+Courier New,		0,	1,	CourierCyrPS-Bold,	0
+Courier New,		1,	0,	CourierCyrPS-Inclined,	0
+Courier New,		1,	1,	CourierCyrPS-BoldInclined,	0
+Fixedsys,		0,	0,	CourierCyrPS,		0
+Fixedsys,		0,	1,	CourierCyrPS-Bold,	0
+Fixedsys,		1,	0,	CourierCyrPS-Inclined,	0
+Fixedsys,		1,	1,	CourierCyrPS-BoldInclined,	0
+Helvetica,		0,	0,	ArialCyrMT,		0
+Helvetica,		0,	1,	ArialCyrMT-Bold,	0
+Helvetica,		1,	0,	ArialCyrMT-Italic,	0
+Helvetica,		1,	1,	ArialCyrMT-BoldItalic,	0
+Lucida Console,		0,	0,	CourierCyrPS,		0
+Lucida Console,		0,	1,	CourierCyrPS-Bold,	0
+Lucida Console,		1,	0,	CourierCyrPS-Inclined,	0
+Lucida Console,		1,	1,	CourierCyrPS-BoldInclined,	0
+Swiss,			0,	0,	Helvetica,		0
+Swiss,			0,	1,	Helvetica-Bold,		0
+Swiss,			1,	0,	Helvetica-Oblique,	0
+Swiss,			1,	1,	Helvetica-BoldOblique,	0
+Univers,		0,	0,	Helvetica,		0
+Univers,		0,	1,	Helvetica-Bold,		0
+Univers,		1,	0,	Helvetica-Oblique,	0
+Univers,		1,	1,	Helvetica-BoldOblique,	0
+# All the other fonts
+*,			0,	0,	TimesNRCyrMT,		0
+*,			0,	1,	TimesNRCyrMT-Bold,	0
+*,			1,	0,	TimesNRCyrMT-Inclined,	0
+*,			1,	1,	TimesNRCyrMT-BoldInclined,	0
diff --git a/Resources/koi8-r.txt b/Resources/koi8-r.txt
new file mode 100644
index 0000000..5105610
--- /dev/null
+++ b/Resources/koi8-r.txt
@@ -0,0 +1,302 @@
+#
+#	Name:             KOI8-R (RFC1489) to Unicode
+#	Unicode version:  3.0
+#	Table version:    1.0
+#	Table format:     Format A
+#	Date:             18 August 1999
+#	Authors:          Helmut Richter <richter@lrz.de>
+#
+#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
+#
+#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+#	No claims are made as to fitness for any particular purpose.  No
+#	warranties of any kind are expressed or implied.  The recipient
+#	agrees to determine applicability of information provided.  If this
+#	file has been provided on optical media by Unicode, Inc., the sole
+#	remedy for any claim will be exchange of defective media within 90
+#	days of receipt.
+#
+#	Unicode, Inc. hereby grants the right to freely use the information
+#	supplied in this file in the creation of products supporting the
+#	Unicode Standard, and to make copies of this file in any form for
+#	internal or external distribution as long as this notice remains
+#	attached.
+#
+#	General notes:
+#
+#	This table contains the data the Unicode Consortium has on how
+#       KOI8-R characters map into Unicode. The underlying document is the
+#	mapping described in RFC 1489. No statements are made as to whether
+#	this mapping is the same as the mapping defined as "Code Page 878"
+#	with some vendors.
+#
+#	Format:  Three tab-separated columns
+#		 Column #1 is the KOI8-R code (in hex as 0xXX)
+#		 Column #2 is the Unicode (in hex as 0xXXXX)
+#		 Column #3 the Unicode name (follows a comment sign, '#')
+#
+#	The entries are in KOI8-R order.
+#
+#	Version history
+#	1.0 version: created.
+#
+#	Any comments or problems, contact <errata@unicode.org>
+#	Please note that <errata@unicode.org> is an archival address;
+#	notices will be checked, but do not expect an immediate response.
+#
+0x00	0x0000	#	NULL
+0x01	0x0001	#	START OF HEADING
+0x02	0x0002	#	START OF TEXT
+0x03	0x0003	#	END OF TEXT
+0x04	0x0004	#	END OF TRANSMISSION
+0x05	0x0005	#	ENQUIRY
+0x06	0x0006	#	ACKNOWLEDGE
+0x07	0x0007	#	BELL
+0x08	0x0008	#	BACKSPACE
+0x09	0x0009	#	HORIZONTAL TABULATION
+0x0A	0x000A	#	LINE FEED
+0x0B	0x000B	#	VERTICAL TABULATION
+0x0C	0x000C	#	FORM FEED
+0x0D	0x000D	#	CARRIAGE RETURN
+0x0E	0x000E	#	SHIFT OUT
+0x0F	0x000F	#	SHIFT IN
+0x10	0x0010	#	DATA LINK ESCAPE
+0x11	0x0011	#	DEVICE CONTROL ONE
+0x12	0x0012	#	DEVICE CONTROL TWO
+0x13	0x0013	#	DEVICE CONTROL THREE
+0x14	0x0014	#	DEVICE CONTROL FOUR
+0x15	0x0015	#	NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#	SYNCHRONOUS IDLE
+0x17	0x0017	#	END OF TRANSMISSION BLOCK
+0x18	0x0018	#	CANCEL
+0x19	0x0019	#	END OF MEDIUM
+0x1A	0x001A	#	SUBSTITUTE
+0x1B	0x001B	#	ESCAPE
+0x1C	0x001C	#	FILE SEPARATOR
+0x1D	0x001D	#	GROUP SEPARATOR
+0x1E	0x001E	#	RECORD SEPARATOR
+0x1F	0x001F	#	UNIT SEPARATOR
+0x20	0x0020	#	SPACE
+0x21	0x0021	#	EXCLAMATION MARK
+0x22	0x0022	#	QUOTATION MARK
+0x23	0x0023	#	NUMBER SIGN
+0x24	0x0024	#	DOLLAR SIGN
+0x25	0x0025	#	PERCENT SIGN
+0x26	0x0026	#	AMPERSAND
+0x27	0x0027	#	APOSTROPHE
+0x28	0x0028	#	LEFT PARENTHESIS
+0x29	0x0029	#	RIGHT PARENTHESIS
+0x2A	0x002A	#	ASTERISK
+0x2B	0x002B	#	PLUS SIGN
+0x2C	0x002C	#	COMMA
+0x2D	0x002D	#	HYPHEN-MINUS
+0x2E	0x002E	#	FULL STOP
+0x2F	0x002F	#	SOLIDUS
+0x30	0x0030	#	DIGIT ZERO
+0x31	0x0031	#	DIGIT ONE
+0x32	0x0032	#	DIGIT TWO
+0x33	0x0033	#	DIGIT THREE
+0x34	0x0034	#	DIGIT FOUR
+0x35	0x0035	#	DIGIT FIVE
+0x36	0x0036	#	DIGIT SIX
+0x37	0x0037	#	DIGIT SEVEN
+0x38	0x0038	#	DIGIT EIGHT
+0x39	0x0039	#	DIGIT NINE
+0x3A	0x003A	#	COLON
+0x3B	0x003B	#	SEMICOLON
+0x3C	0x003C	#	LESS-THAN SIGN
+0x3D	0x003D	#	EQUALS SIGN
+0x3E	0x003E	#	GREATER-THAN SIGN
+0x3F	0x003F	#	QUESTION MARK
+0x40	0x0040	#	COMMERCIAL AT
+0x41	0x0041	#	LATIN CAPITAL LETTER A
+0x42	0x0042	#	LATIN CAPITAL LETTER B
+0x43	0x0043	#	LATIN CAPITAL LETTER C
+0x44	0x0044	#	LATIN CAPITAL LETTER D
+0x45	0x0045	#	LATIN CAPITAL LETTER E
+0x46	0x0046	#	LATIN CAPITAL LETTER F
+0x47	0x0047	#	LATIN CAPITAL LETTER G
+0x48	0x0048	#	LATIN CAPITAL LETTER H
+0x49	0x0049	#	LATIN CAPITAL LETTER I
+0x4A	0x004A	#	LATIN CAPITAL LETTER J
+0x4B	0x004B	#	LATIN CAPITAL LETTER K
+0x4C	0x004C	#	LATIN CAPITAL LETTER L
+0x4D	0x004D	#	LATIN CAPITAL LETTER M
+0x4E	0x004E	#	LATIN CAPITAL LETTER N
+0x4F	0x004F	#	LATIN CAPITAL LETTER O
+0x50	0x0050	#	LATIN CAPITAL LETTER P
+0x51	0x0051	#	LATIN CAPITAL LETTER Q
+0x52	0x0052	#	LATIN CAPITAL LETTER R
+0x53	0x0053	#	LATIN CAPITAL LETTER S
+0x54	0x0054	#	LATIN CAPITAL LETTER T
+0x55	0x0055	#	LATIN CAPITAL LETTER U
+0x56	0x0056	#	LATIN CAPITAL LETTER V
+0x57	0x0057	#	LATIN CAPITAL LETTER W
+0x58	0x0058	#	LATIN CAPITAL LETTER X
+0x59	0x0059	#	LATIN CAPITAL LETTER Y
+0x5A	0x005A	#	LATIN CAPITAL LETTER Z
+0x5B	0x005B	#	LEFT SQUARE BRACKET
+0x5C	0x005C	#	REVERSE SOLIDUS
+0x5D	0x005D	#	RIGHT SQUARE BRACKET
+0x5E	0x005E	#	CIRCUMFLEX ACCENT
+0x5F	0x005F	#	LOW LINE
+0x60	0x0060	#	GRAVE ACCENT
+0x61	0x0061	#	LATIN SMALL LETTER A
+0x62	0x0062	#	LATIN SMALL LETTER B
+0x63	0x0063	#	LATIN SMALL LETTER C
+0x64	0x0064	#	LATIN SMALL LETTER D
+0x65	0x0065	#	LATIN SMALL LETTER E
+0x66	0x0066	#	LATIN SMALL LETTER F
+0x67	0x0067	#	LATIN SMALL LETTER G
+0x68	0x0068	#	LATIN SMALL LETTER H
+0x69	0x0069	#	LATIN SMALL LETTER I
+0x6A	0x006A	#	LATIN SMALL LETTER J
+0x6B	0x006B	#	LATIN SMALL LETTER K
+0x6C	0x006C	#	LATIN SMALL LETTER L
+0x6D	0x006D	#	LATIN SMALL LETTER M
+0x6E	0x006E	#	LATIN SMALL LETTER N
+0x6F	0x006F	#	LATIN SMALL LETTER O
+0x70	0x0070	#	LATIN SMALL LETTER P
+0x71	0x0071	#	LATIN SMALL LETTER Q
+0x72	0x0072	#	LATIN SMALL LETTER R
+0x73	0x0073	#	LATIN SMALL LETTER S
+0x74	0x0074	#	LATIN SMALL LETTER T
+0x75	0x0075	#	LATIN SMALL LETTER U
+0x76	0x0076	#	LATIN SMALL LETTER V
+0x77	0x0077	#	LATIN SMALL LETTER W
+0x78	0x0078	#	LATIN SMALL LETTER X
+0x79	0x0079	#	LATIN SMALL LETTER Y
+0x7A	0x007A	#	LATIN SMALL LETTER Z
+0x7B	0x007B	#	LEFT CURLY BRACKET
+0x7C	0x007C	#	VERTICAL LINE
+0x7D	0x007D	#	RIGHT CURLY BRACKET
+0x7E	0x007E	#	TILDE
+0x7F	0x007F	#	DELETE
+0x80	0x2500	#	BOX DRAWINGS LIGHT HORIZONTAL
+0x81	0x2502	#	BOX DRAWINGS LIGHT VERTICAL
+0x82	0x250C	#	BOX DRAWINGS LIGHT DOWN AND RIGHT
+0x83	0x2510	#	BOX DRAWINGS LIGHT DOWN AND LEFT
+0x84	0x2514	#	BOX DRAWINGS LIGHT UP AND RIGHT
+0x85	0x2518	#	BOX DRAWINGS LIGHT UP AND LEFT
+0x86	0x251C	#	BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+0x87	0x2524	#	BOX DRAWINGS LIGHT VERTICAL AND LEFT
+0x88	0x252C	#	BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+0x89	0x2534	#	BOX DRAWINGS LIGHT UP AND HORIZONTAL
+0x8A	0x253C	#	BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+0x8B	0x2580	#	UPPER HALF BLOCK
+0x8C	0x2584	#	LOWER HALF BLOCK
+0x8D	0x2588	#	FULL BLOCK
+0x8E	0x258C	#	LEFT HALF BLOCK
+0x8F	0x2590	#	RIGHT HALF BLOCK
+0x90	0x2591	#	LIGHT SHADE
+0x91	0x2592	#	MEDIUM SHADE
+0x92	0x2593	#	DARK SHADE
+0x93	0x2320	#	TOP HALF INTEGRAL
+0x94	0x25A0	#	BLACK SQUARE
+0x95	0x2219	#	BULLET OPERATOR
+0x96	0x221A	#	SQUARE ROOT
+0x97	0x2248	#	ALMOST EQUAL TO
+0x98	0x2264	#	LESS-THAN OR EQUAL TO
+0x99	0x2265	#	GREATER-THAN OR EQUAL TO
+0x9A	0x00A0	#	NO-BREAK SPACE
+0x9B	0x2321	#	BOTTOM HALF INTEGRAL
+0x9C	0x00B0	#	DEGREE SIGN
+0x9D	0x00B2	#	SUPERSCRIPT TWO
+0x9E	0x00B7	#	MIDDLE DOT
+0x9F	0x00F7	#	DIVISION SIGN
+0xA0	0x2550	#	BOX DRAWINGS DOUBLE HORIZONTAL
+0xA1	0x2551	#	BOX DRAWINGS DOUBLE VERTICAL
+0xA2	0x2552	#	BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+0xA3	0x0451	#	CYRILLIC SMALL LETTER IO
+0xA4	0x2553	#	BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+0xA5	0x2554	#	BOX DRAWINGS DOUBLE DOWN AND RIGHT
+0xA6	0x2555	#	BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+0xA7	0x2556	#	BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+0xA8	0x2557	#	BOX DRAWINGS DOUBLE DOWN AND LEFT
+0xA9	0x2558	#	BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+0xAA	0x2559	#	BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+0xAB	0x255A	#	BOX DRAWINGS DOUBLE UP AND RIGHT
+0xAC	0x255B	#	BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+0xAD	0x255C	#	BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+0xAE	0x255D	#	BOX DRAWINGS DOUBLE UP AND LEFT
+0xAF	0x255E	#	BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+0xB0	0x255F	#	BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+0xB1	0x2560	#	BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+0xB2	0x2561	#	BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+0xB3	0x0401	#	CYRILLIC CAPITAL LETTER IO
+0xB4	0x2562	#	BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+0xB5	0x2563	#	BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+0xB6	0x2564	#	BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+0xB7	0x2565	#	BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+0xB8	0x2566	#	BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+0xB9	0x2567	#	BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+0xBA	0x2568	#	BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+0xBB	0x2569	#	BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+0xBC	0x256A	#	BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+0xBD	0x256B	#	BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+0xBE	0x256C	#	BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+0xBF	0x00A9	#	COPYRIGHT SIGN
+0xC0	0x044E	#	CYRILLIC SMALL LETTER YU
+0xC1	0x0430	#	CYRILLIC SMALL LETTER A
+0xC2	0x0431	#	CYRILLIC SMALL LETTER BE
+0xC3	0x0446	#	CYRILLIC SMALL LETTER TSE
+0xC4	0x0434	#	CYRILLIC SMALL LETTER DE
+0xC5	0x0435	#	CYRILLIC SMALL LETTER IE
+0xC6	0x0444	#	CYRILLIC SMALL LETTER EF
+0xC7	0x0433	#	CYRILLIC SMALL LETTER GHE
+0xC8	0x0445	#	CYRILLIC SMALL LETTER HA
+0xC9	0x0438	#	CYRILLIC SMALL LETTER I
+0xCA	0x0439	#	CYRILLIC SMALL LETTER SHORT I
+0xCB	0x043A	#	CYRILLIC SMALL LETTER KA
+0xCC	0x043B	#	CYRILLIC SMALL LETTER EL
+0xCD	0x043C	#	CYRILLIC SMALL LETTER EM
+0xCE	0x043D	#	CYRILLIC SMALL LETTER EN
+0xCF	0x043E	#	CYRILLIC SMALL LETTER O
+0xD0	0x043F	#	CYRILLIC SMALL LETTER PE
+0xD1	0x044F	#	CYRILLIC SMALL LETTER YA
+0xD2	0x0440	#	CYRILLIC SMALL LETTER ER
+0xD3	0x0441	#	CYRILLIC SMALL LETTER ES
+0xD4	0x0442	#	CYRILLIC SMALL LETTER TE
+0xD5	0x0443	#	CYRILLIC SMALL LETTER U
+0xD6	0x0436	#	CYRILLIC SMALL LETTER ZHE
+0xD7	0x0432	#	CYRILLIC SMALL LETTER VE
+0xD8	0x044C	#	CYRILLIC SMALL LETTER SOFT SIGN
+0xD9	0x044B	#	CYRILLIC SMALL LETTER YERU
+0xDA	0x0437	#	CYRILLIC SMALL LETTER ZE
+0xDB	0x0448	#	CYRILLIC SMALL LETTER SHA
+0xDC	0x044D	#	CYRILLIC SMALL LETTER E
+0xDD	0x0449	#	CYRILLIC SMALL LETTER SHCHA
+0xDE	0x0447	#	CYRILLIC SMALL LETTER CHE
+0xDF	0x044A	#	CYRILLIC SMALL LETTER HARD SIGN
+0xE0	0x042E	#	CYRILLIC CAPITAL LETTER YU
+0xE1	0x0410	#	CYRILLIC CAPITAL LETTER A
+0xE2	0x0411	#	CYRILLIC CAPITAL LETTER BE
+0xE3	0x0426	#	CYRILLIC CAPITAL LETTER TSE
+0xE4	0x0414	#	CYRILLIC CAPITAL LETTER DE
+0xE5	0x0415	#	CYRILLIC CAPITAL LETTER IE
+0xE6	0x0424	#	CYRILLIC CAPITAL LETTER EF
+0xE7	0x0413	#	CYRILLIC CAPITAL LETTER GHE
+0xE8	0x0425	#	CYRILLIC CAPITAL LETTER HA
+0xE9	0x0418	#	CYRILLIC CAPITAL LETTER I
+0xEA	0x0419	#	CYRILLIC CAPITAL LETTER SHORT I
+0xEB	0x041A	#	CYRILLIC CAPITAL LETTER KA
+0xEC	0x041B	#	CYRILLIC CAPITAL LETTER EL
+0xED	0x041C	#	CYRILLIC CAPITAL LETTER EM
+0xEE	0x041D	#	CYRILLIC CAPITAL LETTER EN
+0xEF	0x041E	#	CYRILLIC CAPITAL LETTER O
+0xF0	0x041F	#	CYRILLIC CAPITAL LETTER PE
+0xF1	0x042F	#	CYRILLIC CAPITAL LETTER YA
+0xF2	0x0420	#	CYRILLIC CAPITAL LETTER ER
+0xF3	0x0421	#	CYRILLIC CAPITAL LETTER ES
+0xF4	0x0422	#	CYRILLIC CAPITAL LETTER TE
+0xF5	0x0423	#	CYRILLIC CAPITAL LETTER U
+0xF6	0x0416	#	CYRILLIC CAPITAL LETTER ZHE
+0xF7	0x0412	#	CYRILLIC CAPITAL LETTER VE
+0xF8	0x042C	#	CYRILLIC CAPITAL LETTER SOFT SIGN
+0xF9	0x042B	#	CYRILLIC CAPITAL LETTER YERU
+0xFA	0x0417	#	CYRILLIC CAPITAL LETTER ZE
+0xFB	0x0428	#	CYRILLIC CAPITAL LETTER SHA
+0xFC	0x042D	#	CYRILLIC CAPITAL LETTER E
+0xFD	0x0429	#	CYRILLIC CAPITAL LETTER SHCHA
+0xFE	0x0427	#	CYRILLIC CAPITAL LETTER CHE
+0xFF	0x042A	#	CYRILLIC CAPITAL LETTER HARD SIGN
diff --git a/Resources/koi8-u.txt b/Resources/koi8-u.txt
new file mode 100644
index 0000000..61a5b40
--- /dev/null
+++ b/Resources/koi8-u.txt
@@ -0,0 +1,303 @@
+#
+#	Name:             KOI8-U (RFC2319) to Unicode
+#	Unicode version:  3.0
+#	Table version:    1.0
+#	Table format:     Format A
+#	Date:             08 September 2001
+#	Authors:          Andriy Rysin <arysin@yahoo.com>
+#
+#	Copyright (c) 1991-2001 Unicode, Inc.  All Rights reserved.
+#
+#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+#	No claims are made as to fitness for any particular purpose.  No
+#	warranties of any kind are expressed or implied.  The recipient
+#	agrees to determine applicability of information provided.  If this
+#	file has been provided on optical media by Unicode, Inc., the sole
+#	remedy for any claim will be exchange of defective media within 90
+#	days of receipt.
+#
+#	Unicode, Inc. hereby grants the right to freely use the information
+#	supplied in this file in the creation of products supporting the
+#	Unicode Standard, and to make copies of this file in any form for
+#	internal or external distribution as long as this notice remains
+#	attached.
+#
+#	General notes:
+#
+#	This table contains the data the Unicode Consortium has on how
+#       KOI8-U characters map into Unicode. The underlying document is the
+#	mapping described in RFC 2319. No statements are made as to whether
+#	this mapping is the same as the mapping defined as "Code Page 878"
+#	with some vendors.
+#
+#	Format:  Three tab-separated columns
+#		 Column #1 is the KOI8-U code (in hex as 0xXX)
+#		 Column #2 is the Unicode (in hex as 0xXXXX)
+#		 Column #3 the Unicode name (follows a comment sign, '#')
+#
+#	The entries are in KOI8-U order.
+#
+#	Version history
+#	1.0 version: created.
+#
+#	Any comments or problems, contact <errata@unicode.org>
+#	Please note that <errata@unicode.org> is an archival address;
+#	notices will be checked, but do not expect an immediate response.
+#
+0x00	0x0000	#	NULL
+0x01	0x0001	#	START OF HEADING
+0x02	0x0002	#	START OF TEXT
+0x03	0x0003	#	END OF TEXT
+0x04	0x0004	#	END OF TRANSMISSION
+0x05	0x0005	#	ENQUIRY
+0x06	0x0006	#	ACKNOWLEDGE
+0x07	0x0007	#	BELL
+0x08	0x0008	#	BACKSPACE
+0x09	0x0009	#	HORIZONTAL TABULATION
+0x0A	0x000A	#	LINE FEED
+0x0B	0x000B	#	VERTICAL TABULATION
+0x0C	0x000C	#	FORM FEED
+0x0D	0x000D	#	CARRIAGE RETURN
+0x0E	0x000E	#	SHIFT OUT
+0x0F	0x000F	#	SHIFT IN
+0x10	0x0010	#	DATA LINK ESCAPE
+0x11	0x0011	#	DEVICE CONTROL ONE
+0x12	0x0012	#	DEVICE CONTROL TWO
+0x13	0x0013	#	DEVICE CONTROL THREE
+0x14	0x0014	#	DEVICE CONTROL FOUR
+0x15	0x0015	#	NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#	SYNCHRONOUS IDLE
+0x17	0x0017	#	END OF TRANSMISSION BLOCK
+0x18	0x0018	#	CANCEL
+0x19	0x0019	#	END OF MEDIUM
+0x1A	0x001A	#	SUBSTITUTE
+0x1B	0x001B	#	ESCAPE
+0x1C	0x001C	#	FILE SEPARATOR
+0x1D	0x001D	#	GROUP SEPARATOR
+0x1E	0x001E	#	RECORD SEPARATOR
+0x1F	0x001F	#	UNIT SEPARATOR
+0x20	0x0020	#	SPACE
+0x21	0x0021	#	EXCLAMATION MARK
+0x22	0x0022	#	QUOTATION MARK
+0x23	0x0023	#	NUMBER SIGN
+0x24	0x0024	#	DOLLAR SIGN
+0x25	0x0025	#	PERCENT SIGN
+0x26	0x0026	#	AMPERSAND
+0x27	0x0027	#	APOSTROPHE
+0x28	0x0028	#	LEFT PARENTHESIS
+0x29	0x0029	#	RIGHT PARENTHESIS
+0x2A	0x002A	#	ASTERISK
+0x2B	0x002B	#	PLUS SIGN
+0x2C	0x002C	#	COMMA
+0x2D	0x002D	#	HYPHEN-MINUS
+0x2E	0x002E	#	FULL STOP
+0x2F	0x002F	#	SOLIDUS
+0x30	0x0030	#	DIGIT ZERO
+0x31	0x0031	#	DIGIT ONE
+0x32	0x0032	#	DIGIT TWO
+0x33	0x0033	#	DIGIT THREE
+0x34	0x0034	#	DIGIT FOUR
+0x35	0x0035	#	DIGIT FIVE
+0x36	0x0036	#	DIGIT SIX
+0x37	0x0037	#	DIGIT SEVEN
+0x38	0x0038	#	DIGIT EIGHT
+0x39	0x0039	#	DIGIT NINE
+0x3A	0x003A	#	COLON
+0x3B	0x003B	#	SEMICOLON
+0x3C	0x003C	#	LESS-THAN SIGN
+0x3D	0x003D	#	EQUALS SIGN
+0x3E	0x003E	#	GREATER-THAN SIGN
+0x3F	0x003F	#	QUESTION MARK
+0x40	0x0040	#	COMMERCIAL AT
+0x41	0x0041	#	LATIN CAPITAL LETTER A
+0x42	0x0042	#	LATIN CAPITAL LETTER B
+0x43	0x0043	#	LATIN CAPITAL LETTER C
+0x44	0x0044	#	LATIN CAPITAL LETTER D
+0x45	0x0045	#	LATIN CAPITAL LETTER E
+0x46	0x0046	#	LATIN CAPITAL LETTER F
+0x47	0x0047	#	LATIN CAPITAL LETTER G
+0x48	0x0048	#	LATIN CAPITAL LETTER H
+0x49	0x0049	#	LATIN CAPITAL LETTER I
+0x4A	0x004A	#	LATIN CAPITAL LETTER J
+0x4B	0x004B	#	LATIN CAPITAL LETTER K
+0x4C	0x004C	#	LATIN CAPITAL LETTER L
+0x4D	0x004D	#	LATIN CAPITAL LETTER M
+0x4E	0x004E	#	LATIN CAPITAL LETTER N
+0x4F	0x004F	#	LATIN CAPITAL LETTER O
+0x50	0x0050	#	LATIN CAPITAL LETTER P
+0x51	0x0051	#	LATIN CAPITAL LETTER Q
+0x52	0x0052	#	LATIN CAPITAL LETTER R
+0x53	0x0053	#	LATIN CAPITAL LETTER S
+0x54	0x0054	#	LATIN CAPITAL LETTER T
+0x55	0x0055	#	LATIN CAPITAL LETTER U
+0x56	0x0056	#	LATIN CAPITAL LETTER V
+0x57	0x0057	#	LATIN CAPITAL LETTER W
+0x58	0x0058	#	LATIN CAPITAL LETTER X
+0x59	0x0059	#	LATIN CAPITAL LETTER Y
+0x5A	0x005A	#	LATIN CAPITAL LETTER Z
+0x5B	0x005B	#	LEFT SQUARE BRACKET
+0x5C	0x005C	#	REVERSE SOLIDUS
+0x5D	0x005D	#	RIGHT SQUARE BRACKET
+0x5E	0x005E	#	CIRCUMFLEX ACCENT
+0x5F	0x005F	#	LOW LINE
+0x60	0x0060	#	GRAVE ACCENT
+0x61	0x0061	#	LATIN SMALL LETTER A
+0x62	0x0062	#	LATIN SMALL LETTER B
+0x63	0x0063	#	LATIN SMALL LETTER C
+0x64	0x0064	#	LATIN SMALL LETTER D
+0x65	0x0065	#	LATIN SMALL LETTER E
+0x66	0x0066	#	LATIN SMALL LETTER F
+0x67	0x0067	#	LATIN SMALL LETTER G
+0x68	0x0068	#	LATIN SMALL LETTER H
+0x69	0x0069	#	LATIN SMALL LETTER I
+0x6A	0x006A	#	LATIN SMALL LETTER J
+0x6B	0x006B	#	LATIN SMALL LETTER K
+0x6C	0x006C	#	LATIN SMALL LETTER L
+0x6D	0x006D	#	LATIN SMALL LETTER M
+0x6E	0x006E	#	LATIN SMALL LETTER N
+0x6F	0x006F	#	LATIN SMALL LETTER O
+0x70	0x0070	#	LATIN SMALL LETTER P
+0x71	0x0071	#	LATIN SMALL LETTER Q
+0x72	0x0072	#	LATIN SMALL LETTER R
+0x73	0x0073	#	LATIN SMALL LETTER S
+0x74	0x0074	#	LATIN SMALL LETTER T
+0x75	0x0075	#	LATIN SMALL LETTER U
+0x76	0x0076	#	LATIN SMALL LETTER V
+0x77	0x0077	#	LATIN SMALL LETTER W
+0x78	0x0078	#	LATIN SMALL LETTER X
+0x79	0x0079	#	LATIN SMALL LETTER Y
+0x7A	0x007A	#	LATIN SMALL LETTER Z
+0x7B	0x007B	#	LEFT CURLY BRACKET
+0x7C	0x007C	#	VERTICAL LINE
+0x7D	0x007D	#	RIGHT CURLY BRACKET
+0x7E	0x007E	#	TILDE
+0x7F	0x007F	#	DELETE
+0x80	0x2500	#	BOX DRAWINGS LIGHT HORIZONTAL
+0x81	0x2502	#	BOX DRAWINGS LIGHT VERTICAL
+0x82	0x250C	#	BOX DRAWINGS LIGHT DOWN AND RIGHT
+0x83	0x2510	#	BOX DRAWINGS LIGHT DOWN AND LEFT
+0x84	0x2514	#	BOX DRAWINGS LIGHT UP AND RIGHT
+0x85	0x2518	#	BOX DRAWINGS LIGHT UP AND LEFT
+0x86	0x251C	#	BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+0x87	0x2524	#	BOX DRAWINGS LIGHT VERTICAL AND LEFT
+0x88	0x252C	#	BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+0x89	0x2534	#	BOX DRAWINGS LIGHT UP AND HORIZONTAL
+0x8A	0x253C	#	BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+0x8B	0x2580	#	UPPER HALF BLOCK
+0x8C	0x2584	#	LOWER HALF BLOCK
+0x8D	0x2588	#	FULL BLOCK
+0x8E	0x258C	#	LEFT HALF BLOCK
+0x8F	0x2590	#	RIGHT HALF BLOCK
+0x90	0x2591	#	LIGHT SHADE
+0x91	0x2592	#	MEDIUM SHADE
+0x92	0x2593	#	DARK SHADE
+0x93	0x2320	#	TOP HALF INTEGRAL
+0x94	0x25A0	#	BLACK SQUARE
+0x95	0x2219	#	BULLET OPERATOR
+0x96	0x221A	#	SQUARE ROOT
+0x97	0x2248	#	ALMOST EQUAL TO
+0x98	0x2264	#	LESS-THAN OR EQUAL TO
+0x99	0x2265	#	GREATER-THAN OR EQUAL TO
+0x9A	0x00A0	#	NO-BREAK SPACE
+0x9B	0x2321	#	BOTTOM HALF INTEGRAL
+0x9C	0x00B0	#	DEGREE SIGN
+0x9D	0x00B2	#	SUPERSCRIPT TWO
+0x9E	0x00B7	#	MIDDLE DOT
+0x9F	0x00F7	#	DIVISION SIGN
+0xA0	0x2550	#	BOX DRAWINGS DOUBLE HORIZONTAL
+0xA1	0x2551	#	BOX DRAWINGS DOUBLE VERTICAL
+0xA2	0x2552	#	BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+0xA3	0x0451	#	CYRILLIC SMALL LETTER IO
+0xA4	0x0454	#	CYRILLIC SMALL LETTER UKRAINIAN IE
+0xA5	0x2554	#	BOX DRAWINGS DOUBLE DOWN AND RIGHT
+0xA6	0x0456	#	CYRILLIC SMALL LETTER BELORUSSIAN-UKRAINIAN I
+0xA7	0x0457	#	CYRILLIC SMALL LETTER YI (UKRAINIAN)
+0xA8	0x2557	#	BOX DRAWINGS DOUBLE DOWN AND LEFT
+0xA9	0x2558	#	BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+0xAA	0x2559	#	BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+0xAB	0x255A	#	BOX DRAWINGS DOUBLE UP AND RIGHT
+0xAC	0x255B	#	BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+0xAD	0x0491	#	CYRILLIC SMALL LETTER UKRAINIAN GHE WITH UPTURN
+0xAE	0x255D	#	BOX DRAWINGS DOUBLE UP AND LEFT
+0xAF	0x255E	#	BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+0xB0	0x255F	#	BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+0xB1	0x2560	#	BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+0xB2	0x2561	#	BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+0xB3	0x0401	#	CYRILLIC CAPITAL LETTER IO
+0xB4	0x0404	#	CYRILLIC CAPITAL LETTER UKRAINIAN IE
+0xB5	0x2563	#	BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+0xB6	0x0406	#	CYRILLIC CAPITAL LETTER BELORUSSIAN-UKRAINIAN I
+0xB7	0x0407	#	CYRILLIC CAPITAL LETTER YI (UKRAINIAN)
+0xB8	0x2566	#	BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+0xB9	0x2567	#	BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+0xBA	0x2568	#	BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+0xBB	0x2569	#	BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+0xBC	0x256A	#	BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+0xBD	0x0490	#	CYRILLIC CAPITAL LETTER UKRAINIAN GHE WITH UPTURN
+0xBD	0x256B	#	BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+0xBE	0x256C	#	BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+0xBF	0x00A9	#	COPYRIGHT SIGN
+0xC0	0x044E	#	CYRILLIC SMALL LETTER YU
+0xC1	0x0430	#	CYRILLIC SMALL LETTER A
+0xC2	0x0431	#	CYRILLIC SMALL LETTER BE
+0xC3	0x0446	#	CYRILLIC SMALL LETTER TSE
+0xC4	0x0434	#	CYRILLIC SMALL LETTER DE
+0xC5	0x0435	#	CYRILLIC SMALL LETTER IE
+0xC6	0x0444	#	CYRILLIC SMALL LETTER EF
+0xC7	0x0433	#	CYRILLIC SMALL LETTER GHE
+0xC8	0x0445	#	CYRILLIC SMALL LETTER HA
+0xC9	0x0438	#	CYRILLIC SMALL LETTER I
+0xCA	0x0439	#	CYRILLIC SMALL LETTER SHORT I
+0xCB	0x043A	#	CYRILLIC SMALL LETTER KA
+0xCC	0x043B	#	CYRILLIC SMALL LETTER EL
+0xCD	0x043C	#	CYRILLIC SMALL LETTER EM
+0xCE	0x043D	#	CYRILLIC SMALL LETTER EN
+0xCF	0x043E	#	CYRILLIC SMALL LETTER O
+0xD0	0x043F	#	CYRILLIC SMALL LETTER PE
+0xD1	0x044F	#	CYRILLIC SMALL LETTER YA
+0xD2	0x0440	#	CYRILLIC SMALL LETTER ER
+0xD3	0x0441	#	CYRILLIC SMALL LETTER ES
+0xD4	0x0442	#	CYRILLIC SMALL LETTER TE
+0xD5	0x0443	#	CYRILLIC SMALL LETTER U
+0xD6	0x0436	#	CYRILLIC SMALL LETTER ZHE
+0xD7	0x0432	#	CYRILLIC SMALL LETTER VE
+0xD8	0x044C	#	CYRILLIC SMALL LETTER SOFT SIGN
+0xD9	0x044B	#	CYRILLIC SMALL LETTER YERU
+0xDA	0x0437	#	CYRILLIC SMALL LETTER ZE
+0xDB	0x0448	#	CYRILLIC SMALL LETTER SHA
+0xDC	0x044D	#	CYRILLIC SMALL LETTER E
+0xDD	0x0449	#	CYRILLIC SMALL LETTER SHCHA
+0xDE	0x0447	#	CYRILLIC SMALL LETTER CHE
+0xDF	0x044A	#	CYRILLIC SMALL LETTER HARD SIGN
+0xE0	0x042E	#	CYRILLIC CAPITAL LETTER YU
+0xE1	0x0410	#	CYRILLIC CAPITAL LETTER A
+0xE2	0x0411	#	CYRILLIC CAPITAL LETTER BE
+0xE3	0x0426	#	CYRILLIC CAPITAL LETTER TSE
+0xE4	0x0414	#	CYRILLIC CAPITAL LETTER DE
+0xE5	0x0415	#	CYRILLIC CAPITAL LETTER IE
+0xE6	0x0424	#	CYRILLIC CAPITAL LETTER EF
+0xE7	0x0413	#	CYRILLIC CAPITAL LETTER GHE
+0xE8	0x0425	#	CYRILLIC CAPITAL LETTER HA
+0xE9	0x0418	#	CYRILLIC CAPITAL LETTER I
+0xEA	0x0419	#	CYRILLIC CAPITAL LETTER SHORT I
+0xEB	0x041A	#	CYRILLIC CAPITAL LETTER KA
+0xEC	0x041B	#	CYRILLIC CAPITAL LETTER EL
+0xED	0x041C	#	CYRILLIC CAPITAL LETTER EM
+0xEE	0x041D	#	CYRILLIC CAPITAL LETTER EN
+0xEF	0x041E	#	CYRILLIC CAPITAL LETTER O
+0xF0	0x041F	#	CYRILLIC CAPITAL LETTER PE
+0xF1	0x042F	#	CYRILLIC CAPITAL LETTER YA
+0xF2	0x0420	#	CYRILLIC CAPITAL LETTER ER
+0xF3	0x0421	#	CYRILLIC CAPITAL LETTER ES
+0xF4	0x0422	#	CYRILLIC CAPITAL LETTER TE
+0xF5	0x0423	#	CYRILLIC CAPITAL LETTER U
+0xF6	0x0416	#	CYRILLIC CAPITAL LETTER ZHE
+0xF7	0x0412	#	CYRILLIC CAPITAL LETTER VE
+0xF8	0x042C	#	CYRILLIC CAPITAL LETTER SOFT SIGN
+0xF9	0x042B	#	CYRILLIC CAPITAL LETTER YERU
+0xFA	0x0417	#	CYRILLIC CAPITAL LETTER ZE
+0xFB	0x0428	#	CYRILLIC CAPITAL LETTER SHA
+0xFC	0x042D	#	CYRILLIC CAPITAL LETTER E
+0xFD	0x0429	#	CYRILLIC CAPITAL LETTER SHCHA
+0xFE	0x0427	#	CYRILLIC CAPITAL LETTER CHE
+0xFF	0x042A	#	CYRILLIC CAPITAL LETTER HARD SIGN
diff --git a/Resources/roman.txt b/Resources/roman.txt
new file mode 100644
index 0000000..d3ed19e
--- /dev/null
+++ b/Resources/roman.txt
@@ -0,0 +1 @@
+#=======================================================================
#   FTP file name:  ROMAN.TXT
#
#   Contents:       Map (external version) from Mac OS Roman
#                   character set to Unicode 2.1
#
#   Copyright:      (c) 1994-1999 by Apple Computer, Inc., all rights
#                   reserved.
#
#   Contact:        charsets@apple.com
#
#   Changes:
#
#       b03  1999-Sep-22    Update contact e-mail address. Matches
#                           internal utom<b4>, ufrm<b3>, and Text
#                           Encoding Converter version 1.5.
#       b02  1998-Aug-18    Encoding changed for Mac OS 8.5; change
#                           mapping of 0xDB from CURRENCY SIGN to
#                           EURO SIGN. Matches internal utom<b3>,
#                           ufrm<b3>.
#       n08  1998-Feb-05    Minor update to header comments
#       n06  1997-Dec-14    Add warning about future changes to 0xDB
#                           from CURRENCY SIGN to EURO SIGN. Clarify
#                           some header information
#       n04  1997-Dec-01    Update to match internal utom<n3>, ufrm<n22>:
#                           Change standard mapping for 0xBD from U+2126
#                           to its canonical decomposition, U+03A9.
#       n03  1995-Apr-15    First version (after fixing some typos).
#                           Matches internal ufrm<n9>.
#
# Standard header:
# ----------------
#
#   Apple, the Apple logo, and Macintosh are trademarks of Apple
#   Computer, Inc., registered in the United States and other countries.
#   Unicode is a trademark of Unicode Inc. For the sake of brevity,
#   throughout this document, "Macintosh" can be used to refer to
#   Macintosh computers and "Unicode" can be used to refer to the
#   Unicode standard.
#
#   Apple makes no warranty or representation, either express or
#   implied, with respect to these tables, their quality, accuracy, or
#   fitness for a particular purpose. In no event will Apple be liable
#   for direct, indirect, special, incidental, or consequential damages 
#   resulting from any defect or inaccuracy in this document or the
#   accompanying tables.
#
#   These mapping tables and character lists are subject to change.
#   The latest tables should be available from the following:
#
#   <ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/APPLE/>
#   <ftp://dev.apple.com/devworld/Technical_Documentation/Misc._Standards/>
#
#   For general information about Mac OS encodings and these mapping
#   tables, see the file "README.TXT".
#
# Format:
# -------
#
#   Three tab-separated columns;
#   '#' begins a comment which continues to the end of the line.
#     Column #1 is the Mac OS Roman code (in hex as 0xNN)
#     Column #2 is the corresponding Unicode (in hex as 0xNNNN)
#     Column #3 is a comment containing the Unicode name
#
#   The entries are in Mac OS Roman code order.
#
#   One of these mappings requires the use of a corporate character.
#   See the file "CORPCHAR.TXT" and notes below.
#
#   Control character mappings are not shown in this table, following
#   the conventions of the standard UTC mapping tables. However, the
#   Mac OS Roman character set uses the standard control characters at
#   0x00-0x1F and 0x7F.
#
# Notes on Mac OS Roman:
# ----------------------
#
#   This character set is used for at least the following Mac OS
#   localizations: U.S., British, Canadian French, French, Swiss
#   French, German, Swiss German, Italian, Swiss Italian, Dutch,
#   Swedish, Norwegian, Danish, Finnish, Spanish, Catalan,
#   Portuguese, Brazilian, and the default International system.
#
#   Variants of Mac OS Roman are used for Croatian, Icelandic,
#   Turkish, Romanian, and other encodings. Separate mapping tables
#   are available for these encodings.
#
#   Before Mac OS 8.5, code point 0xDB was CURRENCY SIGN, and was
#   mapped to U+00A4. In Mac OS 8.5 and later versions, code point
#   0xDB is changed to EURO SIGN and maps to U+20AC; the standard
#   Apple fonts are updated for Mac OS 8.5 to reflect this. There is
#   a "currency sign" variant of the Mac OS Roman encoding that still
#   maps 0xDB to U+00A4; this can be used for older fonts.
#   Note: U+20AC is new with Unicode 2.1; for earlier Unicode
#   versions, Mac OS Roman 0xDB may be mapped to private-use character
#   U+F8A0.
#
#   Before Mac OS 8.5, the ROM bitmap versions of the fonts Chicago,
#   New York, Geneva, and Monaco did not implement the full Mac OS
#   Roman character set; they only supported character codes up to
#   0xD8. The TrueType versions of these fonts have always implemented
#   the full character set, as with the bitmap and TrueType versions
#   of the other standard Roman fonts.
#
#   In all Mac OS encodings, fonts such as Chicago which are used
#   as "system" fonts (for menus, dialogs, etc.) have four glyphs
#   at code points 0x11-0x14 for transient use by the Menu Manager.
#   These glyphs are not intended as characters for use in normal
#   text, and the associated code points are not generally
#   interpreted as associated with these glyphs; they are usually
#   interpreted (if at all) as the control codes DC1-DC4.
#
# Unicode mapping issues and notes:
# ---------------------------------
#
#   The following corporate zone Unicode character is used in this
#   mapping:
#
#     0xF8FF  Apple logo
#
#   NOTE: The graphic image associated with the Apple logo character
#   is not authorized for use without permission of Apple, and
#   unauthorized use might constitute trademark infringement.
#
# Details of mapping changes in each version:
# -------------------------------------------
#
#   Changes from version n08 to version b02:
#
#   - Encoding changed for Mac OS 8.5; change mapping of 0xDB from
#   CURRENCY SIGN (U+00A4) to EURO SIGN (U+20AC).
#
#   Changes from version n03 to version n04:
#
#   - Change mapping of 0xBD from U+2126 to its canonical
#     decomposition, U+03A9.
#
##################

0x20	0x0020	# SPACE
0x21	0x0021	# EXCLAMATION MARK
0x22	0x0022	# QUOTATION MARK
0x23	0x0023	# NUMBER SIGN
0x24	0x0024	# DOLLAR SIGN
0x25	0x0025	# PERCENT SIGN
0x26	0x0026	# AMPERSAND
0x27	0x0027	# APOSTROPHE
0x28	0x0028	# LEFT PARENTHESIS
0x29	0x0029	# RIGHT PARENTHESIS
0x2A	0x002A	# ASTERISK
0x2B	0x002B	# PLUS SIGN
0x2C	0x002C	# COMMA
0x2D	0x002D	# HYPHEN-MINUS
0x2E	0x002E	# FULL STOP
0x2F	0x002F	# SOLIDUS
0x30	0x0030	# DIGIT ZERO
0x31	0x0031	# DIGIT ONE
0x32	0x0032	# DIGIT TWO
0x33	0x0033	# DIGIT THREE
0x34	0x0034	# DIGIT FOUR
0x35	0x0035	# DIGIT FIVE
0x36	0x0036	# DIGIT SIX
0x37	0x0037	# DIGIT SEVEN
0x38	0x0038	# DIGIT EIGHT
0x39	0x0039	# DIGIT NINE
0x3A	0x003A	# COLON
0x3B	0x003B	# SEMICOLON
0x3C	0x003C	# LESS-THAN SIGN
0x3D	0x003D	# EQUALS SIGN
0x3E	0x003E	# GREATER-THAN SIGN
0x3F	0x003F	# QUESTION MARK
0x40	0x0040	# COMMERCIAL AT
0x41	0x0041	# LATIN CAPITAL LETTER A
0x42	0x0042	# LATIN CAPITAL LETTER B
0x43	0x0043	# LATIN CAPITAL LETTER C
0x44	0x0044	# LATIN CAPITAL LETTER D
0x45	0x0045	# LATIN CAPITAL LETTER E
0x46	0x0046	# LATIN CAPITAL LETTER F
0x47	0x0047	# LATIN CAPITAL LETTER G
0x48	0x0048	# LATIN CAPITAL LETTER H
0x49	0x0049	# LATIN CAPITAL LETTER I
0x4A	0x004A	# LATIN CAPITAL LETTER J
0x4B	0x004B	# LATIN CAPITAL LETTER K
0x4C	0x004C	# LATIN CAPITAL LETTER L
0x4D	0x004D	# LATIN CAPITAL LETTER M
0x4E	0x004E	# LATIN CAPITAL LETTER N
0x4F	0x004F	# LATIN CAPITAL LETTER O
0x50	0x0050	# LATIN CAPITAL LETTER P
0x51	0x0051	# LATIN CAPITAL LETTER Q
0x52	0x0052	# LATIN CAPITAL LETTER R
0x53	0x0053	# LATIN CAPITAL LETTER S
0x54	0x0054	# LATIN CAPITAL LETTER T
0x55	0x0055	# LATIN CAPITAL LETTER U
0x56	0x0056	# LATIN CAPITAL LETTER V
0x57	0x0057	# LATIN CAPITAL LETTER W
0x58	0x0058	# LATIN CAPITAL LETTER X
0x59	0x0059	# LATIN CAPITAL LETTER Y
0x5A	0x005A	# LATIN CAPITAL LETTER Z
0x5B	0x005B	# LEFT SQUARE BRACKET
0x5C	0x005C	# REVERSE SOLIDUS
0x5D	0x005D	# RIGHT SQUARE BRACKET
0x5E	0x005E	# CIRCUMFLEX ACCENT
0x5F	0x005F	# LOW LINE
0x60	0x0060	# GRAVE ACCENT
0x61	0x0061	# LATIN SMALL LETTER A
0x62	0x0062	# LATIN SMALL LETTER B
0x63	0x0063	# LATIN SMALL LETTER C
0x64	0x0064	# LATIN SMALL LETTER D
0x65	0x0065	# LATIN SMALL LETTER E
0x66	0x0066	# LATIN SMALL LETTER F
0x67	0x0067	# LATIN SMALL LETTER G
0x68	0x0068	# LATIN SMALL LETTER H
0x69	0x0069	# LATIN SMALL LETTER I
0x6A	0x006A	# LATIN SMALL LETTER J
0x6B	0x006B	# LATIN SMALL LETTER K
0x6C	0x006C	# LATIN SMALL LETTER L
0x6D	0x006D	# LATIN SMALL LETTER M
0x6E	0x006E	# LATIN SMALL LETTER N
0x6F	0x006F	# LATIN SMALL LETTER O
0x70	0x0070	# LATIN SMALL LETTER P
0x71	0x0071	# LATIN SMALL LETTER Q
0x72	0x0072	# LATIN SMALL LETTER R
0x73	0x0073	# LATIN SMALL LETTER S
0x74	0x0074	# LATIN SMALL LETTER T
0x75	0x0075	# LATIN SMALL LETTER U
0x76	0x0076	# LATIN SMALL LETTER V
0x77	0x0077	# LATIN SMALL LETTER W
0x78	0x0078	# LATIN SMALL LETTER X
0x79	0x0079	# LATIN SMALL LETTER Y
0x7A	0x007A	# LATIN SMALL LETTER Z
0x7B	0x007B	# LEFT CURLY BRACKET
0x7C	0x007C	# VERTICAL LINE
0x7D	0x007D	# RIGHT CURLY BRACKET
0x7E	0x007E	# TILDE
#
0x80	0x00C4	# LATIN CAPITAL LETTER A WITH DIAERESIS
0x81	0x00C5	# LATIN CAPITAL LETTER A WITH RING ABOVE
0x82	0x00C7	# LATIN CAPITAL LETTER C WITH CEDILLA
0x83	0x00C9	# LATIN CAPITAL LETTER E WITH ACUTE
0x84	0x00D1	# LATIN CAPITAL LETTER N WITH TILDE
0x85	0x00D6	# LATIN CAPITAL LETTER O WITH DIAERESIS
0x86	0x00DC	# LATIN CAPITAL LETTER U WITH DIAERESIS
0x87	0x00E1	# LATIN SMALL LETTER A WITH ACUTE
0x88	0x00E0	# LATIN SMALL LETTER A WITH GRAVE
0x89	0x00E2	# LATIN SMALL LETTER A WITH CIRCUMFLEX
0x8A	0x00E4	# LATIN SMALL LETTER A WITH DIAERESIS
0x8B	0x00E3	# LATIN SMALL LETTER A WITH TILDE
0x8C	0x00E5	# LATIN SMALL LETTER A WITH RING ABOVE
0x8D	0x00E7	# LATIN SMALL LETTER C WITH CEDILLA
0x8E	0x00E9	# LATIN SMALL LETTER E WITH ACUTE
0x8F	0x00E8	# LATIN SMALL LETTER E WITH GRAVE
0x90	0x00EA	# LATIN SMALL LETTER E WITH CIRCUMFLEX
0x91	0x00EB	# LATIN SMALL LETTER E WITH DIAERESIS
0x92	0x00ED	# LATIN SMALL LETTER I WITH ACUTE
0x93	0x00EC	# LATIN SMALL LETTER I WITH GRAVE
0x94	0x00EE	# LATIN SMALL LETTER I WITH CIRCUMFLEX
0x95	0x00EF	# LATIN SMALL LETTER I WITH DIAERESIS
0x96	0x00F1	# LATIN SMALL LETTER N WITH TILDE
0x97	0x00F3	# LATIN SMALL LETTER O WITH ACUTE
0x98	0x00F2	# LATIN SMALL LETTER O WITH GRAVE
0x99	0x00F4	# LATIN SMALL LETTER O WITH CIRCUMFLEX
0x9A	0x00F6	# LATIN SMALL LETTER O WITH DIAERESIS
0x9B	0x00F5	# LATIN SMALL LETTER O WITH TILDE
0x9C	0x00FA	# LATIN SMALL LETTER U WITH ACUTE
0x9D	0x00F9	# LATIN SMALL LETTER U WITH GRAVE
0x9E	0x00FB	# LATIN SMALL LETTER U WITH CIRCUMFLEX
0x9F	0x00FC	# LATIN SMALL LETTER U WITH DIAERESIS
0xA0	0x2020	# DAGGER
0xA1	0x00B0	# DEGREE SIGN
0xA2	0x00A2	# CENT SIGN
0xA3	0x00A3	# POUND SIGN
0xA4	0x00A7	# SECTION SIGN
0xA5	0x2022	# BULLET
0xA6	0x00B6	# PILCROW SIGN
0xA7	0x00DF	# LATIN SMALL LETTER SHARP S
0xA8	0x00AE	# REGISTERED SIGN
0xA9	0x00A9	# COPYRIGHT SIGN
0xAA	0x2122	# TRADE MARK SIGN
0xAB	0x00B4	# ACUTE ACCENT
0xAC	0x00A8	# DIAERESIS
0xAD	0x2260	# NOT EQUAL TO
0xAE	0x00C6	# LATIN CAPITAL LETTER AE
0xAF	0x00D8	# LATIN CAPITAL LETTER O WITH STROKE
0xB0	0x221E	# INFINITY
0xB1	0x00B1	# PLUS-MINUS SIGN
0xB2	0x2264	# LESS-THAN OR EQUAL TO
0xB3	0x2265	# GREATER-THAN OR EQUAL TO
0xB4	0x00A5	# YEN SIGN
0xB5	0x00B5	# MICRO SIGN
0xB6	0x2202	# PARTIAL DIFFERENTIAL
0xB7	0x2211	# N-ARY SUMMATION
0xB8	0x220F	# N-ARY PRODUCT
0xB9	0x03C0	# GREEK SMALL LETTER PI
0xBA	0x222B	# INTEGRAL
0xBB	0x00AA	# FEMININE ORDINAL INDICATOR
0xBC	0x00BA	# MASCULINE ORDINAL INDICATOR
0xBD	0x03A9	# GREEK CAPITAL LETTER OMEGA
0xBE	0x00E6	# LATIN SMALL LETTER AE
0xBF	0x00F8	# LATIN SMALL LETTER O WITH STROKE
0xC0	0x00BF	# INVERTED QUESTION MARK
0xC1	0x00A1	# INVERTED EXCLAMATION MARK
0xC2	0x00AC	# NOT SIGN
0xC3	0x221A	# SQUARE ROOT
0xC4	0x0192	# LATIN SMALL LETTER F WITH HOOK
0xC5	0x2248	# ALMOST EQUAL TO
0xC6	0x2206	# INCREMENT
0xC7	0x00AB	# LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
0xC8	0x00BB	# RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
0xC9	0x2026	# HORIZONTAL ELLIPSIS
0xCA	0x00A0	# NO-BREAK SPACE
0xCB	0x00C0	# LATIN CAPITAL LETTER A WITH GRAVE
0xCC	0x00C3	# LATIN CAPITAL LETTER A WITH TILDE
0xCD	0x00D5	# LATIN CAPITAL LETTER O WITH TILDE
0xCE	0x0152	# LATIN CAPITAL LIGATURE OE
0xCF	0x0153	# LATIN SMALL LIGATURE OE
0xD0	0x2013	# EN DASH
0xD1	0x2014	# EM DASH
0xD2	0x201C	# LEFT DOUBLE QUOTATION MARK
0xD3	0x201D	# RIGHT DOUBLE QUOTATION MARK
0xD4	0x2018	# LEFT SINGLE QUOTATION MARK
0xD5	0x2019	# RIGHT SINGLE QUOTATION MARK
0xD6	0x00F7	# DIVISION SIGN
0xD7	0x25CA	# LOZENGE
0xD8	0x00FF	# LATIN SMALL LETTER Y WITH DIAERESIS
0xD9	0x0178	# LATIN CAPITAL LETTER Y WITH DIAERESIS
0xDA	0x2044	# FRACTION SLASH
0xDB	0x20AC	# EURO SIGN
0xDC	0x2039	# SINGLE LEFT-POINTING ANGLE QUOTATION MARK
0xDD	0x203A	# SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
0xDE	0xFB01	# LATIN SMALL LIGATURE FI
0xDF	0xFB02	# LATIN SMALL LIGATURE FL
0xE0	0x2021	# DOUBLE DAGGER
0xE1	0x00B7	# MIDDLE DOT
0xE2	0x201A	# SINGLE LOW-9 QUOTATION MARK
0xE3	0x201E	# DOUBLE LOW-9 QUOTATION MARK
0xE4	0x2030	# PER MILLE SIGN
0xE5	0x00C2	# LATIN CAPITAL LETTER A WITH CIRCUMFLEX
0xE6	0x00CA	# LATIN CAPITAL LETTER E WITH CIRCUMFLEX
0xE7	0x00C1	# LATIN CAPITAL LETTER A WITH ACUTE
0xE8	0x00CB	# LATIN CAPITAL LETTER E WITH DIAERESIS
0xE9	0x00C8	# LATIN CAPITAL LETTER E WITH GRAVE
0xEA	0x00CD	# LATIN CAPITAL LETTER I WITH ACUTE
0xEB	0x00CE	# LATIN CAPITAL LETTER I WITH CIRCUMFLEX
0xEC	0x00CF	# LATIN CAPITAL LETTER I WITH DIAERESIS
0xED	0x00CC	# LATIN CAPITAL LETTER I WITH GRAVE
0xEE	0x00D3	# LATIN CAPITAL LETTER O WITH ACUTE
0xEF	0x00D4	# LATIN CAPITAL LETTER O WITH CIRCUMFLEX
0xF0	0xF8FF	# Apple logo
0xF1	0x00D2	# LATIN CAPITAL LETTER O WITH GRAVE
0xF2	0x00DA	# LATIN CAPITAL LETTER U WITH ACUTE
0xF3	0x00DB	# LATIN CAPITAL LETTER U WITH CIRCUMFLEX
0xF4	0x00D9	# LATIN CAPITAL LETTER U WITH GRAVE
0xF5	0x0131	# LATIN SMALL LETTER DOTLESS I
0xF6	0x02C6	# MODIFIER LETTER CIRCUMFLEX ACCENT
0xF7	0x02DC	# SMALL TILDE
0xF8	0x00AF	# MACRON
0xF9	0x02D8	# BREVE
0xFA	0x02D9	# DOT ABOVE
0xFB	0x02DA	# RING ABOVE
0xFC	0x00B8	# CEDILLA
0xFD	0x02DD	# DOUBLE ACUTE ACCENT
0xFE	0x02DB	# OGONEK
0xFF	0x02C7	# CARON
\ No newline at end of file
diff --git a/Unix-only/KDE1-only/Antiword.kdelnk.eu b/Unix-only/KDE1-only/Antiword.kdelnk.eu
new file mode 100644
index 0000000..9de8f49
--- /dev/null
+++ b/Unix-only/KDE1-only/Antiword.kdelnk.eu
@@ -0,0 +1,15 @@
+# KDE Config File
+[KDE Desktop Entry]
+Comment[C]=MS Word reader
+SwallowTitle=
+SwallowExec=
+BinaryPattern=antiword;kantiword;
+Name=Antiword
+Name[C]=Antiword
+MimeType=
+Exec=kantiword a4 %f
+Icon=antiword.xpm
+TerminalOptions=
+Path=
+Type=Application
+Terminal=0
diff --git a/Unix-only/KDE1-only/Antiword.kdelnk.us b/Unix-only/KDE1-only/Antiword.kdelnk.us
new file mode 100644
index 0000000..d54c140
--- /dev/null
+++ b/Unix-only/KDE1-only/Antiword.kdelnk.us
@@ -0,0 +1,15 @@
+# KDE Config File
+[KDE Desktop Entry]
+Comment[C]=MS Word reader
+SwallowTitle=
+SwallowExec=
+BinaryPattern=antiword;kantiword;
+Name=Antiword
+Name[C]=Antiword
+MimeType=
+Exec=kantiword letter %f
+Icon=antiword.xpm
+TerminalOptions=
+Path=
+Type=Application
+Terminal=0
diff --git a/Unix-only/KDE1-only/antiword.xpm b/Unix-only/KDE1-only/antiword.xpm
new file mode 100644
index 0000000..66c9cf7
--- /dev/null
+++ b/Unix-only/KDE1-only/antiword.xpm
@@ -0,0 +1,272 @@
+/* XPM */
+static char *antiword_48[] = {
+/* width height num_colors chars_per_pixel */
+"    48    48      217            2",
+/* colors */
+".. c #040204",
+".# c #548a04",
+".a c #840604",
+".b c #4c460c",
+".c c #bcc2bc",
+".d c #3c0604",
+".e c #b4820c",
+".f c #141e04",
+".g c #acaaa4",
+".h c #74560c",
+".i c #240604",
+".j c #3c5e0c",
+".k c #dca20c",
+".l c #0c1204",
+".m c #dce2dc",
+".n c #ac060c",
+".o c #543e0c",
+".p c #9c720c",
+".q c #3c2e0c",
+".r c #848284",
+".s c #e4b20c",
+".t c #140204",
+".u c #949694",
+".v c #24320c",
+".w c #b4b6b4",
+".x c #5c5a5c",
+".y c #741e0c",
+".z c #3c3e3c",
+".A c #ccd2cc",
+".B c #bc920c",
+".C c #ecf2ec",
+".D c #746e74",
+".E c #f4b20c",
+".F c #1c1604",
+".G c #94060c",
+".H c #6c260c",
+".I c #9ca29c",
+".J c #5c0604",
+".K c #84620c",
+".L c #d40604",
+".M c #5c4244",
+".N c #646664",
+".O c #cc9a0c",
+".P c #747a74",
+".Q c #f4ba0c",
+".R c #0c0204",
+".S c #c4cac4",
+".T c #141a04",
+".U c #8c8e8c",
+".V c #c4bebc",
+".W c #345204",
+".X c #acb2ac",
+".Y c #24160c",
+".Z c #e4aa0c",
+".0 c #e4eae4",
+".1 c #544a2c",
+".2 c #140e04",
+".3 c #9c9e9c",
+".4 c #2c2e2c",
+".5 c #4c4a4c",
+".6 c #f4faf4",
+".7 c #a40604",
+".8 c #242624",
+".9 c #fcba04",
+"#. c #44160c",
+"## c #7c5e0c",
+"#a c #14120c",
+"#b c #c4020c",
+"#c c #848a84",
+"#d c #9c969c",
+"#e c #bcbebc",
+"#f c #dcdadc",
+"#g c #c4920c",
+"#h c #6c6e6c",
+"#i c #3c363c",
+"#j c #3c520c",
+"#k c #7c160c",
+"#l c #4c060c",
+"#m c #b4aeac",
+"#n c #340604",
+"#o c #44720c",
+"#p c #ecb20c",
+"#q c #646264",
+"#r c #747674",
+"#s c #0c0e14",
+"#t c #1c161c",
+"#u c #9c0604",
+"#v c #a4a2a4",
+"#w c #6c0604",
+"#x c #8c6a0c",
+"#y c #dc0204",
+"#z c #d49a0c",
+"#A c #847e84",
+"#B c #0c0604",
+"#C c #cccac4",
+"#D c #ecae0c",
+"#E c #6c4e0c",
+"#F c #343634",
+"#G c #fcbe04",
+"#H c #14160c",
+"#I c #c4960c",
+"#J c #040604",
+"#K c #8c060c",
+"#L c #c4c2c4",
+"#M c #440604",
+"#N c #b48a0c",
+"#O c #1c1e1c",
+"#P c #acaeac",
+"#Q c #7c5a0c",
+"#R c #3c6204",
+"#S c #e4e2e4",
+"#T c #542224",
+"#U c #8c868c",
+"#V c #1c0204",
+"#W c #bcbabc",
+"#X c #645e64",
+"#Y c #444644",
+"#Z c #d4d2d4",
+"#0 c #f4f2f4",
+"#1 c #0c0e0c",
+"#2 c #64060c",
+"#3 c #242224",
+"#4 c #544e54",
+"#5 c #6c666c",
+"#6 c #643a0c",
+"#7 c #742a0c",
+"#8 c #ac7e0c",
+"#9 c #342e0c",
+"a. c #c48e0c",
+"a# c #5c460c",
+"aa c #4c3a0c",
+"ab c #444244",
+"ac c #7c7a7c",
+"ad c #949294",
+"ae c #eceaec",
+"af c #342e34",
+"ag c #fcfafc",
+"ah c #2c262c",
+"ai c #4c360c",
+"aj c #6c521c",
+"ak c #2c060c",
+"al c #b4b2b4",
+"am c #8c8a8c",
+"an c #a47a0c",
+"ao c #b4060c",
+"ap c #442e0c",
+"aq c #140e14",
+"ar c #7c7674",
+"as c #34560c",
+"at c #e4ae0c",
+"au c #4c4e4c",
+"av c #a4a6a4",
+"aw c #cccecc",
+"ax c #745a0c",
+"ay c #dca60c",
+"az c #848684",
+"aA c #949a94",
+"aB c #b4bab4",
+"aC c #5c5e5c",
+"aD c #747274",
+"aE c #f4b60c",
+"aF c #940a0c",
+"aG c #84660c",
+"aH c #f4be0c",
+"aI c #dcdedc",
+"aJ c #3c3a3c",
+"aK c #1c1a1c",
+"aL c #dc0604",
+"aM c #d49e0c",
+"aN c #6c520c",
+"aO c #c4c6c4",
+"aP c #e4e6e4",
+"aQ c #1c0604",
+"aR c #d4d6d4",
+"aS c #f4f6f4",
+"aT c #545254",
+"aU c #6c6a6c",
+"aV c #7c7e7c",
+"aW c #eceeec",
+"aX c #343234",
+"aY c #fcfefc",
+"aZ c #2c2a2c",
+"a0 c #84060c",
+"a1 c #141e0c",
+"a2 c #acaaac",
+"a3 c #e4b214",
+"a4 c #0c0a0c",
+"a5 c #1c160c",
+"a6 c #5c060c",
+"a7 c #241e24",
+"a8 c #d4060c",
+"a9 c #141a0c",
+"b. c #c4bec4",
+"b# c #34520c",
+"ba c #140e0c",
+"bb c #a4060c",
+"bc c #fcba0c",
+"bd c #7c5e14",
+"be c #141214",
+"bf c #bcbec4",
+"bg c #c49214",
+"bh c #6c6e74",
+"bi c #3c5214",
+"bj c #34060c",
+"bk c #9c060c",
+"bl c #0c060c",
+"bm c #cccacc",
+"bn c #fcbe0c",
+"bo c #141614",
+"bp c #04060c",
+"bq c #44060c",
+"br c #3c620c",
+"bs c #e4ae14",
+"bt c #4c4e54",
+"bu c #9c9a9c",
+"bv c #a4a6ac",
+"XX c None",
+/* pixels */
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYXXXX",
+"XXXXaY#WbmaYaYaYaw.waYavaIaYaYaYaYaYaW#vaSaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaY.AalaYa2#faYaYXXXX",
+"XXXXaY.3.uawaY#Zbu.uaYal#SaYaYaYaYaYaP#raWaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaR#W#WaYazaOaYaYXXXX",
+"XXXXaY#vaVadaWbuaV#daYaW.6aYaY#0aWaSaParaW#0aSaYaWagaS#0aY#0aW#0aYaY#0aW#0aWad#PaWaWaz#e#0aYXXXX",
+"XXXXaY.3#PaW.PaP.waAaY#AawaYaS#raraBaP.PaW#P.IaYaraRaO#caY.UaraAaYaYav#r#rac#rac#r.Par.P#vaYXXXX",
+"XXXXaY#v#PagaPag.w#daYaVawaRadaPaP#0aPar.U#LaWaY.PaRaO#UaY.U.XaWaY.ubm.caVaP.U#PaPaP.raBaWaYXXXX",
+"XXXXaY.3#PaYaYaY.waAaY#A.Aaw#AaYaYaYaP#r#raOaYaYaraRaO#caYbm#WaOaYaVawaw.raY.u.waYaYazbmaYaYXXXX",
+"XXXXaY#v.XaYaYaY#W.uaY#A.AaRbuaIaIaWaParadbfaeaY.u.SalamaY#Sav#daYaV#W#L.3aY.u#WaYaYazaOaYaYXXXX",
+"XXXXaY.3#PaYaYaY.w.uaYaVawaYaS#r#r.waP#raW#P.3aYaY#v#razaY.U#raAaY#A.PavaYaY.u.waYaY#UaOaYaYXXXX",
+"XXXXaYaSagaYaYaYagaSaYaSaYaYaYaSaSagaYaSaY.6agaYaYaS#L#caYagaSaSaYaSaSagaYaY.6agaYaYaSagaYaYXXXX",
+"XXXXaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaY.m.x.x.xamaY.x.xam#ZaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYXXXX",
+"XXXXaPaPaPaPaPaPaPaPaPaPaPawavavavbvad#FaJaKaX#v#Y#Y#h#PaPaPaPaPaPaPaPaPaPaPaPaPaPaPaPaPaPaPXXXX",
+"XXXX#Lb.#eb.bf.Vbfb.b.bfb.aV....a4a4#3ad.U#Y#s#1#W#WbhaKbfb.b.bf.Vbfb.#eb.bf.Vb.bf#L.V.cb.#LXXXX",
+"XXXXaYaYaYaYaYaYaYaYaYaYaY#v....#rbuaV....aD#W#W#W#W#h#3aYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYaYXXXX",
+"XXXXawbmawbmawbmaw#Cbm#Y.zaT#rar#i.8aJad.Ua2#W#e#W#ea2az.zal#CawbmawbmawbmawbmawbmbmbmbmbmawXXXX",
+"XXXX#f#f#faIaR#fbu.N.N.5.5auaTbt.x.xaU#W#h.u#W#W#W#W#W#v...w#faIaR#f#f.X#q.N#q.N#q.N.N#P#f#fXXXX",
+"XXXX#0.C#0aW.A#Z#ha7#OacaV#X#3.8.ua2bububoaDalaAbu.X#e.g#3al.m#0#0.CaI.U.T.T.Ta9#H.....U#0.CXXXX",
+"XXXX#W#e#Wav....aTaAbua4..#Y#W#W#W.N..bp...Daz....az#W#W#W#3.N#W#e#Wab.v.#.#.#.##o....aD#W#eXXXX",
+"XXXXaS.xbo.8#Uaz.5bobe.3#v#PalboaK#s....bgajabavav.wacaZ#W.8#s#tbo#ta4#B.lba#1.l#9aya5adaSaSXXXX",
+"XXXXaRab..bebubu.5aK.D#W#rau.5....aibd#JayaN#F#W#4auaCaUbtbi.W.W.W.Wa1bja0.a.iai#8#Ga5#AaR#fXXXX",
+"XXXX#ZaDafba#h.U.5#3az.waba5ai....#Q#z..ay#EaZazaJaJ.xaD..b#.j#Rbr.j.b.H.7#ybj#Q.9.9.YacawawXXXX",
+"XXXXaYaY.u....aV.5....alaba#a3.R..#Q.O#Bay#E....aB#W#h.....R.R.R..#Banan.ta8#n#Q.9aH.YaAaYaYXXXX",
+"XXXX#W#Wbh....aVbuaD..al#Wac#a.Q.q#Q.9.Q.9#E..............ao.Lbb.R#p.Qbcbs.R..#Q.9.9.YaD#W#eXXXX",
+"XXXXaWaeaR#v...8#5#r..#F.Uac#Baa.paM.kaaat#E.f.j#R.jbras...d.G.7..#D.9.9#p....#Q.9#G.F.UaeaeXXXX",
+"XXXX#S.m#SaO....aTazabblac.u.5bpax#I.O#J.K.q.T#j.W#j.W#j#E#E#7#w..#p.9.9.EaN.Fax.9#G.Yaz#S.mXXXX",
+"XXXXaO#L#L.X#3bl.5amaAa4aU#P#m....#E#N.....taQ#V#V.Rba.q.9.9#Q....#D.9.9.9.9.o#x.9.Q.Y#r#LaOXXXX",
+"XXXXaYaYaYaYaY.4...8bua4..ab#P.......R....a0#y#y#ybq#E.9.9.9.h.....E.9.9.9.9.9#G.9#G.Y.uaYaYXXXX",
+"XXXXaObmaOaObm#3...8buaVafab#W.3ah..#O.3bu.Ma6#y#y#b#kai.9bc.Zan..#D.9.9.9.9.9.9.9.9a5araObmXXXX",
+"XXXX#SaIaI#SaI.uabbe.5adaJ#3aC#W.P.NaD#W.Nah#M#y#yaLa0.Y.9.9bn.B..#D.9bc.9.9bc.9.9#G.YazaIaIXXXX",
+"XXXXaWaWaWaWaWaWaD....adauaK#1#W#Wa2.UadaJ.4#T.naL#ybk#..B#p.9.Oap.E.9.9.9.9.9.9.9.Q.Y.UaW#0XXXX",
+"XXXX#W#W#W#W#W#W.x.....Ubu#q#s#W#W#q....#v#Waz.Ra8#y#y#b..aM.9.9.9.9.9.9.9bc.9.9.9#G.Y#h#W#WXXXX",
+"XXXXag.6ag.6ag.6aS.w..a4#5#q..#1ad.w#Pal#WaTbl.Ra8#y#y#b...OaH.9.9bc.9.9#D.2#g.9.9.9.Y.uagagXXXX",
+"XXXX#Z#Z#Z#Z#Z#Z#Z#v.....Naz#X..ad#Wavab#Y.Nacac#lao#y.L#K#6.e.9.9.9.9.9#p..a..9.9#Ga5aV#Z#ZXXXX",
+"XXXXaR#ZaR.AaR.A#Z.waCbpab#rad..aC.u.g#Y#Yambvar..#u#y#y#yakaG#G.9.9.9#G#D..##.O#G.9.YaV#ZaRXXXX",
+"XXXXag.6.6ag.6ag.6ag.6be..#i.U#1#B.x#W#W#m.X#A#sbaaFa8#y#y#n.K#p.9bc.9.9#p....#Q.Q.sa5.uag.6XXXX",
+"XXXX#e#W#W#W#W#W#W#W#Wba..#Fbubu#3.x#W#W#t..aJ#W#W#i#2#y#y#y#2ap.9.9.9.9#D....#Q.O.R..aD#W#WXXXX",
+"XXXXaWaW.CaW.CaW.CaW.CaO#Yaq.4bu.8bo#Y#W.u.U.3#WaB#i.J#y#y#y#w.q.9.9.9.9#p....a5.1#LaOaIaW.CXXXX",
+"XXXX#SaI#SaI#SaI#SaIaIaI#4..a4#daCah#3#e#W#e#W#W.Na7#na0#y#ybb.yaGaEbn.9#D..#Y.xaDaIaIaIaI#SXXXX",
+"XXXXbmaOaObm#LaOaObmaObm.Na7a4aVadaT#Obu.wbvbubu...8#O#V#y#y#ybb..#pay.ObgaX#vaOaObmaObmaOaOXXXX",
+"XXXXaYaYagaYaYaYaYaYaYagaYav....#raT....avau......al.uaQaL#y.L.n.R#pa#..beaYaYaYaYaYagaYaYaYXXXX",
+"XXXX#L#L#L#L#L#L#L#L#L#L#LaV....aqa4....#ta4aXavav#W.wad#V#V#V#V..a5arava2#L#L#L#L#L#L#L#L#LXXXX",
+"XXXXaP#SaP.maP#SaP.m#SaP.mbm.U.....5aV..azaA#PaP#S#S#S#f.ubuaA#daA#d.S#S#SaP.maP#SaP.maP#SaPXXXX",
+"XXXXae.0aeae.0ae.0aeae.0aeaeaIaJaJ.UbmaJaRaeae.0ae.0ae.0aeae.0ae.0aeae.0ae.0ae.0ae.0ae.0aeaeXXXX",
+"XXXX#e#W#W#W#W#W#W#W#W#W#W#W#e#W#W#W#W#W#W#W#W#W#W#e#Wbf#W#W#W#W#W#W#W#W#W#W#W#W#W#W#W#W#W#WXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+};
diff --git a/Unix-only/KDE1-only/kantiword.sh b/Unix-only/KDE1-only/kantiword.sh
new file mode 100644
index 0000000..acbdd86
--- /dev/null
+++ b/Unix-only/KDE1-only/kantiword.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+#
+# Script to make drag and drop in KDE possible
+#set -x
+#
+
+if [ $# -lt 2 ]
+then
+	exit 0
+fi
+
+# Determine the temp directory
+if [ -d "$TMPDIR" ] && [ -w "$TMPDIR" ]
+then
+	tmp_dir=$TMPDIR
+elif [ -d "$TEMP" ] && [ -w "$TEMP" ]
+then
+	tmp_dir=$TEMP
+else
+	tmp_dir="/tmp"
+fi                        
+out_file=$tmp_dir"/antiword.$$.ps"
+err_file=$tmp_dir"/antiword.$$.err"
+
+# Determine the paper size
+paper_size=$1
+shift
+
+# Make the PostScript file
+antiword -p $paper_size -i 0 "$@" 2>$err_file >$out_file
+if [ $? -ne 0 ]
+then
+	rm -f $out_file
+	exit 1
+fi
+
+# Show the PostScript file
+gv $out_file -nocentre -media $paper_size
+
+# Clean up
+rm -f $out_file $err_file
+exit 0
diff --git a/Unix-only/KDE3-only/Antiword.desktop.eu b/Unix-only/KDE3-only/Antiword.desktop.eu
new file mode 100644
index 0000000..58ca6df
--- /dev/null
+++ b/Unix-only/KDE3-only/Antiword.desktop.eu
@@ -0,0 +1,8 @@
+[Desktop Entry]
+BinaryPattern=kantiword;Kantiword
+MimeType=application/msword
+Name=Antiword
+Exec=kantiword a4 "%f"
+Icon=antiword
+Type=Application
+Terminal=0
diff --git a/Unix-only/KDE3-only/Antiword.desktop.us b/Unix-only/KDE3-only/Antiword.desktop.us
new file mode 100644
index 0000000..da6aa1a
--- /dev/null
+++ b/Unix-only/KDE3-only/Antiword.desktop.us
@@ -0,0 +1,8 @@
+[Desktop Entry]
+BinaryPattern=kantiword;Kantiword
+MimeType=application/msword
+Name=Antiword
+Exec=kantiword letter "%f"
+Icon=antiword
+Type=Application
+Terminal=0
diff --git a/Unix-only/KDE3-only/hi32-app-antiword.png b/Unix-only/KDE3-only/hi32-app-antiword.png
new file mode 100644
index 0000000..ff4f921
Binary files /dev/null and b/Unix-only/KDE3-only/hi32-app-antiword.png differ
diff --git a/Unix-only/KDE3-only/hi48-app-antiword.png b/Unix-only/KDE3-only/hi48-app-antiword.png
new file mode 100644
index 0000000..c0900de
Binary files /dev/null and b/Unix-only/KDE3-only/hi48-app-antiword.png differ
diff --git a/Unix-only/KDE3-only/kantiword.sh b/Unix-only/KDE3-only/kantiword.sh
new file mode 100644
index 0000000..40e6637
--- /dev/null
+++ b/Unix-only/KDE3-only/kantiword.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+#
+# Script to make drag and drop in KDE possible
+#set -x
+#
+
+if [ $# -lt 2 ]
+then
+	exit 0
+fi
+
+# Determine the temp directory
+if [ -d "$TMPDIR" ] && [ -w "$TMPDIR" ]
+then
+	tmp_dir=$TMPDIR
+elif [ -d "$TEMP" ] && [ -w "$TEMP" ]
+then
+	tmp_dir=$TEMP
+else
+	tmp_dir="/tmp"
+fi                        
+
+# Try to create the temp files in a secure way
+if [ -x /bin/tempfile ]
+then
+	out_file=`/bin/tempfile -d "$tmp_dir" -p antiword -s ".ps"` || exit 1
+	err_file=`/bin/tempfile -d "$tmp_dir" -p antiword -s ".err"`
+	if [ $? -ne 0 ]
+	then
+		rm -f "$out_file"
+		exit 1
+	fi
+elif [ -x /bin/mktemp ]
+then
+	out_file=`/bin/mktemp -q -p "$tmp_dir" antiword.ps.XXXXXXXXX` || exit 1
+	err_file=`/bin/mktemp -q -p "$tmp_dir" antiword.err.XXXXXXXXX`
+	if [ $? -ne 0 ]
+	then
+		rm -f "$out_file"
+		exit 1
+	fi
+else
+	# Creating the temp files in an un-secure way
+	out_file=$tmp_dir"/antiword.$$.ps"
+	err_file=$tmp_dir"/antiword.$$.err"
+fi
+
+# Determine the paper size
+paper_size=$1
+shift
+
+# Make the PostScript file
+antiword -p $paper_size -i 0 "$@" 2>"$err_file" >"$out_file"
+if [ $? -ne 0 ]
+then
+	# Something went wrong
+	if [ -r "$err_file" ] && [ -s "$err_file" ]
+	then
+		konsole --caption "Error from Antword" -e less "$err_file"
+	fi
+	# Clean up
+	rm -f "$out_file" "$err_file"
+	exit 1
+fi
+
+# Show the PostScript file
+gv "$out_file" -nocentre -media $paper_size
+
+# Clean up
+rm -f "$out_file" "$err_file"
+exit 0
diff --git a/Unix-only/KDE3-only/lo16-app-antiword.png b/Unix-only/KDE3-only/lo16-app-antiword.png
new file mode 100644
index 0000000..d26d00d
Binary files /dev/null and b/Unix-only/KDE3-only/lo16-app-antiword.png differ
diff --git a/Unix-only/KDE3-only/lo32-app-antiword.png b/Unix-only/KDE3-only/lo32-app-antiword.png
new file mode 100644
index 0000000..299ce9f
Binary files /dev/null and b/Unix-only/KDE3-only/lo32-app-antiword.png differ
diff --git a/Unix-only/RPM-only/antiword.spec b/Unix-only/RPM-only/antiword.spec
new file mode 100644
index 0000000..3f14697
--- /dev/null
+++ b/Unix-only/RPM-only/antiword.spec
@@ -0,0 +1,49 @@
+
+%define version	0.33
+%define release	1
+%define name	antiword
+
+Summary: an application to display Microsoft(R) Word files.
+Name: %{name}
+Version: %{version}
+Release: %{release}
+License: GPL
+Group: Applications/Text
+Source: http://www.winfield.demon.nl/linux/%{name}-%{version}.tar.gz
+URL: http://www.winfield.demon.nl/index.html
+BuildRoot: /var/tmp/%{name}-%{version}
+Packager: marco antonio cabazal <nightshiphter@yahoo.com>
+
+%description
+Antiword is a free MS Word reader for Linux and RISC OS. There are ports to 
+BeOS, OS/2, Mac OS X, Amiga, VMS, NetWare and DOS. Antiword converts the 
+binary files from Word 2, 6, 7, 97, 2000 and 2002 to plain text and to 
+PostScript TM.
+.
+
+%prep
+# nothing to be done here
+
+%build
+make all
+
+%install
+rm -rf $RPM_BUILD_ROOT
+install -d 555 $RPM_BUILD_ROOT/%{_prefix}/bin
+install -d 555 $RPM_BUILD_ROOT/%{_prefix}/share/antiword
+install -d 555 $RPM_BUILD_ROOT/%{_prefix}/share/man/man1
+install -m 555 ./antiword $RPM_BUILD_ROOT%{_prefix}/bin/antiword
+install -m 555 ./kantiword $RPM_BUILD_ROOT%{_prefix}/bin/kantiword
+install -m 444 ./Resources/* $RPM_BUILD_ROOT%{_prefix}/share/antiword
+install -m 444 ./Docs/antiword.1 $RPM_BUILD_ROOT/%{_prefix}/share/man/man1/antiword.1
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root)
+%doc Docs/*
+%{_prefix}/bin/*
+%{_prefix}/share/antiword/*
+%{_prefix}/share/man/man1/*
+
diff --git a/Unix-only/fontinfo.h b/Unix-only/fontinfo.h
new file mode 100644
index 0000000..8538dfa
--- /dev/null
+++ b/Unix-only/fontinfo.h
@@ -0,0 +1,2251 @@
+/* THIS FILE IS AUTOMATICALLY GENERATED - DO NOT EDIT! */
+static const char *szFontnames[32] = {
+	"Courier",
+	"Courier-Bold",
+	"Courier-Oblique",
+	"Courier-BoldOblique",
+	"Times-Roman",
+	"Times-Bold",
+	"Times-Italic",
+	"Times-BoldItalic",
+	"Helvetica",
+	"Helvetica-Bold",
+	"Helvetica-Oblique",
+	"Helvetica-BoldOblique",
+	"Palatino-Roman",
+	"Palatino-Bold",
+	"Palatino-Italic",
+	"Palatino-BoldItalic",
+	"Helvetica-Narrow",
+	"Helvetica-Narrow-Bold",
+	"Helvetica-Narrow-Oblique",
+	"Helvetica-Narrow-BoldOblique",
+	"Bookman-Light",
+	"Bookman-Demi",
+	"Bookman-LightItalic",
+	"Bookman-DemiItalic",
+	"AvantGarde-Book",
+	"AvantGarde-Demi",
+	"AvantGarde-BookOblique",
+	"AvantGarde-DemiOblique",
+	"NewCenturySchlbk-Roman",
+	"NewCenturySchlbk-Bold",
+	"NewCenturySchlbk-Italic",
+	"NewCenturySchlbk-BoldItalic",
+};
+static unsigned short ausCharacterWidths1[32][256] = {
+	{	/* Courier */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  40 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  48 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  56 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  64 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  72 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  80 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  88 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  96 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 104 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 112 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 120 */   600,  600,  600,  600,  600,  600,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,  600,  600,  600,  600,
+	/* 144 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 152 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 160 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 168 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 176 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 184 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 192 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 200 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 208 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 216 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 224 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 232 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 240 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 248 */   600,  600,  600,  600,  600,  600,  600,  600,
+	},
+	{	/* Courier-Bold */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  40 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  48 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  56 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  64 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  72 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  80 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  88 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  96 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 104 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 112 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 120 */   600,  600,  600,  600,  600,  600,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,  600,  600,  600,  600,
+	/* 144 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 152 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 160 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 168 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 176 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 184 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 192 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 200 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 208 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 216 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 224 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 232 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 240 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 248 */   600,  600,  600,  600,  600,  600,  600,  600,
+	},
+	{	/* Courier-Oblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  40 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  48 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  56 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  64 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  72 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  80 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  88 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  96 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 104 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 112 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 120 */   600,  600,  600,  600,  600,  600,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,  600,  600,  600,  600,
+	/* 144 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 152 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 160 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 168 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 176 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 184 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 192 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 200 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 208 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 216 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 224 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 232 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 240 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 248 */   600,  600,  600,  600,  600,  600,  600,  600,
+	},
+	{	/* Courier-BoldOblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  40 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  48 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  56 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  64 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  72 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  80 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  88 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  96 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 104 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 112 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 120 */   600,  600,  600,  600,  600,  600,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,  600,  600,  600,  600,
+	/* 144 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 152 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 160 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 168 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 176 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 184 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 192 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 200 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 208 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 216 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 224 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 232 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 240 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 248 */   600,  600,  600,  600,  600,  600,  600,  600,
+	},
+	{	/* Times-Roman */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  333,  408,  500,  500,  833,  778,  333,
+	/*  40 */   333,  333,  500,  564,  250,  333,  250,  278,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  278,  278,  564,  564,  564,  444,
+	/*  64 */   921,  722,  667,  667,  722,  611,  556,  722,
+	/*  72 */   722,  333,  389,  722,  611,  889,  722,  722,
+	/*  80 */   556,  722,  667,  556,  611,  722,  722,  944,
+	/*  88 */   722,  722,  611,  333,  278,  333,  469,  500,
+	/*  96 */   333,  444,  500,  444,  500,  444,  333,  500,
+	/* 104 */   500,  278,  278,  500,  278,  778,  500,  500,
+	/* 112 */   500,  500,  333,  389,  278,  500,  500,  722,
+	/* 120 */   500,  500,  444,  480,  200,  480,  541,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000,  980, 1000,  350,
+	/* 144 */   333,  333,  333,  333,  444,  444,  444,  500,
+	/* 152 */  1000,  564,  889,  722,  500,  500,  556,  556,
+	/* 160 */   250,  333,  500,  500,  500,  500,  200,  500,
+	/* 168 */   333,  760,  276,  500,  564,  333,  760,  333,
+	/* 176 */   400,  564,  300,  300,  333,  500,  453,  250,
+	/* 184 */   333,  300,  310,  500,  750,  750,  750,  444,
+	/* 192 */   722,  722,  722,  722,  722,  722,  889,  667,
+	/* 200 */   611,  611,  611,  611,  333,  333,  333,  333,
+	/* 208 */   722,  722,  722,  722,  722,  722,  722,  564,
+	/* 216 */   722,  722,  722,  722,  722,  722,  556,  500,
+	/* 224 */   444,  444,  444,  444,  444,  444,  667,  444,
+	/* 232 */   444,  444,  444,  444,  278,  278,  278,  278,
+	/* 240 */   500,  500,  500,  500,  500,  500,  500,  564,
+	/* 248 */   500,  500,  500,  500,  500,  500,  500,  500,
+	},
+	{	/* Times-Bold */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  333,  555,  500,  500, 1000,  833,  333,
+	/*  40 */   333,  333,  500,  570,  250,  333,  250,  278,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  333,  333,  570,  570,  570,  500,
+	/*  64 */   930,  722,  667,  722,  722,  667,  611,  778,
+	/*  72 */   778,  389,  500,  778,  667,  944,  722,  778,
+	/*  80 */   611,  778,  722,  556,  667,  722,  722, 1000,
+	/*  88 */   722,  722,  667,  333,  278,  333,  581,  500,
+	/*  96 */   333,  500,  556,  444,  556,  444,  333,  500,
+	/* 104 */   556,  278,  333,  556,  278,  833,  556,  500,
+	/* 112 */   556,  556,  444,  389,  333,  556,  500,  722,
+	/* 120 */   500,  500,  444,  394,  220,  394,  520,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1000,  350,
+	/* 144 */   333,  333,  333,  333,  500,  500,  500,  500,
+	/* 152 */  1000,  570, 1000,  722,  500,  500,  556,  556,
+	/* 160 */   250,  333,  500,  500,  500,  500,  220,  500,
+	/* 168 */   333,  747,  300,  500,  570,  333,  747,  333,
+	/* 176 */   400,  570,  300,  300,  333,  556,  540,  250,
+	/* 184 */   333,  300,  330,  500,  750,  750,  750,  500,
+	/* 192 */   722,  722,  722,  722,  722,  722, 1000,  722,
+	/* 200 */   667,  667,  667,  667,  389,  389,  389,  389,
+	/* 208 */   722,  722,  778,  778,  778,  778,  778,  570,
+	/* 216 */   778,  722,  722,  722,  722,  722,  611,  556,
+	/* 224 */   500,  500,  500,  500,  500,  500,  722,  444,
+	/* 232 */   444,  444,  444,  444,  278,  278,  278,  278,
+	/* 240 */   500,  556,  500,  500,  500,  500,  500,  570,
+	/* 248 */   500,  556,  556,  556,  556,  500,  556,  500,
+	},
+	{	/* Times-Italic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  333,  420,  500,  500,  833,  778,  333,
+	/*  40 */   333,  333,  500,  675,  250,  333,  250,  278,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  333,  333,  675,  675,  675,  500,
+	/*  64 */   920,  611,  611,  667,  722,  611,  611,  722,
+	/*  72 */   722,  333,  444,  667,  556,  833,  667,  722,
+	/*  80 */   611,  722,  611,  500,  556,  722,  611,  833,
+	/*  88 */   611,  556,  556,  389,  278,  389,  422,  500,
+	/*  96 */   333,  500,  500,  444,  500,  444,  278,  500,
+	/* 104 */   500,  278,  278,  444,  278,  722,  500,  500,
+	/* 112 */   500,  500,  389,  389,  278,  500,  444,  667,
+	/* 120 */   444,  444,  389,  400,  275,  400,  541,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,  889,  980, 1000,  350,
+	/* 144 */   333,  333,  333,  333,  556,  556,  556,  500,
+	/* 152 */   889,  675,  944,  667,  500,  500,  500,  500,
+	/* 160 */   250,  389,  500,  500,  500,  500,  275,  500,
+	/* 168 */   333,  760,  276,  500,  675,  333,  760,  333,
+	/* 176 */   400,  675,  300,  300,  333,  500,  523,  250,
+	/* 184 */   333,  300,  310,  500,  750,  750,  750,  500,
+	/* 192 */   611,  611,  611,  611,  611,  611,  889,  667,
+	/* 200 */   611,  611,  611,  611,  333,  333,  333,  333,
+	/* 208 */   722,  667,  722,  722,  722,  722,  722,  675,
+	/* 216 */   722,  722,  722,  722,  722,  556,  611,  500,
+	/* 224 */   500,  500,  500,  500,  500,  500,  667,  444,
+	/* 232 */   444,  444,  444,  444,  278,  278,  278,  278,
+	/* 240 */   500,  500,  500,  500,  500,  500,  500,  675,
+	/* 248 */   500,  500,  500,  500,  500,  444,  500,  444,
+	},
+	{	/* Times-BoldItalic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  389,  555,  500,  500,  833,  778,  333,
+	/*  40 */   333,  333,  500,  570,  250,  333,  250,  278,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  333,  333,  570,  570,  570,  500,
+	/*  64 */   832,  667,  667,  667,  722,  667,  667,  722,
+	/*  72 */   778,  389,  500,  667,  611,  889,  722,  722,
+	/*  80 */   611,  722,  667,  556,  611,  722,  667,  889,
+	/*  88 */   667,  611,  611,  333,  278,  333,  570,  500,
+	/*  96 */   333,  500,  500,  444,  500,  444,  333,  500,
+	/* 104 */   556,  278,  278,  500,  278,  778,  556,  500,
+	/* 112 */   500,  500,  389,  389,  278,  556,  444,  667,
+	/* 120 */   500,  444,  389,  348,  220,  348,  570,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1000,  350,
+	/* 144 */   333,  333,  333,  333,  500,  500,  500,  500,
+	/* 152 */  1000,  606,  944,  722,  500,  500,  556,  556,
+	/* 160 */   250,  389,  500,  500,  500,  500,  220,  500,
+	/* 168 */   333,  747,  266,  500,  606,  333,  747,  333,
+	/* 176 */   400,  570,  300,  300,  333,  576,  500,  250,
+	/* 184 */   333,  300,  300,  500,  750,  750,  750,  500,
+	/* 192 */   667,  667,  667,  667,  667,  667,  944,  667,
+	/* 200 */   667,  667,  667,  667,  389,  389,  389,  389,
+	/* 208 */   722,  722,  722,  722,  722,  722,  722,  570,
+	/* 216 */   722,  722,  722,  722,  722,  611,  611,  500,
+	/* 224 */   500,  500,  500,  500,  500,  500,  722,  444,
+	/* 232 */   444,  444,  444,  444,  278,  278,  278,  278,
+	/* 240 */   500,  556,  500,  500,  500,  500,  500,  570,
+	/* 248 */   500,  556,  556,  556,  556,  444,  500,  444,
+	},
+	{	/* Helvetica */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   278,  278,  355,  556,  556,  889,  667,  221,
+	/*  40 */   333,  333,  389,  584,  278,  333,  278,  278,
+	/*  48 */   556,  556,  556,  556,  556,  556,  556,  556,
+	/*  56 */   556,  556,  278,  278,  584,  584,  584,  556,
+	/*  64 */  1015,  667,  667,  722,  722,  667,  611,  778,
+	/*  72 */   722,  278,  500,  667,  556,  833,  722,  778,
+	/*  80 */   667,  778,  722,  667,  611,  722,  667,  944,
+	/*  88 */   667,  667,  611,  278,  278,  278,  469,  556,
+	/*  96 */   222,  556,  556,  500,  556,  556,  278,  556,
+	/* 104 */   556,  222,  222,  500,  222,  833,  556,  556,
+	/* 112 */   556,  556,  333,  500,  278,  556,  500,  722,
+	/* 120 */   500,  500,  500,  334,  260,  334,  584,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1000,  350,
+	/* 144 */   222,  221,  333,  333,  333,  333,  333,  556,
+	/* 152 */  1000,  584, 1000,  944,  556,  556,  500,  500,
+	/* 160 */   278,  333,  556,  556,  556,  556,  260,  556,
+	/* 168 */   333,  737,  370,  556,  584,  333,  737,  333,
+	/* 176 */   606,  584,  351,  351,  333,  556,  537,  278,
+	/* 184 */   333,  351,  365,  556,  869,  869,  869,  611,
+	/* 192 */   667,  667,  667,  667,  667,  667, 1000,  722,
+	/* 200 */   667,  667,  667,  667,  278,  278,  278,  278,
+	/* 208 */   722,  722,  778,  778,  778,  778,  778,  584,
+	/* 216 */   778,  722,  722,  722,  722,  666,  666,  611,
+	/* 224 */   556,  556,  556,  556,  556,  556,  889,  500,
+	/* 232 */   556,  556,  556,  556,  278,  278,  278,  278,
+	/* 240 */   556,  556,  556,  556,  556,  556,  556,  584,
+	/* 248 */   611,  556,  556,  556,  556,  500,  555,  500,
+	},
+	{	/* Helvetica-Bold */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   278,  333,  474,  556,  556,  889,  722,  278,
+	/*  40 */   333,  333,  389,  584,  278,  333,  278,  278,
+	/*  48 */   556,  556,  556,  556,  556,  556,  556,  556,
+	/*  56 */   556,  556,  333,  333,  584,  584,  584,  611,
+	/*  64 */   975,  722,  722,  722,  722,  667,  611,  778,
+	/*  72 */   722,  278,  556,  722,  611,  833,  722,  778,
+	/*  80 */   667,  778,  722,  667,  611,  722,  667,  944,
+	/*  88 */   667,  667,  611,  333,  278,  333,  584,  556,
+	/*  96 */   278,  556,  611,  556,  611,  556,  333,  611,
+	/* 104 */   611,  278,  278,  556,  278,  889,  611,  611,
+	/* 112 */   611,  611,  389,  556,  333,  611,  556,  778,
+	/* 120 */   556,  556,  500,  389,  280,  389,  584,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1000,  350,
+	/* 144 */   278,  278,  333,  333,  500,  500,  500,  556,
+	/* 152 */  1000,  584, 1000,  944,  556,  556,  611,  611,
+	/* 160 */   278,  333,  556,  556,  556,  556,  280,  556,
+	/* 168 */   333,  737,  370,  556,  584,  333,  737,  333,
+	/* 176 */   606,  584,  351,  351,  333,  611,  556,  278,
+	/* 184 */   333,  351,  365,  556,  869,  869,  869,  611,
+	/* 192 */   722,  722,  722,  722,  722,  722, 1000,  722,
+	/* 200 */   667,  667,  667,  667,  278,  278,  278,  278,
+	/* 208 */   722,  722,  778,  778,  778,  778,  778,  584,
+	/* 216 */   778,  722,  722,  722,  722,  667,  667,  611,
+	/* 224 */   556,  556,  556,  556,  556,  556,  889,  556,
+	/* 232 */   556,  556,  556,  556,  278,  278,  278,  278,
+	/* 240 */   611,  611,  611,  611,  611,  611,  611,  584,
+	/* 248 */   611,  611,  611,  611,  611,  556,  611,  556,
+	},
+	{	/* Helvetica-Oblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   278,  278,  355,  556,  556,  889,  667,  222,
+	/*  40 */   333,  333,  389,  584,  278,  333,  278,  278,
+	/*  48 */   556,  556,  556,  556,  556,  556,  556,  556,
+	/*  56 */   556,  556,  278,  278,  584,  584,  584,  556,
+	/*  64 */  1015,  667,  667,  722,  722,  667,  611,  778,
+	/*  72 */   722,  278,  500,  667,  556,  833,  722,  778,
+	/*  80 */   667,  778,  722,  667,  611,  722,  667,  944,
+	/*  88 */   667,  667,  611,  278,  278,  278,  469,  556,
+	/*  96 */   222,  556,  556,  500,  556,  556,  278,  556,
+	/* 104 */   556,  222,  222,  500,  222,  833,  556,  556,
+	/* 112 */   556,  556,  333,  500,  278,  556,  500,  722,
+	/* 120 */   500,  500,  500,  334,  260,  334,  584,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1000,  350,
+	/* 144 */   222,  222,  333,  333,  333,  333,  333,  556,
+	/* 152 */  1000,  584, 1000,  944,  556,  556,  500,  500,
+	/* 160 */   278,  333,  556,  556,  556,  556,  260,  556,
+	/* 168 */   333,  737,  370,  556,  584,  333,  737,  333,
+	/* 176 */   606,  584,  390,  390,  333,  556,  537,  278,
+	/* 184 */   333,  390,  365,  556,  947,  947,  947,  611,
+	/* 192 */   667,  667,  667,  667,  667,  667, 1000,  722,
+	/* 200 */   667,  667,  667,  667,  278,  278,  278,  278,
+	/* 208 */   722,  722,  778,  778,  778,  778,  778,  584,
+	/* 216 */   778,  722,  722,  722,  722,  667,  667,  611,
+	/* 224 */   556,  556,  556,  556,  556,  556,  889,  500,
+	/* 232 */   556,  556,  556,  556,  278,  278,  278,  278,
+	/* 240 */   556,  556,  556,  556,  556,  556,  556,  584,
+	/* 248 */   611,  556,  556,  556,  556,  500,  556,  500,
+	},
+	{	/* Helvetica-BoldOblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   278,  333,  474,  556,  556,  889,  722,  278,
+	/*  40 */   333,  333,  389,  584,  278,  333,  278,  278,
+	/*  48 */   556,  556,  556,  556,  556,  556,  556,  556,
+	/*  56 */   556,  556,  333,  333,  584,  584,  584,  611,
+	/*  64 */   975,  722,  722,  722,  722,  667,  611,  778,
+	/*  72 */   722,  278,  556,  722,  611,  833,  722,  778,
+	/*  80 */   667,  778,  722,  667,  611,  722,  667,  944,
+	/*  88 */   667,  667,  611,  333,  278,  333,  584,  556,
+	/*  96 */   278,  556,  611,  556,  611,  556,  333,  611,
+	/* 104 */   611,  278,  278,  556,  278,  889,  611,  611,
+	/* 112 */   611,  611,  389,  556,  333,  611,  556,  778,
+	/* 120 */   556,  556,  500,  389,  280,  389,  584,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1000,  350,
+	/* 144 */   278,  278,  333,  333,  500,  500,  500,  556,
+	/* 152 */  1000,  584, 1000,  944,  556,  556,  611,  611,
+	/* 160 */   278,  333,  556,  556,  556,  556,  280,  556,
+	/* 168 */   333,  737,  370,  556,  584,  333,  737,  333,
+	/* 176 */   606,  584,  444,  444,  333,  611,  556,  278,
+	/* 184 */   333,  444,  365,  556, 1055, 1055, 1055,  611,
+	/* 192 */   722,  722,  722,  722,  722,  722, 1000,  722,
+	/* 200 */   667,  667,  667,  667,  278,  278,  278,  278,
+	/* 208 */   722,  722,  778,  778,  778,  778,  778,  584,
+	/* 216 */   778,  722,  722,  722,  722,  667,  667,  611,
+	/* 224 */   556,  556,  556,  556,  556,  556,  889,  556,
+	/* 232 */   556,  556,  556,  556,  278,  278,  278,  278,
+	/* 240 */   611,  611,  611,  611,  611,  611,  611,  584,
+	/* 248 */   611,  611,  611,  611,  611,  556,  611,  556,
+	},
+	{	/* Palatino-Roman */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  278,  371,  500,  500,  840,  778,  278,
+	/*  40 */   333,  333,  389,  606,  250,  333,  250,  606,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  250,  250,  606,  606,  606,  444,
+	/*  64 */   747,  778,  611,  709,  774,  611,  556,  763,
+	/*  72 */   832,  337,  333,  726,  611,  946,  831,  786,
+	/*  80 */   604,  786,  668,  525,  613,  778,  722, 1000,
+	/*  88 */   667,  667,  667,  333,  606,  333,  606,  500,
+	/*  96 */   278,  500,  553,  444,  611,  479,  333,  556,
+	/* 104 */   582,  291,  234,  556,  291,  883,  582,  546,
+	/* 112 */   601,  560,  395,  424,  326,  603,  565,  834,
+	/* 120 */   516,  556,  500,  333,  606,  333,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000,  979, 1144,  606,
+	/* 144 */   278,  278,  331,  331,  500,  500,  500,  500,
+	/* 152 */  1000,  606,  998,  827,  500,  500,  605,  608,
+	/* 160 */   250,  278,  500,  500,  500,  500,  606,  500,
+	/* 168 */   333,  747,  333,  500,  606,  333,  747,  333,
+	/* 176 */   400,  606,  300,  300,  333,  603,  628,  250,
+	/* 184 */   333,  300,  333,  500,  750,  750,  750,  444,
+	/* 192 */   778,  778,  778,  778,  778,  778,  944,  709,
+	/* 200 */   611,  611,  611,  611,  337,  337,  337,  337,
+	/* 208 */   774,  831,  786,  786,  786,  786,  786,  606,
+	/* 216 */   833,  778,  778,  778,  778,  667,  604,  556,
+	/* 224 */   500,  500,  500,  500,  500,  500,  758,  444,
+	/* 232 */   479,  479,  479,  479,  287,  287,  287,  287,
+	/* 240 */   546,  582,  546,  546,  546,  546,  546,  606,
+	/* 248 */   556,  603,  603,  603,  603,  556,  601,  556,
+	},
+	{	/* Palatino-Bold */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  278,  402,  500,  500,  889,  833,  278,
+	/*  40 */   333,  333,  444,  606,  250,  333,  250,  296,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  250,  250,  606,  606,  606,  444,
+	/*  64 */   747,  778,  667,  722,  833,  611,  556,  833,
+	/*  72 */   833,  389,  389,  778,  611, 1000,  833,  833,
+	/*  80 */   611,  833,  722,  611,  667,  778,  778, 1000,
+	/*  88 */   667,  667,  667,  333,  606,  333,  606,  500,
+	/*  96 */   278,  500,  611,  444,  611,  500,  389,  556,
+	/* 104 */   611,  333,  333,  611,  333,  889,  611,  556,
+	/* 112 */   611,  611,  389,  444,  333,  611,  556,  833,
+	/* 120 */   500,  556,  500,  310,  606,  310,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000,  998, 1000,  606,
+	/* 144 */   278,  278,  389,  389,  500,  500,  500,  500,
+	/* 152 */  1000,  606, 1000,  833,  500,  500,  611,  611,
+	/* 160 */   250,  278,  500,  500,  500,  500,  606,  500,
+	/* 168 */   333,  747,  438,  500,  606,  333,  747,  333,
+	/* 176 */   400,  606,  300,  300,  333,  611,  641,  250,
+	/* 184 */   333,  300,  488,  500,  750,  750,  750,  444,
+	/* 192 */   778,  778,  778,  778,  778,  778, 1000,  722,
+	/* 200 */   611,  611,  611,  611,  389,  389,  389,  389,
+	/* 208 */   833,  833,  833,  833,  833,  833,  833,  606,
+	/* 216 */   833,  778,  778,  778,  778,  667,  611,  611,
+	/* 224 */   500,  500,  500,  500,  500,  500,  778,  444,
+	/* 232 */   500,  500,  500,  500,  333,  333,  333,  333,
+	/* 240 */   556,  611,  556,  556,  556,  556,  556,  606,
+	/* 248 */   556,  611,  611,  611,  611,  556,  611,  556,
+	},
+	{	/* Palatino-Italic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  333,  500,  500,  500,  889,  778,  278,
+	/*  40 */   333,  333,  389,  606,  250,  333,  250,  296,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  250,  250,  606,  606,  606,  500,
+	/*  64 */   747,  722,  611,  667,  778,  611,  556,  722,
+	/*  72 */   778,  333,  333,  667,  556,  944,  778,  778,
+	/*  80 */   611,  778,  667,  556,  611,  778,  722,  944,
+	/*  88 */   722,  667,  667,  333,  606,  333,  606,  500,
+	/*  96 */   278,  444,  463,  407,  500,  389,  278,  500,
+	/* 104 */   500,  278,  278,  444,  278,  778,  556,  444,
+	/* 112 */   500,  463,  389,  389,  333,  556,  500,  722,
+	/* 120 */   500,  500,  444,  333,  606,  333,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1000,  500,
+	/* 144 */   278,  278,  333,  333,  500,  500,  500,  500,
+	/* 152 */  1000,  606, 1028,  669,  500,  500,  528,  545,
+	/* 160 */   250,  333,  500,  500,  500,  500,  606,  500,
+	/* 168 */   333,  747,  333,  500,  606,  333,  747,  333,
+	/* 176 */   400,  606,  300,  300,  333,  556,  500,  250,
+	/* 184 */   333,  300,  333,  500,  750,  750,  750,  500,
+	/* 192 */   722,  722,  722,  722,  722,  722,  941,  667,
+	/* 200 */   611,  611,  611,  611,  333,  333,  333,  333,
+	/* 208 */   778,  778,  778,  778,  778,  778,  778,  606,
+	/* 216 */   778,  778,  778,  778,  778,  667,  611,  500,
+	/* 224 */   444,  444,  444,  444,  444,  444,  638,  407,
+	/* 232 */   389,  389,  389,  389,  278,  278,  278,  278,
+	/* 240 */   444,  556,  444,  444,  444,  444,  444,  606,
+	/* 248 */   444,  556,  556,  556,  556,  500,  500,  500,
+	},
+	{	/* Palatino-BoldItalic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  333,  500,  500,  500,  889,  833,  278,
+	/*  40 */   333,  333,  444,  606,  250,  389,  250,  315,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  250,  250,  606,  606,  606,  444,
+	/*  64 */   833,  722,  667,  685,  778,  611,  556,  778,
+	/*  72 */   778,  389,  389,  722,  611,  944,  778,  833,
+	/*  80 */   667,  833,  722,  556,  611,  778,  667, 1000,
+	/*  88 */   722,  611,  667,  333,  606,  333,  606,  500,
+	/*  96 */   278,  556,  537,  444,  556,  444,  333,  500,
+	/* 104 */   556,  333,  333,  556,  333,  833,  556,  556,
+	/* 112 */   556,  537,  389,  444,  389,  556,  556,  833,
+	/* 120 */   500,  556,  500,  333,  606,  333,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1000,  606,
+	/* 144 */   278,  278,  333,  333,  500,  500,  500,  500,
+	/* 152 */  1000,  606,  944,  778,  556,  556,  611,  611,
+	/* 160 */   250,  333,  500,  500,  500,  500,  606,  556,
+	/* 168 */   333,  747,  333,  500,  606,  389,  747,  333,
+	/* 176 */   400,  606,  300,  300,  333,  556,  556,  250,
+	/* 184 */   333,  300,  333,  500,  750,  750,  750,  444,
+	/* 192 */   722,  722,  722,  722,  722,  722,  944,  685,
+	/* 200 */   611,  611,  611,  611,  389,  389,  389,  389,
+	/* 208 */   778,  778,  833,  833,  833,  833,  833,  606,
+	/* 216 */   833,  778,  778,  778,  778,  611,  667,  556,
+	/* 224 */   556,  556,  556,  556,  556,  556,  738,  444,
+	/* 232 */   444,  444,  444,  444,  333,  333,  333,  333,
+	/* 240 */   556,  556,  556,  556,  556,  556,  556,  606,
+	/* 248 */   556,  556,  556,  556,  556,  556,  556,  556,
+	},
+	{	/* Helvetica-Narrow */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   228,  228,  291,  456,  456,  729,  547,  182,
+	/*  40 */   273,  273,  319,  479,  228,  273,  228,  228,
+	/*  48 */   456,  456,  456,  456,  456,  456,  456,  456,
+	/*  56 */   456,  456,  228,  228,  479,  479,  479,  456,
+	/*  64 */   832,  547,  547,  592,  592,  547,  501,  638,
+	/*  72 */   592,  228,  410,  547,  456,  683,  592,  638,
+	/*  80 */   547,  638,  592,  547,  501,  592,  547,  774,
+	/*  88 */   547,  547,  501,  228,  228,  228,  385,  456,
+	/*  96 */   182,  456,  456,  410,  456,  456,  228,  456,
+	/* 104 */   456,  182,  182,  410,  182,  683,  456,  456,
+	/* 112 */   456,  456,  273,  410,  228,  456,  410,  592,
+	/* 120 */   410,  410,  410,  274,  213,  274,  479,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,  820,  820,  820,  287,
+	/* 144 */   182,  182,  273,  273,  273,  273,  273,  456,
+	/* 152 */   820,  479,  820,  774,  456,  456,  410,  410,
+	/* 160 */   228,  273,  456,  456,  456,  456,  213,  456,
+	/* 168 */   273,  604,  303,  456,  479,  273,  604,  273,
+	/* 176 */   328,  479,  273,  273,  273,  456,  440,  228,
+	/* 184 */   273,  273,  299,  456,  684,  684,  684,  501,
+	/* 192 */   547,  547,  547,  547,  547,  547,  820,  592,
+	/* 200 */   547,  547,  547,  547,  228,  228,  228,  228,
+	/* 208 */   592,  592,  638,  638,  638,  638,  638,  479,
+	/* 216 */   638,  592,  592,  592,  592,  547,  547,  501,
+	/* 224 */   456,  456,  456,  456,  456,  456,  729,  410,
+	/* 232 */   456,  456,  456,  456,  228,  228,  228,  228,
+	/* 240 */   456,  456,  456,  456,  456,  456,  456,  479,
+	/* 248 */   501,  456,  456,  456,  456,  410,  456,  410,
+	},
+	{	/* Helvetica-Narrow-Bold */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   228,  273,  389,  456,  456,  729,  592,  228,
+	/*  40 */   273,  273,  319,  479,  228,  273,  228,  228,
+	/*  48 */   456,  456,  456,  456,  456,  456,  456,  456,
+	/*  56 */   456,  456,  273,  273,  479,  479,  479,  501,
+	/*  64 */   800,  592,  592,  592,  592,  547,  501,  638,
+	/*  72 */   592,  228,  456,  592,  501,  683,  592,  638,
+	/*  80 */   547,  638,  592,  547,  501,  592,  547,  774,
+	/*  88 */   547,  547,  501,  273,  228,  273,  479,  456,
+	/*  96 */   228,  456,  501,  456,  501,  456,  273,  501,
+	/* 104 */   501,  228,  228,  456,  228,  729,  501,  501,
+	/* 112 */   501,  501,  319,  456,  273,  501,  456,  638,
+	/* 120 */   456,  456,  410,  319,  230,  319,  479,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,  820,  820,  820,  287,
+	/* 144 */   228,  228,  273,  273,  410,  410,  410,  456,
+	/* 152 */   820,  479,  820,  774,  456,  456,  501,  501,
+	/* 160 */   228,  273,  456,  456,  456,  456,  230,  456,
+	/* 168 */   273,  604,  303,  456,  479,  273,  604,  273,
+	/* 176 */   328,  479,  273,  273,  273,  501,  456,  228,
+	/* 184 */   273,  273,  299,  456,  684,  684,  684,  501,
+	/* 192 */   592,  592,  592,  592,  592,  592,  820,  592,
+	/* 200 */   547,  547,  547,  547,  228,  228,  228,  228,
+	/* 208 */   592,  592,  638,  638,  638,  638,  638,  479,
+	/* 216 */   638,  592,  592,  592,  592,  547,  547,  501,
+	/* 224 */   456,  456,  456,  456,  456,  456,  729,  456,
+	/* 232 */   456,  456,  456,  456,  228,  228,  228,  228,
+	/* 240 */   501,  501,  501,  501,  501,  501,  501,  479,
+	/* 248 */   501,  501,  501,  501,  501,  456,  501,  456,
+	},
+	{	/* Helvetica-Narrow-Oblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   228,  228,  291,  456,  456,  729,  547,  182,
+	/*  40 */   273,  273,  319,  479,  228,  273,  228,  228,
+	/*  48 */   456,  456,  456,  456,  456,  456,  456,  456,
+	/*  56 */   456,  456,  228,  228,  479,  479,  479,  456,
+	/*  64 */   832,  547,  547,  592,  592,  547,  501,  638,
+	/*  72 */   592,  228,  410,  547,  456,  683,  592,  638,
+	/*  80 */   547,  638,  592,  547,  501,  592,  547,  774,
+	/*  88 */   547,  547,  501,  228,  228,  228,  385,  456,
+	/*  96 */   182,  456,  456,  410,  456,  456,  228,  456,
+	/* 104 */   456,  182,  182,  410,  182,  683,  456,  456,
+	/* 112 */   456,  456,  273,  410,  228,  456,  410,  592,
+	/* 120 */   410,  410,  410,  274,  213,  274,  479,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,  820,  820,  820,  287,
+	/* 144 */   182,  182,  273,  273,  273,  273,  273,  456,
+	/* 152 */   820,  479,  820,  774,  456,  456,  410,  410,
+	/* 160 */   228,  273,  456,  456,  456,  456,  213,  456,
+	/* 168 */   273,  604,  303,  456,  479,  273,  604,  273,
+	/* 176 */   328,  479,  273,  273,  273,  456,  440,  228,
+	/* 184 */   273,  273,  299,  456,  684,  684,  684,  501,
+	/* 192 */   547,  547,  547,  547,  547,  547,  820,  592,
+	/* 200 */   547,  547,  547,  547,  228,  228,  228,  228,
+	/* 208 */   592,  592,  638,  638,  638,  638,  638,  479,
+	/* 216 */   638,  592,  592,  592,  592,  547,  547,  501,
+	/* 224 */   456,  456,  456,  456,  456,  456,  729,  410,
+	/* 232 */   456,  456,  456,  456,  228,  228,  228,  228,
+	/* 240 */   456,  456,  456,  456,  456,  456,  456,  479,
+	/* 248 */   501,  456,  456,  456,  456,  410,  456,  410,
+	},
+	{	/* Helvetica-Narrow-BoldOblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   228,  273,  389,  456,  456,  729,  592,  228,
+	/*  40 */   273,  273,  319,  479,  228,  273,  228,  228,
+	/*  48 */   456,  456,  456,  456,  456,  456,  456,  456,
+	/*  56 */   456,  456,  273,  273,  479,  479,  479,  501,
+	/*  64 */   800,  592,  592,  592,  592,  547,  501,  638,
+	/*  72 */   592,  228,  456,  592,  501,  683,  592,  638,
+	/*  80 */   547,  638,  592,  547,  501,  592,  547,  774,
+	/*  88 */   547,  547,  501,  273,  228,  273,  479,  456,
+	/*  96 */   228,  456,  501,  456,  501,  456,  273,  501,
+	/* 104 */   501,  228,  228,  456,  228,  729,  501,  501,
+	/* 112 */   501,  501,  319,  456,  273,  501,  456,  638,
+	/* 120 */   456,  456,  410,  319,  230,  319,  479,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,  820,  820,  820,  287,
+	/* 144 */   228,  228,  273,  273,  410,  410,  410,  456,
+	/* 152 */   820,  479,  820,  774,  456,  456,  501,  501,
+	/* 160 */   228,  273,  456,  456,  456,  456,  230,  456,
+	/* 168 */   273,  604,  303,  456,  479,  273,  604,  273,
+	/* 176 */   328,  479,  273,  273,  273,  501,  456,  228,
+	/* 184 */   273,  273,  299,  456,  684,  684,  684,  501,
+	/* 192 */   592,  592,  592,  592,  592,  592,  820,  592,
+	/* 200 */   547,  547,  547,  547,  228,  228,  228,  228,
+	/* 208 */   592,  592,  638,  638,  638,  638,  638,  479,
+	/* 216 */   638,  592,  592,  592,  592,  547,  547,  501,
+	/* 224 */   456,  456,  456,  456,  456,  456,  729,  456,
+	/* 232 */   456,  456,  456,  456,  228,  228,  228,  228,
+	/* 240 */   501,  501,  501,  501,  501,  501,  501,  479,
+	/* 248 */   501,  501,  501,  501,  501,  456,  501,  456,
+	},
+	{	/* Bookman-Light */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   320,  300,  380,  620,  620,  900,  800,  220,
+	/*  40 */   300,  300,  440,  600,  320,  400,  320,  600,
+	/*  48 */   620,  620,  620,  620,  620,  620,  620,  620,
+	/*  56 */   620,  620,  320,  320,  600,  600,  600,  540,
+	/*  64 */   820,  680,  740,  740,  800,  720,  640,  800,
+	/*  72 */   800,  340,  600,  720,  600,  920,  740,  800,
+	/*  80 */   620,  820,  720,  660,  620,  780,  700,  960,
+	/*  88 */   720,  640,  640,  300,  600,  300,  600,  500,
+	/*  96 */   220,  580,  620,  520,  620,  520,  320,  540,
+	/* 104 */   660,  300,  300,  620,  300,  940,  660,  560,
+	/* 112 */   620,  580,  440,  520,  380,  680,  520,  780,
+	/* 120 */   560,  540,  480,  280,  600,  280,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000,  980, 1280,  460,
+	/* 144 */   220,  220,  240,  240,  400,  400,  400,  500,
+	/* 152 */  1000,  600, 1240,  900,  540,  540,  620,  620,
+	/* 160 */   320,  300,  620,  620,  620,  620,  600,  520,
+	/* 168 */   420,  740,  420,  360,  600,  400,  740,  440,
+	/* 176 */   400,  600,  372,  372,  340,  680,  600,  320,
+	/* 184 */   320,  372,  420,  360,  930,  930,  930,  540,
+	/* 192 */   680,  680,  680,  680,  680,  680, 1260,  740,
+	/* 200 */   720,  720,  720,  720,  340,  340,  340,  340,
+	/* 208 */   800,  740,  800,  800,  800,  800,  800,  600,
+	/* 216 */   800,  780,  780,  780,  780,  640,  620,  660,
+	/* 224 */   580,  580,  580,  580,  580,  580,  860,  520,
+	/* 232 */   520,  520,  520,  520,  300,  300,  300,  300,
+	/* 240 */   560,  660,  560,  560,  560,  560,  560,  600,
+	/* 248 */   560,  680,  680,  680,  680,  540,  620,  540,
+	},
+	{	/* Bookman-Demi */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   340,  360,  420,  660,  660,  940,  800,  320,
+	/*  40 */   320,  320,  460,  600,  340,  360,  340,  600,
+	/*  48 */   660,  660,  660,  660,  660,  660,  660,  660,
+	/*  56 */   660,  660,  340,  340,  600,  600,  600,  660,
+	/*  64 */   820,  720,  720,  740,  780,  720,  680,  780,
+	/*  72 */   820,  400,  640,  800,  640,  940,  740,  800,
+	/*  80 */   660,  800,  780,  660,  700,  740,  720,  940,
+	/*  88 */   780,  700,  640,  300,  600,  300,  600,  500,
+	/*  96 */   320,  580,  600,  580,  640,  580,  380,  580,
+	/* 104 */   680,  360,  340,  660,  340, 1000,  680,  620,
+	/* 112 */   640,  620,  460,  520,  460,  660,  600,  800,
+	/* 120 */   600,  620,  560,  320,  600,  320,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000,  980, 1360,  460,
+	/* 144 */   320,  320,  220,  220,  540,  540,  540,  500,
+	/* 152 */  1000,  600, 1220,  940,  440,  380,  740,  740,
+	/* 160 */   340,  360,  660,  660,  660,  660,  600,  600,
+	/* 168 */   500,  740,  400,  400,  600,  360,  740,  460,
+	/* 176 */   400,  600,  396,  396,  400,  660,  800,  340,
+	/* 184 */   360,  396,  400,  400,  990,  990,  990,  660,
+	/* 192 */   720,  720,  720,  720,  720,  720, 1140,  740,
+	/* 200 */   720,  720,  720,  720,  400,  400,  400,  400,
+	/* 208 */   780,  740,  800,  800,  800,  800,  800,  600,
+	/* 216 */   800,  740,  740,  740,  740,  700,  660,  660,
+	/* 224 */   580,  580,  580,  580,  580,  580,  880,  580,
+	/* 232 */   580,  580,  580,  580,  360,  360,  360,  360,
+	/* 240 */   620,  680,  620,  620,  620,  620,  620,  600,
+	/* 248 */   620,  660,  660,  660,  660,  620,  640,  620,
+	},
+	{	/* Bookman-LightItalic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   300,  320,  360,  620,  620,  800,  820,  280,
+	/*  40 */   280,  280,  440,  600,  300,  320,  300,  600,
+	/*  48 */   620,  620,  620,  620,  620,  620,  620,  620,
+	/*  56 */   620,  620,  300,  300,  600,  600,  600,  540,
+	/*  64 */   780,  700,  720,  720,  740,  680,  620,  760,
+	/*  72 */   800,  320,  560,  720,  580,  860,  720,  760,
+	/*  80 */   600,  780,  700,  640,  600,  720,  680,  960,
+	/*  88 */   700,  660,  580,  260,  600,  260,  600,  500,
+	/*  96 */   280,  620,  600,  480,  640,  540,  340,  560,
+	/* 104 */   620,  280,  280,  600,  280,  880,  620,  540,
+	/* 112 */   600,  560,  400,  540,  340,  620,  540,  880,
+	/* 120 */   540,  600,  520,  360,  600,  380,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000,  980, 1180,  460,
+	/* 144 */   280,  280,  180,  180,  440,  440,  480,  500,
+	/* 152 */  1000,  600, 1180,  900,  620,  620,  640,  660,
+	/* 160 */   300,  320,  620,  620,  620,  620,  600,  620,
+	/* 168 */   420,  740,  440,  300,  600,  320,  740,  440,
+	/* 176 */   400,  600,  372,  372,  320,  620,  620,  300,
+	/* 184 */   320,  372,  400,  300,  930,  930,  930,  540,
+	/* 192 */   700,  700,  700,  700,  700,  700, 1220,  720,
+	/* 200 */   680,  680,  680,  680,  320,  320,  320,  320,
+	/* 208 */   740,  720,  760,  760,  760,  760,  760,  600,
+	/* 216 */   760,  720,  720,  720,  720,  660,  600,  620,
+	/* 224 */   620,  620,  620,  620,  620,  620,  880,  480,
+	/* 232 */   540,  540,  540,  540,  280,  280,  280,  280,
+	/* 240 */   540,  620,  540,  540,  540,  540,  540,  600,
+	/* 248 */   540,  620,  620,  620,  620,  600,  600,  600,
+	},
+	{	/* Bookman-DemiItalic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   340,  320,  380,  680,  680,  880,  980,  320,
+	/*  40 */   260,  260,  460,  600,  340,  280,  340,  360,
+	/*  48 */   680,  680,  680,  680,  680,  680,  680,  680,
+	/*  56 */   680,  680,  340,  340,  620,  600,  620,  620,
+	/*  64 */   780,  720,  720,  700,  760,  720,  660,  760,
+	/*  72 */   800,  380,  620,  780,  640,  860,  740,  760,
+	/*  80 */   640,  760,  740,  700,  700,  740,  660, 1000,
+	/*  88 */   740,  660,  680,  260,  580,  260,  620,  500,
+	/*  96 */   320,  680,  600,  560,  680,  560,  420,  620,
+	/* 104 */   700,  380,  320,  700,  380,  960,  680,  600,
+	/* 112 */   660,  620,  500,  540,  440,  680,  540,  860,
+	/* 120 */   620,  600,  560,  300,  620,  300,  620,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000,  940, 1360,  360,
+	/* 144 */   320,  320,  220,  220,  520,  520,  520,  500,
+	/* 152 */  1000,  600, 1180,  920,  420,  420,  820,  820,
+	/* 160 */   340,  320,  680,  680,  680,  680,  620,  620,
+	/* 168 */   520,  780,  440,  380,  620,  280,  780,  480,
+	/* 176 */   400,  600,  408,  408,  340,  680,  680,  340,
+	/* 184 */   360,  408,  440,  380, 1020, 1020, 1020,  620,
+	/* 192 */   720,  720,  720,  720,  720,  720, 1140,  700,
+	/* 200 */   720,  720,  720,  720,  380,  380,  380,  380,
+	/* 208 */   760,  740,  760,  760,  760,  760,  760,  600,
+	/* 216 */   760,  740,  740,  740,  740,  660,  640,  660,
+	/* 224 */   680,  680,  680,  680,  680,  680,  880,  560,
+	/* 232 */   560,  560,  560,  560,  380,  380,  380,  380,
+	/* 240 */   600,  680,  600,  600,  600,  600,  600,  600,
+	/* 248 */   600,  680,  680,  680,  680,  600,  660,  600,
+	},
+	{	/* AvantGarde-Book */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   277,  295,  309,  554,  554,  775,  757,  351,
+	/*  40 */   369,  369,  425,  606,  277,  332,  277,  437,
+	/*  48 */   554,  554,  554,  554,  554,  554,  554,  554,
+	/*  56 */   554,  554,  277,  277,  606,  606,  606,  591,
+	/*  64 */   867,  740,  574,  813,  744,  536,  485,  872,
+	/*  72 */   683,  226,  482,  591,  462,  919,  740,  869,
+	/*  80 */   592,  871,  607,  498,  426,  655,  702,  960,
+	/*  88 */   609,  592,  480,  351,  605,  351,  606,  500,
+	/*  96 */   351,  683,  682,  647,  685,  650,  314,  673,
+	/* 104 */   610,  200,  203,  502,  200,  938,  610,  655,
+	/* 112 */   682,  682,  301,  388,  339,  608,  554,  831,
+	/* 120 */   480,  536,  425,  351,  672,  351,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1174,  606,
+	/* 144 */   351,  351,  251,  251,  502,  484,  502,  500,
+	/* 152 */  1000,  606, 1194, 1137,  553,  553,  487,  485,
+	/* 160 */   277,  295,  554,  554,  554,  554,  672,  615,
+	/* 168 */   369,  747,  369,  425,  606,  332,  747,  485,
+	/* 176 */   400,  606,  332,  332,  375,  608,  564,  277,
+	/* 184 */   324,  332,  369,  425,  831,  831,  831,  591,
+	/* 192 */   740,  740,  740,  740,  740,  740,  992,  813,
+	/* 200 */   536,  536,  536,  536,  226,  226,  226,  226,
+	/* 208 */   790,  740,  869,  869,  869,  869,  869,  606,
+	/* 216 */   868,  655,  655,  655,  655,  592,  592,  554,
+	/* 224 */   683,  683,  683,  683,  683,  683, 1157,  647,
+	/* 232 */   650,  650,  650,  650,  200,  200,  200,  200,
+	/* 240 */   655,  610,  655,  655,  655,  655,  655,  606,
+	/* 248 */   653,  608,  608,  608,  608,  536,  682,  536,
+	},
+	{	/* AvantGarde-Demi */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   280,  280,  360,  560,  560,  860,  680,  280,
+	/*  40 */   380,  380,  440,  600,  280,  420,  280,  460,
+	/*  48 */   560,  560,  560,  560,  560,  560,  560,  560,
+	/*  56 */   560,  560,  280,  280,  600,  600,  600,  560,
+	/*  64 */   740,  740,  580,  780,  700,  520,  480,  840,
+	/*  72 */   680,  280,  480,  620,  440,  900,  740,  840,
+	/*  80 */   560,  840,  580,  520,  420,  640,  700,  900,
+	/*  88 */   680,  620,  500,  320,  640,  320,  600,  500,
+	/*  96 */   280,  660,  660,  640,  660,  640,  280,  660,
+	/* 104 */   600,  240,  260,  580,  240,  940,  600,  640,
+	/* 112 */   660,  660,  320,  440,  300,  600,  560,  800,
+	/* 120 */   560,  580,  460,  340,  600,  340,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1280,  600,
+	/* 144 */   280,  280,  240,  240,  480,  480,  480,  500,
+	/* 152 */  1000,  600, 1060, 1080,  560,  560,  520,  520,
+	/* 160 */   280,  280,  560,  560,  560,  560,  600,  560,
+	/* 168 */   500,  740,  360,  460,  600,  420,  740,  420,
+	/* 176 */   400,  600,  336,  336,  420,  576,  600,  280,
+	/* 184 */   340,  336,  360,  460,  840,  840,  840,  560,
+	/* 192 */   740,  740,  740,  740,  740,  740,  900,  780,
+	/* 200 */   520,  520,  520,  520,  280,  280,  280,  280,
+	/* 208 */   742,  740,  840,  840,  840,  840,  840,  600,
+	/* 216 */   840,  640,  640,  640,  640,  620,  560,  600,
+	/* 224 */   660,  660,  660,  660,  660,  660, 1080,  640,
+	/* 232 */   640,  640,  640,  640,  240,  240,  240,  240,
+	/* 240 */   640,  600,  640,  640,  640,  640,  640,  600,
+	/* 248 */   660,  600,  600,  600,  600,  580,  660,  580,
+	},
+	{	/* AvantGarde-BookOblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   277,  295,  309,  554,  554,  775,  757,  351,
+	/*  40 */   369,  369,  425,  606,  277,  332,  277,  437,
+	/*  48 */   554,  554,  554,  554,  554,  554,  554,  554,
+	/*  56 */   554,  554,  277,  277,  606,  606,  606,  591,
+	/*  64 */   867,  740,  574,  813,  744,  536,  485,  872,
+	/*  72 */   683,  226,  482,  591,  462,  919,  740,  869,
+	/*  80 */   592,  871,  607,  498,  426,  655,  702,  960,
+	/*  88 */   609,  592,  480,  351,  605,  351,  606,  500,
+	/*  96 */   351,  683,  682,  647,  685,  650,  314,  673,
+	/* 104 */   610,  200,  203,  502,  200,  938,  610,  655,
+	/* 112 */   682,  682,  301,  388,  339,  608,  554,  831,
+	/* 120 */   480,  536,  425,  351,  672,  351,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1174,  606,
+	/* 144 */   351,  351,  251,  251,  502,  484,  502,  500,
+	/* 152 */  1000,  606, 1194, 1137,  553,  553,  487,  485,
+	/* 160 */   277,  295,  554,  554,  554,  554,  672,  615,
+	/* 168 */   369,  747,  369,  425,  606,  332,  747,  485,
+	/* 176 */   400,  606,  332,  332,  375,  608,  564,  277,
+	/* 184 */   324,  332,  369,  425,  831,  831,  831,  591,
+	/* 192 */   740,  740,  740,  740,  740,  740,  992,  813,
+	/* 200 */   536,  536,  536,  536,  226,  226,  226,  226,
+	/* 208 */   790,  740,  869,  869,  869,  869,  869,  606,
+	/* 216 */   868,  655,  655,  655,  655,  592,  592,  554,
+	/* 224 */   683,  683,  683,  683,  683,  683, 1157,  647,
+	/* 232 */   650,  650,  650,  650,  200,  200,  200,  200,
+	/* 240 */   655,  610,  655,  655,  655,  655,  655,  606,
+	/* 248 */   653,  608,  608,  608,  608,  536,  682,  536,
+	},
+	{	/* AvantGarde-DemiOblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   280,  280,  360,  560,  560,  860,  680,  280,
+	/*  40 */   380,  380,  440,  600,  280,  420,  280,  460,
+	/*  48 */   560,  560,  560,  560,  560,  560,  560,  560,
+	/*  56 */   560,  560,  280,  280,  600,  600,  600,  560,
+	/*  64 */   740,  740,  580,  780,  700,  520,  480,  840,
+	/*  72 */   680,  280,  480,  620,  440,  900,  740,  840,
+	/*  80 */   560,  840,  580,  520,  420,  640,  700,  900,
+	/*  88 */   680,  620,  500,  320,  640,  320,  600,  500,
+	/*  96 */   280,  660,  660,  640,  660,  640,  280,  660,
+	/* 104 */   600,  240,  260,  580,  240,  940,  600,  640,
+	/* 112 */   660,  660,  320,  440,  300,  600,  560,  800,
+	/* 120 */   560,  580,  460,  340,  600,  340,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1280,  600,
+	/* 144 */   280,  280,  240,  240,  480,  480,  480,  500,
+	/* 152 */  1000,  600, 1060, 1080,  560,  560,  520,  520,
+	/* 160 */   280,  280,  560,  560,  560,  560,  600,  560,
+	/* 168 */   500,  740,  360,  460,  600,  420,  740,  420,
+	/* 176 */   400,  600,  336,  336,  420,  576,  600,  280,
+	/* 184 */   340,  336,  360,  460,  840,  840,  840,  560,
+	/* 192 */   740,  740,  740,  740,  740,  740,  900,  780,
+	/* 200 */   520,  520,  520,  520,  280,  280,  280,  280,
+	/* 208 */   742,  740,  840,  840,  840,  840,  840,  600,
+	/* 216 */   840,  640,  640,  640,  640,  620,  560,  600,
+	/* 224 */   660,  660,  660,  660,  660,  660, 1080,  640,
+	/* 232 */   640,  640,  640,  640,  240,  240,  240,  240,
+	/* 240 */   640,  600,  640,  640,  640,  640,  640,  600,
+	/* 248 */   660,  600,  600,  600,  600,  580,  660,  580,
+	},
+	{	/* NewCenturySchlbk-Roman */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   278,  296,  389,  556,  556,  833,  815,  204,
+	/*  40 */   333,  333,  500,  606,  278,  333,  278,  278,
+	/*  48 */   556,  556,  556,  556,  556,  556,  556,  556,
+	/*  56 */   556,  556,  278,  278,  606,  606,  606,  444,
+	/*  64 */   737,  722,  722,  722,  778,  722,  667,  778,
+	/*  72 */   833,  407,  556,  778,  667,  944,  815,  778,
+	/*  80 */   667,  778,  722,  630,  667,  815,  722,  981,
+	/*  88 */   704,  704,  611,  333,  606,  333,  606,  500,
+	/*  96 */   204,  556,  556,  444,  574,  500,  333,  537,
+	/* 104 */   611,  315,  296,  593,  315,  889,  611,  500,
+	/* 112 */   574,  556,  444,  463,  389,  611,  537,  778,
+	/* 120 */   537,  537,  481,  333,  606,  333,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1000,  606,
+	/* 144 */   204,  204,  259,  259,  389,  389,  389,  556,
+	/* 152 */  1000,  606, 1000,  833,  500,  500,  611,  611,
+	/* 160 */   278,  296,  556,  556,  556,  556,  606,  500,
+	/* 168 */   333,  737,  334,  426,  606,  333,  737,  333,
+	/* 176 */   400,  606,  333,  333,  333,  611,  606,  278,
+	/* 184 */   333,  333,  300,  426,  834,  834,  834,  444,
+	/* 192 */   722,  722,  722,  722,  722,  722, 1000,  722,
+	/* 200 */   722,  722,  722,  722,  407,  407,  407,  407,
+	/* 208 */   778,  815,  778,  778,  778,  778,  778,  606,
+	/* 216 */   778,  815,  815,  815,  815,  704,  667,  574,
+	/* 224 */   556,  556,  556,  556,  556,  556,  796,  444,
+	/* 232 */   500,  500,  500,  500,  315,  315,  315,  315,
+	/* 240 */   500,  611,  500,  500,  500,  500,  500,  606,
+	/* 248 */   500,  611,  611,  611,  611,  537,  574,  537,
+	},
+	{	/* NewCenturySchlbk-Bold */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   287,  296,  333,  574,  574,  833,  852,  241,
+	/*  40 */   389,  389,  500,  606,  278,  333,  278,  278,
+	/*  48 */   574,  574,  574,  574,  574,  574,  574,  574,
+	/*  56 */   574,  574,  278,  278,  606,  606,  606,  500,
+	/*  64 */   747,  759,  778,  778,  833,  759,  722,  833,
+	/*  72 */   870,  444,  648,  815,  722,  981,  833,  833,
+	/*  80 */   759,  833,  815,  667,  722,  833,  759,  981,
+	/*  88 */   722,  722,  667,  389,  606,  389,  606,  500,
+	/*  96 */   241,  611,  648,  556,  667,  574,  389,  611,
+	/* 104 */   685,  370,  352,  667,  352,  963,  685,  611,
+	/* 112 */   667,  648,  519,  500,  426,  685,  611,  889,
+	/* 120 */   611,  611,  537,  389,  606,  389,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1000,  606,
+	/* 144 */   241,  241,  333,  333,  481,  481,  481,  500,
+	/* 152 */  1000,  606, 1000,  907,  500,  500,  685,  685,
+	/* 160 */   287,  296,  574,  574,  574,  574,  606,  500,
+	/* 168 */   333,  747,  367,  500,  606,  333,  747,  333,
+	/* 176 */   400,  606,  344,  344,  333,  685,  747,  278,
+	/* 184 */   333,  344,  367,  500,  861,  861,  861,  500,
+	/* 192 */   759,  759,  759,  759,  759,  759,  981,  778,
+	/* 200 */   759,  759,  759,  759,  444,  444,  444,  444,
+	/* 208 */   833,  833,  833,  833,  833,  833,  833,  606,
+	/* 216 */   833,  833,  833,  833,  833,  722,  759,  611,
+	/* 224 */   611,  611,  611,  611,  611,  611,  870,  556,
+	/* 232 */   574,  574,  574,  574,  370,  370,  370,  370,
+	/* 240 */   611,  685,  611,  611,  611,  611,  611,  606,
+	/* 248 */   611,  685,  685,  685,  685,  611,  667,  611,
+	},
+	{	/* NewCenturySchlbk-Italic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   278,  333,  400,  556,  556,  833,  852,  204,
+	/*  40 */   333,  333,  500,  606,  278,  333,  278,  606,
+	/*  48 */   556,  556,  556,  556,  556,  556,  556,  556,
+	/*  56 */   556,  556,  278,  278,  606,  606,  606,  444,
+	/*  64 */   747,  704,  722,  722,  778,  722,  667,  778,
+	/*  72 */   833,  407,  611,  741,  667,  944,  815,  778,
+	/*  80 */   667,  778,  741,  667,  685,  815,  704,  926,
+	/*  88 */   704,  685,  667,  333,  606,  333,  606,  500,
+	/*  96 */   204,  574,  556,  444,  611,  444,  333,  537,
+	/* 104 */   611,  333,  315,  556,  333,  889,  611,  500,
+	/* 112 */   574,  556,  444,  444,  352,  611,  519,  778,
+	/* 120 */   500,  500,  463,  333,  606,  333,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000,  950, 1000,  606,
+	/* 144 */   204,  204,  333,  333,  389,  389,  389,  500,
+	/* 152 */  1000,  606,  981,  778,  500,  500,  611,  611,
+	/* 160 */   278,  333,  556,  556,  556,  556,  606,  500,
+	/* 168 */   333,  747,  422,  426,  606,  333,  747,  333,
+	/* 176 */   400,  606,  333,  333,  333,  611,  650,  278,
+	/* 184 */   333,  333,  372,  426,  834,  834,  834,  444,
+	/* 192 */   704,  704,  704,  704,  704,  704,  870,  722,
+	/* 200 */   722,  722,  722,  722,  407,  407,  407,  407,
+	/* 208 */   778,  815,  778,  778,  778,  778,  778,  606,
+	/* 216 */   778,  815,  815,  815,  815,  685,  667,  556,
+	/* 224 */   574,  574,  574,  574,  574,  574,  722,  444,
+	/* 232 */   444,  444,  444,  444,  333,  333,  333,  333,
+	/* 240 */   500,  611,  500,  500,  500,  500,  500,  606,
+	/* 248 */   500,  611,  611,  611,  611,  500,  574,  500,
+	},
+	{	/* NewCenturySchlbk-BoldItalic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   287,  333,  400,  574,  574,  889,  889,  259,
+	/*  40 */   407,  407,  500,  606,  287,  333,  287,  278,
+	/*  48 */   574,  574,  574,  574,  574,  574,  574,  574,
+	/*  56 */   574,  574,  287,  287,  606,  606,  606,  481,
+	/*  64 */   747,  741,  759,  759,  833,  741,  704,  815,
+	/*  72 */   870,  444,  667,  778,  704,  944,  852,  833,
+	/*  80 */   741,  833,  796,  685,  722,  833,  741,  944,
+	/*  88 */   741,  704,  704,  407,  606,  407,  606,  500,
+	/*  96 */   259,  667,  611,  537,  667,  519,  389,  611,
+	/* 104 */   685,  389,  370,  648,  389,  944,  685,  574,
+	/* 112 */   648,  630,  519,  481,  407,  685,  556,  833,
+	/* 120 */   574,  519,  519,  407,  606,  407,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000,  950, 1167,  606,
+	/* 144 */   259,  259,  278,  278,  481,  481,  481,  500,
+	/* 152 */  1000,  606,  963,  852,  500,  500,  685,  685,
+	/* 160 */   287,  333,  574,  574,  574,  574,  606,  500,
+	/* 168 */   333,  747,  412,  481,  606,  333,  747,  333,
+	/* 176 */   400,  606,  344,  344,  333,  685,  650,  287,
+	/* 184 */   333,  344,  356,  481,  861,  861,  861,  481,
+	/* 192 */   741,  741,  741,  741,  741,  741,  889,  759,
+	/* 200 */   741,  741,  741,  741,  444,  444,  444,  444,
+	/* 208 */   833,  852,  833,  833,  833,  833,  833,  606,
+	/* 216 */   833,  833,  833,  833,  833,  704,  741,  574,
+	/* 224 */   667,  667,  667,  667,  667,  667,  815,  537,
+	/* 232 */   519,  519,  519,  519,  389,  389,  389,  389,
+	/* 240 */   574,  685,  574,  574,  574,  574,  574,  606,
+	/* 248 */   574,  685,  685,  685,  685,  519,  648,  519,
+	},
+};
+static unsigned short ausCharacterWidths2[32][256] = {
+	{	/* Courier */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  40 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  48 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  56 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  64 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  72 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  80 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  88 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  96 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 104 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 112 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 120 */   600,  600,  600,  600,  600,  600,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 168 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 176 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 184 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 192 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 200 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 208 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 216 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 224 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 232 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 240 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 248 */   600,  600,  600,  600,  600,  600,  600,  600,
+	},
+	{	/* Courier-Bold */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  40 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  48 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  56 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  64 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  72 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  80 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  88 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  96 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 104 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 112 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 120 */   600,  600,  600,  600,  600,  600,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 168 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 176 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 184 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 192 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 200 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 208 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 216 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 224 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 232 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 240 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 248 */   600,  600,  600,  600,  600,  600,  600,  600,
+	},
+	{	/* Courier-Oblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  40 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  48 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  56 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  64 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  72 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  80 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  88 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  96 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 104 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 112 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 120 */   600,  600,  600,  600,  600,  600,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 168 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 176 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 184 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 192 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 200 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 208 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 216 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 224 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 232 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 240 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 248 */   600,  600,  600,  600,  600,  600,  600,  600,
+	},
+	{	/* Courier-BoldOblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  40 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  48 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  56 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  64 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  72 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  80 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  88 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  96 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 104 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 112 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 120 */   600,  600,  600,  600,  600,  600,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 168 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 176 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 184 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 192 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 200 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 208 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 216 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 224 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 232 */   600,  600,  600,  600,  600,  600,  600,  740,
+	/* 240 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 248 */   600,  600,  600,  600,  600,  600,  600,  600,
+	},
+	{	/* Times-Roman */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  333,  408,  500,  500,  833,  778,  180,
+	/*  40 */   333,  333,  500,  564,  250,  333,  250,  278,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  278,  278,  564,  564,  564,  444,
+	/*  64 */   921,  722,  667,  667,  722,  611,  556,  722,
+	/*  72 */   722,  333,  389,  722,  611,  889,  722,  722,
+	/*  80 */   556,  722,  667,  556,  611,  722,  722,  944,
+	/*  88 */   722,  722,  611,  333,  278,  333,  469,  500,
+	/*  96 */   333,  444,  500,  444,  500,  444,  333,  500,
+	/* 104 */   500,  278,  278,  500,  278,  778,  500,  500,
+	/* 112 */   500,  500,  333,  389,  278,  500,  500,  722,
+	/* 120 */   500,  500,  444,  480,  200,  480,  541,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   250,  722,  333,  611,  500,  611,  556,  500,
+	/* 168 */   333,  556,  556,  611,  611,  333,  611,  611,
+	/* 176 */   333,  444,  333,  278,  333,  348,  389,  333,
+	/* 184 */   333,  389,  389,  278,  444,  333,  444,  444,
+	/* 192 */   667,  722,  722,  722,  722,  611,  667,  667,
+	/* 200 */   667,  611,  611,  611,  611,  333,  333,  722,
+	/* 208 */   722,  722,  722,  722,  722,  722,  722,  564,
+	/* 216 */   667,  722,  722,  722,  722,  722,  611,  500,
+	/* 224 */   333,  444,  444,  444,  444,  278,  444,  444,
+	/* 232 */   444,  444,  444,  444,  444,  278,  278,  600,
+	/* 240 */   500,  500,  500,  500,  500,  500,  500,  564,
+	/* 248 */   333,  500,  500,  500,  500,  500,  278,  333,
+	},
+	{	/* Times-Bold */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  333,  555,  500,  500, 1000,  833,  278,
+	/*  40 */   333,  333,  500,  570,  250,  333,  250,  278,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  333,  333,  570,  570,  570,  500,
+	/*  64 */   930,  722,  667,  722,  722,  667,  611,  778,
+	/*  72 */   778,  389,  500,  778,  667,  944,  722,  778,
+	/*  80 */   611,  778,  722,  556,  667,  722,  722, 1000,
+	/*  88 */   722,  722,  667,  333,  278,  333,  581,  500,
+	/*  96 */   333,  500,  556,  444,  556,  444,  333,  500,
+	/* 104 */   556,  278,  333,  556,  278,  833,  556,  500,
+	/* 112 */   556,  556,  444,  389,  333,  556,  500,  722,
+	/* 120 */   500,  500,  444,  394,  220,  394,  520,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   250,  722,  333,  667,  500,  667,  556,  500,
+	/* 168 */   333,  556,  556,  667,  667,  333,  667,  667,
+	/* 176 */   333,  500,  333,  278,  333,  396,  389,  333,
+	/* 184 */   333,  389,  389,  400,  444,  333,  444,  444,
+	/* 192 */   722,  722,  722,  722,  722,  667,  722,  722,
+	/* 200 */   722,  667,  667,  667,  667,  389,  389,  722,
+	/* 208 */   722,  722,  722,  778,  778,  778,  778,  570,
+	/* 216 */   722,  722,  722,  722,  722,  722,  667,  556,
+	/* 224 */   444,  500,  500,  500,  500,  278,  444,  444,
+	/* 232 */   444,  444,  444,  444,  444,  278,  278,  665,
+	/* 240 */   556,  556,  556,  500,  500,  500,  500,  570,
+	/* 248 */   444,  556,  556,  556,  556,  500,  333,  333,
+	},
+	{	/* Times-Italic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  333,  420,  500,  500,  833,  778,  214,
+	/*  40 */   333,  333,  500,  675,  250,  333,  250,  278,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  333,  333,  675,  675,  675,  500,
+	/*  64 */   920,  611,  611,  667,  722,  611,  611,  722,
+	/*  72 */   722,  333,  444,  667,  556,  833,  667,  722,
+	/*  80 */   611,  722,  611,  500,  556,  722,  611,  833,
+	/*  88 */   611,  556,  556,  389,  278,  389,  422,  500,
+	/*  96 */   333,  500,  500,  444,  500,  444,  278,  500,
+	/* 104 */   500,  278,  278,  444,  278,  722,  500,  500,
+	/* 112 */   500,  500,  389,  389,  278,  500,  444,  667,
+	/* 120 */   444,  444,  389,  400,  275,  400,  541,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   250,  611,  333,  556,  500,  556,  500,  500,
+	/* 168 */   333,  500,  500,  556,  556,  333,  556,  556,
+	/* 176 */   333,  500,  333,  278,  333,  278,  389,  333,
+	/* 184 */   333,  389,  389,  278,  389,  333,  389,  389,
+	/* 192 */   611,  611,  611,  611,  611,  556,  667,  667,
+	/* 200 */   667,  611,  611,  611,  611,  333,  333,  722,
+	/* 208 */   722,  667,  667,  722,  722,  722,  722,  675,
+	/* 216 */   611,  722,  722,  722,  722,  556,  556,  500,
+	/* 224 */   389,  500,  500,  500,  500,  278,  444,  444,
+	/* 232 */   444,  444,  444,  444,  444,  278,  278,  521,
+	/* 240 */   500,  500,  500,  500,  500,  500,  500,  675,
+	/* 248 */   389,  500,  500,  500,  500,  444,  278,  333,
+	},
+	{	/* Times-BoldItalic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  389,  555,  500,  500,  833,  778,  278,
+	/*  40 */   333,  333,  500,  570,  250,  333,  250,  278,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  333,  333,  570,  570,  570,  500,
+	/*  64 */   832,  667,  667,  667,  722,  667,  667,  722,
+	/*  72 */   778,  389,  500,  667,  611,  889,  722,  722,
+	/*  80 */   611,  722,  667,  556,  611,  722,  667,  889,
+	/*  88 */   667,  611,  611,  333,  278,  333,  570,  500,
+	/*  96 */   333,  500,  500,  444,  500,  444,  333,  500,
+	/* 104 */   556,  278,  278,  500,  278,  778,  556,  500,
+	/* 112 */   500,  500,  389,  389,  278,  556,  444,  667,
+	/* 120 */   500,  444,  389,  348,  220,  348,  570,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   250,  667,  333,  611,  500,  611,  556,  500,
+	/* 168 */   333,  556,  556,  611,  611,  333,  611,  611,
+	/* 176 */   333,  500,  333,  278,  333,  382,  389,  333,
+	/* 184 */   333,  389,  389,  345,  389,  333,  389,  389,
+	/* 192 */   667,  667,  667,  667,  667,  611,  667,  667,
+	/* 200 */   667,  667,  667,  667,  667,  389,  389,  722,
+	/* 208 */   722,  722,  722,  722,  722,  722,  722,  570,
+	/* 216 */   667,  722,  722,  722,  722,  611,  611,  500,
+	/* 224 */   389,  500,  500,  500,  500,  278,  444,  444,
+	/* 232 */   444,  444,  444,  444,  444,  278,  278,  600,
+	/* 240 */   500,  556,  556,  500,  500,  500,  500,  570,
+	/* 248 */   389,  556,  556,  556,  556,  444,  278,  333,
+	},
+	{	/* Helvetica */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   278,  278,  355,  556,  556,  889,  667,  191,
+	/*  40 */   333,  333,  389,  584,  278,  333,  278,  278,
+	/*  48 */   556,  556,  556,  556,  556,  556,  556,  556,
+	/*  56 */   556,  556,  278,  278,  584,  584,  584,  556,
+	/*  64 */  1015,  667,  667,  722,  722,  667,  611,  778,
+	/*  72 */   722,  278,  500,  667,  556,  833,  722,  778,
+	/*  80 */   667,  778,  722,  667,  611,  722,  667,  944,
+	/*  88 */   667,  667,  611,  278,  278,  278,  469,  556,
+	/*  96 */   333,  556,  556,  500,  556,  556,  278,  556,
+	/* 104 */   556,  222,  222,  500,  222,  833,  556,  556,
+	/* 112 */   556,  556,  333,  500,  278,  556,  500,  722,
+	/* 120 */   500,  500,  500,  334,  260,  334,  584,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   278,  667,  333,  556,  556,  556,  667,  556,
+	/* 168 */   333,  667,  667,  611,  611,  333,  611,  611,
+	/* 176 */   333,  556,  333,  222,  333,  292,  500,  333,
+	/* 184 */   333,  500,  500,  308,  500,  333,  500,  500,
+	/* 192 */   722,  667,  667,  667,  667,  556,  722,  722,
+	/* 200 */   722,  667,  667,  667,  667,  278,  278,  722,
+	/* 208 */   722,  722,  722,  778,  778,  778,  778,  584,
+	/* 216 */   722,  722,  722,  722,  722,  666,  611,  611,
+	/* 224 */   333,  556,  556,  556,  556,  222,  500,  500,
+	/* 232 */   500,  556,  556,  556,  556,  278,  278,  635,
+	/* 240 */   556,  556,  556,  556,  556,  556,  556,  584,
+	/* 248 */   333,  556,  556,  556,  556,  500,  278,  333,
+	},
+	{	/* Helvetica-Bold */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   278,  333,  474,  556,  556,  889,  722,  238,
+	/*  40 */   333,  333,  389,  584,  278,  333,  278,  278,
+	/*  48 */   556,  556,  556,  556,  556,  556,  556,  556,
+	/*  56 */   556,  556,  333,  333,  584,  584,  584,  611,
+	/*  64 */   975,  722,  722,  722,  722,  667,  611,  778,
+	/*  72 */   722,  278,  556,  722,  611,  833,  722,  778,
+	/*  80 */   667,  778,  722,  667,  611,  722,  667,  944,
+	/*  88 */   667,  667,  611,  333,  278,  333,  584,  556,
+	/*  96 */   333,  556,  611,  556,  611,  556,  333,  611,
+	/* 104 */   611,  278,  278,  556,  278,  889,  611,  611,
+	/* 112 */   611,  611,  389,  556,  333,  611,  556,  778,
+	/* 120 */   556,  556,  500,  389,  280,  389,  584,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   278,  722,  333,  611,  556,  611,  667,  556,
+	/* 168 */   333,  667,  667,  611,  611,  333,  611,  611,
+	/* 176 */   333,  556,  333,  278,  333,  369,  556,  333,
+	/* 184 */   333,  556,  556,  385,  500,  333,  500,  500,
+	/* 192 */   722,  722,  722,  722,  722,  611,  722,  722,
+	/* 200 */   722,  667,  667,  667,  667,  278,  278,  722,
+	/* 208 */   722,  722,  722,  778,  778,  778,  778,  584,
+	/* 216 */   722,  722,  722,  722,  722,  667,  611,  611,
+	/* 224 */   389,  556,  556,  556,  556,  278,  556,  556,
+	/* 232 */   556,  556,  556,  556,  556,  278,  278,  707,
+	/* 240 */   611,  611,  611,  611,  611,  611,  611,  584,
+	/* 248 */   389,  611,  611,  611,  611,  556,  333,  333,
+	},
+	{	/* Helvetica-Oblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   278,  278,  355,  556,  556,  889,  667,  191,
+	/*  40 */   333,  333,  389,  584,  278,  333,  278,  278,
+	/*  48 */   556,  556,  556,  556,  556,  556,  556,  556,
+	/*  56 */   556,  556,  278,  278,  584,  584,  584,  556,
+	/*  64 */  1015,  667,  667,  722,  722,  667,  611,  778,
+	/*  72 */   722,  278,  500,  667,  556,  833,  722,  778,
+	/*  80 */   667,  778,  722,  667,  611,  722,  667,  944,
+	/*  88 */   667,  667,  611,  278,  278,  278,  469,  556,
+	/*  96 */   333,  556,  556,  500,  556,  556,  278,  556,
+	/* 104 */   556,  222,  222,  500,  222,  833,  556,  556,
+	/* 112 */   556,  556,  333,  500,  278,  556,  500,  722,
+	/* 120 */   500,  500,  500,  334,  260,  334,  584,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   278,  667,  333,  556,  556,  556,  667,  556,
+	/* 168 */   333,  667,  667,  611,  611,  333,  611,  611,
+	/* 176 */   333,  556,  333,  222,  333,  307,  500,  333,
+	/* 184 */   333,  500,  500,  319,  500,  333,  500,  500,
+	/* 192 */   722,  667,  667,  667,  667,  556,  722,  722,
+	/* 200 */   722,  667,  667,  667,  667,  278,  278,  722,
+	/* 208 */   722,  722,  722,  778,  778,  778,  778,  584,
+	/* 216 */   722,  722,  722,  722,  722,  667,  611,  611,
+	/* 224 */   333,  556,  556,  556,  556,  222,  500,  500,
+	/* 232 */   500,  556,  556,  556,  556,  278,  278,  650,
+	/* 240 */   556,  556,  556,  556,  556,  556,  556,  584,
+	/* 248 */   333,  556,  556,  556,  556,  500,  278,  333,
+	},
+	{	/* Helvetica-BoldOblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   278,  333,  474,  556,  556,  889,  722,  238,
+	/*  40 */   333,  333,  389,  584,  278,  333,  278,  278,
+	/*  48 */   556,  556,  556,  556,  556,  556,  556,  556,
+	/*  56 */   556,  556,  333,  333,  584,  584,  584,  611,
+	/*  64 */   975,  722,  722,  722,  722,  667,  611,  778,
+	/*  72 */   722,  278,  556,  722,  611,  833,  722,  778,
+	/*  80 */   667,  778,  722,  667,  611,  722,  667,  944,
+	/*  88 */   667,  667,  611,  333,  278,  333,  584,  556,
+	/*  96 */   333,  556,  611,  556,  611,  556,  333,  611,
+	/* 104 */   611,  278,  278,  556,  278,  889,  611,  611,
+	/* 112 */   611,  611,  389,  556,  333,  611,  556,  778,
+	/* 120 */   556,  556,  500,  389,  280,  389,  584,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   278,  722,  333,  611,  556,  611,  667,  556,
+	/* 168 */   333,  667,  667,  611,  611,  333,  611,  611,
+	/* 176 */   333,  556,  333,  278,  333,  384,  556,  333,
+	/* 184 */   333,  556,  556,  404,  500,  333,  500,  500,
+	/* 192 */   722,  722,  722,  722,  722,  611,  722,  722,
+	/* 200 */   722,  667,  667,  667,  667,  278,  278,  722,
+	/* 208 */   722,  722,  722,  778,  778,  778,  778,  584,
+	/* 216 */   722,  722,  722,  722,  722,  667,  611,  611,
+	/* 224 */   389,  556,  556,  556,  556,  278,  556,  556,
+	/* 232 */   556,  556,  556,  556,  556,  278,  278,  722,
+	/* 240 */   611,  611,  611,  611,  611,  611,  611,  584,
+	/* 248 */   389,  611,  611,  611,  611,  556,  333,  333,
+	},
+	{	/* Palatino-Roman */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  278,  371,  500,  500,  840,  778,  208,
+	/*  40 */   333,  333,  389,  606,  250,  333,  250,  606,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  250,  250,  606,  606,  606,  444,
+	/*  64 */   747,  778,  611,  709,  774,  611,  556,  763,
+	/*  72 */   832,  337,  333,  726,  611,  946,  831,  786,
+	/*  80 */   604,  786,  668,  525,  613,  778,  722, 1000,
+	/*  88 */   667,  667,  667,  333,  606,  333,  606,  500,
+	/*  96 */   333,  500,  553,  444,  611,  479,  333,  556,
+	/* 104 */   582,  291,  234,  556,  291,  883,  582,  546,
+	/* 112 */   601,  560,  395,  424,  326,  603,  565,  834,
+	/* 120 */   516,  556,  500,  333,  606,  333,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   250,  778,  333,  611,  500,  611,  525,  500,
+	/* 168 */   333,  525,  525,  613,  667,  333,  667,  667,
+	/* 176 */   333,  500,  313,  291,  333,  375,  424,  333,
+	/* 184 */   333,  424,  424,  375,  500,  380,  500,  500,
+	/* 192 */   668,  778,  778,  778,  778,  611,  709,  709,
+	/* 200 */   709,  611,  611,  611,  611,  337,  337,  774,
+	/* 208 */   774,  831,  831,  786,  786,  786,  786,  606,
+	/* 216 */   668,  778,  778,  778,  778,  667,  613,  556,
+	/* 224 */   395,  500,  500,  500,  500,  291,  444,  444,
+	/* 232 */   444,  479,  479,  479,  479,  287,  287,  671,
+	/* 240 */   611,  582,  582,  546,  546,  546,  546,  606,
+	/* 248 */   395,  603,  603,  603,  603,  556,  326,  250,
+	},
+	{	/* Palatino-Bold */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  278,  402,  500,  500,  889,  833,  227,
+	/*  40 */   333,  333,  444,  606,  250,  333,  250,  296,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  250,  250,  606,  606,  606,  444,
+	/*  64 */   747,  778,  667,  722,  833,  611,  556,  833,
+	/*  72 */   833,  389,  389,  778,  611, 1000,  833,  833,
+	/*  80 */   611,  833,  722,  611,  667,  778,  778, 1000,
+	/*  88 */   667,  667,  667,  333,  606,  333,  606,  500,
+	/*  96 */   333,  500,  611,  444,  611,  500,  389,  556,
+	/* 104 */   611,  333,  333,  611,  333,  889,  611,  556,
+	/* 112 */   611,  611,  389,  444,  333,  611,  556,  833,
+	/* 120 */   500,  556,  500,  310,  606,  310,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   250,  778,  333,  611,  500,  611,  611,  500,
+	/* 168 */   333,  611,  611,  667,  667,  333,  667,  667,
+	/* 176 */   333,  500,  333,  333,  333,  433,  444,  333,
+	/* 184 */   333,  444,  444,  402,  500,  333,  500,  500,
+	/* 192 */   722,  778,  778,  778,  778,  611,  722,  722,
+	/* 200 */   722,  611,  611,  611,  611,  389,  389,  833,
+	/* 208 */   833,  833,  833,  833,  833,  833,  833,  606,
+	/* 216 */   722,  778,  778,  778,  778,  667,  667,  611,
+	/* 224 */   389,  500,  500,  500,  500,  333,  444,  444,
+	/* 232 */   444,  500,  500,  500,  500,  333,  333,  711,
+	/* 240 */   611,  611,  611,  556,  556,  556,  556,  606,
+	/* 248 */   389,  611,  611,  611,  611,  556,  333,  333,
+	},
+	{	/* Palatino-Italic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  333,  500,  500,  500,  889,  778,  333,
+	/*  40 */   333,  333,  389,  606,  250,  333,  250,  296,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  250,  250,  606,  606,  606,  500,
+	/*  64 */   747,  722,  611,  667,  778,  611,  556,  722,
+	/*  72 */   778,  333,  333,  667,  556,  944,  778,  778,
+	/*  80 */   611,  778,  667,  556,  611,  778,  722,  944,
+	/*  88 */   722,  667,  667,  333,  606,  333,  606,  500,
+	/*  96 */   333,  444,  463,  407,  500,  389,  278,  500,
+	/* 104 */   500,  278,  278,  444,  278,  778,  556,  444,
+	/* 112 */   500,  463,  389,  389,  333,  556,  500,  722,
+	/* 120 */   500,  500,  444,  333,  606,  333,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   250,  722,  333,  556,  500,  556,  556,  500,
+	/* 168 */   333,  556,  556,  611,  667,  333,  667,  667,
+	/* 176 */   333,  444,  333,  278,  333,  346,  389,  333,
+	/* 184 */   333,  389,  389,  361,  444,  333,  444,  444,
+	/* 192 */   667,  722,  722,  722,  722,  556,  667,  667,
+	/* 200 */   667,  611,  611,  611,  611,  333,  333,  778,
+	/* 208 */   778,  778,  778,  778,  778,  778,  778,  606,
+	/* 216 */   667,  778,  778,  778,  778,  667,  611,  500,
+	/* 224 */   389,  444,  444,  444,  444,  278,  407,  407,
+	/* 232 */   407,  389,  389,  389,  389,  278,  278,  577,
+	/* 240 */   500,  556,  556,  444,  444,  444,  444,  606,
+	/* 248 */   389,  556,  556,  556,  556,  500,  333,  333,
+	},
+	{	/* Palatino-BoldItalic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  333,  500,  500,  500,  889,  833,  250,
+	/*  40 */   333,  333,  444,  606,  250,  389,  250,  315,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  250,  250,  606,  606,  606,  444,
+	/*  64 */   833,  722,  667,  685,  778,  611,  556,  778,
+	/*  72 */   778,  389,  389,  722,  611,  944,  778,  833,
+	/*  80 */   667,  833,  722,  556,  611,  778,  667, 1000,
+	/*  88 */   722,  611,  667,  333,  606,  333,  606,  500,
+	/*  96 */   333,  556,  537,  444,  556,  444,  333,  500,
+	/* 104 */   556,  333,  333,  556,  333,  833,  556,  556,
+	/* 112 */   556,  537,  389,  444,  389,  556,  556,  833,
+	/* 120 */   500,  556,  500,  333,  606,  333,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   250,  722,  333,  611,  500,  611,  556,  556,
+	/* 168 */   333,  556,  556,  611,  667,  389,  667,  667,
+	/* 176 */   556,  556,  333,  333,  333,  429,  444,  333,
+	/* 184 */   333,  444,  444,  389,  500,  333,  500,  500,
+	/* 192 */   722,  722,  722,  722,  722,  611,  685,  685,
+	/* 200 */   685,  611,  611,  611,  611,  389,  389,  778,
+	/* 208 */   778,  778,  778,  833,  833,  833,  833,  606,
+	/* 216 */   722,  778,  778,  778,  778,  611,  611,  556,
+	/* 224 */   389,  556,  556,  556,  556,  333,  444,  444,
+	/* 232 */   444,  444,  444,  444,  444,  333,  333,  667,
+	/* 240 */   556,  556,  556,  556,  556,  556,  556,  606,
+	/* 248 */   389,  556,  556,  556,  556,  556,  389,  333,
+	},
+	{	/* Helvetica-Narrow */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   228,  228,  291,  456,  456,  729,  547,  157,
+	/*  40 */   273,  273,  319,  479,  228,  273,  228,  228,
+	/*  48 */   456,  456,  456,  456,  456,  456,  456,  456,
+	/*  56 */   456,  456,  228,  228,  479,  479,  479,  456,
+	/*  64 */   832,  547,  547,  592,  592,  547,  501,  638,
+	/*  72 */   592,  228,  410,  547,  456,  683,  592,  638,
+	/*  80 */   547,  638,  592,  547,  501,  592,  547,  774,
+	/*  88 */   547,  547,  501,  228,  228,  228,  385,  456,
+	/*  96 */   273,  456,  456,  410,  456,  456,  228,  456,
+	/* 104 */   456,  182,  182,  410,  182,  683,  456,  456,
+	/* 112 */   456,  456,  273,  410,  228,  456,  410,  592,
+	/* 120 */   410,  410,  410,  274,  213,  274,  479,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   228,  547,  273,  456,  456,  456,  547,  456,
+	/* 168 */   273,  547,  547,  501,  501,  273,  501,  501,
+	/* 176 */   273,  456,  273,  182,  273,  212,  410,  273,
+	/* 184 */   273,  410,  410,  248,  410,  273,  410,  410,
+	/* 192 */   592,  547,  547,  547,  547,  456,  592,  592,
+	/* 200 */   592,  547,  547,  547,  547,  228,  228,  592,
+	/* 208 */   592,  592,  592,  638,  638,  638,  638,  479,
+	/* 216 */   592,  592,  592,  592,  592,  547,  501,  501,
+	/* 224 */   273,  456,  456,  456,  456,  182,  410,  410,
+	/* 232 */   410,  456,  456,  456,  456,  228,  228,  496,
+	/* 240 */   456,  456,  456,  456,  456,  456,  456,  479,
+	/* 248 */   273,  456,  456,  456,  456,  410,  228,  273,
+	},
+	{	/* Helvetica-Narrow-Bold */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   228,  273,  389,  456,  456,  729,  592,  195,
+	/*  40 */   273,  273,  319,  479,  228,  273,  228,  228,
+	/*  48 */   456,  456,  456,  456,  456,  456,  456,  456,
+	/*  56 */   456,  456,  273,  273,  479,  479,  479,  501,
+	/*  64 */   800,  592,  592,  592,  592,  547,  501,  638,
+	/*  72 */   592,  228,  456,  592,  501,  683,  592,  638,
+	/*  80 */   547,  638,  592,  547,  501,  592,  547,  774,
+	/*  88 */   547,  547,  501,  273,  228,  273,  479,  456,
+	/*  96 */   273,  456,  501,  456,  501,  456,  273,  501,
+	/* 104 */   501,  228,  228,  456,  228,  729,  501,  501,
+	/* 112 */   501,  501,  319,  456,  273,  501,  456,  638,
+	/* 120 */   456,  456,  410,  319,  230,  319,  479,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   228,  592,  273,  501,  456,  501,  547,  456,
+	/* 168 */   273,  547,  547,  501,  501,  273,  501,  501,
+	/* 176 */   273,  456,  273,  228,  273,  280,  456,  273,
+	/* 184 */   273,  456,  456,  338,  410,  273,  410,  410,
+	/* 192 */   592,  592,  592,  592,  592,  501,  592,  592,
+	/* 200 */   592,  547,  547,  547,  547,  228,  228,  592,
+	/* 208 */   592,  592,  592,  638,  638,  638,  638,  479,
+	/* 216 */   592,  592,  592,  592,  592,  547,  501,  501,
+	/* 224 */   319,  456,  456,  456,  456,  228,  456,  456,
+	/* 232 */   456,  456,  456,  456,  456,  228,  228,  561,
+	/* 240 */   501,  501,  501,  501,  501,  501,  501,  479,
+	/* 248 */   319,  501,  501,  501,  501,  456,  273,  273,
+	},
+	{	/* Helvetica-Narrow-Oblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   228,  228,  291,  456,  456,  729,  547,  157,
+	/*  40 */   273,  273,  319,  479,  228,  273,  228,  228,
+	/*  48 */   456,  456,  456,  456,  456,  456,  456,  456,
+	/*  56 */   456,  456,  228,  228,  479,  479,  479,  456,
+	/*  64 */   832,  547,  547,  592,  592,  547,  501,  638,
+	/*  72 */   592,  228,  410,  547,  456,  683,  592,  638,
+	/*  80 */   547,  638,  592,  547,  501,  592,  547,  774,
+	/*  88 */   547,  547,  501,  228,  228,  228,  385,  456,
+	/*  96 */   273,  456,  456,  410,  456,  456,  228,  456,
+	/* 104 */   456,  182,  182,  410,  182,  683,  456,  456,
+	/* 112 */   456,  456,  273,  410,  228,  456,  410,  592,
+	/* 120 */   410,  410,  410,  274,  213,  274,  479,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   228,  547,  273,  456,  456,  456,  547,  456,
+	/* 168 */   273,  547,  547,  501,  501,  273,  501,  501,
+	/* 176 */   273,  456,  273,  182,  273,  217,  410,  273,
+	/* 184 */   273,  410,  410,  254,  410,  273,  410,  410,
+	/* 192 */   592,  547,  547,  547,  547,  456,  592,  592,
+	/* 200 */   592,  547,  547,  547,  547,  228,  228,  592,
+	/* 208 */   592,  592,  592,  638,  638,  638,  638,  479,
+	/* 216 */   592,  592,  592,  592,  592,  547,  501,  501,
+	/* 224 */   273,  456,  456,  456,  456,  182,  410,  410,
+	/* 232 */   410,  456,  456,  456,  456,  228,  228,  503,
+	/* 240 */   456,  456,  456,  456,  456,  456,  456,  479,
+	/* 248 */   273,  456,  456,  456,  456,  410,  228,  273,
+	},
+	{	/* Helvetica-Narrow-BoldOblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   228,  273,  389,  456,  456,  729,  592,  195,
+	/*  40 */   273,  273,  319,  479,  228,  273,  228,  228,
+	/*  48 */   456,  456,  456,  456,  456,  456,  456,  456,
+	/*  56 */   456,  456,  273,  273,  479,  479,  479,  501,
+	/*  64 */   800,  592,  592,  592,  592,  547,  501,  638,
+	/*  72 */   592,  228,  456,  592,  501,  683,  592,  638,
+	/*  80 */   547,  638,  592,  547,  501,  592,  547,  774,
+	/*  88 */   547,  547,  501,  273,  228,  273,  479,  456,
+	/*  96 */   273,  456,  501,  456,  501,  456,  273,  501,
+	/* 104 */   501,  228,  228,  456,  228,  729,  501,  501,
+	/* 112 */   501,  501,  319,  456,  273,  501,  456,  638,
+	/* 120 */   456,  456,  410,  319,  230,  319,  479,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   228,  592,  273,  501,  456,  501,  547,  456,
+	/* 168 */   273,  547,  547,  501,  501,  273,  501,  501,
+	/* 176 */   273,  456,  273,  228,  273,  283,  456,  273,
+	/* 184 */   273,  456,  456,  312,  410,  273,  410,  410,
+	/* 192 */   592,  592,  592,  592,  592,  501,  592,  592,
+	/* 200 */   592,  547,  547,  547,  547,  228,  228,  592,
+	/* 208 */   592,  592,  592,  638,  638,  638,  638,  479,
+	/* 216 */   592,  592,  592,  592,  592,  547,  501,  501,
+	/* 224 */   319,  456,  456,  456,  456,  228,  456,  456,
+	/* 232 */   456,  456,  456,  456,  456,  228,  228,  561,
+	/* 240 */   501,  501,  501,  501,  501,  501,  501,  479,
+	/* 248 */   319,  501,  501,  501,  501,  456,  273,  273,
+	},
+	{	/* Bookman-Light */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   320,  300,  380,  620,  620,  900,  800,  220,
+	/*  40 */   300,  300,  440,  600,  320,  400,  320,  600,
+	/*  48 */   620,  620,  620,  620,  620,  620,  620,  620,
+	/*  56 */   620,  620,  320,  320,  600,  600,  600,  540,
+	/*  64 */   820,  680,  740,  740,  800,  720,  640,  800,
+	/*  72 */   800,  340,  600,  720,  600,  920,  740,  800,
+	/*  80 */   620,  820,  720,  660,  620,  780,  700,  960,
+	/*  88 */   720,  640,  640,  300,  600,  300,  600,  500,
+	/*  96 */   340,  580,  620,  520,  620,  520,  320,  540,
+	/* 104 */   660,  300,  300,  620,  300,  940,  660,  560,
+	/* 112 */   620,  580,  440,  520,  380,  680,  520,  780,
+	/* 120 */   560,  540,  480,  280,  600,  280,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   320,  680,  460,  600,  620,  600,  660,  520,
+	/* 168 */   420,  660,  660,  620,  640,  400,  640,  640,
+	/* 176 */   320,  580,  320,  320,  340,  336,  520,  420,
+	/* 184 */   320,  520,  520,  380,  480,  380,  480,  480,
+	/* 192 */   720,  680,  680,  680,  680,  600,  740,  740,
+	/* 200 */   740,  720,  720,  720,  720,  340,  340,  800,
+	/* 208 */   800,  740,  740,  800,  800,  800,  800,  600,
+	/* 216 */   720,  780,  780,  780,  780,  640,  620,  660,
+	/* 224 */   440,  580,  580,  580,  580,  300,  520,  520,
+	/* 232 */   520,  520,  520,  520,  520,  300,  300,  620,
+	/* 240 */   620,  660,  660,  560,  560,  560,  560,  600,
+	/* 248 */   440,  680,  680,  680,  680,  540,  380,  260,
+	},
+	{	/* Bookman-Demi */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   340,  360,  420,  660,  660,  940,  800,  240,
+	/*  40 */   320,  320,  460,  600,  340,  360,  340,  600,
+	/*  48 */   660,  660,  660,  660,  660,  660,  660,  660,
+	/*  56 */   660,  660,  340,  340,  600,  600,  600,  660,
+	/*  64 */   820,  720,  720,  740,  780,  720,  680,  780,
+	/*  72 */   820,  400,  640,  800,  640,  940,  740,  800,
+	/*  80 */   660,  800,  780,  660,  700,  740,  720,  940,
+	/*  88 */   780,  700,  640,  300,  600,  300,  600,  500,
+	/*  96 */   400,  580,  600,  580,  640,  580,  380,  580,
+	/* 104 */   680,  360,  340,  660,  340, 1000,  680,  620,
+	/* 112 */   640,  620,  460,  520,  460,  660,  600,  800,
+	/* 120 */   600,  620,  560,  320,  600,  320,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   340,  720,  500,  640,  660,  640,  660,  600,
+	/* 168 */   500,  660,  660,  700,  640,  360,  640,  640,
+	/* 176 */   340,  580,  320,  340,  400,  430,  520,  500,
+	/* 184 */   360,  520,  520,  470,  560,  440,  560,  560,
+	/* 192 */   780,  720,  720,  720,  720,  640,  740,  740,
+	/* 200 */   740,  720,  720,  720,  720,  400,  400,  780,
+	/* 208 */   780,  740,  740,  800,  800,  800,  800,  600,
+	/* 216 */   780,  740,  740,  740,  740,  700,  700,  660,
+	/* 224 */   460,  580,  580,  580,  580,  340,  580,  580,
+	/* 232 */   580,  580,  580,  580,  580,  360,  360,  720,
+	/* 240 */   640,  680,  680,  620,  620,  620,  620,  600,
+	/* 248 */   460,  660,  660,  660,  660,  620,  460,  320,
+	},
+	{	/* Bookman-LightItalic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   300,  320,  360,  620,  620,  800,  820,  200,
+	/*  40 */   280,  280,  440,  600,  300,  320,  300,  600,
+	/*  48 */   620,  620,  620,  620,  620,  620,  620,  620,
+	/*  56 */   620,  620,  300,  300,  600,  600,  600,  540,
+	/*  64 */   780,  700,  720,  720,  740,  680,  620,  760,
+	/*  72 */   800,  320,  560,  720,  580,  860,  720,  760,
+	/*  80 */   600,  780,  700,  640,  600,  720,  680,  960,
+	/*  88 */   700,  660,  580,  260,  600,  260,  600,  500,
+	/*  96 */   340,  620,  600,  480,  640,  540,  340,  560,
+	/* 104 */   620,  280,  280,  600,  280,  880,  620,  540,
+	/* 112 */   600,  560,  400,  540,  340,  620,  540,  880,
+	/* 120 */   540,  600,  520,  360,  600,  380,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   300,  700,  440,  580,  620,  580,  640,  620,
+	/* 168 */   420,  640,  640,  600,  580,  320,  580,  580,
+	/* 176 */   300,  620,  260,  340,  320,  380,  540,  440,
+	/* 184 */   320,  540,  540,  340,  520,  340,  520,  520,
+	/* 192 */   700,  700,  700,  700,  700,  580,  720,  720,
+	/* 200 */   720,  680,  680,  680,  680,  320,  320,  740,
+	/* 208 */   740,  720,  720,  760,  760,  760,  760,  600,
+	/* 216 */   700,  720,  720,  720,  720,  660,  600,  620,
+	/* 224 */   400,  620,  620,  620,  620,  280,  480,  480,
+	/* 232 */   480,  540,  540,  540,  540,  280,  280,  730,
+	/* 240 */   640,  620,  620,  540,  540,  540,  540,  600,
+	/* 248 */   400,  620,  620,  620,  620,  600,  340,  260,
+	},
+	{	/* Bookman-DemiItalic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   340,  320,  380,  680,  680,  880,  980,  180,
+	/*  40 */   260,  260,  460,  600,  340,  280,  340,  360,
+	/*  48 */   680,  680,  680,  680,  680,  680,  680,  680,
+	/*  56 */   680,  680,  340,  340,  620,  600,  620,  620,
+	/*  64 */   780,  720,  720,  700,  760,  720,  660,  760,
+	/*  72 */   800,  380,  620,  780,  640,  860,  740,  760,
+	/*  80 */   640,  760,  740,  700,  700,  740,  660, 1000,
+	/*  88 */   740,  660,  680,  260,  580,  260,  620,  500,
+	/*  96 */   380,  680,  600,  560,  680,  560,  420,  620,
+	/* 104 */   700,  380,  320,  700,  380,  960,  680,  600,
+	/* 112 */   660,  620,  500,  540,  440,  680,  540,  860,
+	/* 120 */   620,  600,  560,  300,  620,  300,  620,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   340,  720,  460,  640,  680,  640,  700,  620,
+	/* 168 */   520,  700,  700,  700,  680,  280,  680,  680,
+	/* 176 */   360,  680,  320,  380,  340,  509,  540,  480,
+	/* 184 */   360,  540,  540,  520,  560,  560,  560,  560,
+	/* 192 */   740,  720,  720,  720,  720,  640,  700,  700,
+	/* 200 */   700,  720,  720,  720,  720,  380,  380,  760,
+	/* 208 */   760,  740,  740,  760,  760,  760,  760,  600,
+	/* 216 */   740,  740,  740,  740,  740,  660,  700,  660,
+	/* 224 */   500,  680,  680,  680,  680,  380,  560,  560,
+	/* 232 */   560,  560,  560,  560,  560,  380,  380,  810,
+	/* 240 */   680,  680,  680,  600,  600,  600,  600,  600,
+	/* 248 */   500,  680,  680,  680,  680,  600,  440,  380,
+	},
+	{	/* AvantGarde-Book */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   277,  295,  309,  554,  554,  775,  757,  198,
+	/*  40 */   369,  369,  425,  606,  277,  332,  277,  437,
+	/*  48 */   554,  554,  554,  554,  554,  554,  554,  554,
+	/*  56 */   554,  554,  277,  277,  606,  606,  606,  591,
+	/*  64 */   867,  740,  574,  813,  744,  536,  485,  872,
+	/*  72 */   683,  226,  482,  591,  462,  919,  740,  869,
+	/*  80 */   592,  871,  607,  498,  426,  655,  702,  960,
+	/*  88 */   609,  592,  480,  351,  605,  351,  606,  500,
+	/*  96 */   378,  683,  682,  647,  685,  650,  314,  673,
+	/* 104 */   610,  200,  203,  502,  200,  938,  610,  655,
+	/* 112 */   682,  682,  301,  388,  339,  608,  554,  831,
+	/* 120 */   480,  536,  425,  351,  672,  351,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   277,  740,  453,  517,  554,  462,  498,  615,
+	/* 168 */   369,  498,  498,  426,  480,  332,  480,  480,
+	/* 176 */   332,  683,  302,  300,  375,  245,  388,  502,
+	/* 184 */   324,  388,  388,  339,  425,  552,  425,  425,
+	/* 192 */   607,  740,  740,  740,  740,  462,  813,  813,
+	/* 200 */   813,  536,  536,  536,  536,  226,  226,  744,
+	/* 208 */   790,  740,  740,  869,  869,  869,  869,  606,
+	/* 216 */   607,  655,  655,  655,  655,  592,  426,  554,
+	/* 224 */   301,  683,  683,  683,  683,  200,  647,  647,
+	/* 232 */   647,  650,  650,  650,  650,  200,  200,  725,
+	/* 240 */   685,  610,  610,  655,  655,  655,  655,  606,
+	/* 248 */   301,  608,  608,  608,  608,  536,  339,  222,
+	},
+	{	/* AvantGarde-Demi */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   280,  280,  360,  560,  560,  860,  680,  220,
+	/*  40 */   380,  380,  440,  600,  280,  420,  280,  460,
+	/*  48 */   560,  560,  560,  560,  560,  560,  560,  560,
+	/*  56 */   560,  560,  280,  280,  600,  600,  600,  560,
+	/*  64 */   740,  740,  580,  780,  700,  520,  480,  840,
+	/*  72 */   680,  280,  480,  620,  440,  900,  740,  840,
+	/*  80 */   560,  840,  580,  520,  420,  640,  700,  900,
+	/*  88 */   680,  620,  500,  320,  640,  320,  600,  500,
+	/*  96 */   420,  660,  660,  640,  660,  640,  280,  660,
+	/* 104 */   600,  240,  260,  580,  240,  940,  600,  640,
+	/* 112 */   660,  660,  320,  440,  300,  600,  560,  800,
+	/* 120 */   560,  580,  460,  340,  600,  340,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   280,  740,  480,  480,  560,  440,  520,  560,
+	/* 168 */   500,  520,  520,  420,  500,  420,  500,  500,
+	/* 176 */   360,  660,  340,  320,  420,  330,  440,  540,
+	/* 184 */   340,  440,  440,  369,  460,  700,  460,  460,
+	/* 192 */   580,  740,  740,  740,  740,  440,  780,  780,
+	/* 200 */   780,  520,  520,  520,  520,  280,  280,  700,
+	/* 208 */   742,  740,  740,  840,  840,  840,  840,  600,
+	/* 216 */   580,  640,  640,  640,  640,  620,  420,  600,
+	/* 224 */   320,  660,  660,  660,  660,  240,  640,  640,
+	/* 232 */   640,  640,  640,  640,  640,  240,  240,  754,
+	/* 240 */   660,  600,  600,  640,  640,  640,  640,  600,
+	/* 248 */   320,  600,  600,  600,  600,  580,  300,  280,
+	},
+	{	/* AvantGarde-BookOblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   277,  295,  309,  554,  554,  775,  757,  198,
+	/*  40 */   369,  369,  425,  606,  277,  332,  277,  437,
+	/*  48 */   554,  554,  554,  554,  554,  554,  554,  554,
+	/*  56 */   554,  554,  277,  277,  606,  606,  606,  591,
+	/*  64 */   867,  740,  574,  813,  744,  536,  485,  872,
+	/*  72 */   683,  226,  482,  591,  462,  919,  740,  869,
+	/*  80 */   592,  871,  607,  498,  426,  655,  702,  960,
+	/*  88 */   609,  592,  480,  351,  605,  351,  606,  500,
+	/*  96 */   378,  683,  682,  647,  685,  650,  314,  673,
+	/* 104 */   610,  200,  203,  502,  200,  938,  610,  655,
+	/* 112 */   682,  682,  301,  388,  339,  608,  554,  831,
+	/* 120 */   480,  536,  425,  351,  672,  351,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   277,  740,  453,  517,  554,  462,  498,  615,
+	/* 168 */   369,  498,  498,  426,  480,  332,  480,  480,
+	/* 176 */   332,  683,  302,  300,  375,  231,  388,  502,
+	/* 184 */   324,  388,  388,  339,  425,  552,  425,  425,
+	/* 192 */   607,  740,  740,  740,  740,  462,  813,  813,
+	/* 200 */   813,  536,  536,  536,  536,  226,  226,  744,
+	/* 208 */   790,  740,  740,  869,  869,  869,  869,  606,
+	/* 216 */   607,  655,  655,  655,  655,  592,  426,  554,
+	/* 224 */   301,  683,  683,  683,  683,  200,  647,  647,
+	/* 232 */   647,  650,  650,  650,  650,  200,  200,  714,
+	/* 240 */   685,  610,  610,  655,  655,  655,  655,  606,
+	/* 248 */   301,  608,  608,  608,  608,  536,  339,  222,
+	},
+	{	/* AvantGarde-DemiOblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   280,  280,  360,  560,  560,  860,  680,  220,
+	/*  40 */   380,  380,  440,  600,  280,  420,  280,  460,
+	/*  48 */   560,  560,  560,  560,  560,  560,  560,  560,
+	/*  56 */   560,  560,  280,  280,  600,  600,  600,  560,
+	/*  64 */   740,  740,  580,  780,  700,  520,  480,  840,
+	/*  72 */   680,  280,  480,  620,  440,  900,  740,  840,
+	/*  80 */   560,  840,  580,  520,  420,  640,  700,  900,
+	/*  88 */   680,  620,  500,  320,  640,  320,  600,  500,
+	/*  96 */   420,  660,  660,  640,  660,  640,  280,  660,
+	/* 104 */   600,  240,  260,  580,  240,  940,  600,  640,
+	/* 112 */   660,  660,  320,  440,  300,  600,  560,  800,
+	/* 120 */   560,  580,  460,  340,  600,  340,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   280,  740,  480,  480,  560,  440,  520,  560,
+	/* 168 */   500,  520,  520,  420,  500,  420,  500,  500,
+	/* 176 */   360,  660,  340,  320,  420,  326,  440,  540,
+	/* 184 */   340,  440,  440,  364,  460,  700,  460,  460,
+	/* 192 */   580,  740,  740,  740,  740,  440,  780,  780,
+	/* 200 */   780,  520,  520,  520,  520,  280,  280,  700,
+	/* 208 */   742,  740,  740,  840,  840,  840,  840,  600,
+	/* 216 */   580,  640,  640,  640,  640,  620,  420,  600,
+	/* 224 */   320,  660,  660,  660,  660,  240,  640,  640,
+	/* 232 */   640,  640,  640,  640,  640,  240,  240,  752,
+	/* 240 */   660,  600,  600,  640,  640,  640,  640,  600,
+	/* 248 */   320,  600,  600,  600,  600,  580,  300,  280,
+	},
+	{	/* NewCenturySchlbk-Roman */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   278,  296,  389,  556,  556,  833,  815,  204,
+	/*  40 */   333,  333,  500,  606,  278,  333,  278,  278,
+	/*  48 */   556,  556,  556,  556,  556,  556,  556,  556,
+	/*  56 */   556,  556,  278,  278,  606,  606,  606,  444,
+	/*  64 */   737,  722,  722,  722,  778,  722,  667,  778,
+	/*  72 */   833,  407,  556,  778,  667,  944,  815,  778,
+	/*  80 */   667,  778,  722,  630,  667,  815,  722,  981,
+	/*  88 */   704,  704,  611,  333,  606,  333,  606,  500,
+	/*  96 */   333,  556,  556,  444,  574,  500,  333,  537,
+	/* 104 */   611,  315,  296,  593,  315,  889,  611,  500,
+	/* 112 */   574,  556,  444,  463,  389,  611,  537,  778,
+	/* 120 */   537,  537,  481,  333,  606,  333,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   278,  722,  333,  667,  556,  667,  630,  500,
+	/* 168 */   333,  630,  630,  667,  611,  333,  611,  611,
+	/* 176 */   333,  556,  333,  315,  333,  339,  463,  333,
+	/* 184 */   333,  463,  463,  389,  481,  333,  481,  481,
+	/* 192 */   722,  722,  722,  722,  722,  667,  722,  722,
+	/* 200 */   722,  722,  722,  722,  722,  407,  407,  778,
+	/* 208 */   778,  815,  815,  778,  778,  778,  778,  606,
+	/* 216 */   722,  815,  815,  815,  815,  704,  667,  574,
+	/* 224 */   444,  556,  556,  556,  556,  315,  444,  444,
+	/* 232 */   444,  500,  500,  500,  500,  315,  315,  606,
+	/* 240 */   574,  611,  611,  500,  500,  500,  500,  606,
+	/* 248 */   444,  611,  611,  611,  611,  537,  389,  333,
+	},
+	{	/* NewCenturySchlbk-Bold */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   287,  296,  333,  574,  574,  833,  852,  241,
+	/*  40 */   389,  389,  500,  606,  278,  333,  278,  278,
+	/*  48 */   574,  574,  574,  574,  574,  574,  574,  574,
+	/*  56 */   574,  574,  278,  278,  606,  606,  606,  500,
+	/*  64 */   747,  759,  778,  778,  833,  759,  722,  833,
+	/*  72 */   870,  444,  648,  815,  722,  981,  833,  833,
+	/*  80 */   759,  833,  815,  667,  722,  833,  759,  981,
+	/*  88 */   722,  722,  667,  389,  606,  389,  606,  500,
+	/*  96 */   333,  611,  648,  556,  667,  574,  389,  611,
+	/* 104 */   685,  370,  352,  667,  352,  963,  685,  611,
+	/* 112 */   667,  648,  519,  500,  426,  685,  611,  889,
+	/* 120 */   611,  611,  537,  389,  606,  389,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   287,  759,  333,  722,  574,  722,  667,  500,
+	/* 168 */   333,  667,  667,  722,  667,  333,  667,  667,
+	/* 176 */   333,  611,  333,  352,  333,  436,  500,  333,
+	/* 184 */   333,  500,  500,  446,  537,  333,  537,  537,
+	/* 192 */   815,  759,  759,  759,  759,  722,  778,  778,
+	/* 200 */   778,  759,  759,  759,  759,  444,  444,  833,
+	/* 208 */   833,  833,  833,  833,  833,  833,  833,  606,
+	/* 216 */   815,  833,  833,  833,  833,  722,  722,  611,
+	/* 224 */   519,  611,  611,  611,  611,  352,  556,  556,
+	/* 232 */   556,  574,  574,  574,  574,  370,  370,  747,
+	/* 240 */   667,  685,  685,  611,  611,  611,  611,  606,
+	/* 248 */   519,  685,  685,  685,  685,  611,  426,  333,
+	},
+	{	/* NewCenturySchlbk-Italic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   278,  333,  400,  556,  556,  833,  852,  278,
+	/*  40 */   333,  333,  500,  606,  278,  333,  278,  606,
+	/*  48 */   556,  556,  556,  556,  556,  556,  556,  556,
+	/*  56 */   556,  556,  278,  278,  606,  606,  606,  444,
+	/*  64 */   747,  704,  722,  722,  778,  722,  667,  778,
+	/*  72 */   833,  407,  611,  741,  667,  944,  815,  778,
+	/*  80 */   667,  778,  741,  667,  685,  815,  704,  926,
+	/*  88 */   704,  685,  667,  333,  606,  333,  606,  500,
+	/*  96 */   333,  574,  556,  444,  611,  444,  333,  537,
+	/* 104 */   611,  333,  315,  556,  333,  889,  611,  500,
+	/* 112 */   574,  556,  444,  444,  352,  611,  519,  778,
+	/* 120 */   500,  500,  463,  333,  606,  333,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   278,  704,  333,  667,  556,  667,  667,  500,
+	/* 168 */   333,  667,  667,  685,  667,  333,  667,  667,
+	/* 176 */   333,  574,  333,  333,  333,  359,  444,  333,
+	/* 184 */   333,  444,  444,  368,  463,  333,  463,  463,
+	/* 192 */   741,  704,  704,  704,  704,  667,  722,  722,
+	/* 200 */   722,  722,  722,  722,  722,  407,  407,  778,
+	/* 208 */   778,  815,  815,  778,  778,  778,  778,  606,
+	/* 216 */   741,  815,  815,  815,  815,  685,  685,  556,
+	/* 224 */   444,  574,  574,  574,  574,  333,  444,  444,
+	/* 232 */   444,  444,  444,  444,  444,  333,  333,  651,
+	/* 240 */   611,  611,  611,  500,  500,  500,  500,  606,
+	/* 248 */   444,  611,  611,  611,  611,  500,  352,  333,
+	},
+	{	/* NewCenturySchlbk-BoldItalic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   287,  333,  400,  574,  574,  889,  889,  287,
+	/*  40 */   407,  407,  500,  606,  287,  333,  287,  278,
+	/*  48 */   574,  574,  574,  574,  574,  574,  574,  574,
+	/*  56 */   574,  574,  287,  287,  606,  606,  606,  481,
+	/*  64 */   747,  741,  759,  759,  833,  741,  704,  815,
+	/*  72 */   870,  444,  667,  778,  704,  944,  852,  833,
+	/*  80 */   741,  833,  796,  685,  722,  833,  741,  944,
+	/*  88 */   741,  704,  704,  407,  606,  407,  606,  500,
+	/*  96 */   333,  667,  611,  537,  667,  519,  389,  611,
+	/* 104 */   685,  389,  370,  648,  389,  944,  685,  574,
+	/* 112 */   648,  630,  519,  481,  407,  685,  556,  833,
+	/* 120 */   574,  519,  519,  407,  606,  407,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   287,  741,  333,  704,  574,  704,  685,  500,
+	/* 168 */   333,  685,  685,  722,  704,  333,  704,  704,
+	/* 176 */   333,  667,  333,  389,  333,  486,  481,  333,
+	/* 184 */   333,  481,  481,  483,  519,  333,  519,  519,
+	/* 192 */   796,  741,  741,  741,  741,  704,  759,  759,
+	/* 200 */   759,  741,  741,  741,  741,  444,  444,  833,
+	/* 208 */   833,  852,  852,  833,  833,  833,  833,  606,
+	/* 216 */   796,  833,  833,  833,  833,  704,  722,  574,
+	/* 224 */   519,  667,  667,  667,  667,  389,  537,  537,
+	/* 232 */   537,  519,  519,  519,  519,  389,  389,  780,
+	/* 240 */   667,  685,  685,  574,  574,  574,  574,  606,
+	/* 248 */   519,  685,  685,  685,  685,  519,  407,  333,
+	},
+};
+#if 0 /* Until this array is needed */
+static int aiUnderlineInfo[32][2] = {
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -151, 50 },
+	{ -155, 69 },
+	{ -151, 50 },
+	{ -111, 69 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -125, 60 },
+	{ -125, 60 },
+	{ -125, 60 },
+	{ -125, 60 },
+	{ -96, 58 },
+	{ -93, 90 },
+	{ -96, 58 },
+	{ -93, 90 },
+	{ -104, 61 },
+	{ -103, 90 },
+	{ -102, 42 },
+	{ -102, 54 },
+};
+#endif /* 0 */
diff --git a/Unix-only/fontinfo.pl b/Unix-only/fontinfo.pl
new file mode 100755
index 0000000..d117c8d
--- /dev/null
+++ b/Unix-only/fontinfo.pl
@@ -0,0 +1,207 @@
+#! /usr/bin/perl -w
+#
+# Generate the fontinformation tables for the required fonts (Linux version)
+#
+
+@charnames1 = (
+"ellipsis", "trademark", "perthousand", "bullet",
+"quoteleft", "quoteright", "guilsinglleft", "guilsinglright",
+"quotedblleft", "quotedblright", "quotedblbase", "endash", "emdash",
+"minus", "OE", "oe", "dagger", "daggerdbl", "fi", "fl",
+"space", "exclamdown", "cent", "sterling", "currency",
+"yen", "brokenbar", "section", "dieresis", "copyright",
+"ordfeminine", "guillemotleft", "logicalnot", "hyphen", "registered",
+"macron", "degree", "plusminus", "twosuperior", "threesuperior",
+"acute", "mu", "paragraph", "periodcentered", "cedilla",
+"onesuperior", "ordmasculine", "guillemotright", "onequarter",
+"onehalf", "threequarters", "questiondown", "Agrave", "Aacute",
+"Acircumflex", "Atilde", "Adieresis", "Aring", "AE", "Ccedilla",
+"Egrave", "Eacute", "Ecircumflex", "Edieresis", "Igrave", "Iacute",
+"Icircumflex", "Idieresis", "Eth", "Ntilde", "Ograve", "Oacute",
+"Ocircumflex", "Otilde", "Odieresis", "multiply", "Oslash",
+"Ugrave", "Uacute", "Ucircumflex", "Udieresis", "Yacute", "Thorn",
+"germandbls", "agrave", "aacute", "acircumflex", "atilde",
+"adieresis", "aring", "ae", "ccedilla", "egrave", "eacute",
+"ecircumflex", "edieresis", "igrave", "iacute", "icircumflex",
+"idieresis", "eth", "ntilde", "ograve", "oacute", "ocircumflex",
+"otilde", "odieresis", "divide", "oslash", "ugrave", "uacute",
+"ucircumflex", "udieresis", "yacute", "thorn", "ydieresis"
+);
+
+@charnames2 = (
+"space", "Aogonek", "breve", "Lslash", "currency", "Lcaron",
+"Sacute", "section", "dieresis", "Scaron", "Scedilla",
+"Tcaron", "Zacute", "hyphen", "Zcaron", "Zdotaccent", "ring",
+"aogonek", "ogonek", "lslash", "acute", "lcaron", "sacute",
+"caron", "cedilla", "scaron", "scedilla", "tcaron",
+"zacute", "hungarumlaut", "zcaron", "zdotaccent", "Racute",
+"Aacute", "Acircumflex", "Abreve", "Adieresis", "Lacute",
+"Cacute", "Ccedilla", "Ccaron", "Eacute", "Eogonek",
+"Edieresis", "Ecaron", "Iacute", "Icircumflex", "Dcaron",
+"Dslash", "Nacute", "Ncaron", "Oacute", "Ocircumflex",
+"Ohungarumlaut", "Odieresis", "multiply", "Rcaron", "Uring",
+"Uacute", "Uhungarumlaut", "Udieresis", "Yacute", "Tcommaaccent",
+"germandbls", "racute", "aacute", "acircumflex", "abreve",
+"adieresis", "lacute", "cacute", "ccedilla", "ccaron", "eacute",
+"eogonek", "edieresis", "ecaron", "iacute", "icircumflex",
+"dcaron", "dmacron", "nacute", "ncaron", "oacute", "ocircumflex",
+"ohungarumlaut", "odieresis", "divide", "rcaron", "uring",
+"uacute", "uhungarumlaut", "udieresis", "yacute", "tcommaaccent",
+"dotaccent"
+);
+
+$gs_dir1 = '/usr/share/ghostscript/fonts';
+$gs_dir2 = '/usr/share/ghostscript/fonts2';
+
+@fontnames = (
+"Courier", "Courier-Bold", "Courier-Oblique", "Courier-BoldOblique",
+"Times-Roman", "Times-Bold", "Times-Italic", "Times-BoldItalic",
+"Helvetica", "Helvetica-Bold", "Helvetica-Oblique", "Helvetica-BoldOblique",
+"Palatino-Roman", "Palatino-Bold", "Palatino-Italic", "Palatino-BoldItalic",
+"Helvetica-Narrow", "Helvetica-Narrow-Bold", "Helvetica-Narrow-Oblique", "Helvetica-Narrow-BoldOblique",
+"Bookman-Light", "Bookman-Demi", "Bookman-LightItalic", "Bookman-DemiItalic",
+"AvantGarde-Book", "AvantGarde-Demi", "AvantGarde-BookOblique", "AvantGarde-DemiOblique",
+"NewCenturySchlbk-Roman", "NewCenturySchlbk-Bold", "NewCenturySchlbk-Italic", "NewCenturySchlbk-BoldItalic",
+);
+
+@files = (
+"n022003l.afm", "n022004l.afm", "n022023l.afm", "n022024l.afm",
+"n021003l.afm", "n021004l.afm", "n021023l.afm", "n021024l.afm",
+"n019003l.afm", "n019004l.afm", "n019023l.afm", "n019024l.afm",
+"p052003l.afm", "p052004l.afm", "p052023l.afm", "p052024l.afm",
+"n019043l.afm", "n019044l.afm", "n019063l.afm", "n019064l.afm",
+"b018012l.afm", "b018015l.afm", "b018032l.afm", "b018035l.afm",
+"a010013l.afm", "a010015l.afm", "a010033l.afm", "a010035l.afm",
+"c059013l.afm", "c059016l.afm", "c059033l.afm", "c059036l.afm",
+);
+
+
+# Generate the array with the fontnames
+sub generate_fontnames
+{
+	printf STDOUT "static const char *szFontnames[%d] = {\n", $#fontnames + 1;
+	for ($n = 0; $n <= $#fontnames; $n++) {
+		printf STDOUT "\t\"%s\",\n", $fontnames[$n];
+	}
+	printf STDOUT "};\n";
+}
+
+# Generate the array with the character widths
+sub generate_character_widths
+{
+	my ($char_set, $gs_dir, @charnames) = @_;
+	my ($n, $i, $file, $name, $start);
+	my (@a, @charwidth);
+
+	if ($char_set == 1) {
+		$start = 140;
+	} else {
+		$start = 160;
+	}
+	printf STDOUT "static unsigned short ausCharacterWidths%d[%d][256] = {\n", $char_set, $#files + 1;
+	for ($n = 0; $n <= $#files; $n++) {
+		$file = $files[$n];
+		$name = $fontnames[$n];
+		open(F_IN, "<$gs_dir/$file") || die "Cannot open $gs_dir/$file";
+		printf STDOUT "\t{\t/* %s */\n", $name;
+		while (<F_IN>) {
+			chop();
+			@a = split(/\s+/);
+			if ($a[0] eq 'UnderlinePosition') {
+				$underlineposition[$n] = $a[1];
+			} elsif ($a[0] eq 'UnderlineThickness') {
+				#printf STDERR "%d %d\n", $a[0], $a[1];
+				$underlinethickness[$n] = $a[1];
+			} elsif ($a[0] eq 'C' && $a[2] eq ';' && $a[3] eq 'WX') {
+				#printf STDERR "%d %d %s\n", $a[1], $a[4], $a[7];
+				if (($a[1] < 0 || $a[1] >= 129) && defined($a[7])) {
+					for ($i = 0; $i <= $#charnames; $i++) {
+						if ($charnames[$i] eq $a[7]) {
+							$charwidth[$start + $i] = $a[4];
+							last;
+						}
+					}
+				}
+				if ($a[1] >= 0 && $a[1] <= 128 && !defined($charwidth[$a[1]])) {
+					$charwidth[$a[1]] = $a[4];
+				}
+			}
+			if (defined($a[7])) {
+				for ($i = 0; $i <= $#charnames; $i++) {
+					if ($charnames[$i] eq $a[7]) {
+						$charwidth[$start + $i] = $a[4];
+						last;
+					}
+				}
+			}
+		}
+		close(F_IN);
+
+		# Set the width of the control characters zero
+		for ($i = 0; $i < 32; $i++) {
+			$charwidth[$i] = 0;
+		}
+		# Set the width of the unused characters to zero
+		for ($i = 127; $i < $start; $i++) {
+			$charwidth[$i] = 0;
+		}
+
+		# Print the results
+		for ($i = 0; $i < 256; $i += 8) {
+			printf STDOUT "\t/* %3d */ ", $i;
+			for ($j = 0; $j < 8; $j++) {
+				if (!defined($charwidth[$i + $j])) {
+					printf STDERR "%d:%s: character %3d is undefined\n", $char_set, $name, $i + $j;
+					$charwidth[$i + $j] = 0;
+				}
+				printf STDOUT "%5d,", $charwidth[$i + $j];
+			}
+			printf STDOUT "\n";
+		}
+		printf STDOUT "\t},\n";
+		undef @charwidth;
+	}
+	printf STDOUT "};\n";
+}
+
+# Generate the array with the underline information
+sub generate_underline_information
+{
+	printf STDOUT "#if 0 /* Until this array is needed */\n";
+
+	printf STDOUT "static int aiUnderlineInfo[%d][2] = {\n", $#fontnames + 1;
+	for ($n = 0; $n <= $#fontnames; $n++) {
+		if (!defined($underlineposition[$n])) {
+			$underlineposition[$n] = 0;
+		}
+		if (!defined($underlinethickness[$n])) {
+			$underlinethickness[$n] = 0;
+		}
+		printf STDOUT "\t{ %d, %d },\n", $underlineposition[$n], $underlinethickness[$n];
+	}
+	printf STDOUT "};\n";
+
+	printf STDOUT "#endif /* 0 */\n";
+}
+
+
+# main()
+
+if ($#fontnames != $#files) {
+	die "The fontnames-array and the files-array are of unequel length";
+}
+if ($#charnames1 != 255 - 140) {
+	die "The charname1 table length is $#charnames1";
+}
+if ($#charnames2 != 255 - 160) {
+	die "The charname2 table length is $#charnames2";
+}
+
+printf STDOUT "/* THIS FILE IS AUTOMATICALLY GENERATED - DO NOT EDIT! */\n";
+
+&generate_fontnames();
+&generate_character_widths(1, $gs_dir1, @charnames1);
+&generate_character_widths(2, $gs_dir2, @charnames2);
+&generate_underline_information();
+
+exit 0;
diff --git a/antiword.h b/antiword.h
new file mode 100644
index 0000000..3f4aad5
--- /dev/null
+++ b/antiword.h
@@ -0,0 +1,735 @@
+/*
+ * antiword.h
+ * Copyright (C) 1998-2004 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Generic include file for project 'Antiword'
+ */
+
+#if !defined(__antiword_h)
+#define __antiword_h 1
+
+#if defined(DEBUG) == defined(NDEBUG)
+#error Exactly one of the DEBUG and NDEBUG flags MUST be set
+#endif /* DEBUG == NDEBUG */
+
+#include <stdio.h>
+#include <limits.h>
+#if defined(__riscos)
+#include "DeskLib:Font.h"
+#include "DeskLib:Wimp.h"
+#include "Desklib:Window.h"
+#include "drawfile.h"
+#define window_ANY	event_ANY
+#define icon_ANY	event_ANY
+#else
+#include <sys/types.h>
+#endif /* __riscos */
+#include "wordconst.h"
+#include "wordtypes.h"
+#include "fail.h"
+#include "debug.h"
+
+/* Constants */
+#if !defined(PATH_MAX)
+ #if defined(__riscos)
+ #define PATH_MAX		 255
+ #else
+  #if defined(MAXPATHLEN)
+  #define PATH_MAX		MAXPATHLEN
+  #else
+  #define PATH_MAX		1024
+  #endif /* MAXPATHLEN */
+ #endif /* __riscos */
+#endif /* !PATH_MAX */
+
+#if !defined(CHAR_BIT)
+#define CHAR_BIT		8
+#endif /* CHAR_BIT */
+
+#if !defined(TIME_T_MIN)
+#define TIME_T_MIN		((time_t)0 < (time_t)-1 ?\
+				(time_t)0 :\
+				(time_t)1 << (sizeof(time_t) * CHAR_BIT - 1))
+#endif /* TIMER_T_MIN */
+
+#if !defined(TIME_T_MAX)
+#if defined(__TURBOC__)	/* Turbo C chokes on the subtraction below */
+#define TIME_T_MAX		(LONG_MAX)
+#else	/* All others */
+#define TIME_T_MAX		(~(time_t)0 - TIME_T_MIN)
+#endif /* __TURBOC__ */
+#endif /* TIME_T_MAX */
+
+#if !defined(SIZE_T_MAX)
+#define SIZE_T_MAX		(~(size_t)0)
+#endif /* SIZE_T_MAX */
+
+#if defined(__riscos)
+#define FILE_SEPARATOR		"."
+#elif defined(__dos) || defined(__CYGMING__)
+#define FILE_SEPARATOR		"\\"
+#else	/* All others */
+#define FILE_SEPARATOR		"/"
+#endif /* __riscos */
+
+/* PNG chunk names */
+#define PNG_CN_IDAT		0x49444154
+#define PNG_CN_IEND		0x49454e44
+#define PNG_CN_IHDR		0x49484452
+#define PNG_CN_PLTE		0x504c5445
+
+/* The screen width */
+#define MIN_SCREEN_WIDTH	 45
+#define DEFAULT_SCREEN_WIDTH	 76
+#define MAX_SCREEN_WIDTH	145
+
+#if defined(__riscos)
+/* The scale factors as percentages */
+#define MIN_SCALE_FACTOR	 25
+#define DEFAULT_SCALE_FACTOR	100
+#define MAX_SCALE_FACTOR	400
+
+/* Filetypes */
+#define FILETYPE_MSWORD		0xae6
+#define FILETYPE_DRAW		0xaff
+#define FILETYPE_JPEG		0xc85
+#define FILETYPE_POSCRIPT	0xff5
+#define FILETYPE_SPRITE		0xff9
+#define FILETYPE_TEXT		0xfff
+
+/* The button numbers in the choices window */
+#define CHOICES_DEFAULT_BUTTON		 3
+#define CHOICES_SAVE_BUTTON		 2
+#define CHOICES_CANCEL_BUTTON		 1
+#define CHOICES_APPLY_BUTTON		 0
+#define CHOICES_BREAK_BUTTON		 6
+#define CHOICES_BREAK_WRITEABLE		 7
+#define CHOICES_BREAK_UP_BUTTON		 8
+#define CHOICES_BREAK_DOWN_BUTTON	 9
+#define CHOICES_NO_BREAK_BUTTON		11
+#define CHOICES_AUTOFILETYPE_BUTTON	14
+#define CHOICES_HIDDEN_TEXT_BUTTON	22
+#define CHOICES_WITH_IMAGES_BUTTON	17
+#define CHOICES_NO_IMAGES_BUTTON	18
+#define CHOICES_TEXTONLY_BUTTON		19
+#define CHOICES_SCALE_WRITEABLE		25
+#define CHOICES_SCALE_UP_BUTTON		26
+#define CHOICES_SCALE_DOWN_BUTTON	27
+
+/* The button numbers in the scale view window */
+#define SCALE_CANCEL_BUTTON		 1
+#define SCALE_SCALE_BUTTON		 0
+#define SCALE_SCALE_WRITEABLE		 3
+#define SCALE_50_PCT			 5
+#define SCALE_75_PCT			 6
+#define SCALE_100_PCT			 7
+#define SCALE_150_PCT			 8
+
+/* Save menu fields */
+#define SAVEMENU_SCALEVIEW		0
+#define SAVEMENU_SAVEDRAW		1
+#define SAVEMENU_SAVETEXT		2
+#else
+/* Margins for the PostScript version */
+#define PS_LEFT_MARGIN			(72 * 640L)
+#define PS_RIGHT_MARGIN			(48 * 640L)
+#define PS_TOP_MARGIN			(72 * 640L)
+#define PS_BOTTOM_MARGIN		(72 * 640L)
+#endif /* __riscos */
+
+/* Macros */
+#define STREQ(x,y)	(*(x) == *(y) && strcmp(x,y) == 0)
+#define STRNEQ(x,y,n)	(*(x) == *(y) && strncmp(x,y,n) == 0)
+#if defined(__dos) || defined(__EMX__)
+#define STRCEQ(x,y)	(stricmp(x,y) == 0)
+#else
+#define STRCEQ(x,y)	(strcasecmp(x,y) == 0)
+#endif /* __dos or __EMX__ */
+#define elementsof(a)	(sizeof(a) / sizeof(a[0]))
+#define odd(x)		(((x)&0x01)!=0)
+#define ROUND4(x)	(((x)+3)&~0x03)
+#define ROUND128(x)	(((x)+127)&~0x7f)
+#define BIT(x)		(1UL << (x))
+#if !defined(max)
+#define max(x,y)	((x)>(y)?(x):(y))
+#endif /* !max */
+#if !defined(min)
+#define min(x,y)	((x)<(y)?(x):(y))
+#endif /* !min */
+
+#if defined(__riscos)
+/* The name of the table font */
+#define TABLE_FONT			"Corpus.Medium"
+/* Names of the default fonts */
+#define FONT_MONOSPACED_PLAIN		"Corpus.Medium"
+#define FONT_MONOSPACED_BOLD		"Corpus.Bold"
+#define FONT_MONOSPACED_ITALIC		"Corpus.Medium.Oblique"
+#define FONT_MONOSPACED_BOLDITALIC	"Corpus.Bold.Oblique"
+#define FONT_SERIF_PLAIN		"Trinity.Medium"
+#define FONT_SERIF_BOLD			"Trinity.Bold"
+#define FONT_SERIF_ITALIC		"Trinity.Medium.Italic"
+#define FONT_SERIF_BOLDITALIC		"Trinity.Bold.Italic"
+#define FONT_SANS_SERIF_PLAIN		"Homerton.Medium"
+#define FONT_SANS_SERIF_BOLD		"Homerton.Bold"
+#define FONT_SANS_SERIF_ITALIC		"Homerton.Medium.Oblique"
+#define FONT_SANS_SERIF_BOLDITALIC	"Homerton.Bold.Oblique"
+#else
+/* The name of the table font */
+#define TABLE_FONT			"Courier"
+/* Names of the default fonts */
+#define FONT_MONOSPACED_PLAIN		"Courier"
+#define FONT_MONOSPACED_BOLD		"Courier-Bold"
+#define FONT_MONOSPACED_ITALIC		"Courier-Oblique"
+#define FONT_MONOSPACED_BOLDITALIC	"Courier-BoldOblique"
+#define FONT_SERIF_PLAIN		"Times-Roman"
+#define FONT_SERIF_BOLD			"Times-Bold"
+#define FONT_SERIF_ITALIC		"Times-Italic"
+#define FONT_SERIF_BOLDITALIC		"Times-BoldItalic"
+#define FONT_SANS_SERIF_PLAIN		"Helvetica"
+#define FONT_SANS_SERIF_BOLD		"Helvetica-Bold"
+#define FONT_SANS_SERIF_ITALIC		"Helvetica-Oblique"
+#define FONT_SANS_SERIF_BOLDITALIC	"Helvetica-BoldOblique"
+/* The name of the antiword directories and the font information file */
+#if defined(__dos)
+#define GLOBAL_ANTIWORD_DIR	"C:\\antiword"
+#define ANTIWORD_DIR		"antiword"
+#define FONTNAMES_FILE		"fontname.txt"
+#elif defined(__amigaos)
+#define GLOBAL_ANTIWORD_DIR	"SYS:.antiword"
+#define ANTIWORD_DIR		".antiword"
+#define FONTNAMES_FILE		"fontnames"
+#elif defined(N_PLAT_NLM)
+#define GLOBAL_ANTIWORD_DIR	"SYS:/antiword"
+#define ANTIWORD_DIR		"antiword"
+#define FONTNAMES_FILE		"fontname.txt"
+#elif defined(__vms)
+#define GLOBAL_ANTIWORD_DIR	"/usr/share/antiword"
+#define ANTIWORD_DIR		"antiword"
+#define FONTNAMES_FILE		"fontnames"
+#elif defined(__BEOS__)
+#define GLOBAL_ANTIWORD_DIR	"/boot/home/config/apps/antiword"
+#define ANTIWORD_DIR		"antiword"
+#define FONTNAMES_FILE		"fontnames"
+#elif defined(__CYGMING__)
+#define GLOBAL_ANTIWORD_DIR	"C:\\antiword"
+#define ANTIWORD_DIR		"antiword"
+#define FONTNAMES_FILE		"fontnames"
+#elif defined(__Plan9__)
+#define GLOBAL_ANTIWORD_DIR	"/sys/lib/antiword"
+#define ANTIWORD_DIR		"lib/antiword"
+#define FONTNAMES_FILE		"fontnames"
+#elif defined(__sun__)
+#define GLOBAL_ANTIWORD_DIR	"/usr/local/share/antiword"
+#define ANTIWORD_DIR		".antiword"
+#define FONTNAMES_FILE		"fontnames"
+#else	/* All others */
+#define GLOBAL_ANTIWORD_DIR	"/usr/share/antiword"
+#define ANTIWORD_DIR		".antiword"
+#define FONTNAMES_FILE		"fontnames"
+#endif /* __dos */
+/* The names of grouped mapping files */
+	/* ASCII */
+#define MAPPING_FILE_CP437	"cp437.txt"
+	/* Latin1 */
+#define MAPPING_FILE_8859_1	"8859-1.txt"
+	/* Latin2 */
+#define MAPPING_FILE_8859_2	"8859-2.txt"
+#define MAPPING_FILE_CP852	"cp852.txt"
+#define MAPPING_FILE_CP1250	"cp1250.txt"
+	/* Cyrillic */
+#define MAPPING_FILE_8859_5	"8859-5.txt"
+#define MAPPING_FILE_KOI8_R	"koi8-r.txt"
+#define MAPPING_FILE_KOI8_U	"koi8-u.txt"
+#define MAPPING_FILE_CP866	"cp866.txt"
+#define MAPPING_FILE_CP1251	"cp1251.txt"
+	/* Latin9 */
+#define MAPPING_FILE_8859_15	"8859-15.txt"
+	/* UTF-8 */
+#define MAPPING_FILE_UTF_8	"UTF-8.txt"
+#endif /* __riscos */
+
+/* Prototypes */
+
+/* asc85enc.c */
+extern void	vASCII85EncodeByte(FILE *, int);
+extern void	vASCII85EncodeArray(FILE *, FILE *, size_t);
+extern void	vASCII85EncodeFile(FILE *, FILE *, size_t);
+/* blocklist.c */
+extern void	vDestroyTextBlockList(void);
+extern BOOL	bAdd2TextBlockList(const text_block_type *);
+extern void	vSplitBlockList(FILE *, ULONG, ULONG, ULONG, ULONG, ULONG,
+			ULONG, ULONG, ULONG, BOOL);
+extern BOOL	bExistsHdrFtr(void);
+extern BOOL	bExistsTextBox(void);
+extern BOOL	bExistsHdrTextBox(void);
+extern USHORT	usNextChar(FILE *, list_id_enum, ULONG *, ULONG *, USHORT *);
+extern USHORT	usToHdrFtrPosition(FILE *, ULONG);
+extern USHORT	usToFootnotePosition(FILE *, ULONG);
+extern ULONG	ulCharPos2FileOffsetX(ULONG, list_id_enum *);
+extern ULONG	ulCharPos2FileOffset(ULONG);
+extern ULONG	ulHdrFtrOffset2CharPos(ULONG);
+extern ULONG	ulGetSeqNumber(ULONG);
+#if defined(__riscos)
+extern ULONG	ulGetDocumentLength(void);
+#endif /* __riscos */
+/* chartrans.c */
+extern UCHAR	ucGetBulletCharacter(conversion_type, encoding_type);
+extern UCHAR	ucGetNbspCharacter(void);
+extern BOOL	bReadCharacterMappingTable(FILE *);
+extern ULONG	ulTranslateCharacters(USHORT, ULONG, int, conversion_type,
+			encoding_type, BOOL);
+extern ULONG	ulToUpper(ULONG);
+/* datalist.c */
+extern void	vDestroyDataBlockList(void);
+extern BOOL	bAdd2DataBlockList(const data_block_type *);
+extern ULONG	ulGetDataOffset(FILE *);
+extern BOOL	bSetDataOffset(FILE *, ULONG);
+extern int	iNextByte(FILE *);
+extern USHORT	usNextWord(FILE *);
+extern ULONG	ulNextLong(FILE *);
+extern USHORT	usNextWordBE(FILE *);
+extern ULONG	ulNextLongBE(FILE *);
+extern size_t	tSkipBytes(FILE *, size_t);
+extern ULONG	ulDataPos2FileOffset(ULONG);
+/* depot.c */
+extern void	vDestroySmallBlockList(void);
+extern BOOL	bCreateSmallBlockList(ULONG, const ULONG *, size_t);
+extern ULONG	ulDepotOffset(ULONG, size_t);
+/* dib2eps & dib2sprt.c */
+extern BOOL	bTranslateDIB(diagram_type *,
+			FILE *, ULONG, const imagedata_type *);
+#if defined(__dos)
+/* dos.c */
+extern int	iGetCodepage(void);
+#endif /* __dos */
+/* doclist.c */
+extern void	vDestroyDocumentInfoList(void);
+extern void	vCreateDocumentInfoList(const document_block_type *);
+extern UCHAR	ucGetDopHdrFtrSpecification(void);
+/* draw.c & output.c */
+extern BOOL	bAddDummyImage(diagram_type *, const imagedata_type *);
+extern diagram_type *pCreateDiagram(const char *, const char *);
+extern void	vPrologue2(diagram_type *, int);
+extern void	vMove2NextLine(diagram_type *, drawfile_fontref, USHORT);
+extern void	vSubstring2Diagram(diagram_type *,
+			char *, size_t, long, UCHAR, USHORT,
+			drawfile_fontref, USHORT, USHORT);
+extern void	vStartOfParagraph1(diagram_type *, long);
+extern void	vStartOfParagraph2(diagram_type *);
+extern void	vEndOfParagraph(diagram_type *, drawfile_fontref, USHORT, long);
+extern void	vEndOfPage(diagram_type *, long, BOOL);
+extern void	vSetHeaders(diagram_type *, USHORT);
+extern void	vStartOfList(diagram_type *, UCHAR, BOOL);
+extern void	vEndOfList(diagram_type *);
+extern void	vStartOfListItem(diagram_type *, BOOL);
+extern void	vEndOfTable(diagram_type *);
+extern BOOL	bAddTableRow(diagram_type *, char **, int,
+			const short *, UCHAR);
+#if defined(__riscos)
+extern BOOL	bDestroyDiagram(event_pollblock *, void *);
+extern void	vImage2Diagram(diagram_type *, const imagedata_type *,
+			UCHAR *, size_t);
+extern BOOL	bVerifyDiagram(diagram_type *);
+extern void	vShowDiagram(diagram_type *);
+extern void	vMainButtonClick(mouse_block *);
+extern BOOL	bMainKeyPressed(event_pollblock *, void *);
+extern BOOL	bMainEventHandler(event_pollblock *, void *);
+extern BOOL	bRedrawMainWindow(event_pollblock *, void *);
+extern BOOL	bScaleOpenAction(event_pollblock *, void *);
+extern void	vSetTitle(diagram_type *);
+extern void	vScaleButtonClick(mouse_block *, diagram_type *);
+extern BOOL	bScaleKeyPressed(event_pollblock *, void *);
+extern BOOL	bScaleEventHandler(event_pollblock *, void *);
+#else
+extern void	vImagePrologue(diagram_type *, const imagedata_type *);
+extern void	vImageEpilogue(diagram_type *);
+extern void	vDestroyDiagram(diagram_type *);
+#endif /* __riscos */
+/* finddata.c */
+extern BOOL	bAddDataBlocks(ULONG , ULONG, ULONG, const ULONG *, size_t);
+extern BOOL	bGet6DocumentData(FILE *, ULONG,
+				const ULONG *, size_t, const UCHAR *);
+/* findtext.c */
+extern BOOL	bAddTextBlocks(ULONG , ULONG, BOOL,
+				USHORT, ULONG, const ULONG *, size_t);
+extern BOOL	bGet6DocumentText(FILE *, BOOL, ULONG,
+				const ULONG *, size_t, const UCHAR *);
+extern BOOL	bGet8DocumentText(FILE *, const pps_info_type *,
+				const ULONG *, size_t, const ULONG *, size_t,
+				const UCHAR *);
+/* fmt_text.c */
+extern void	vPrologueFMT(diagram_type *, const options_type *);
+extern void	vSubstringFMT(diagram_type *, const char *, size_t, long,
+				USHORT);
+/* fontlist.c */
+extern void	vDestroyFontInfoList(void);
+extern void	vCorrectFontValues(font_block_type *);
+extern void	vAdd2FontInfoList(const font_block_type *);
+extern const font_block_type	*pGetNextFontInfoListItem(
+					const font_block_type *);
+/* fonts.c */
+extern int	iGetFontByNumber(UCHAR, USHORT);
+extern const char	*szGetOurFontname(int);
+extern int	iFontname2Fontnumber(const char *, USHORT);
+extern void	vCreate0FontTable(void);
+extern void	vCreate2FontTable(FILE *, int, const UCHAR *);
+extern void	vCreate6FontTable(FILE *, ULONG,
+			const ULONG *, size_t, const UCHAR *);
+extern void	vCreate8FontTable(FILE *, const pps_info_type *,
+			const ULONG *, size_t, const ULONG *, size_t,
+			const UCHAR *);
+extern void	vDestroyFontTable(void);
+extern const font_table_type	*pGetNextFontTableRecord(
+						const font_table_type *);
+extern size_t	tGetFontTableLength(void);
+extern void	vCorrectFontTable(conversion_type, encoding_type);
+extern long	lComputeSpaceWidth(drawfile_fontref, USHORT);
+/* fonts_r.c & fonts_u.c */
+extern FILE	*pOpenFontTableFile(void);
+extern void	vCloseFont(void);
+extern drawfile_fontref	tOpenFont(UCHAR, USHORT, USHORT);
+extern drawfile_fontref	tOpenTableFont(USHORT);
+extern long	lComputeStringWidth(const char *, size_t, drawfile_fontref, USHORT);
+extern size_t	tCountColumns(const char *, size_t);
+extern size_t	tGetCharacterLength(const char *);
+/* fonts_u.c */
+#if !defined(__riscos)
+extern const char	*szGetFontname(drawfile_fontref);
+#endif /* !__riscos */
+/* hdrftrlist.c */
+extern void	vDestroyHdrFtrInfoList(void);
+extern void	vCreat8HdrFtrInfoList(const ULONG *, size_t);
+extern void	vCreat6HdrFtrInfoList(const ULONG *, size_t);
+extern void	vCreat2HdrFtrInfoList(const ULONG *, size_t);
+extern const hdrftr_block_type *pGetHdrFtrInfo(int, BOOL, BOOL, BOOL);
+extern void	vPrepareHdrFtrText(FILE *);
+#if defined(__riscos)
+/* icons.c */
+extern void	vUpdateIcon(window_handle, icon_block *);
+extern void	vUpdateRadioButton(window_handle, icon_handle, BOOL);
+extern void	vUpdateWriteable(window_handle, icon_handle, const char *);
+extern void	vUpdateWriteableNumber(window_handle, icon_handle, int);
+#endif /* __riscos */
+/* imgexam.c */
+extern image_info_enum	eExamineImage(FILE *, ULONG, imagedata_type *);
+/* imgtrans */
+extern BOOL	bTranslateImage(diagram_type *,
+			FILE *, BOOL, ULONG, const imagedata_type *);
+/* jpeg2eps.c & jpeg2spr.c */
+extern BOOL	bTranslateJPEG(diagram_type *,
+			FILE *, ULONG, size_t, const imagedata_type *);
+/* listlist.c */
+extern void	vDestroyListInfoList(void);
+extern void	vBuildLfoList(const UCHAR *, size_t);
+extern void	vAdd2ListInfoList(ULONG, USHORT, UCHAR,
+			const list_block_type *);
+extern const list_block_type	*pGetListInfo(USHORT, UCHAR);
+extern USHORT	usGetListValue(int, int, const style_block_type *);
+/* misc.c */
+#if !defined(__riscos)
+extern const char	*szGetHomeDirectory(void);
+extern const char	*szGetAntiwordDirectory(void);
+#endif /* !__riscos */
+extern long	lGetFilesize(const char *);
+#if defined(DEBUG)
+extern void	vPrintBlock(const char *, int, const UCHAR *, size_t);
+extern void	vPrintUnicode(const char *, int, const UCHAR *, size_t);
+extern BOOL	bCheckDoubleLinkedList(output_type *);
+#endif /* DEBUG */
+extern BOOL	bReadBytes(UCHAR *, size_t, ULONG, FILE *);
+extern BOOL	bReadBuffer(FILE *, ULONG, const ULONG *, size_t, size_t,
+			UCHAR *, ULONG, size_t);
+extern ULONG	ulColor2Color(UCHAR);
+extern output_type *pSplitList(output_type *);
+extern size_t	tNumber2Roman(UINT, BOOL, char *);
+extern size_t	tNumber2Alpha(UINT, BOOL, char *);
+extern char	*unincpy(char *, const UCHAR *, size_t);
+extern size_t	unilen(const UCHAR *);
+extern const char	*szBasename(const char *);
+extern long	lComputeLeading(USHORT);
+extern size_t	tUcs2Utf8(ULONG, char *, size_t);
+extern void	vGetBulletValue(conversion_type, encoding_type, char *, size_t);
+extern BOOL	bAllZero(const UCHAR *, size_t);
+extern BOOL	bGetNormalizedCodeset(char *, size_t, BOOL *);
+extern const char	*szGetDefaultMappingFile(void);
+extern time_t	tConvertDTTM(ULONG);
+/* notes.c */
+extern void	vDestroyNotesInfoLists(void);
+extern void	vGetNotesInfo(FILE *, const pps_info_type *,
+			const ULONG *, size_t, const ULONG *, size_t,
+			const UCHAR *, int);
+extern void	vPrepareFootnoteText(FILE *);
+extern const char	*szGetFootnootText(UINT);
+extern notetype_enum eGetNotetype(ULONG);
+/* options.c */
+extern int	iReadOptions(int, char **);
+extern void	vGetOptions(options_type *);
+#if defined(__riscos)
+extern void	vChoicesOpenAction(window_handle);
+extern BOOL	bChoicesMouseClick(event_pollblock *, void *);
+extern BOOL	bChoicesKeyPressed(event_pollblock *, void *);
+#endif /* __riscos */
+/* out2window.c */
+extern void	vSetLeftIndentation(diagram_type *, long);
+extern void	vAlign2Window(diagram_type *, output_type *,
+			long, UCHAR);
+extern void	vJustify2Window(diagram_type *, output_type *,
+			long, long, UCHAR);
+extern void	vResetStyles(void);
+extern size_t	tStyle2Window(char *, size_t, const style_block_type *,
+			const section_block_type *);
+extern void	vTableRow2Window(diagram_type *, output_type *,
+			const row_block_type *, conversion_type, int);
+/* pdf.c */
+extern void	vCreateInfoDictionary(diagram_type *, int);
+extern void	vProloguePDF(diagram_type *,
+			const char *, const options_type *);
+extern void	vEpiloguePDF(diagram_type *);
+extern void	vImageProloguePDF(diagram_type *, const imagedata_type *);
+extern void	vImageEpiloguePDF(diagram_type *);
+extern BOOL	bAddDummyImagePDF(diagram_type *, const imagedata_type *);
+extern void	vAddFontsPDF(diagram_type *);
+extern void	vMove2NextLinePDF(diagram_type *, USHORT);
+extern void	vSubstringPDF(diagram_type *,
+				char *, size_t, long, UCHAR, USHORT,
+				drawfile_fontref, USHORT, USHORT);
+extern void	vStartOfParagraphPDF(diagram_type *, long);
+extern void	vEndOfParagraphPDF(diagram_type *, USHORT, long);
+extern void	vEndOfPagePDF(diagram_type *, BOOL);
+/* pictlist.c */
+extern void	vDestroyPictInfoList(void);
+extern void	vAdd2PictInfoList(const picture_block_type *);
+extern ULONG	ulGetPictInfoListItem(ULONG);
+/* png2eps.c & png2spr.c */
+extern BOOL	bTranslatePNG(diagram_type *,
+			FILE *, ULONG, size_t, const imagedata_type *);
+/* postscript.c */
+extern void	vProloguePS(diagram_type *,
+			const char *, const char *, const options_type *);
+extern void	vEpiloguePS(diagram_type *);
+extern void	vImageProloguePS(diagram_type *, const imagedata_type *);
+extern void	vImageEpiloguePS(diagram_type *);
+extern BOOL	bAddDummyImagePS(diagram_type *, const imagedata_type *);
+extern void	vAddFontsPS(diagram_type *);
+extern void	vMove2NextLinePS(diagram_type *, USHORT);
+extern void	vSubstringPS(diagram_type *,
+				char *, size_t, long, UCHAR, USHORT,
+				drawfile_fontref, USHORT, USHORT);
+extern void	vStartOfParagraphPS(diagram_type *, long);
+extern void	vEndOfParagraphPS(diagram_type *, USHORT, long);
+extern void	vEndOfPagePS(diagram_type *, BOOL);
+/* prop0.c */
+extern void	vGet0DopInfo(FILE *, const UCHAR *);
+extern void	vGet0SepInfo(FILE *, const UCHAR *);
+extern void	vGet0PapInfo(FILE *, const UCHAR *);
+extern void	vGet0ChrInfo(FILE *, const UCHAR *);
+/* prop2.c */
+extern void	vGet2DopInfo(FILE *, const UCHAR *);
+extern void	vGet2SepInfo(FILE *, const UCHAR *);
+extern void	vGet2HdrFtrInfo(FILE *, const UCHAR *);
+extern row_info_enum	eGet2RowInfo(int,
+			const UCHAR *, int, row_block_type *);
+extern void	vGet2StyleInfo(int,
+			const UCHAR *, int, style_block_type *);
+extern void	vGet2PapInfo(FILE *, const UCHAR *);
+extern void	vGet1FontInfo(int,
+			const UCHAR *, size_t, font_block_type *);
+extern void	vGet2FontInfo(int,
+			const UCHAR *, size_t, font_block_type *);
+extern void	vGet2ChrInfo(FILE *, int, const UCHAR *);
+/* prop6.c */
+extern void	vGet6DopInfo(FILE *, ULONG, const ULONG *, size_t,
+			const UCHAR *);
+extern void	vGet6SepInfo(FILE *, ULONG, const ULONG *, size_t,
+			const UCHAR *);
+extern void	vGet6HdrFtrInfo(FILE *, ULONG, const ULONG *, size_t,
+			const UCHAR *);
+extern row_info_enum	eGet6RowInfo(int,
+			const UCHAR *, int, row_block_type *);
+extern void	vGet6StyleInfo(int,
+			const UCHAR *, int, style_block_type *);
+extern void	vGet6PapInfo(FILE *, ULONG, const ULONG *, size_t,
+			const UCHAR *);
+extern void	vGet6FontInfo(int, USHORT,
+			const UCHAR *, int, font_block_type *);
+extern void	vGet6ChrInfo(FILE *, ULONG, const ULONG *, size_t,
+			const UCHAR *);
+/* prop8.c */
+extern void	vGet8DopInfo(FILE *, const pps_type *,
+			const ULONG *, size_t, const ULONG *, size_t,
+			const UCHAR *);
+extern void	vGet8SepInfo(FILE *, const pps_info_type *,
+			const ULONG *, size_t, const ULONG *, size_t,
+			const UCHAR *);
+extern void	vGet8HdrFtrInfo(FILE *, const pps_type *,
+			const ULONG *, size_t, const ULONG *, size_t,
+			const UCHAR *);
+extern row_info_enum	eGet8RowInfo(int,
+			const UCHAR *, int, row_block_type *);
+extern void	vGet8StyleInfo(int,
+			const UCHAR *, int, style_block_type *);
+extern void	vGet8LstInfo(FILE *, const pps_info_type *,
+			const ULONG *, size_t, const ULONG *, size_t,
+			const UCHAR *);
+extern void	vGet8PapInfo(FILE *, const pps_info_type *,
+			const ULONG *, size_t, const ULONG *, size_t,
+			const UCHAR *);
+extern void	vGet8FontInfo(int, USHORT,
+			const UCHAR *, int, font_block_type *);
+extern void	vGet8ChrInfo(FILE *, const pps_info_type *,
+			const ULONG *, size_t, const ULONG *, size_t,
+			const UCHAR *);
+/* properties.c */
+extern void	vGetPropertyInfo(FILE *, const pps_info_type *,
+			const ULONG *, size_t, const ULONG *, size_t,
+			const UCHAR *, int);
+extern row_info_enum	ePropMod2RowInfo(USHORT, int);
+/* propmod.c */
+extern void	vDestroyPropModList(void);
+extern void	vAdd2PropModList(const UCHAR *);
+extern const UCHAR	*aucReadPropModListItem(USHORT);
+/* rowlist.c */
+extern void	vDestroyRowInfoList(void);
+extern void	vAdd2RowInfoList(const row_block_type *);
+extern const row_block_type	*pGetNextRowInfoListItem(void);
+/* riscos.c */
+#if defined(__riscos)
+extern int	iGetFiletype(const char *);
+extern void	vSetFiletype(const char *, int);
+extern BOOL	bMakeDirectory(const char *);
+extern int	iReadCurrentAlphabetNumber(void);
+extern int	iGetRiscOsVersion(void);
+extern BOOL	bDrawRenderDiag360(void *, size_t,
+			window_redrawblock *, double, os_error *);
+#if defined(DEBUG)
+extern BOOL	bGetJpegInfo(UCHAR *, size_t);
+#endif /* DEBUG */
+#endif /* __riscos */
+/* saveas.c */
+#if defined(__riscos)
+extern BOOL	bSaveTextfile(event_pollblock *, void *);
+extern BOOL	bSaveDrawfile(event_pollblock *, void *);
+#endif /* __riscos */
+/* sectlist.c */
+extern void	vDestroySectionInfoList(void);
+extern void	vAdd2SectionInfoList(const section_block_type *, ULONG);
+extern void	vGetDefaultSection(section_block_type *);
+extern void	vDefault2SectionInfoList(ULONG);
+extern const section_block_type *
+		pGetSectionInfo(const section_block_type *, ULONG);
+extern size_t	tGetNumberOfSections(void);
+extern UCHAR	ucGetSepHdrFtrSpecification(size_t);
+/* stylelist.c */
+extern void	vDestroyStyleInfoList(void);
+extern level_type_enum	eGetNumType(UCHAR);
+extern void	vCorrectStyleValues(style_block_type *);
+extern void	vAdd2StyleInfoList(const style_block_type *);
+extern const style_block_type	*pGetNextStyleInfoListItem(
+					const style_block_type *);
+extern const style_block_type	*pGetNextTextStyle(const style_block_type *);
+extern USHORT	usGetIstd(ULONG);
+extern BOOL	bStyleImpliesList(const style_block_type *, int);
+/* stylesheet.c */
+extern void	vDestroyStylesheetList(void);
+extern USHORT	usStc2istd(UCHAR);
+extern void	vGet2Stylesheet(FILE *, int, const UCHAR *);
+extern void	vGet6Stylesheet(FILE *, ULONG, const ULONG *, size_t,
+			const UCHAR *);
+extern void	vGet8Stylesheet(FILE *, const pps_info_type *,
+			const ULONG *, size_t, const ULONG *, size_t,
+			const UCHAR *);
+extern void	vFillStyleFromStylesheet(USHORT, style_block_type *);
+extern void	vFillFontFromStylesheet(USHORT, font_block_type *);
+/* summary.c */
+extern void	vDestroySummaryInfo(void);
+extern void	vSet0SummaryInfo(FILE *, const UCHAR *);
+extern void	vSet2SummaryInfo(FILE *, int, const UCHAR *);
+extern void	vSet6SummaryInfo(FILE *, const pps_info_type *,
+			const ULONG *, size_t, const ULONG *, size_t,
+			const UCHAR *);
+extern void	vSet8SummaryInfo(FILE *, const pps_info_type *,
+			const ULONG *, size_t, const ULONG *, size_t,
+			const UCHAR *);
+extern const char	*szGetTitle(void);
+extern const char	*szGetSubject(void);
+extern const char	*szGetAuthor(void);
+extern const char	*szGetLastSaveDtm(void);
+extern const char	*szGetModDate(void);
+extern const char	*szGetCreationDate(void);
+extern const char	*szGetCompany(void);
+extern const char	*szGetLanguage(void);
+/* tabstop.c */
+extern void	vSetDefaultTabWidth(FILE *, const pps_info_type *,
+			const ULONG *, size_t, const ULONG *, size_t,
+			const UCHAR *, int);
+extern long	lGetDefaultTabWidth(void);
+/* text.c */
+extern void	vPrologueTXT(diagram_type *, const options_type *);
+extern void	vEpilogueTXT(FILE *);
+extern void	vMove2NextLineTXT(diagram_type *);
+extern void	vSubstringTXT(diagram_type *, const char *, size_t, long);
+extern void	vStartOfParagraphTXT(diagram_type *, long);
+extern void	vEndOfParagraphTXT(diagram_type *, long);
+extern void	vEndOfPageTXT(diagram_type *, long);
+/* unix.c */
+extern void	werr(int, const char *, ...);
+#if !defined(__riscos)
+extern void	Hourglass_On(void);
+extern void	Hourglass_Off(void);
+#endif /* !__riscos */
+/* utf8.c */
+#if !defined(__riscos)
+extern long	utf8_strwidth(const char *, size_t);
+extern int	utf8_chrlength(const char *);
+extern BOOL	is_locale_utf8(void);
+#endif /* !__riscos */
+/* word2text.c */
+extern BOOL	bOutputContainsText(const output_type *);
+extern BOOL	bWordDecryptor(FILE *, long, diagram_type *);
+extern output_type	*pHdrFtrDecryptor(FILE *, ULONG, ULONG);
+extern char		*szFootnoteDecryptor(FILE *, ULONG, ULONG);
+/* worddos.c */
+extern int	iInitDocumentDOS(FILE *, long);
+/* wordlib.c */
+extern BOOL	bIsWordForDosFile(FILE *, long);
+extern BOOL	bIsRtfFile(FILE *);
+extern BOOL	bIsWordPerfectFile(FILE *);
+extern BOOL	bIsWinWord12File(FILE *, long);
+extern BOOL	bIsMacWord45File(FILE *);
+extern int	iGuessVersionNumber(FILE *, long);
+extern int	iGetVersionNumber(const UCHAR *);
+extern BOOL	bIsOldMacFile(void);
+extern int	iInitDocument(FILE *, long);
+extern void	vFreeDocument(void);
+/* wordmac.c */
+extern int	iInitDocumentMAC(FILE *, long);
+/* wordole.c */
+extern int	iInitDocumentOLE(FILE *, long);
+/* wordwin.c */
+extern int	iInitDocumentWIN(FILE *, long);
+/* xmalloc.c */
+extern void 	*xmalloc(size_t);
+extern void	*xcalloc(size_t, size_t);
+extern void 	*xrealloc(void *, size_t);
+extern char	*xstrdup(const char *);
+extern void 	*xfree(void *);
+/* xml.c */
+extern void	vCreateBookIntro(diagram_type *, int);
+extern void	vPrologueXML(diagram_type *, const options_type *);
+extern void	vEpilogueXML(diagram_type *);
+extern void	vMove2NextLineXML(diagram_type *);
+extern void	vSubstringXML(diagram_type *,
+				const char *, size_t, long, USHORT);
+extern void	vStartOfParagraphXML(diagram_type *, UINT);
+extern void	vEndOfParagraphXML(diagram_type *, UINT);
+extern void	vEndOfPageXML(diagram_type *);
+extern void	vSetHeadersXML(diagram_type *, USHORT);
+extern void	vStartOfListXML(diagram_type *, UCHAR, BOOL);
+extern void	vEndOfListXML(diagram_type *);
+extern void	vStartOfListItemXML(diagram_type *, BOOL);
+extern void	vEndOfTableXML(diagram_type *);
+extern void	vAddTableRowXML(diagram_type *, char **, int,
+			const short *, UCHAR);
+
+#endif /* __antiword_h */
diff --git a/asc85enc.c b/asc85enc.c
new file mode 100644
index 0000000..8ff6bc8
--- /dev/null
+++ b/asc85enc.c
@@ -0,0 +1,154 @@
+/*
+ * asc85enc.c
+ * Copyright (C) 2000-2003 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Functions to for ASCII 85 encoding
+ *
+ *====================================================================
+ * This part of the software is based on:
+ * asc85ec.c - ASCII85 and Hex encoding for PostScript Level 2 and PDF
+ * Copyright (C) 1994-99 Thomas Merz (tm@muc.de)
+ *====================================================================
+ * The credit should go to him, but all the bugs are mine.
+ */
+
+#include <stdio.h>
+#include "antiword.h"
+
+static const ULONG	aulPower85[5] = {
+	1UL, 85UL, 85UL * 85, 85UL * 85 * 85, 85UL * 85 * 85 * 85,
+};
+static int	iOutBytes = 0;	/* Number of characters in an output line */
+static char	cCharPrev = '\0';
+
+/*
+ * Two percent characters at the start of a line will cause trouble
+ * with some post-processing software. In order to avoid this, we
+ * simply insert a line break if we encounter two percent characters
+ * at the start of the line. Of course, this rather simplistic
+ * algorithm may lead to a large line count in pathological cases,
+ * but the chance for hitting such a case is very small, and even
+ * so it's only a cosmetic flaw and not a functional restriction.
+ */
+
+/*
+ * vOutputByte - output one byte
+ */
+static void
+vOutputByte(ULONG ulChar, FILE *pOutFile)
+{
+	if (iOutBytes == 1 && cCharPrev == '%' && ulChar == (ULONG)'%') {
+		if (putc('\n', pOutFile) != EOF) {
+			iOutBytes = 0;
+		}
+	}
+	if (putc((int)ulChar, pOutFile) == EOF) {
+		return;
+	}
+	iOutBytes++;
+	if (iOutBytes > 63) {
+		if (putc('\n', pOutFile) != EOF) {
+			iOutBytes = 0;
+		}
+	}
+	cCharPrev = (char)ulChar;
+} /* end of vOutputByte */
+
+/*
+ * vASCII85EncodeByte - ASCII 85 encode a byte
+ */
+void
+vASCII85EncodeByte(FILE *pOutFile, int iByte)
+{
+	static ULONG	ulBuffer[4] = { 0, 0, 0, 0 };
+	static int	iInBuffer = 0;
+	ULONG	ulValue, ulTmp;
+	int	iIndex;
+
+	fail(pOutFile == NULL);
+	fail(iInBuffer < 0);
+	fail(iInBuffer > 3);
+
+	if (iByte == EOF) {
+		/* End Of File, time to clean up */
+		if (iInBuffer > 0 && iInBuffer < 4) {
+			/* Encode the remaining bytes */
+			ulValue = 0;
+			for (iIndex = iInBuffer - 1; iIndex >= 0; iIndex--) {
+				ulValue |=
+					ulBuffer[iIndex] << (8 * (3 - iIndex));
+			}
+			for (iIndex = 4; iIndex >= 4 - iInBuffer; iIndex--) {
+				ulTmp = ulValue / aulPower85[iIndex];
+				vOutputByte(ulTmp + '!', pOutFile);
+				ulValue -= ulTmp * aulPower85[iIndex];
+			}
+		}
+		/* Add the End Of Data marker */
+		(void)putc('~', pOutFile);
+		(void)putc('>', pOutFile);
+		(void)putc('\n', pOutFile);
+		/* Reset the control variables */
+		iInBuffer = 0;
+		iOutBytes = 0;
+		cCharPrev = '\0';
+		return;
+	}
+
+	ulBuffer[iInBuffer] = (ULONG)iByte & 0xff;
+	iInBuffer++;
+
+	if (iInBuffer >= 4) {
+		ulValue = (ulBuffer[0] << 24) | (ulBuffer[1] << 16) |
+			(ulBuffer[2] << 8) | ulBuffer[3];
+		if (ulValue == 0) {
+			vOutputByte((ULONG)'z', pOutFile); /* Shortcut for 0 */
+		} else {
+			for (iIndex = 4; iIndex >= 0; iIndex--) {
+				ulTmp = ulValue / aulPower85[iIndex];
+				vOutputByte(ulTmp + '!', pOutFile);
+				ulValue -= ulTmp * aulPower85[iIndex];
+			}
+		}
+		/* Reset the buffer */
+		iInBuffer = 0;
+	}
+} /* end of vASCII85EncodeByte */
+
+/*
+ * vASCII85EncodeArray - ASCII 85 encode a byte array
+ */
+void
+vASCII85EncodeArray(FILE *pInFile, FILE *pOutFile, size_t tLength)
+{
+	size_t	tCount;
+	int	iByte;
+
+	fail(pInFile == NULL);
+	fail(pOutFile == NULL);
+
+	DBG_DEC(tLength);
+
+	for (tCount = 0; tCount < tLength; tCount++) {
+		iByte = iNextByte(pInFile);
+		if (iByte == EOF) {
+			break;
+		}
+		vASCII85EncodeByte(pOutFile, iByte);
+	}
+} /* end of vASCII85EncodeArray */
+
+/*
+ * vASCII85EncodeFile - ASCII 85 encode part of a file
+ */
+void
+vASCII85EncodeFile(FILE *pInFile, FILE *pOutFile, size_t tLength)
+{
+	fail(pInFile == NULL);
+	fail(pOutFile == NULL);
+	fail(tLength == 0);
+
+	vASCII85EncodeArray(pInFile, pOutFile, tLength);
+	vASCII85EncodeByte(pOutFile, EOF);
+} /* end of vASCII85EncodeFile */
diff --git a/blocklist.c b/blocklist.c
new file mode 100644
index 0000000..c847c27
--- /dev/null
+++ b/blocklist.c
@@ -0,0 +1,823 @@
+/*
+ * blocklist.c
+ * Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Build, read and destroy the lists of Word "text" blocks
+ */
+
+#include <stdlib.h>
+#include "antiword.h"
+
+
+/*
+ * Private structure to hide the way the information
+ * is stored from the rest of the program
+ */
+typedef struct list_mem_tag {
+	text_block_type		tInfo;
+	struct list_mem_tag	*pNext;
+} list_mem_type;
+
+typedef struct readinfo_tag {
+	list_mem_type		*pBlockCurrent;
+	ULONG			ulBlockOffset;
+	size_t			tByteNext;
+	UCHAR			aucBlock[BIG_BLOCK_SIZE];
+} readinfo_type;
+
+/* Variables to describe the start of the block lists */
+static list_mem_type	*pTextAnchor = NULL;
+static list_mem_type	*pFootnoteAnchor = NULL;
+static list_mem_type	*pHdrFtrAnchor = NULL;
+static list_mem_type	*pMacroAnchor = NULL;
+static list_mem_type	*pAnnotationAnchor = NULL;
+static list_mem_type	*pEndnoteAnchor = NULL;
+static list_mem_type	*pTextBoxAnchor = NULL;
+static list_mem_type	*pHdrTextBoxAnchor = NULL;
+/* Variable needed to build the block list */
+static list_mem_type	*pBlockLast = NULL;
+/* Variable needed to read the block lists */
+static readinfo_type	tOthers = { NULL, 0, 0, };
+static readinfo_type	tHdrFtr = { NULL, 0, 0, };
+static readinfo_type	tFootnote = { NULL, 0, 0, };
+
+
+/*
+ * pFreeOneList - free a text block list
+ *
+ * Will always return NULL
+ */
+static list_mem_type *
+pFreeOneList(list_mem_type *pAnchor)
+{
+	list_mem_type	*pCurr, *pNext;
+
+	pCurr = pAnchor;
+	while (pCurr != NULL) {
+		pNext = pCurr->pNext;
+		pCurr = xfree(pCurr);
+		pCurr = pNext;
+	}
+	return NULL;
+} /* end of pFreeOneList */
+
+/*
+ * vDestroyTextBlockList - destroy the text block lists
+ */
+void
+vDestroyTextBlockList(void)
+{
+	DBG_MSG("vDestroyTextBlockList");
+
+	/* Free the lists one by one */
+	pTextAnchor = pFreeOneList(pTextAnchor);
+	pFootnoteAnchor = pFreeOneList(pFootnoteAnchor);
+	pHdrFtrAnchor = pFreeOneList(pHdrFtrAnchor);
+	pMacroAnchor = pFreeOneList(pMacroAnchor);
+	pAnnotationAnchor = pFreeOneList(pAnnotationAnchor);
+	pEndnoteAnchor = pFreeOneList(pEndnoteAnchor);
+	pTextBoxAnchor = pFreeOneList(pTextBoxAnchor);
+	pHdrTextBoxAnchor = pFreeOneList(pHdrTextBoxAnchor);
+	/* Reset all the controle variables */
+	pBlockLast = NULL;
+	tOthers.pBlockCurrent = NULL;
+	tHdrFtr.pBlockCurrent = NULL;
+	tFootnote.pBlockCurrent = NULL;
+} /* end of vDestroyTextBlockList */
+
+/*
+ * bAdd2TextBlockList - add an element to the text block list
+ *
+ * returns: TRUE when successful, otherwise FALSE
+ */
+BOOL
+bAdd2TextBlockList(const text_block_type *pTextBlock)
+{
+	list_mem_type	*pListMember;
+
+	fail(pTextBlock == NULL);
+	fail(pTextBlock->ulFileOffset == FC_INVALID);
+	fail(pTextBlock->ulCharPos == CP_INVALID);
+	fail(pTextBlock->ulLength == 0);
+	fail(pTextBlock->bUsesUnicode && odd(pTextBlock->ulLength));
+
+	NO_DBG_MSG("bAdd2TextBlockList");
+	NO_DBG_HEX(pTextBlock->ulFileOffset);
+	NO_DBG_HEX(pTextBlock->ulCharPos);
+	NO_DBG_HEX(pTextBlock->ulLength);
+	NO_DBG_DEC(pTextBlock->bUsesUnicode);
+	NO_DBG_DEC(pTextBlock->usPropMod);
+
+	if (pTextBlock->ulFileOffset == FC_INVALID ||
+	    pTextBlock->ulCharPos == CP_INVALID ||
+	    pTextBlock->ulLength == 0 ||
+	    (pTextBlock->bUsesUnicode && odd(pTextBlock->ulLength))) {
+		werr(0, "Software (textblock) error");
+		return FALSE;
+	}
+	/*
+	 * Check for continuous blocks of the same character size and
+	 * the same properties modifier
+	 */
+	if (pBlockLast != NULL &&
+	    pBlockLast->tInfo.ulFileOffset +
+	     pBlockLast->tInfo.ulLength == pTextBlock->ulFileOffset &&
+	    pBlockLast->tInfo.ulCharPos +
+	     pBlockLast->tInfo.ulLength == pTextBlock->ulCharPos &&
+	    pBlockLast->tInfo.bUsesUnicode == pTextBlock->bUsesUnicode &&
+	    pBlockLast->tInfo.usPropMod == pTextBlock->usPropMod) {
+		/* These are continous blocks */
+		pBlockLast->tInfo.ulLength += pTextBlock->ulLength;
+		return TRUE;
+	}
+	/* Make a new block */
+	pListMember = xmalloc(sizeof(list_mem_type));
+	/* Add the block to the list */
+	pListMember->tInfo = *pTextBlock;
+	pListMember->pNext = NULL;
+	if (pTextAnchor == NULL) {
+		pTextAnchor = pListMember;
+	} else {
+		fail(pBlockLast == NULL);
+		pBlockLast->pNext = pListMember;
+	}
+	pBlockLast = pListMember;
+	return TRUE;
+} /* end of bAdd2TextBlockList */
+
+/*
+ * vSpitList - Split the list in two
+ */
+static void
+vSpitList(list_mem_type **ppAnchorCurr, list_mem_type **ppAnchorNext,
+	ULONG ulListLen)
+{
+	list_mem_type	*pCurr;
+	long		lCharsToGo, lBytesTooFar;
+
+	fail(ppAnchorCurr == NULL);
+	fail(ppAnchorNext == NULL);
+	fail(ulListLen > (ULONG)LONG_MAX);
+
+	pCurr = NULL;
+	lCharsToGo = (long)ulListLen;
+	lBytesTooFar = -1;
+	if (ulListLen != 0) {
+		DBG_DEC(ulListLen);
+		for (pCurr = *ppAnchorCurr;
+		     pCurr != NULL;
+		     pCurr = pCurr->pNext) {
+			NO_DBG_DEC(pCurr->tInfo.ulLength);
+			fail(pCurr->tInfo.ulLength == 0);
+			fail(pCurr->tInfo.ulLength > (ULONG)LONG_MAX);
+			if (pCurr->tInfo.bUsesUnicode) {
+				fail(odd(pCurr->tInfo.ulLength));
+				lCharsToGo -= (long)(pCurr->tInfo.ulLength / 2);
+				if (lCharsToGo < 0) {
+					lBytesTooFar = -2 * lCharsToGo;
+				}
+			} else {
+				lCharsToGo -= (long)pCurr->tInfo.ulLength;
+				if (lCharsToGo < 0) {
+					lBytesTooFar = -lCharsToGo;
+				}
+			}
+			if (lCharsToGo <= 0) {
+				break;
+			}
+		}
+	}
+/* Split the list */
+	if (ulListLen == 0) {
+		/* Current blocklist is empty */
+		*ppAnchorNext = *ppAnchorCurr;
+		*ppAnchorCurr = NULL;
+	} else if (pCurr == NULL) {
+		/* No blocks for the next list */
+		*ppAnchorNext = NULL;
+	} else if (lCharsToGo == 0) {
+		/* Move the integral number of blocks to the next list */
+		*ppAnchorNext = pCurr->pNext;
+		pCurr->pNext = NULL;
+	} else {
+		/* Split the part current block list, part next block list */
+		DBG_DEC(lBytesTooFar);
+		fail(lBytesTooFar <= 0);
+		*ppAnchorNext = xmalloc(sizeof(list_mem_type));
+		DBG_HEX(pCurr->tInfo.ulFileOffset);
+		(*ppAnchorNext)->tInfo.ulFileOffset =
+				pCurr->tInfo.ulFileOffset +
+				pCurr->tInfo.ulLength -
+				lBytesTooFar;
+		DBG_HEX((*ppAnchorNext)->tInfo.ulFileOffset);
+		DBG_HEX(pCurr->tInfo.ulCharPos);
+		(*ppAnchorNext)->tInfo.ulCharPos =
+				pCurr->tInfo.ulCharPos +
+				pCurr->tInfo.ulLength -
+				lBytesTooFar;
+		DBG_HEX((*ppAnchorNext)->tInfo.ulCharPos);
+		(*ppAnchorNext)->tInfo.ulLength = (ULONG)lBytesTooFar;
+		pCurr->tInfo.ulLength -= (ULONG)lBytesTooFar;
+		(*ppAnchorNext)->tInfo.bUsesUnicode = pCurr->tInfo.bUsesUnicode;
+		(*ppAnchorNext)->tInfo.usPropMod = pCurr->tInfo.usPropMod;
+		/* Move the integral number of blocks to the next list */
+		(*ppAnchorNext)->pNext = pCurr->pNext;
+		pCurr->pNext = NULL;
+	}
+} /* end of vSpitList */
+
+#if defined(DEBUG) || defined(__riscos)
+/*
+ * ulComputeListLength - compute the length of a list
+ *
+ * returns the list length in characters
+ */
+static ULONG
+ulComputeListLength(const list_mem_type *pAnchor)
+{
+	const list_mem_type	*pCurr;
+	ULONG		ulTotal;
+
+	ulTotal = 0;
+	for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
+		fail(pCurr->tInfo.ulLength == 0);
+		if (pCurr->tInfo.bUsesUnicode) {
+			fail(odd(pCurr->tInfo.ulLength));
+			ulTotal += pCurr->tInfo.ulLength / 2;
+		} else {
+			ulTotal += pCurr->tInfo.ulLength;
+		}
+	}
+	return ulTotal;
+} /* end of ulComputeListLength */
+#endif /* DEBUG || __riscos */
+
+#if defined(DEBUG)
+/*
+ * vCheckList - check the number of bytes in a block list
+ */
+static void
+vCheckList(const list_mem_type *pAnchor, ULONG ulListLen, char *szMsg)
+{
+	ULONG		ulTotal;
+
+	ulTotal = ulComputeListLength(pAnchor);
+	DBG_DEC(ulTotal);
+	if (ulTotal != ulListLen) {
+		DBG_DEC(ulListLen);
+		werr(1, szMsg);
+	}
+} /* end of vCheckList */
+#endif /* DEBUG */
+
+/*
+ * bIsEmptyBox - check to see if the given text box is empty
+ */
+static BOOL
+bIsEmptyBox(FILE *pFile, const list_mem_type *pAnchor)
+{
+	const list_mem_type	*pCurr;
+	size_t	tIndex, tSize;
+	UCHAR	*aucBuffer;
+	char	cChar;
+
+	fail(pFile == NULL);
+
+	if (pAnchor == NULL) {
+		return TRUE;
+	}
+
+	aucBuffer = NULL;
+	for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
+		fail(pCurr->tInfo.ulLength == 0);
+		tSize = (size_t)pCurr->tInfo.ulLength;
+#if defined(__dos) && !defined(__DJGPP__)
+		if (pCurr->tInfo.ulLength > 0xffffUL) {
+			tSize = 0xffff;
+		}
+#endif /* __dos && !__DJGPP__ */
+		fail(aucBuffer != NULL);
+		aucBuffer = xmalloc(tSize);
+		if (!bReadBytes(aucBuffer, tSize,
+				pCurr->tInfo.ulFileOffset, pFile)) {
+			aucBuffer = xfree(aucBuffer);
+			return FALSE;
+		}
+		for (tIndex = 0; tIndex < tSize; tIndex++) {
+			cChar = (char)aucBuffer[tIndex];
+			switch (cChar) {
+			case '\0': case '\r': case '\n':
+			case '\f': case '\t': case '\v':
+			case ' ':
+				break;
+			default:
+				aucBuffer = xfree(aucBuffer);
+				return FALSE;
+			}
+		}
+		aucBuffer = xfree(aucBuffer);
+	}
+	fail(aucBuffer != NULL);
+	return TRUE;
+} /* end of bIsEmptyBox */
+
+/*
+ * vSplitBlockList - split the block list in the various parts
+ *
+ * Split the blocklist in a Text block list, a Footnote block list, a
+ * HeaderFooter block list, a Macro block list, an Annotation block list,
+ * an Endnote block list, a TextBox list and a HeaderTextBox list.
+ *
+ * NOTE:
+ * The various ul*Len input parameters are given in characters, but the
+ * length of the blocks are in bytes.
+ */
+void
+vSplitBlockList(FILE *pFile, ULONG ulTextLen, ULONG ulFootnoteLen,
+	ULONG ulHdrFtrLen, ULONG ulMacroLen, ULONG ulAnnotationLen,
+	ULONG ulEndnoteLen, ULONG ulTextBoxLen, ULONG ulHdrTextBoxLen,
+	BOOL bMustExtend)
+{
+	list_mem_type	*apAnchors[8];
+	list_mem_type	*pGarbageAnchor, *pCurr;
+	size_t		tIndex;
+
+	DBG_MSG("vSplitBlockList");
+
+	pGarbageAnchor = NULL;
+
+	DBG_MSG_C(ulTextLen != 0, "Text block list");
+	vSpitList(&pTextAnchor, &pFootnoteAnchor, ulTextLen);
+	DBG_MSG_C(ulFootnoteLen != 0, "Footnote block list");
+	vSpitList(&pFootnoteAnchor, &pHdrFtrAnchor, ulFootnoteLen);
+	DBG_MSG_C(ulHdrFtrLen != 0, "Header/Footer block list");
+	vSpitList(&pHdrFtrAnchor, &pMacroAnchor, ulHdrFtrLen);
+	DBG_MSG_C(ulMacroLen != 0, "Macro block list");
+	vSpitList(&pMacroAnchor, &pAnnotationAnchor, ulMacroLen);
+	DBG_MSG_C(ulAnnotationLen != 0, "Annotation block list");
+	vSpitList(&pAnnotationAnchor, &pEndnoteAnchor, ulAnnotationLen);
+	DBG_MSG_C(ulEndnoteLen != 0, "Endnote block list");
+	vSpitList(&pEndnoteAnchor, &pTextBoxAnchor, ulEndnoteLen);
+	DBG_MSG_C(ulTextBoxLen != 0, "Textbox block list");
+	vSpitList(&pTextBoxAnchor, &pHdrTextBoxAnchor, ulTextBoxLen);
+	DBG_MSG_C(ulHdrTextBoxLen != 0, "HeaderTextbox block list");
+	vSpitList(&pHdrTextBoxAnchor, &pGarbageAnchor, ulHdrTextBoxLen);
+
+	/* Free the garbage block list, this should not be needed */
+	DBG_DEC_C(pGarbageAnchor != NULL, pGarbageAnchor->tInfo.ulLength);
+	pGarbageAnchor = pFreeOneList(pGarbageAnchor);
+
+#if defined(DEBUG)
+	vCheckList(pTextAnchor, ulTextLen, "Software error (Text)");
+	vCheckList(pFootnoteAnchor, ulFootnoteLen, "Software error (Footnote)");
+	vCheckList(pHdrFtrAnchor, ulHdrFtrLen, "Software error (Hdr/Ftr)");
+	vCheckList(pMacroAnchor, ulMacroLen, "Software error (Macro)");
+	vCheckList(pAnnotationAnchor, ulAnnotationLen,
+						"Software error (Annotation)");
+	vCheckList(pEndnoteAnchor, ulEndnoteLen, "Software error (Endnote)");
+	vCheckList(pTextBoxAnchor, ulTextBoxLen, "Software error (TextBox)");
+	vCheckList(pHdrTextBoxAnchor, ulHdrTextBoxLen,
+						"Software error (HdrTextBox)");
+#endif /* DEBUG */
+
+	/* Remove the list if the text box is empty */
+	if (bIsEmptyBox(pFile, pTextBoxAnchor)) {
+		pTextBoxAnchor = pFreeOneList(pTextBoxAnchor);
+	}
+	if (bIsEmptyBox(pFile, pHdrTextBoxAnchor)) {
+		pHdrTextBoxAnchor = pFreeOneList(pHdrTextBoxAnchor);
+	}
+
+	if (!bMustExtend) {
+		return;
+	}
+	/*
+	 * All blocks (except the last one) must have a length that
+	 * is a multiple of the Big Block Size
+	 */
+
+	apAnchors[0] = pTextAnchor;
+	apAnchors[1] = pFootnoteAnchor;
+	apAnchors[2] = pHdrFtrAnchor;
+	apAnchors[3] = pMacroAnchor;
+	apAnchors[4] = pAnnotationAnchor;
+	apAnchors[5] = pEndnoteAnchor;
+	apAnchors[6] = pTextBoxAnchor;
+	apAnchors[7] = pHdrTextBoxAnchor;
+
+	for (tIndex = 0; tIndex < elementsof(apAnchors); tIndex++) {
+		for (pCurr = apAnchors[tIndex];
+		     pCurr != NULL;
+		     pCurr = pCurr->pNext) {
+			if (pCurr->pNext != NULL &&
+			    pCurr->tInfo.ulLength % BIG_BLOCK_SIZE != 0) {
+				DBG_DEC(tIndex);
+				DBG_HEX(pCurr->tInfo.ulFileOffset);
+				DBG_HEX(pCurr->tInfo.ulCharPos);
+				DBG_DEC(pCurr->tInfo.ulLength);
+				pCurr->tInfo.ulLength /= BIG_BLOCK_SIZE;
+				pCurr->tInfo.ulLength++;
+				pCurr->tInfo.ulLength *= BIG_BLOCK_SIZE;
+				DBG_DEC(pCurr->tInfo.ulLength);
+			}
+		}
+	}
+} /* end of vSplitBlockList */
+
+#if defined(__riscos)
+/*
+ * ulGetDocumentLength - get the total character length of the printable lists
+ *
+ * returns: The total number of characters
+ */
+ULONG
+ulGetDocumentLength(void)
+{
+	long		ulTotal;
+
+	DBG_MSG("ulGetDocumentLength");
+
+	ulTotal = ulComputeListLength(pTextAnchor);
+	ulTotal += ulComputeListLength(pFootnoteAnchor);
+	ulTotal += ulComputeListLength(pEndnoteAnchor);
+	ulTotal += ulComputeListLength(pTextBoxAnchor);
+	ulTotal += ulComputeListLength(pHdrTextBoxAnchor);
+	DBG_DEC(ulTotal);
+	return ulTotal;
+} /* end of ulGetDocumentLength */
+#endif /* __riscos */
+
+#if 0
+/*
+ * bExistsHdrFtr - are there headers and/or footers?
+ */
+BOOL
+bExistsHdrFtr(void)
+{
+	return pHdrFtrAnchor != NULL &&
+		pHdrFtrAnchor->tInfo.ulLength != 0;
+} /* end of bExistsHdrFtr */
+#endif
+
+/*
+ * bExistsTextBox - is there a text box?
+ */
+BOOL
+bExistsTextBox(void)
+{
+	return pTextBoxAnchor != NULL &&
+		pTextBoxAnchor->tInfo.ulLength != 0;
+} /* end of bExistsTextBox */
+
+/*
+ * bExistsHdrTextBox - is there a header text box?
+ */
+BOOL
+bExistsHdrTextBox(void)
+{
+	return pHdrTextBoxAnchor != NULL &&
+		pHdrTextBoxAnchor->tInfo.ulLength != 0;
+} /* end of bExistsHdrTextBox */
+
+/*
+ * usGetNextByte - get the next byte from the specified block list
+ */
+static USHORT
+usGetNextByte(FILE *pFile, readinfo_type *pInfoCurrent, list_mem_type *pAnchor,
+	ULONG *pulFileOffset, ULONG *pulCharPos, USHORT *pusPropMod)
+{
+	ULONG	ulReadOff;
+	size_t	tReadLen;
+
+	fail(pInfoCurrent == NULL);
+
+	if (pInfoCurrent->pBlockCurrent == NULL ||
+	    pInfoCurrent->tByteNext >= sizeof(pInfoCurrent->aucBlock) ||
+	    pInfoCurrent->ulBlockOffset + pInfoCurrent->tByteNext >=
+				pInfoCurrent->pBlockCurrent->tInfo.ulLength) {
+		if (pInfoCurrent->pBlockCurrent == NULL) {
+			/* First block, first part */
+			pInfoCurrent->pBlockCurrent = pAnchor;
+			pInfoCurrent->ulBlockOffset = 0;
+		} else if (pInfoCurrent->ulBlockOffset +
+				sizeof(pInfoCurrent->aucBlock) <
+				pInfoCurrent->pBlockCurrent->tInfo.ulLength) {
+			/* Same block, next part */
+			pInfoCurrent->ulBlockOffset +=
+					sizeof(pInfoCurrent->aucBlock);
+		} else {
+			/* Next block, first part */
+			pInfoCurrent->pBlockCurrent =
+					pInfoCurrent->pBlockCurrent->pNext;
+			pInfoCurrent->ulBlockOffset = 0;
+		}
+		if (pInfoCurrent->pBlockCurrent == NULL) {
+			/* Past the last part of the last block */
+			return (USHORT)EOF;
+		}
+		tReadLen = (size_t)
+			(pInfoCurrent->pBlockCurrent->tInfo.ulLength -
+			 pInfoCurrent->ulBlockOffset);
+		if (tReadLen > sizeof(pInfoCurrent->aucBlock)) {
+			tReadLen = sizeof(pInfoCurrent->aucBlock);
+		}
+		ulReadOff = pInfoCurrent->pBlockCurrent->tInfo.ulFileOffset +
+				pInfoCurrent->ulBlockOffset;
+		if (!bReadBytes(pInfoCurrent->aucBlock,
+						tReadLen, ulReadOff, pFile)) {
+			/* Don't read from this list any longer */
+			pInfoCurrent->pBlockCurrent = NULL;
+			return (USHORT)EOF;
+		}
+		pInfoCurrent->tByteNext = 0;
+	}
+	if (pulFileOffset != NULL) {
+		*pulFileOffset =
+			pInfoCurrent->pBlockCurrent->tInfo.ulFileOffset +
+			pInfoCurrent->ulBlockOffset +
+			pInfoCurrent->tByteNext;
+	}
+	if (pulCharPos != NULL) {
+		*pulCharPos =
+			pInfoCurrent->pBlockCurrent->tInfo.ulCharPos +
+			pInfoCurrent->ulBlockOffset +
+			pInfoCurrent->tByteNext;
+	}
+	if (pusPropMod != NULL) {
+		*pusPropMod = pInfoCurrent->pBlockCurrent->tInfo.usPropMod;
+	}
+	return (USHORT)pInfoCurrent->aucBlock[pInfoCurrent->tByteNext++];
+} /* end of usGetNextByte */
+
+
+/*
+ * usGetNextChar - get the next character from the specified block list
+ */
+static USHORT
+usGetNextChar(FILE *pFile, list_id_enum eListID,
+	ULONG *pulFileOffset, ULONG *pulCharPos, USHORT *pusPropMod)
+{
+	readinfo_type	*pReadinfo;
+	list_mem_type	*pAnchor;
+	USHORT	usLSB, usMSB;
+
+	switch (eListID) {
+	case text_list:
+		pReadinfo = &tOthers;
+		pAnchor = pTextAnchor;
+		break;
+	case footnote_list:
+		pReadinfo = &tFootnote;
+		pAnchor = pFootnoteAnchor;
+		break;
+	case hdrftr_list:
+		pReadinfo = &tHdrFtr;
+		pAnchor = pHdrFtrAnchor;
+		break;
+	case endnote_list:
+		pReadinfo = &tOthers;
+		pAnchor = pEndnoteAnchor;
+		break;
+	case textbox_list:
+		pReadinfo = &tOthers;
+		pAnchor = pTextBoxAnchor;
+		break;
+	case hdrtextbox_list:
+		pReadinfo = &tOthers;
+		pAnchor = pHdrTextBoxAnchor;
+		break;
+	default:
+		DBG_DEC(eListID);
+		return (USHORT)EOF;
+	}
+
+	usLSB = usGetNextByte(pFile, pReadinfo, pAnchor,
+				pulFileOffset, pulCharPos, pusPropMod);
+	if (usLSB == (USHORT)EOF) {
+		return (USHORT)EOF;
+	}
+	fail(pReadinfo->pBlockCurrent == NULL);
+
+	if (pReadinfo->pBlockCurrent->tInfo.bUsesUnicode) {
+		usMSB = usGetNextByte(pFile,
+				pReadinfo, pAnchor, NULL, NULL, NULL);
+	} else {
+		usMSB = 0x00;
+	}
+	if (usMSB == (USHORT)EOF) {
+		DBG_MSG("usGetNextChar: Unexpected EOF");
+		DBG_HEX_C(pulFileOffset != NULL, *pulFileOffset);
+		DBG_HEX_C(pulCharPos != NULL, *pulCharPos);
+		return (USHORT)EOF;
+	}
+	return (usMSB << 8) | usLSB;
+} /* end of usGetNextChar */
+
+/*
+ * usNextChar - get the next character from the given block list
+ */
+USHORT
+usNextChar(FILE *pFile, list_id_enum eListID,
+	ULONG *pulFileOffset, ULONG *pulCharPos, USHORT *pusPropMod)
+{
+	USHORT	usRetVal;
+
+	fail(pFile == NULL);
+
+	usRetVal = usGetNextChar(pFile, eListID,
+				pulFileOffset, pulCharPos, pusPropMod);
+	if (usRetVal == (USHORT)EOF) {
+		if (pulFileOffset != NULL) {
+			*pulFileOffset = FC_INVALID;
+		}
+		if (pulCharPos != NULL) {
+			*pulCharPos = CP_INVALID;
+		}
+		if (pusPropMod != NULL) {
+			*pusPropMod = IGNORE_PROPMOD;
+		}
+	}
+	return usRetVal;
+} /* end of usNextChar */
+
+/*
+ * usToHdrFtrPosition - Go to a character position in header/foorter list
+ *
+ * Returns the character found on the specified character position
+ */
+USHORT
+usToHdrFtrPosition(FILE *pFile, ULONG ulCharPos)
+{
+	ULONG	ulCharPosCurr;
+	USHORT	usChar;
+
+	tHdrFtr.pBlockCurrent = NULL;	/* To reset the header/footer list */
+	do {
+		usChar = usNextChar(pFile,
+				hdrftr_list, NULL, &ulCharPosCurr, NULL);
+	} while (usChar != (USHORT)EOF && ulCharPosCurr != ulCharPos);
+	return usChar;
+} /* end of usToHdrFtrPosition */
+
+/*
+ * usToFootnotePosition - Go to a character position in footnote list
+ *
+ * Returns the character found on the specified character position
+ */
+USHORT
+usToFootnotePosition(FILE *pFile, ULONG ulCharPos)
+{
+	ULONG	ulCharPosCurr;
+	USHORT	usChar;
+
+	tFootnote.pBlockCurrent = NULL;	/* To reset the footnote list */
+	do {
+		usChar = usNextChar(pFile,
+				footnote_list, NULL, &ulCharPosCurr, NULL);
+	} while (usChar != (USHORT)EOF && ulCharPosCurr != ulCharPos);
+	return usChar;
+} /* end of usToFootnotePosition */
+
+/*
+ * Convert a character position to an offset in the file.
+ * Logical to physical offset.
+ *
+ * Returns:	FC_INVALID: in case of error
+ *		otherwise: the computed file offset
+ */
+ULONG
+ulCharPos2FileOffsetX(ULONG ulCharPos, list_id_enum *peListID)
+{
+	static list_id_enum	eListIDs[8] = {
+		text_list,	footnote_list,		hdrftr_list,
+		macro_list,	annotation_list,	endnote_list,
+		textbox_list,	hdrtextbox_list,
+	};
+	list_mem_type	*apAnchors[8];
+	list_mem_type	*pCurr;
+	list_id_enum	eListGuess;
+	ULONG		ulBestGuess;
+	size_t		tIndex;
+
+	fail(peListID == NULL);
+
+	if (ulCharPos == CP_INVALID) {
+		*peListID = no_list;
+		return FC_INVALID;
+	}
+
+	apAnchors[0] = pTextAnchor;
+	apAnchors[1] = pFootnoteAnchor;
+	apAnchors[2] = pHdrFtrAnchor;
+	apAnchors[3] = pMacroAnchor;
+	apAnchors[4] = pAnnotationAnchor;
+	apAnchors[5] = pEndnoteAnchor;
+	apAnchors[6] = pTextBoxAnchor;
+	apAnchors[7] = pHdrTextBoxAnchor;
+
+	eListGuess = no_list;	  /* Best guess is no list */
+	ulBestGuess = FC_INVALID; /* Best guess is "file offset not found" */
+
+	for (tIndex = 0; tIndex < elementsof(apAnchors); tIndex++) {
+		for (pCurr = apAnchors[tIndex];
+		     pCurr != NULL;
+		     pCurr = pCurr->pNext) {
+			if (ulCharPos == pCurr->tInfo.ulCharPos +
+			     pCurr->tInfo.ulLength &&
+			    pCurr->pNext != NULL) {
+				/*
+				 * The character position is one beyond this
+				 * block, so we guess it's the first byte of
+				 * the next block (if there is a next block)
+				 */
+				eListGuess= eListIDs[tIndex];
+				ulBestGuess = pCurr->pNext->tInfo.ulFileOffset;
+			}
+
+			if (ulCharPos < pCurr->tInfo.ulCharPos ||
+			    ulCharPos >= pCurr->tInfo.ulCharPos +
+			     pCurr->tInfo.ulLength) {
+				/* Character position is not in this block */
+				continue;
+			}
+
+			/* The character position is in the current block */
+			*peListID = eListIDs[tIndex];
+			return pCurr->tInfo.ulFileOffset +
+				ulCharPos - pCurr->tInfo.ulCharPos;
+		}
+	}
+	/* Passed beyond the end of the last list */
+	NO_DBG_HEX(ulCharPos);
+	NO_DBG_HEX(ulBestGuess);
+	*peListID = eListGuess;
+	return ulBestGuess;
+} /* end of ulCharPos2FileOffsetX */
+
+/*
+ * Convert a character position to an offset in the file.
+ * Logical to physical offset.
+ *
+ * Returns:	FC_INVALID: in case of error
+ *		otherwise: the computed file offset
+ */
+ULONG
+ulCharPos2FileOffset(ULONG ulCharPos)
+{
+	list_id_enum	eListID;
+
+	return ulCharPos2FileOffsetX(ulCharPos, &eListID);
+} /* end of ulCharPos2FileOffset */
+
+/*
+ * Convert an offset in the header/footer list to a character position.
+ *
+ * Returns:	CP_INVALID: in case of error
+ *		otherwise: the computed character position
+ */
+ULONG
+ulHdrFtrOffset2CharPos(ULONG ulHdrFtrOffset)
+{
+	list_mem_type	*pCurr;
+	ULONG		ulOffset;
+
+	ulOffset = ulHdrFtrOffset;
+	for (pCurr = pHdrFtrAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
+		if (ulOffset >= pCurr->tInfo.ulLength) {
+			/* The offset is not in this block */
+			ulOffset -= pCurr->tInfo.ulLength;
+			continue;
+		}
+		return pCurr->tInfo.ulCharPos + ulOffset;
+	}
+	return CP_INVALID;
+} /* end of ulHdrFtrOffset2CharPos */
+
+/*
+ * Get the sequence number beloning to the given file offset
+ *
+ * Returns the sequence number
+ */
+ULONG
+ulGetSeqNumber(ULONG ulFileOffset)
+{
+	list_mem_type	*pCurr;
+	ULONG		ulSeq;
+
+	if (ulFileOffset == FC_INVALID) {
+		return FC_INVALID;
+	}
+
+	ulSeq = 0;
+	for (pCurr = pTextAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
+		if (ulFileOffset >= pCurr->tInfo.ulFileOffset &&
+		    ulFileOffset < pCurr->tInfo.ulFileOffset +
+		     pCurr->tInfo.ulLength) {
+			/* The file offset is within the current textblock */
+			return ulSeq + ulFileOffset - pCurr->tInfo.ulFileOffset;
+		}
+		ulSeq += pCurr->tInfo.ulLength;
+	}
+	return FC_INVALID;
+} /* end of ulGetSeqNumber */
diff --git a/chartrans.c b/chartrans.c
new file mode 100644
index 0000000..5edaae9
--- /dev/null
+++ b/chartrans.c
@@ -0,0 +1,720 @@
+/*
+ * chartrans.c
+ * Copyright (C) 1999-2004 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Translate Word characters to local representation
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#if defined(__STDC_ISO_10646__)
+#include <wctype.h>
+#endif /* __STDC_ISO_10646__ */
+#include "antiword.h"
+
+static const USHORT usCp850[] = {	/* DOS implementation of Latin1 */
+	0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
+	0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
+	0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
+	0x00ff, 0x00d6, 0x00dc, 0x00f8, 0x00a3, 0x00d8, 0x00d7, 0x0192,
+	0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
+	0x00bf, 0x00ae, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
+	0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00c1, 0x00c2, 0x00c0,
+	0x00a9, 0x2563, 0x2551, 0x2557, 0x255d, 0x00a2, 0x00a5, 0x2510,
+	0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x00e3, 0x00c3,
+	0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x00a4,
+	0x00f0, 0x00d0, 0x00ca, 0x00cb, 0x00c8, 0x0131, 0x00cd, 0x00ce,
+	0x00cf, 0x2518, 0x250c, 0x2588, 0x2584, 0x00a6, 0x00cc, 0x2580,
+	0x00d3, 0x00df, 0x00d4, 0x00d2, 0x00f5, 0x00d5, 0x00b5, 0x00fe,
+	0x00de, 0x00da, 0x00db, 0x00d9, 0x00fd, 0x00dd, 0x00af, 0x00b4,
+	0x00ad, 0x00b1, 0x2017, 0x00be, 0x00b6, 0x00a7, 0x00f7, 0x00b8,
+	0x00b0, 0x00a8, 0x00b7, 0x00b9, 0x00b3, 0x00b2, 0x25a0, 0x00a0,
+};
+
+static const USHORT usCp1250[] = {	/* Windows implementation of Latin2 */
+	0x20ac, 0x003f, 0x201a, 0x003f, 0x201e, 0x2026, 0x2020, 0x2021,
+	0x003f, 0x2030, 0x0160, 0x2039, 0x015a, 0x0164, 0x017d, 0x0179,
+	0x003f, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
+	0x003f, 0x2122, 0x0161, 0x203a, 0x015b, 0x0165, 0x017e, 0x017a,
+	0x00a0, 0x02c7, 0x02d8, 0x0141, 0x00a4, 0x0104, 0x00a6, 0x00a7,
+	0x00a8, 0x00a9, 0x015e, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x017b,
+	0x00b0, 0x00b1, 0x02db, 0x0142, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
+	0x00b8, 0x0105, 0x015f, 0x00bb, 0x013d, 0x02dd, 0x013e, 0x017c,
+	0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7,
+	0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e,
+	0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7,
+	0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df,
+	0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7,
+	0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f,
+	0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7,
+	0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9,
+};
+
+static const USHORT usCp1251[] = {	/* Windows implementation of Cyrillic */
+	0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021,
+	0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f,
+	0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
+	0x00f3, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f,
+	0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7,
+	0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407,
+	0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7,
+	0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457,
+	0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
+	0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
+	0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
+	0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
+	0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
+	0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
+	0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
+	0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f,
+};
+
+static const USHORT usCp1252[] = {	/* Windows implementation of Latin1 */
+	0x20ac, 0x003f, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
+	0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x003f, 0x017d, 0x003f,
+	0x003f, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
+	0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x003f, 0x017e, 0x0178,
+	0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
+	0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
+	0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
+	0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
+	0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
+	0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
+	0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
+	0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
+	0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
+	0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
+	0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
+	0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff,
+};
+
+static const USHORT usMacRoman[] = {	/* Apple implementation of Latin1 */
+	0x00c4, 0x00c5, 0x00c7, 0x00c9, 0x00d1, 0x00d6, 0x00dc, 0x00e1,
+	0x00e0, 0x00e2, 0x00e4, 0x00e3, 0x00e5, 0x00e7, 0x00e9, 0x00e8,
+	0x00ea, 0x00eb, 0x00ed, 0x00ec, 0x00ee, 0x00ef, 0x00f1, 0x00f3,
+	0x00f2, 0x00f4, 0x00f6, 0x00f5, 0x00fa, 0x00f9, 0x00fb, 0x00fc,
+	0x2020, 0x00b0, 0x00a2, 0x00a3, 0x00a7, 0x2022, 0x00b6, 0x00df,
+	0x00ae, 0x00a9, 0x2122, 0x00b4, 0x00a8, 0x2260, 0x00c6, 0x00d8,
+	0x221e, 0x00b1, 0x2264, 0x2265, 0x00a5, 0x00b5, 0x2202, 0x2211,
+	0x220f, 0x03c0, 0x222b, 0x00aa, 0x00ba, 0x2126, 0x00e6, 0x00f8,
+	0x00bf, 0x00a1, 0x00ac, 0x221a, 0x0192, 0x2248, 0x2206, 0x00ab,
+	0x00bb, 0x2026, 0x00a0, 0x00c0, 0x00c3, 0x00d5, 0x0152, 0x0153,
+	0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x25ca,
+	0x00ff, 0x0178, 0x2044, 0x00a4, 0x2039, 0x203a, 0xfb01, 0xfb02,
+	0x2021, 0x00b7, 0x201a, 0x201e, 0x2030, 0x00c2, 0x00ca, 0x00c1,
+	0x00cb, 0x00c8, 0x00cd, 0x00ce, 0x00cf, 0x00cc, 0x00d3, 0x00d4,
+	0x003f, 0x00d2, 0x00da, 0x00db, 0x00d9, 0x0131, 0x02c6, 0x02dc,
+	0x00af, 0x02d8, 0x02d9, 0x02da, 0x00b8, 0x02dd, 0x02db, 0x02c7,
+};
+
+static const USHORT usPrivateArea[] = {
+	0x0020, 0x0021, 0x2200, 0x0023, 0x2203, 0x0025, 0x0026, 0x220d,
+	0x0028, 0x0029, 0x2217, 0x002b, 0x002c, 0x2212, 0x002e, 0x002f,
+	0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+	0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x2019, 0x003e, 0x003f,
+	0x201d, 0x201c, 0x0392, 0x03a7, 0x0394, 0x0395, 0x03a6, 0x0393,
+	0x0397, 0x0399, 0x03d1, 0x039a, 0x039b, 0x039c, 0x039d, 0x039f,
+	0x03a0, 0x0398, 0x03a1, 0x03a3, 0x03a4, 0x03a5, 0x03c2, 0x03a9,
+	0x039e, 0x03a8, 0x0396, 0x005b, 0x2234, 0x005d, 0x22a5, 0x005f,
+	0x003f, 0x03b1, 0x03b2, 0x03c7, 0x03b4, 0x03b5, 0x03c6, 0x03b3,
+	0x03b7, 0x03b9, 0x03d5, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03bf,
+	0x03c0, 0x03b8, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03d6, 0x03c9,
+	0x03be, 0x03c8, 0x03b6, 0x007b, 0x007c, 0x007d, 0x223c, 0x003f,
+	0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f,
+	0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f,
+	0x003f, 0x003f, 0x003f, 0x2022, 0x003f, 0x003f, 0x003f, 0x003f,
+	0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f,
+	0x20ac, 0x03d2, 0x2032, 0x2264, 0x2044, 0x221e, 0x0192, 0x2663,
+	0x2666, 0x2665, 0x2660, 0x2194, 0x2190, 0x2191, 0x2192, 0x2193,
+	0x00b0, 0x00b1, 0x2033, 0x2265, 0x00d7, 0x221d, 0x2202, 0x2022,
+	0x00f7, 0x2260, 0x2261, 0x2248, 0x2026, 0x007c, 0x23af, 0x21b5,
+	0x2135, 0x2111, 0x211c, 0x2118, 0x2297, 0x2295, 0x2205, 0x2229,
+	0x222a, 0x2283, 0x2287, 0x2284, 0x2282, 0x2286, 0x2208, 0x2209,
+	0x2220, 0x2207, 0x00ae, 0x00a9, 0x2122, 0x220f, 0x221a, 0x22c5,
+	0x00ac, 0x2227, 0x2228, 0x21d4, 0x21d0, 0x21d1, 0x21d2, 0x21d3,
+	0x22c4, 0x3008, 0x00ae, 0x00a9, 0x2122, 0x2211, 0x239b, 0x239c,
+	0x239d, 0x23a1, 0x23a2, 0x23a3, 0x23a7, 0x23a8, 0x23a9, 0x23aa,
+	0x003f, 0x3009, 0x222b, 0x2320, 0x23ae, 0x2321, 0x239e, 0x239f,
+	0x23a0, 0x23a4, 0x23a5, 0x23a6, 0x23ab, 0x23ac, 0x23ad, 0x003f,
+};
+
+typedef struct char_table_tag {
+	UCHAR	ucLocal;
+	USHORT	usUnicode;
+} char_table_type;
+
+static char_table_type	atCharTable[256];
+static size_t		tNextPosFree = 0;
+
+
+/*
+ * iCompare - compare two records
+ *
+ * Compares two records. For use by qsort(3C) and bsearch(3C).
+ *
+ * returns -1 if rec1 < rec2, 0 if rec1 == rec2, 1 if rec1 > rec2
+ */
+static int
+iCompare(const void *pvRecord1, const void *pvRecord2)
+{
+	USHORT	usUnicode1, usUnicode2;
+
+	usUnicode1 = ((char_table_type *)pvRecord1)->usUnicode;
+	usUnicode2 = ((char_table_type *)pvRecord2)->usUnicode;
+
+	if (usUnicode1 < usUnicode2) {
+		return -1;
+	}
+	if (usUnicode1 > usUnicode2) {
+		return 1;
+	}
+	return 0;
+} /* end of iCompare */
+
+/*
+ * pGetCharTableRecord - get the character table record
+ *
+ * returns a pointer to the record when found, otherwise NULL
+ */
+static const char_table_type *
+pGetCharTableRecord(USHORT usUnicode)
+{
+	char_table_type	tKey;
+
+	if (tNextPosFree == 0) {
+		return NULL;
+	}
+	tKey.usUnicode = usUnicode;
+	tKey.ucLocal = 0;
+	return (char_table_type *)bsearch(&tKey,
+			atCharTable,
+			tNextPosFree, sizeof(atCharTable[0]),
+			iCompare);
+} /* end of pGetCharTableRecord */
+
+/*
+ * ucGetBulletCharacter - get the local representation of the bullet
+ */
+UCHAR
+ucGetBulletCharacter(conversion_type eConversionType, encoding_type eEncoding)
+{
+#if defined(__riscos)
+	return 0x8f;
+#else
+	const char_table_type	*pRec;
+
+	fail(eEncoding == encoding_utf_8);
+
+	if (eEncoding == encoding_latin_1 &&
+	    (eConversionType == conversion_ps ||
+	     eConversionType == conversion_pdf)) {
+		/* Ugly, but it makes the PostScript and PDF look better */
+		return (UCHAR)143;
+	}
+	if (eConversionType != conversion_text &&
+	    eConversionType != conversion_fmt_text) {
+		pRec = pGetCharTableRecord(UNICODE_BULLET);
+		if (pRec != NULL) {
+			return pRec->ucLocal;
+		}
+		pRec = pGetCharTableRecord(UNICODE_BULLET_OPERATOR);
+		if (pRec != NULL) {
+			return pRec->ucLocal;
+		}
+		pRec = pGetCharTableRecord(UNICODE_MIDDLE_DOT);
+		if (pRec != NULL) {
+			return pRec->ucLocal;
+		}
+	}
+	return (UCHAR)'.';
+#endif /* __riscos */
+} /* end of ucGetBulletCharacter */
+
+/*
+ * ucGetNbspCharacter - get the local representation of the non-breaking space
+ */
+UCHAR
+ucGetNbspCharacter(void)
+{
+	const char_table_type	*pRec;
+
+	pRec = pGetCharTableRecord(0x00a0);	/* Unicode non-breaking space */
+	if (pRec == NULL) {
+		DBG_MSG("Non-breaking space record not found");
+		/* No value found, use the best guess */
+		return (UCHAR)0xa0;
+	}
+	return pRec->ucLocal;
+} /* end of ucGetNbspCharacter */
+
+/*
+ * bReadCharacterMappingTable - read the mapping table
+ *
+ * Read the character mapping table from file and have the contents sorted
+ *
+ * returns TRUE if successful, otherwise FALSE
+ */
+BOOL
+bReadCharacterMappingTable(FILE *pFile)
+{
+	char	*pcTmp;
+	ULONG	ulUnicode;
+	UINT	uiLocal;
+	int	iFields;
+	char	szLine[81];
+
+	if (pFile == NULL) {
+		return FALSE;
+	}
+
+	/* Clean the table first */
+	(void)memset(atCharTable, 0, sizeof(atCharTable));
+
+	/* Fill the table */
+	while (fgets(szLine, (int)sizeof(szLine), pFile)) {
+		if (szLine[0] == '#' ||
+		    szLine[0] == '\r' ||
+		    szLine[0] == '\n') {
+			/* Comment or empty line */
+			continue;
+		}
+		iFields = sscanf(szLine, "%x %lx %*s", &uiLocal, &ulUnicode);
+		if (iFields != 2) {
+			pcTmp = strchr(szLine, '\r');
+			if (pcTmp != NULL) {
+				*pcTmp = '\0';
+			}
+			pcTmp = strchr(szLine, '\n');
+			if (pcTmp != NULL) {
+				*pcTmp = '\0';
+			}
+			werr(0, "Syntax error in: '%s'", szLine);
+			continue;
+		}
+		if (uiLocal > 0xff || ulUnicode > 0xffff) {
+			werr(0, "Syntax error in: '%02x %04lx'",
+					uiLocal, ulUnicode);
+			continue;
+		}
+		/* Store only the relevant entries */
+		if (uiLocal != ulUnicode || uiLocal >= 0x80) {
+			atCharTable[tNextPosFree].ucLocal = (UCHAR)uiLocal;
+			atCharTable[tNextPosFree].usUnicode = (USHORT)ulUnicode;
+			tNextPosFree++;
+		}
+		if (tNextPosFree >= elementsof(atCharTable)) {
+			werr(0, "Too many entries in the character mapping "
+				"file. Ignoring the rest.");
+			break;
+		}
+	}
+
+	if (tNextPosFree != 0) {
+		DBG_HEX(atCharTable[0].usUnicode);
+		DBG_HEX(atCharTable[tNextPosFree - 1].usUnicode);
+
+		qsort(atCharTable,
+			tNextPosFree, sizeof(atCharTable[0]),
+			iCompare);
+
+		DBG_HEX(atCharTable[0].usUnicode);
+		DBG_HEX(atCharTable[tNextPosFree - 1].usUnicode);
+	}
+
+	return TRUE;
+} /* end of bReadCharacterMappingTable */
+
+/*
+ * ulTranslateCharacters - Translate characters to local representation
+ *
+ * Translate all characters to local representation
+ *
+ * returns the translated character
+ */
+ULONG
+ulTranslateCharacters(USHORT usChar, ULONG ulFileOffset, int iWordVersion,
+	conversion_type eConversionType, encoding_type eEncoding,
+	BOOL bUseMacCharSet)
+{
+	const char_table_type	*pTmp;
+	const USHORT	*usCharSet;
+
+	usCharSet = NULL;
+	if (bUseMacCharSet) {
+		/* Macintosh character set */
+		usCharSet = usMacRoman;
+	} else if (iWordVersion == 0) {
+		/* DOS character set */
+		usCharSet = usCp850;
+	} else {
+		/* Windows character set */
+		switch (eEncoding) {
+		case encoding_latin_2:
+			usCharSet = usCp1250;
+			break;
+		case encoding_cyrillic:
+			usCharSet = usCp1251;
+			break;
+		case encoding_latin_1:
+		default:
+			usCharSet = usCp1252;
+			break;
+		}
+	}
+	fail(usCharSet == NULL);
+	if (usChar >= 0x80 && usChar <= 0x9f) {
+		/* Translate implementation defined characters */
+		usChar = usCharSet[usChar - 0x80];
+	} else if (iWordVersion < 8 && usChar >= 0xa0 && usChar <= 0xff) {
+		/* Translate old character set to Unixcode */
+		usChar = usCharSet[usChar - 0x80];
+	}
+
+	/* Microsoft Unicode to real Unicode */
+	if (usChar >= 0xf020 && usChar <= 0xf0ff) {
+		DBG_HEX_C(usPrivateArea[usChar - 0xf020] == 0x003f, usChar);
+		usChar = usPrivateArea[usChar - 0xf020];
+	}
+
+	/* Characters with a special meaning in Word */
+	switch (usChar) {
+	case IGNORE_CHARACTER:
+	case FOOTNOTE_SEPARATOR:
+	case FOOTNOTE_CONTINUATION:
+	case ANNOTATION:
+	case FRAME:
+	case LINE_FEED:
+	case WORD_SOFT_HYPHEN:
+	case UNICODE_HYPHENATION_POINT:
+		return IGNORE_CHARACTER;
+	case PICTURE:
+	case TABLE_SEPARATOR:
+	case TAB:
+	case HARD_RETURN:
+	case PAGE_BREAK:
+	case PAR_END:
+	case COLUMN_FEED:
+		return (ULONG)usChar;
+	case FOOTNOTE_OR_ENDNOTE:
+		NO_DBG_HEX(ulFileOffset);
+		switch (eGetNotetype(ulFileOffset)) {
+		case notetype_is_footnote:
+			return FOOTNOTE_CHAR;
+		case notetype_is_endnote:
+			return ENDNOTE_CHAR;
+		default:
+			return UNKNOWN_NOTE_CHAR;
+		}
+	case WORD_UNBREAKABLE_JOIN:
+		return (ULONG)OUR_UNBREAKABLE_JOIN;
+	default:
+		break;
+	}
+
+	if (eEncoding != encoding_utf_8) {
+		/* Latin characters in an oriental text */
+		if (usChar >= 0xff01 && usChar <= 0xff5e) {
+			usChar -= 0xfee0;
+		}
+	}
+
+	if (eEncoding == encoding_latin_1 &&
+	    (eConversionType == conversion_ps ||
+	     eConversionType == conversion_pdf)) {
+		/* Ugly, but it makes the PostScript and PDF look better */
+		switch (usChar) {
+		case UNICODE_ELLIPSIS:
+			return 140;
+		case UNICODE_TRADEMARK_SIGN:
+			return 141;
+		case UNICODE_PER_MILLE_SIGN:
+			return 142;
+		case UNICODE_BULLET:
+		case UNICODE_BULLET_OPERATOR:
+		case UNICODE_BLACK_CLUB_SUIT:
+			return 143;
+		case UNICODE_LEFT_SINGLE_QMARK:
+			return 144;
+		case UNICODE_RIGHT_SINGLE_QMARK:
+			return 145;
+		case UNICODE_SINGLE_LEFT_ANGLE_QMARK:
+			return 146;
+		case UNICODE_SINGLE_RIGHT_ANGLE_QMARK:
+			return 147;
+		case UNICODE_LEFT_DOUBLE_QMARK:
+			return 148;
+		case UNICODE_RIGHT_DOUBLE_QMARK:
+			return 149;
+		case UNICODE_DOUBLE_LOW_9_QMARK:
+			return 150;
+		case UNICODE_EN_DASH:
+			return 151;
+		case UNICODE_EM_DASH:
+			return 152;
+		case UNICODE_MINUS_SIGN:
+			return 153;
+		case UNICODE_CAPITAL_LIGATURE_OE:
+			return 154;
+		case UNICODE_SMALL_LIGATURE_OE:
+			return 155;
+		case UNICODE_DAGGER:
+			return 156;
+		case UNICODE_DOUBLE_DAGGER:
+			return 157;
+		case UNICODE_SMALL_LIGATURE_FI:
+			return 158;
+		case UNICODE_SMALL_LIGATURE_FL:
+			return 159;
+		default:
+			break;
+		}
+	}
+
+	if (eConversionType == conversion_pdf) {
+		if (eEncoding == encoding_latin_1) {
+			switch (usChar) {
+			case UNICODE_EURO_SIGN:
+				return 128;
+			default:
+				break;
+			}
+		} else if (eEncoding == encoding_latin_2) {
+			switch (usChar) {
+			case UNICODE_CAPITAL_D_WITH_STROKE:
+			case UNICODE_SMALL_D_WITH_STROKE:
+				return 0x3f;
+			default:
+				break;
+			}
+		}
+	}
+
+	if (usChar < 0x80) {
+		/* US ASCII */
+		if (usChar < 0x20 || usChar == 0x7f) {
+			/* Ignore control characters */
+			DBG_HEX(usChar);
+			DBG_FIXME();
+			return IGNORE_CHARACTER;
+		}
+		return (ULONG)usChar;
+	}
+
+	if (eEncoding == encoding_utf_8) {
+		/* No need to convert Unicode characters */
+		return (ULONG)usChar;
+	}
+
+	/* Unicode to local representation */
+	pTmp = pGetCharTableRecord(usChar);
+	if (pTmp != NULL) {
+		DBG_HEX_C(usChar >= 0x7f && usChar <= 0x9f, usChar);
+		return (ULONG)pTmp->ucLocal;
+	}
+
+	/* Fancy characters to simple US ASCII */
+	switch (usChar) {
+	case UNICODE_SMALL_F_HOOK:
+		return (ULONG)'f';
+	case UNICODE_GREEK_CAPITAL_CHI:
+		return (ULONG)'X';
+	case UNICODE_GREEK_SMALL_UPSILON:
+		return (ULONG)'v';
+	case UNICODE_MODIFIER_CIRCUMFLEX:
+	case UNICODE_UPWARDS_ARROW:
+		return (ULONG)'^';
+	case UNICODE_SMALL_TILDE:
+	case UNICODE_TILDE_OPERATOR:
+		return (ULONG)'~';
+	case UNICODE_EN_QUAD:
+	case UNICODE_EM_QUAD:
+	case UNICODE_EN_SPACE:
+	case UNICODE_EM_SPACE:
+	case UNICODE_THREE_PER_EM_SPACE:
+	case UNICODE_FOUR_PER_EM_SPACE:
+	case UNICODE_SIX_PER_EM_SPACE:
+	case UNICODE_FIGURE_SPACE:
+	case UNICODE_PUNCTUATION_SPACE:
+	case UNICODE_THIN_SPACE:
+	case UNICODE_NARROW_NO_BREAK_SPACE:
+	case UNICODE_LIGHT_SHADE:
+	case UNICODE_MEDIUM_SHADE:
+	case UNICODE_DARK_SHADE:
+		return (ULONG)' ';
+	case UNICODE_LEFT_DOUBLE_QMARK:
+	case UNICODE_RIGHT_DOUBLE_QMARK:
+	case UNICODE_DOUBLE_LOW_9_QMARK:
+	case UNICODE_DOUBLE_HIGH_REV_9_QMARK:
+	case UNICODE_DOUBLE_PRIME:
+		return (ULONG)'"';
+	case UNICODE_LEFT_SINGLE_QMARK:
+	case UNICODE_RIGHT_SINGLE_QMARK:
+	case UNICODE_SINGLE_LOW_9_QMARK:
+	case UNICODE_SINGLE_HIGH_REV_9_QMARK:
+	case UNICODE_PRIME:
+		return (ULONG)'\'';
+	case UNICODE_HYPHEN:
+	case UNICODE_NON_BREAKING_HYPHEN:
+	case UNICODE_FIGURE_DASH:
+	case UNICODE_EN_DASH:
+	case UNICODE_EM_DASH:
+	case UNICODE_HORIZONTAL_BAR:
+	case UNICODE_MINUS_SIGN:
+	case UNICODE_BD_LIGHT_HORIZONTAL:
+	case UNICODE_BD_DOUBLE_HORIZONTAL:
+		return (ULONG)'-';
+	case UNICODE_DOUBLE_VERTICAL_LINE:
+	case UNICODE_BD_LIGHT_VERTICAL:
+	case UNICODE_BD_DOUBLE_VERTICAL:
+		return (ULONG)'|';
+	case UNICODE_DOUBLE_LOW_LINE:
+		return (ULONG)'_';
+	case UNICODE_DAGGER:
+		return (ULONG)'+';
+	case UNICODE_DOUBLE_DAGGER:
+		return (ULONG)'#';
+	case UNICODE_BULLET:
+	case UNICODE_BULLET_OPERATOR:
+	case UNICODE_BLACK_CLUB_SUIT:
+		return (ULONG)ucGetBulletCharacter(eConversionType, eEncoding);
+	case UNICODE_ONE_DOT_LEADER:
+	case UNICODE_TWO_DOT_LEADER:
+		return (ULONG)'.';
+	case UNICODE_ELLIPSIS:
+#if defined(__riscos)
+		return (ULONG)OUR_ELLIPSIS;
+#else
+		if (ulFileOffset == 0) {
+			return (ULONG)OUR_ELLIPSIS;
+		}
+		return UNICODE_ELLIPSIS;
+#endif /* __riscos */
+	case UNICODE_DOUBLE_LEFT_ANGLE_QMARK:
+	case UNICODE_TRIANGULAR_BULLET:
+	case UNICODE_SINGLE_LEFT_ANGLE_QMARK:
+	case UNICODE_LEFTWARDS_ARROW:
+		return (ULONG)'<';
+	case UNICODE_DOUBLE_RIGHT_ANGLE_QMARK:
+	case UNICODE_SINGLE_RIGHT_ANGLE_QMARK:
+	case UNICODE_RIGHTWARDS_ARROW:
+		return (ULONG)'>';
+	case UNICODE_UNDERTIE:
+		return (ULONG)'-';
+	case UNICODE_N_ARY_SUMMATION:
+		return (ULONG)'S';
+	case UNICODE_EURO_SIGN:
+		return (ULONG)'E';
+	case UNICODE_CIRCLE:
+	case UNICODE_SQUARE:
+		return (ULONG)'O';
+	case UNICODE_DIAMOND:
+		return (ULONG)OUR_DIAMOND;
+	case UNICODE_NUMERO_SIGN:
+		return (ULONG)'N';
+	case UNICODE_KELVIN_SIGN:
+		return (ULONG)'K';
+	case UNICODE_DOWNWARDS_ARROW:
+		return (ULONG)'v';
+	case UNICODE_FRACTION_SLASH:
+	case UNICODE_DIVISION_SLASH:
+		return (ULONG)'/';
+	case UNICODE_ASTERISK_OPERATOR:
+		return (ULONG)'*';
+	case UNICODE_RATIO:
+		return (ULONG)':';
+	case UNICODE_BD_LIGHT_DOWN_RIGHT:
+	case UNICODE_BD_LIGHT_DOWN_AND_LEFT:
+	case UNICODE_BD_LIGHT_UP_AND_RIGHT:
+	case UNICODE_BD_LIGHT_UP_AND_LEFT:
+	case UNICODE_BD_LIGHT_VERTICAL_AND_RIGHT:
+	case UNICODE_BD_LIGHT_VERTICAL_AND_LEFT:
+	case UNICODE_BD_LIGHT_DOWN_AND_HORIZONTAL:
+	case UNICODE_BD_LIGHT_UP_AND_HORIZONTAL:
+	case UNICODE_BD_LIGHT_VERTICAL_AND_HORIZONTAL:
+	case UNICODE_BD_DOUBLE_DOWN_AND_RIGHT:
+	case UNICODE_BD_DOUBLE_DOWN_AND_LEFT:
+	case UNICODE_BD_DOUBLE_UP_AND_RIGHT:
+	case UNICODE_BD_DOUBLE_UP_AND_LEFT:
+	case UNICODE_BD_DOUBLE_VERTICAL_AND_RIGHT:
+	case UNICODE_BD_DOUBLE_VERTICAL_AND_LEFT:
+	case UNICODE_BD_DOUBLE_DOWN_AND_HORIZONTAL:
+	case UNICODE_BD_DOUBLE_UP_AND_HORIZONTAL:
+	case UNICODE_BD_DOUBLE_VERTICAL_AND_HORIZONTAL:
+	case UNICODE_BLACK_SQUARE:
+		return (ULONG)'+';
+	case UNICODE_HAIR_SPACE:
+	case UNICODE_ZERO_WIDTH_SPACE:
+	case UNICODE_ZERO_WIDTH_NON_JOINER:
+	case UNICODE_ZERO_WIDTH_JOINER:
+	case UNICODE_LEFT_TO_RIGHT_MARK:
+	case UNICODE_RIGHT_TO_LEFT_MARK:
+	case UNICODE_LEFT_TO_RIGHT_EMBEDDING:
+	case UNICODE_RIGHT_TO_LEFT_EMBEDDING:
+	case UNICODE_POP_DIRECTIONAL_FORMATTING:
+	case UNICODE_LEFT_TO_RIGHT_OVERRIDE:
+	case UNICODE_RIGHT_TO_LEFT_OVERRIDE:
+	case UNICODE_ZERO_WIDTH_NO_BREAK_SPACE:
+		return IGNORE_CHARACTER;
+	default:
+		break;
+	}
+
+	if (usChar == UNICODE_TRADEMARK_SIGN) {
+		/*
+		 * No local representation, it doesn't look like anything in
+		 * US-ASCII and a question mark does more harm than good.
+		 */
+		return IGNORE_CHARACTER;
+	}
+
+	if (usChar >= 0xa0 && usChar <= 0xff) {
+		/* Before Word 97, Word did't use Unicode */
+		return (ULONG)usChar;
+	}
+
+	DBG_HEX_C(usChar < 0x3000 || usChar >= 0xd800, ulFileOffset);
+	DBG_HEX_C(usChar < 0x3000 || usChar >= 0xd800, usChar);
+	DBG_MSG_C(usChar >= 0xe000 && usChar < 0xf900, "Private Use Area");
+
+	/* Untranslated Unicode character */
+	return 0x3f;
+} /* end of ulTranslateCharacters */
+
+/*
+ * ulToUpper - convert letter to upper case
+ *
+ * This function converts a letter to upper case. Unlike toupper(3) this
+ * function is independent from the settings of locale. This comes in handy
+ * for people who have to read Word documents in more than one language or
+ * contain more than one language.
+ *
+ * returns the converted letter, or ulChar if the conversion was not possible.
+ */
+ULONG
+ulToUpper(ULONG ulChar)
+{
+	if (ulChar < 0x80) {
+		/* US ASCII: use standard function */
+		return (ULONG)toupper((int)ulChar);
+	}
+	if (ulChar >= 0xe0 && ulChar <= 0xfe && ulChar != 0xf7) {
+		/*
+		 * Lower case accented characters
+		 * 0xf7 is Division sign; 0xd7 is Multiplication sign
+		 * 0xff is y with diaeresis; 0xdf is Sharp s
+		 */
+		return ulChar & ~0x20;
+	}
+#if defined(__STDC_ISO_10646__)
+	/*
+	 * If this is ISO C99 and all locales have wchar_t = ISO 10646
+	 * (e.g., glibc 2.2 or newer), then use standard function
+	 */
+	if (ulChar > 0xff) {
+		return (ULONG)towupper((wint_t)ulChar);
+	}
+#endif /* __STDC_ISO_10646__ */
+	return ulChar;
+} /* end of ulToUpper */
diff --git a/datalist.c b/datalist.c
new file mode 100644
index 0000000..564f469
--- /dev/null
+++ b/datalist.c
@@ -0,0 +1,374 @@
+/*
+ * datalist.c
+ * Copyright (C) 2000-2002 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Build, read and destroy a list of Word data blocks
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include "antiword.h"
+
+#if defined(__riscos)
+#define EIO		42
+#endif /* __riscos */
+
+
+/*
+ * Private structure to hide the way the information
+ * is stored from the rest of the program
+ */
+typedef struct data_mem_tag {
+	data_block_type		tInfo;
+	struct data_mem_tag	*pNext;
+} data_mem_type;
+
+/* Variable to describe the start of the data block list */
+static data_mem_type	*pAnchor = NULL;
+/* Variable needed to read the data block list */
+static data_mem_type	*pBlockLast = NULL;
+/* Variable needed to read the data block list */
+static data_mem_type	*pBlockCurrent = NULL;
+static ULONG	ulBlockOffset = 0;
+static size_t	tByteNext = 0;
+/* Last block read */
+static UCHAR	aucBlock[BIG_BLOCK_SIZE];
+
+
+/*
+ * vDestroyDataBlockList - destroy the data block list
+ */
+void
+vDestroyDataBlockList(void)
+{
+	data_mem_type	*pCurr, *pNext;
+
+	DBG_MSG("vDestroyDataBlockList");
+
+	pCurr = pAnchor;
+	while (pCurr != NULL) {
+		pNext = pCurr->pNext;
+		pCurr = xfree(pCurr);
+		pCurr = pNext;
+	}
+	pAnchor = NULL;
+	/* Reset all the control variables */
+	pBlockLast = NULL;
+	pBlockCurrent = NULL;
+	ulBlockOffset = 0;
+	tByteNext = 0;
+} /* end of vDestroyDataBlockList */
+
+/*
+ * bAdd2DataBlockList - add an element to the data block list
+ *
+ * Returns TRUE when successful, otherwise FALSE
+ */
+BOOL
+bAdd2DataBlockList(const data_block_type *pDataBlock)
+{
+	data_mem_type	*pListMember;
+
+	fail(pDataBlock == NULL);
+	fail(pDataBlock->ulFileOffset == FC_INVALID);
+	fail(pDataBlock->ulDataPos == CP_INVALID);
+	fail(pDataBlock->ulLength == 0);
+
+	NO_DBG_MSG("bAdd2DataBlockList");
+	NO_DBG_HEX(pDataBlock->ulFileOffset);
+	NO_DBG_HEX(pDataBlock->ulDataPos);
+	NO_DBG_HEX(pDataBlock->ulLength);
+
+	if (pDataBlock->ulFileOffset == FC_INVALID ||
+	    pDataBlock->ulDataPos == CP_INVALID ||
+	    pDataBlock->ulLength == 0) {
+		werr(0, "Software (datablock) error");
+		return FALSE;
+	}
+	/* Check for continuous blocks */
+	if (pBlockLast != NULL &&
+	    pBlockLast->tInfo.ulFileOffset +
+	     pBlockLast->tInfo.ulLength == pDataBlock->ulFileOffset &&
+	    pBlockLast->tInfo.ulDataPos +
+	     pBlockLast->tInfo.ulLength == pDataBlock->ulDataPos) {
+		/* These are continous blocks */
+		pBlockLast->tInfo.ulLength += pDataBlock->ulLength;
+		return TRUE;
+	}
+	/* Make a new block */
+	pListMember = xmalloc(sizeof(data_mem_type));
+	/* Add the block to the data list */
+	pListMember->tInfo = *pDataBlock;
+	pListMember->pNext = NULL;
+	if (pAnchor == NULL) {
+		pAnchor = pListMember;
+	} else {
+		fail(pBlockLast == NULL);
+		pBlockLast->pNext = pListMember;
+	}
+	pBlockLast = pListMember;
+	return TRUE;
+} /* end of bAdd2DataBlockList */
+
+/*
+ * ulGetDataOffset - get the offset in the data block list
+ *
+ * Get the fileoffset the current position in the data block list
+ */
+ULONG
+ulGetDataOffset(FILE *pFile)
+{
+	return pBlockCurrent->tInfo.ulFileOffset + ulBlockOffset + tByteNext;
+} /* end of ulGetDataOffset */
+
+/*
+ * bSetDataOffset - set the offset in the data block list
+ *
+ * Make the given fileoffset the current position in the data block list
+ */
+BOOL
+bSetDataOffset(FILE *pFile, ULONG ulFileOffset)
+{
+	data_mem_type	*pCurr;
+	size_t	tReadLen;
+
+	DBG_HEX(ulFileOffset);
+
+	for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
+		if (ulFileOffset < pCurr->tInfo.ulFileOffset ||
+		    ulFileOffset >= pCurr->tInfo.ulFileOffset +
+		     pCurr->tInfo.ulLength) {
+			/* The file offset is not in this block */
+			continue;
+		}
+		/* Compute the maximum number of bytes to read */
+		tReadLen = (size_t)(pCurr->tInfo.ulFileOffset +
+				pCurr->tInfo.ulLength -
+				ulFileOffset);
+		/* Compute the real number of bytes to read */
+		if (tReadLen > sizeof(aucBlock)) {
+			tReadLen = sizeof(aucBlock);
+		}
+		/* Read the bytes */
+		if (!bReadBytes(aucBlock, tReadLen, ulFileOffset, pFile)) {
+			return FALSE;
+		}
+		/* Set the control variables */
+		pBlockCurrent = pCurr;
+		ulBlockOffset = ulFileOffset - pCurr->tInfo.ulFileOffset;
+		tByteNext = 0;
+		return TRUE;
+	}
+	return FALSE;
+} /* end of bSetDataOffset */
+
+/*
+ * iNextByte - get the next byte from the data block list
+ */
+int
+iNextByte(FILE *pFile)
+{
+	ULONG	ulReadOff;
+	size_t	tReadLen;
+
+	fail(pBlockCurrent == NULL);
+
+	if (tByteNext >= sizeof(aucBlock) ||
+	    ulBlockOffset + tByteNext >= pBlockCurrent->tInfo.ulLength) {
+		if (ulBlockOffset + sizeof(aucBlock) <
+					pBlockCurrent->tInfo.ulLength) {
+			/* Same block, next part */
+			ulBlockOffset += sizeof(aucBlock);
+		} else {
+			/* Next block, first part */
+			pBlockCurrent = pBlockCurrent->pNext;
+			ulBlockOffset = 0;
+		}
+		if (pBlockCurrent == NULL) {
+			/* Past the last part of the last block */
+			errno = EIO;
+			return EOF;
+		}
+		tReadLen = (size_t)
+				(pBlockCurrent->tInfo.ulLength - ulBlockOffset);
+		if (tReadLen > sizeof(aucBlock)) {
+			tReadLen = sizeof(aucBlock);
+		}
+		ulReadOff = pBlockCurrent->tInfo.ulFileOffset + ulBlockOffset;
+		if (!bReadBytes(aucBlock, tReadLen, ulReadOff, pFile)) {
+			errno = EIO;
+			return EOF;
+		}
+		tByteNext = 0;
+	}
+	return (int)aucBlock[tByteNext++];
+} /* end of iNextByte */
+
+/*
+ * usNextWord - get the next word from the data block list
+ *
+ * Read a two byte value in Little Endian order, that means MSB last
+ *
+ * All return values can be valid so errno is set in case of error
+ */
+USHORT
+usNextWord(FILE *pFile)
+{
+	USHORT	usLSB, usMSB;
+
+	usLSB = (USHORT)iNextByte(pFile);
+	if (usLSB == (USHORT)EOF) {
+		errno = EIO;
+		return (USHORT)EOF;
+	}
+	usMSB = (USHORT)iNextByte(pFile);
+	if (usMSB == (USHORT)EOF) {
+		DBG_MSG("usNextWord: Unexpected EOF");
+		errno = EIO;
+		return (USHORT)EOF;
+	}
+	return (usMSB << 8) | usLSB;
+} /* end of usNextWord */
+
+/*
+ * ulNextLong - get the next long from the data block list
+ *
+ * Read a four byte value in Little Endian order, that means MSW last
+ *
+ * All return values can be valid so errno is set in case of error
+ */
+ULONG
+ulNextLong(FILE *pFile)
+{
+	ULONG	ulLSW, ulMSW;
+
+	ulLSW = (ULONG)usNextWord(pFile);
+	if (ulLSW == (ULONG)EOF) {
+		errno = EIO;
+		return (ULONG)EOF;
+	}
+	ulMSW = (ULONG)usNextWord(pFile);
+	if (ulMSW == (ULONG)EOF) {
+		DBG_MSG("ulNextLong: Unexpected EOF");
+		errno = EIO;
+		return (ULONG)EOF;
+	}
+	return (ulMSW << 16) | ulLSW;
+} /* end of ulNextLong */
+
+/*
+ * usNextWordBE - get the next two byte value
+ *
+ * Read a two byte value in Big Endian order, that means MSB first
+ *
+ * All return values can be valid so errno is set in case of error
+ */
+USHORT
+usNextWordBE(FILE *pFile)
+{
+	USHORT usLSB, usMSB;
+
+	usMSB = (USHORT)iNextByte(pFile);
+	if (usMSB == (USHORT)EOF) {
+		errno = EIO;
+		return (USHORT)EOF;
+	}
+	usLSB = (USHORT)iNextByte(pFile);
+	if (usLSB == (USHORT)EOF) {
+		DBG_MSG("usNextWordBE: Unexpected EOF");
+		errno = EIO;
+		return (USHORT)EOF;
+	}
+	return (usMSB << 8) | usLSB;
+} /* end of usNextWordBE */
+
+/*
+ * ulNextLongBE - get the next four byte value
+ *
+ * Read a four byte value in Big Endian order, that means MSW first
+ *
+ * All return values can be valid so errno is set in case of error
+ */
+ULONG
+ulNextLongBE(FILE *pFile)
+{
+	ULONG	ulLSW, ulMSW;
+
+	ulMSW = (ULONG)usNextWordBE(pFile);
+	if (ulMSW == (ULONG)EOF) {
+		errno = EIO;
+		return (ULONG)EOF;
+	}
+	ulLSW = (ULONG)usNextWordBE(pFile);
+	if (ulLSW == (ULONG)EOF) {
+		DBG_MSG("ulNextLongBE: Unexpected EOF");
+		errno = EIO;
+		return (ULONG)EOF;
+	}
+	return (ulMSW << 16) | ulLSW;
+} /* end of ulNextLongBE */
+
+/*
+ * tSkipBytes - skip over the given number of bytes
+ *
+ * Returns the number of skipped bytes
+ */
+size_t
+tSkipBytes(FILE *pFile, size_t tToSkip)
+{
+	size_t	tToGo, tMaxMove, tMove;
+
+	fail(pFile == NULL);
+	fail(pBlockCurrent == NULL);
+
+	tToGo = tToSkip;
+	while (tToGo != 0) {
+		/* Goto the end of the current block */
+		tMaxMove = min(sizeof(aucBlock) - tByteNext,
+				(size_t)(pBlockCurrent->tInfo.ulLength -
+				ulBlockOffset - tByteNext));
+		tMove = min(tMaxMove, tToGo);
+		tByteNext += tMove;
+		tToGo -= tMove;
+		if (tToGo != 0) {
+			/* Goto the next block */
+			if (iNextByte(pFile) == EOF) {
+				return tToSkip - tToGo;
+			}
+			tToGo--;
+		}
+	}
+	return tToSkip;
+} /* end of tSkipBytes */
+
+/*
+ * Translate  a data position to an offset in the file.
+ * Logical to physical offset.
+ *
+ * Returns:	FC_INVALID: in case of error
+ *		otherwise: the computed file offset
+ */
+ULONG
+ulDataPos2FileOffset(ULONG ulDataPos)
+{
+	data_mem_type	*pCurr;
+
+	fail(ulDataPos == CP_INVALID);
+
+	for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
+		if (ulDataPos < pCurr->tInfo.ulDataPos ||
+		    ulDataPos >= pCurr->tInfo.ulDataPos +
+		     pCurr->tInfo.ulLength) {
+			/* The data offset is not in this block, try the next */
+			continue;
+		}
+		/* The data offset is in the current block */
+		return pCurr->tInfo.ulFileOffset +
+				ulDataPos -
+				pCurr->tInfo.ulDataPos;
+	}
+	/* Passed beyond the end of the list */
+	DBG_HEX_C(ulDataPos != 0, ulDataPos);
+	return FC_INVALID;
+} /* end of ulDataPos2FileOffset */
diff --git a/debug.h b/debug.h
new file mode 100644
index 0000000..4dee4d4
--- /dev/null
+++ b/debug.h
@@ -0,0 +1,117 @@
+/*
+ * debug.h
+ * Copyright (C) 1998-2005 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Macro's for debuging.
+ */
+
+#if !defined(__debug_h)
+#define __debug_h 1
+
+#include <stdio.h>
+#include <ctype.h>
+
+#if defined(DEBUG)
+
+#define DBG_MSG(t)	(void)fprintf(stderr,\
+				"%s[%3d]: %.240s\n",\
+				__FILE__, __LINE__, (t))
+
+#define DBG_STRN(t,m)	(void)fprintf(stderr,\
+				"%s[%3d]: %d '%.*s'\n",\
+				__FILE__, __LINE__,\
+				(int)(m), (int)(m), (const char *)(t))
+
+#define DBG_CHR(m)    (void)fprintf(stderr,\
+				"%s[%3d]: "#m" = %3d 0x%02x '%c'\n",\
+				__FILE__, __LINE__,\
+				(int)(m), (unsigned int)(unsigned char)(m),\
+				isprint((int)(unsigned char)(m))?(char)(m):' ')
+
+#define DBG_DEC(m)	(void)fprintf(stderr,\
+				"%s[%3d]: "#m" = %ld\n",\
+				__FILE__, __LINE__, (long)(m))
+
+#define DBG_HEX(m)	(void)fprintf(stderr,\
+				"%s[%3d]: "#m" = 0x%02lx\n",\
+				__FILE__, __LINE__, (unsigned long)(m))
+
+#define DBG_FLT(m)	(void)fprintf(stderr,\
+				"%s[%3d]: "#m" = %.3f\n",\
+				__FILE__, __LINE__, (double)(m))
+
+#define DBG_FIXME()	(void)fprintf(stderr,\
+				"%s[%3d]: FIXME\n",\
+				__FILE__, __LINE__)
+
+#define DBG_PRINT_BLOCK(b,m)	vPrintBlock(__FILE__, __LINE__,(b),(m))
+#define DBG_UNICODE(t)		vPrintUnicode(__FILE__, __LINE__,\
+					(const UCHAR *)(t),unilen(t))
+#define DBG_UNICODE_N(t,m)	vPrintUnicode(__FILE__, __LINE__,\
+					(const UCHAR *)(t),(m))
+
+#define DBG_MSG_C(c,t)		do { if (c) DBG_MSG(t); } while(0)
+#define DBG_STRN_C(c,t,m)	do { if (c) DBG_STRN(t,m); } while(0)
+#define DBG_CHR_C(c,m)		do { if (c) DBG_CHR(m); } while(0)
+#define DBG_DEC_C(c,m)		do { if (c) DBG_DEC(m); } while(0)
+#define DBG_HEX_C(c,m)		do { if (c) DBG_HEX(m); } while(0)
+#define DBG_FLT_C(c,m)		do { if (c) DBG_FLT(m); } while(0)
+
+#else
+
+#define DBG_MSG(t)		/* EMPTY */
+#define DBG_STRN(t,m)		/* EMPTY */
+#define DBG_CHR(m)		/* EMPTY */
+#define DBG_DEC(m)		/* EMPTY */
+#define DBG_HEX(m)		/* EMPTY */
+#define DBG_FLT(m)		/* EMPTY */
+
+#define DBG_FIXME()		/* EMPTY */
+#define DBG_PRINT_BLOCK(b,m)	/* EMPTY */
+#define DBG_UNICODE(t)		/* EMPTY */
+#define DBG_UNICODE_N(t,m)	/* EMPTY */
+
+#define DBG_MSG_C(c,t)		/* EMPTY */
+#define DBG_STRN_C(c,t,m)	/* EMPTY */
+#define DBG_CHR_C(c,m)		/* EMPTY */
+#define DBG_DEC_C(c,m)		/* EMPTY */
+#define DBG_HEX_C(c,m)		/* EMPTY */
+#define DBG_FLT_C(c,m)		/* EMPTY */
+
+#endif /* DEBUG */
+
+#define NO_DBG_MSG(t)		/* EMPTY */
+#define NO_DBG_STRN(t,m)	/* EMPTY */
+#define NO_DBG_CHR(m)		/* EMPTY */
+#define NO_DBG_DEC(m)		/* EMPTY */
+#define NO_DBG_HEX(m)		/* EMPTY */
+#define NO_DBG_FLT(m)		/* EMPTY */
+
+#define NO_DBG_PRINT_BLOCK(b,m)	/* EMPTY */
+#define NO_DBG_UNICODE(t)	/* EMPTY */
+#define NO_DBG_UNICODE_N(t,m)	/* EMPTY */
+
+#define NO_DBG_MSG_C(c,t)	/* EMPTY */
+#define NO_DBG_STRN_C(c,t,m)	/* EMPTY */
+#define NO_DBG_CHR_C(c,m)	/* EMPTY */
+#define NO_DBG_DEC_C(c,m)	/* EMPTY */
+#define NO_DBG_HEX_C(c,m)	/* EMPTY */
+#define NO_DBG_FLT_C(c,m)	/* EMPTY */
+
+#if defined(TRACE)
+
+#define TRACE_MSG(t)	do {\
+			(void)fprintf(stderr,\
+				"%s[%3d]: TRACE:%.40s\n",\
+				__FILE__, __LINE__, (t));\
+			(void)fflush(stderr);\
+			} while(0)
+
+#else
+
+#define TRACE_MSG(t)		/* EMPTY */
+
+#endif /* TRACE */
+
+#endif /* !__debug_h */
diff --git a/depot.c b/depot.c
new file mode 100644
index 0000000..295c39d
--- /dev/null
+++ b/depot.c
@@ -0,0 +1,114 @@
+/*
+ * depot.c
+ * Copyright (C) 1998-2002 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Functions to compute the depot offset
+ */
+
+#include "antiword.h"
+
+#define SIZE_RATIO	(BIG_BLOCK_SIZE/SMALL_BLOCK_SIZE)
+
+static ULONG	*aulSmallBlockList = NULL;
+static size_t	tSmallBlockListLen = 0;
+
+
+/*
+ * vDestroySmallBlockList - destroy the small block list
+ */
+void
+vDestroySmallBlockList(void)
+{
+	DBG_MSG("vDestroySmallBlockList");
+
+	aulSmallBlockList = xfree(aulSmallBlockList);
+	tSmallBlockListLen = 0;
+} /* end of vDestroySmalBlockList */
+
+/*
+ * vCreateSmallBlockList - create the small block list
+ *
+ * returns: TRUE when successful, otherwise FALSE
+ */
+BOOL
+bCreateSmallBlockList(ULONG ulStartblock, const ULONG *aulBBD, size_t tBBDLen)
+{
+	ULONG	ulTmp;
+	size_t	tSize;
+	int	iIndex;
+
+	fail(aulSmallBlockList != NULL);
+	fail(tSmallBlockListLen != 0);
+	fail(ulStartblock > MAX_BLOCKNUMBER && ulStartblock != END_OF_CHAIN);
+	fail(aulBBD == NULL);
+	fail(tBBDLen == 0);
+
+	/* Find the length of the small block list */
+	for (tSmallBlockListLen = 0, ulTmp = ulStartblock;
+	     tSmallBlockListLen < tBBDLen && ulTmp != END_OF_CHAIN;
+	     tSmallBlockListLen++, ulTmp = aulBBD[ulTmp]) {
+		if (ulTmp >= (ULONG)tBBDLen) {
+			DBG_DEC(ulTmp);
+			DBG_DEC(tBBDLen);
+			werr(1, "The Big Block Depot is damaged");
+		}
+	}
+	DBG_DEC(tSmallBlockListLen);
+
+	if (tSmallBlockListLen == 0) {
+		/* There is no small block list */
+		fail(ulStartblock != END_OF_CHAIN);
+		aulSmallBlockList = NULL;
+		return TRUE;
+	}
+
+	/* Create the small block list */
+	tSize = tSmallBlockListLen * sizeof(ULONG);
+	aulSmallBlockList = xmalloc(tSize);
+	for (iIndex = 0, ulTmp = ulStartblock;
+	     iIndex < (int)tBBDLen && ulTmp != END_OF_CHAIN;
+	     iIndex++, ulTmp = aulBBD[ulTmp]) {
+		if (ulTmp >= (ULONG)tBBDLen) {
+			DBG_DEC(ulTmp);
+			DBG_DEC(tBBDLen);
+			werr(1, "The Big Block Depot is damaged");
+		}
+		aulSmallBlockList[iIndex] = ulTmp;
+		NO_DBG_DEC(aulSmallBlockList[iIndex]);
+	}
+	return TRUE;
+} /* end of bCreateSmallBlockList */
+
+/*
+ * ulDepotOffset - get the depot offset the block list
+ */
+ULONG
+ulDepotOffset(ULONG ulIndex, size_t tBlockSize)
+{
+	ULONG	ulTmp;
+	size_t	tTmp;
+
+	fail(ulIndex >= ULONG_MAX / BIG_BLOCK_SIZE);
+
+	switch (tBlockSize) {
+	case BIG_BLOCK_SIZE:
+		return (ulIndex + 1) * BIG_BLOCK_SIZE;
+	case SMALL_BLOCK_SIZE:
+		tTmp = (size_t)(ulIndex / SIZE_RATIO);
+		ulTmp = ulIndex % SIZE_RATIO;
+		if (aulSmallBlockList == NULL ||
+		    tTmp >= tSmallBlockListLen) {
+			DBG_HEX(aulSmallBlockList);
+			DBG_DEC(tSmallBlockListLen);
+			DBG_DEC(tTmp);
+			return 0;
+		}
+		return ((aulSmallBlockList[tTmp] + 1) * SIZE_RATIO +
+				ulTmp) * SMALL_BLOCK_SIZE;
+	default:
+		DBG_DEC(tBlockSize);
+		DBG_FIXME();
+		return 0;
+	}
+} /* end of ulDepotOffset */
diff --git a/dib2eps.c b/dib2eps.c
new file mode 100644
index 0000000..2673d38
--- /dev/null
+++ b/dib2eps.c
@@ -0,0 +1,509 @@
+/*
+ * dib2eps.c
+ * Copyright (C) 2000-2003 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Functions to translate dib pictures into eps
+ *
+ *================================================================
+ * This part of the software is based on:
+ * The Windows Bitmap Decoder Class part of paintlib
+ * Paintlib is copyright (c) 1996-2000 Ulrich von Zadow
+ *================================================================
+ * The credit should go to him, but all the bugs are mine.
+ */
+
+#include <stdio.h>
+#include "antiword.h"
+
+
+/*
+ * vDecode1bpp - decode an uncompressed 1 bit per pixel image
+ */
+static void
+vDecode1bpp(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg)
+{
+	size_t	tPadding;
+	int	iX, iY, iN, iByte, iTmp, iEighthWidth, iUse;
+
+	DBG_MSG("vDecode1bpp");
+
+	fail(pOutFile == NULL);
+	fail(pImg == NULL);
+	fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 2);
+
+	DBG_DEC(pImg->iWidth);
+	DBG_DEC(pImg->iHeight);
+
+	iEighthWidth = (pImg->iWidth + 7) / 8;
+	tPadding = (size_t)(ROUND4(iEighthWidth) - iEighthWidth);
+
+	for (iY = 0; iY < pImg->iHeight; iY++) {
+		for (iX = 0; iX < iEighthWidth; iX++) {
+			iByte = iNextByte(pInFile);
+			if (iByte == EOF) {
+				vASCII85EncodeByte(pOutFile, EOF);
+				return;
+			}
+			if (iX == iEighthWidth - 1 && pImg->iWidth % 8 != 0) {
+				iUse = pImg->iWidth % 8;
+			} else {
+				iUse = 8;
+			}
+			for (iN = 0; iN < iUse; iN++) {
+				switch (iN) {
+				case 0: iTmp = (iByte & 0x80) / 128; break;
+				case 1: iTmp = (iByte & 0x40) / 64; break;
+				case 2: iTmp = (iByte & 0x20) / 32; break;
+				case 3: iTmp = (iByte & 0x10) / 16; break;
+				case 4: iTmp = (iByte & 0x08) / 8; break;
+				case 5: iTmp = (iByte & 0x04) / 4; break;
+				case 6: iTmp = (iByte & 0x02) / 2; break;
+				case 7: iTmp = (iByte & 0x01); break;
+				default: iTmp = 0; break;
+				}
+				vASCII85EncodeByte(pOutFile, iTmp);
+			}
+		}
+		(void)tSkipBytes(pInFile, tPadding);
+	}
+	vASCII85EncodeByte(pOutFile, EOF);
+} /* end of vDecode1bpp */
+
+/*
+ * vDecode4bpp - decode an uncompressed 4 bits per pixel image
+ */
+static void
+vDecode4bpp(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg)
+{
+	size_t	tPadding;
+	int	iX, iY, iN, iByte, iTmp, iHalfWidth, iUse;
+
+	DBG_MSG("vDecode4bpp");
+
+	fail(pInFile == NULL);
+	fail(pOutFile == NULL);
+	fail(pImg == NULL);
+	fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 16);
+
+	DBG_DEC(pImg->iWidth);
+	DBG_DEC(pImg->iHeight);
+
+	iHalfWidth = (pImg->iWidth + 1) / 2;
+	tPadding = (size_t)(ROUND4(iHalfWidth) - iHalfWidth);
+
+	for (iY = 0; iY < pImg->iHeight; iY++) {
+		for (iX = 0; iX < iHalfWidth; iX++) {
+			iByte = iNextByte(pInFile);
+			if (iByte == EOF) {
+				vASCII85EncodeByte(pOutFile, EOF);
+				return;
+			}
+			if (iX == iHalfWidth - 1 && odd(pImg->iWidth)) {
+				iUse = 1;
+			} else {
+				iUse = 2;
+			}
+			for (iN = 0; iN < iUse; iN++) {
+				if (odd(iN)) {
+					iTmp = iByte & 0x0f;
+				} else {
+					iTmp = (iByte & 0xf0) / 16;
+				}
+				vASCII85EncodeByte(pOutFile, iTmp);
+			}
+		}
+		(void)tSkipBytes(pInFile, tPadding);
+	}
+	vASCII85EncodeByte(pOutFile, EOF);
+} /* end of vDecode4bpp */
+
+/*
+ * vDecode8bpp - decode an uncompressed 8 bits per pixel image
+ */
+static void
+vDecode8bpp(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg)
+{
+	size_t	tPadding;
+	int	iX, iY, iByte;
+
+	DBG_MSG("vDecode8bpp");
+
+	fail(pInFile == NULL);
+	fail(pOutFile == NULL);
+	fail(pImg == NULL);
+	fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 256);
+
+	DBG_DEC(pImg->iWidth);
+	DBG_DEC(pImg->iHeight);
+
+	tPadding = (size_t)(ROUND4(pImg->iWidth) - pImg->iWidth);
+
+	for (iY = 0; iY < pImg->iHeight; iY++) {
+		for (iX = 0; iX < pImg->iWidth; iX++) {
+			iByte = iNextByte(pInFile);
+			if (iByte == EOF) {
+				vASCII85EncodeByte(pOutFile, EOF);
+				return;
+			}
+			vASCII85EncodeByte(pOutFile, iByte);
+		}
+		(void)tSkipBytes(pInFile, tPadding);
+	}
+	vASCII85EncodeByte(pOutFile, EOF);
+} /* end of vDecode8bpp */
+
+/*
+ * vDecode24bpp - decode an uncompressed 24 bits per pixel image
+ */
+static void
+vDecode24bpp(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg)
+{
+	size_t	tPadding;
+	int	iX, iY, iBlue, iGreen, iRed, iTripleWidth;
+
+	DBG_MSG("vDecode24bpp");
+
+	fail(pInFile == NULL);
+	fail(pOutFile == NULL);
+	fail(pImg == NULL);
+	fail(!pImg->bColorImage);
+
+	DBG_DEC(pImg->iWidth);
+	DBG_DEC(pImg->iHeight);
+
+	iTripleWidth = pImg->iWidth * 3;
+	tPadding = (size_t)(ROUND4(iTripleWidth) - iTripleWidth);
+
+	for (iY = 0; iY < pImg->iHeight; iY++) {
+		for (iX = 0; iX < pImg->iWidth; iX++) {
+			/* Change from BGR order to RGB order */
+			iBlue = iNextByte(pInFile);
+			if (iBlue == EOF) {
+				vASCII85EncodeByte(pOutFile, EOF);
+				return;
+			}
+			iGreen = iNextByte(pInFile);
+			if (iGreen == EOF) {
+				vASCII85EncodeByte(pOutFile, EOF);
+				return;
+			}
+			iRed = iNextByte(pInFile);
+			if (iRed == EOF) {
+				vASCII85EncodeByte(pOutFile, EOF);
+				return;
+			}
+			vASCII85EncodeByte(pOutFile, iRed);
+			vASCII85EncodeByte(pOutFile, iGreen);
+			vASCII85EncodeByte(pOutFile, iBlue);
+		}
+		(void)tSkipBytes(pInFile, tPadding);
+	}
+	vASCII85EncodeByte(pOutFile, EOF);
+} /* end of vDecode24bpp */
+
+/*
+ * vDecodeRle4 - decode a RLE compressed 4 bits per pixel image
+ */
+static void
+vDecodeRle4(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg)
+{
+	int	iX, iY, iByte, iTmp, iRunLength, iRun;
+	BOOL	bEOF, bEOL;
+
+	DBG_MSG("vDecodeRle4");
+
+	fail(pInFile == NULL);
+	fail(pOutFile == NULL);
+	fail(pImg == NULL);
+	fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 16);
+
+	DBG_DEC(pImg->iWidth);
+	DBG_DEC(pImg->iHeight);
+
+	bEOF = FALSE;
+
+	for (iY =  0; iY < pImg->iHeight && !bEOF; iY++) {
+		bEOL = FALSE;
+		iX = 0;
+		while (!bEOL) {
+			iRunLength = iNextByte(pInFile);
+			if (iRunLength == EOF) {
+				vASCII85EncodeByte(pOutFile, EOF);
+				return;
+			}
+			if (iRunLength != 0) {
+				/*
+				 * Encoded packet:
+				 * RunLength pixels, all the "same" value
+				 */
+				iByte = iNextByte(pInFile);
+				if (iByte == EOF) {
+					vASCII85EncodeByte(pOutFile, EOF);
+					return;
+				}
+				for (iRun = 0; iRun < iRunLength; iRun++) {
+					if (odd(iRun)) {
+						iTmp = iByte & 0x0f;
+					} else {
+						iTmp = (iByte & 0xf0) / 16;
+					}
+					if (iX < pImg->iWidth) {
+						vASCII85EncodeByte(pOutFile, iTmp);
+					}
+					iX++;
+				}
+				continue;
+			}
+			/* Literal or escape */
+			iRunLength = iNextByte(pInFile);
+			if (iRunLength == EOF) {
+				vASCII85EncodeByte(pOutFile, EOF);
+				return;
+			}
+			if (iRunLength == 0) {		/* End of line escape */
+				bEOL = TRUE;
+			} else if (iRunLength == 1) {	/* End of file escape */
+				bEOF = TRUE;
+				bEOL = TRUE;
+			} else if (iRunLength == 2) {	/* Delta escape */
+				DBG_MSG("RLE4: encountered delta escape");
+				bEOF = TRUE;
+				bEOL = TRUE;
+			} else {			/* Literal packet */
+				iByte = 0;
+				for (iRun = 0; iRun < iRunLength; iRun++) {
+					if (odd(iRun)) {
+						iTmp = iByte & 0x0f;
+					} else {
+						iByte = iNextByte(pInFile);
+						if (iByte == EOF) {
+							vASCII85EncodeByte(pOutFile, EOF);
+							return;
+						}
+						iTmp = (iByte & 0xf0) / 16;
+					}
+					if (iX < pImg->iWidth) {
+						vASCII85EncodeByte(pOutFile, iTmp);
+					}
+					iX++;
+				}
+				/* Padding if the number of bytes is odd */
+				if (odd((iRunLength + 1) / 2)) {
+					(void)tSkipBytes(pInFile, 1);
+				}
+			}
+		}
+		DBG_DEC_C(iX != pImg->iWidth, iX);
+	}
+	vASCII85EncodeByte(pOutFile, EOF);
+} /* end of vDecodeRle4 */
+
+/*
+ * vDecodeRle8 - decode a RLE compressed 8 bits per pixel image
+ */
+static void
+vDecodeRle8(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg)
+{
+	int	iX, iY, iByte, iRunLength, iRun;
+	BOOL	bEOF, bEOL;
+
+	DBG_MSG("vDecodeRle8");
+
+	fail(pInFile == NULL);
+	fail(pOutFile == NULL);
+	fail(pImg == NULL);
+	fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 256);
+
+	DBG_DEC(pImg->iWidth);
+	DBG_DEC(pImg->iHeight);
+
+	bEOF = FALSE;
+
+	for (iY = 0; iY < pImg->iHeight && !bEOF; iY++) {
+		bEOL = FALSE;
+		iX = 0;
+		while (!bEOL) {
+			iRunLength = iNextByte(pInFile);
+			if (iRunLength == EOF) {
+				vASCII85EncodeByte(pOutFile, EOF);
+				return;
+			}
+			if (iRunLength != 0) {
+				/*
+				 * Encoded packet:
+				 * RunLength pixels, all the same value
+				 */
+				iByte = iNextByte(pInFile);
+				if (iByte == EOF) {
+					vASCII85EncodeByte(pOutFile, EOF);
+					return;
+				}
+				for (iRun = 0; iRun < iRunLength; iRun++) {
+					if (iX < pImg->iWidth) {
+						vASCII85EncodeByte(pOutFile, iByte);
+					}
+					iX++;
+				}
+				continue;
+			}
+			/* Literal or escape */
+			iRunLength = iNextByte(pInFile);
+			if (iRunLength == EOF) {
+				vASCII85EncodeByte(pOutFile, EOF);
+				return;
+			}
+			if (iRunLength == 0) {		/* End of line escape */
+				bEOL = TRUE;
+			} else if (iRunLength == 1) {	/* End of file escape */
+				bEOF = TRUE;
+				bEOL = TRUE;
+			} else if (iRunLength == 2) {	/* Delta escape */
+				DBG_MSG("RLE8: encountered delta escape");
+				bEOF = TRUE;
+				bEOL = TRUE;
+			} else {			/* Literal packet */
+				for (iRun = 0; iRun < iRunLength; iRun++) {
+					iByte = iNextByte(pInFile);
+					if (iByte == EOF) {
+						vASCII85EncodeByte(pOutFile, EOF);
+						return;
+					}
+					if (iX < pImg->iWidth) {
+						vASCII85EncodeByte(pOutFile, iByte);
+					}
+					iX++;
+				}
+				/* Padding if the number of bytes is odd */
+				if (odd(iRunLength)) {
+					(void)tSkipBytes(pInFile, 1);
+				}
+			}
+		}
+		DBG_DEC_C(iX != pImg->iWidth, iX);
+	}
+	vASCII85EncodeByte(pOutFile, EOF);
+} /* end of vDecodeRle8 */
+
+/*
+ * vDecodeDIB - decode a dib picture
+ */
+static void
+vDecodeDIB(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg)
+{
+	size_t	tHeaderSize;
+
+	fail(pInFile == NULL);
+	fail(pOutFile == NULL);
+	fail(pImg == NULL);
+
+	/* Skip the bitmap info header */
+	tHeaderSize = (size_t)ulNextLong(pInFile);
+	(void)tSkipBytes(pInFile, tHeaderSize - 4);
+	/* Skip the colortable */
+	if (pImg->uiBitsPerComponent <= 8) {
+		(void)tSkipBytes(pInFile,
+			(size_t)(pImg->iColorsUsed *
+			 ((tHeaderSize > 12) ? 4 : 3)));
+	}
+
+	switch (pImg->uiBitsPerComponent) {
+	case 1:
+		fail(pImg->eCompression != compression_none);
+		vDecode1bpp(pInFile, pOutFile, pImg);
+		break;
+	case 4:
+		fail(pImg->eCompression != compression_none &&
+				pImg->eCompression != compression_rle4);
+		if (pImg->eCompression == compression_rle4) {
+			vDecodeRle4(pInFile, pOutFile, pImg);
+		} else {
+			vDecode4bpp(pInFile, pOutFile, pImg);
+		}
+		break;
+	case 8:
+		fail(pImg->eCompression != compression_none &&
+				pImg->eCompression != compression_rle8);
+		if (pImg->eCompression == compression_rle8) {
+			vDecodeRle8(pInFile, pOutFile, pImg);
+		} else {
+			vDecode8bpp(pInFile, pOutFile, pImg);
+		}
+		break;
+	case 24:
+		fail(pImg->eCompression != compression_none);
+		vDecode24bpp(pInFile, pOutFile, pImg);
+		break;
+	default:
+		DBG_DEC(pImg->uiBitsPerComponent);
+		break;
+	}
+} /* end of vDecodeDIB */
+
+#if defined(DEBUG)
+/*
+ * vCopy2File
+ */
+static void
+vCopy2File(FILE *pInFile, ULONG ulFileOffset, size_t tPictureLen)
+{
+	static int	iPicCounter = 0;
+	FILE	*pOutFile;
+	size_t	tIndex;
+	int	iTmp;
+	char	szFilename[30];
+
+	if (!bSetDataOffset(pInFile, ulFileOffset)) {
+		return;
+	}
+
+	sprintf(szFilename, "/tmp/pic/pic%04d.bmp", ++iPicCounter);
+	pOutFile = fopen(szFilename, "wb");
+	if (pOutFile == NULL) {
+		return;
+	}
+	/* Turn a dib into a bmp by adding a fake 14 byte header */
+	(void)putc('B', pOutFile);
+	(void)putc('M', pOutFile);
+	for (iTmp = 0; iTmp < 12; iTmp++) {
+		if (putc(0, pOutFile) == EOF) {
+			break;
+		}
+	}
+	for (tIndex = 0; tIndex < tPictureLen; tIndex++) {
+		iTmp = iNextByte(pInFile);
+		if (putc(iTmp, pOutFile) == EOF) {
+			break;
+		}
+	}
+	(void)fclose(pOutFile);
+} /* end of vCopy2File */
+#endif /* DEBUG */
+
+/*
+ * bTranslateDIB - translate a DIB picture
+ *
+ * This function translates a picture from dib to eps
+ *
+ * return TRUE when sucessful, otherwise FALSE
+ */
+BOOL
+bTranslateDIB(diagram_type *pDiag, FILE *pInFile,
+		ULONG ulFileOffset, const imagedata_type *pImg)
+{
+#if defined(DEBUG)
+	fail(pImg->tPosition > pImg->tLength);
+	vCopy2File(pInFile, ulFileOffset, pImg->tLength - pImg->tPosition);
+#endif /* DEBUG */
+
+	/* Seek to start position of DIB data */
+	if (!bSetDataOffset(pInFile, ulFileOffset)) {
+		return FALSE;
+	}
+
+	vImagePrologue(pDiag, pImg);
+	vDecodeDIB(pInFile, pDiag->pOutFile, pImg);
+	vImageEpilogue(pDiag);
+
+	return TRUE;
+} /* end of bTranslateDIB */
diff --git a/dib2sprt.c b/dib2sprt.c
new file mode 100644
index 0000000..b8fc364
--- /dev/null
+++ b/dib2sprt.c
@@ -0,0 +1,597 @@
+/*
+ * dib2sprt.c
+ * Copyright (C) 2000-2003 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Functions to translate dib pictures into sprites
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "DeskLib:Error.h"
+#include "DeskLib:Sprite.h"
+#include "antiword.h"
+
+#if 0 /* defined(DEBUG) */
+static int iPicCounter = 0;
+#endif /* DEBUG */
+
+
+/*
+ * iGetByteWidth - compute the number of bytes needed for a row of pixels
+ */
+static int
+iGetByteWidth(const imagedata_type *pImg)
+{
+	switch (pImg->uiBitsPerComponent) {
+	case  1:
+		return (pImg->iWidth + 31) / 32 * sizeof(int);
+	case  4:
+		return (pImg->iWidth + 7) / 8 * sizeof(int);
+	case  8:
+	case 24:
+		return (pImg->iWidth + 3) / 4 * sizeof(int);
+	default:
+		DBG_DEC(pImg->uiBitsPerComponent);
+		return 0;
+	}
+} /* end of iGetByteWidth */
+
+/*
+ * pCreateBlankSprite - Create a blank sprite.
+ *
+ * Create a blank sprite and add a palette if needed
+ *
+ * returns a pointer to the sprite when successful, otherwise NULL
+ */
+static sprite_areainfo *
+pCreateBlankSprite(const imagedata_type *pImg, size_t *pSize)
+{
+	sprite_areainfo	*pArea;
+	UCHAR	*pucTmp;
+	size_t	tSize;
+	screen_modeval	uMode;
+	int	iIndex, iPaletteEntries;
+
+	TRACE_MSG("pCreateBlankSprite");
+
+	fail(pImg == NULL);
+	fail(pSize == NULL);
+
+	switch (pImg->uiBitsPerComponent) {
+	case  1:
+		uMode.screen_mode = 18;
+		iPaletteEntries = 2;
+		break;
+	case  4:
+		uMode.screen_mode = 20;
+		iPaletteEntries = 16;
+		break;
+	case  8:
+	case 24:
+		uMode.screen_mode = 21;
+		iPaletteEntries = 0;
+		break;
+	default:
+		DBG_DEC(pImg->uiBitsPerComponent);
+		return NULL;
+	}
+	fail(iPaletteEntries < 0 || iPaletteEntries > 16);
+
+	/* Get memory for the sprite */
+	tSize = sizeof(sprite_areainfo) +
+		Sprite_MemorySize(pImg->iWidth, pImg->iHeight, uMode,
+		iPaletteEntries > 0 ? sprite_HASPAL : sprite_HASNOMASKPAL);
+	DBG_DEC(tSize);
+	pArea = xmalloc(tSize);
+
+	/* Initialise sprite area */
+	pArea->areasize = tSize;
+	pArea->numsprites = 0;
+	pArea->firstoffset = sizeof(sprite_areainfo);
+	pArea->freeoffset = sizeof(sprite_areainfo);
+
+	/* Create a blank sprite */
+	Error_CheckFatal(Sprite_Create(pArea, "wordimage",
+		iPaletteEntries > 0 ? 1 : 0,
+		pImg->iWidth, pImg->iHeight, uMode));
+
+	/* Add the palette */
+	pucTmp = (UCHAR *)pArea + pArea->firstoffset + sizeof(sprite_header);
+	for (iIndex = 0; iIndex < iPaletteEntries; iIndex++) {
+		/* First color */
+		*pucTmp++ = 0;
+		*pucTmp++ = pImg->aucPalette[iIndex][0];
+		*pucTmp++ = pImg->aucPalette[iIndex][1];
+		*pucTmp++ = pImg->aucPalette[iIndex][2];
+		/* Second color */
+		*pucTmp++ = 0;
+		*pucTmp++ = pImg->aucPalette[iIndex][0];
+		*pucTmp++ = pImg->aucPalette[iIndex][1];
+		*pucTmp++ = pImg->aucPalette[iIndex][2];
+	}
+
+	*pSize = tSize;
+	return pArea;
+} /* end of pCreateBlankSprite */
+
+/*
+ * iReduceColor - reduce from 24 bit to 8 bit color
+ *
+ * Reduce 24 bit true colors to RISC OS default 256 color palette
+ *
+ * returns the resulting color
+ */
+static int
+iReduceColor(int iRed, int iGreen, int iBlue)
+{
+	int	iResult;
+
+	iResult = (iBlue & 0x80) ? 0x80 : 0;
+	iResult |= (iGreen & 0x80) ? 0x40 : 0;
+	iResult |= (iGreen & 0x40) ? 0x20 : 0;
+	iResult |= (iRed & 0x80) ? 0x10 : 0;
+	iResult |= (iBlue & 0x40) ? 0x08 : 0;
+	iResult |= (iRed & 0x40) ? 0x04 : 0;
+	iResult |= ((iRed | iGreen | iBlue) & 0x20) ? 0x02 : 0;
+	iResult |= ((iRed | iGreen | iBlue) & 0x10) ? 0x01 : 0;
+	return iResult;
+} /* end of iReduceColor */
+
+/*
+ * vDecode1bpp - decode an uncompressed 1 bit per pixel image
+ */
+static void
+vDecode1bpp(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
+{
+	int	iX, iY, iByteWidth, iOffset, iTmp, iEighthWidth, iPadding;
+	UCHAR	ucTmp;
+
+	DBG_MSG("vDecode1bpp");
+
+	fail(pFile == NULL);
+	fail(pucData == NULL);
+	fail(pImg == NULL);
+	fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 2);
+
+	iByteWidth = iGetByteWidth(pImg);
+
+	iEighthWidth = (pImg->iWidth + 7) / 8;
+	iPadding = ROUND4(iEighthWidth) - iEighthWidth;
+
+	for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
+		for (iX = 0; iX < iEighthWidth; iX++) {
+			iTmp = iNextByte(pFile);
+			if (iTmp == EOF) {
+				return;
+			}
+			/* Reverse the bit order */
+			ucTmp  = (iTmp & BIT(0)) ? (UCHAR)BIT(7) : 0;
+			ucTmp |= (iTmp & BIT(1)) ? (UCHAR)BIT(6) : 0;
+			ucTmp |= (iTmp & BIT(2)) ? (UCHAR)BIT(5) : 0;
+			ucTmp |= (iTmp & BIT(3)) ? (UCHAR)BIT(4) : 0;
+			ucTmp |= (iTmp & BIT(4)) ? (UCHAR)BIT(3) : 0;
+			ucTmp |= (iTmp & BIT(5)) ? (UCHAR)BIT(2) : 0;
+			ucTmp |= (iTmp & BIT(6)) ? (UCHAR)BIT(1) : 0;
+			ucTmp |= (iTmp & BIT(7)) ? (UCHAR)BIT(0) : 0;
+			iOffset = iY * iByteWidth + iX;
+			*(pucData + iOffset) = ucTmp;
+		}
+		(void)tSkipBytes(pFile, iPadding);
+	}
+} /* end of vDecode1bpp */
+
+/*
+ * vDecode4bpp - decode an uncompressed 4 bits per pixel image
+ */
+static void
+vDecode4bpp(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
+{
+	int	iX, iY, iByteWidth, iOffset, iTmp, iHalfWidth, iPadding;
+	UCHAR	ucTmp;
+
+	DBG_MSG("vDecode4bpp");
+
+	fail(pFile == NULL);
+	fail(pucData == NULL);
+	fail(pImg == NULL);
+	fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 16);
+
+	iByteWidth = iGetByteWidth(pImg);
+
+	iHalfWidth = (pImg->iWidth + 1) / 2;
+	iPadding = ROUND4(iHalfWidth) - iHalfWidth;
+
+	for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
+		for (iX = 0; iX < iHalfWidth; iX++) {
+			iTmp = iNextByte(pFile);
+			if (iTmp == EOF) {
+				return;
+			}
+			/* Reverse the nibble order */
+			ucTmp = (iTmp & 0xf0) >> 4;
+			ucTmp |= (iTmp & 0x0f) << 4;
+			iOffset = iY * iByteWidth + iX;
+			*(pucData + iOffset) = ucTmp;
+		}
+		(void)tSkipBytes(pFile, iPadding);
+	}
+} /* end of vDecode4bpp */
+
+/*
+ * vDecode8bpp - decode an uncompressed 8 bits per pixel image
+ */
+static void
+vDecode8bpp(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
+{
+	int	iX, iY, iByteWidth, iOffset, iIndex, iPadding;
+
+	DBG_MSG("vDecode8bpp");
+
+	fail(pFile == NULL);
+	fail(pucData == NULL);
+	fail(pImg == NULL);
+	fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 256);
+
+	iByteWidth = iGetByteWidth(pImg);
+
+	iPadding = ROUND4(pImg->iWidth) - pImg->iWidth;
+
+	for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
+		for (iX = 0; iX < pImg->iWidth; iX++) {
+			iIndex = iNextByte(pFile);
+			if (iIndex == EOF) {
+				return;
+			}
+			iOffset = iY * iByteWidth + iX;
+			*(pucData + iOffset) = iReduceColor(
+				pImg->aucPalette[iIndex][0],
+				pImg->aucPalette[iIndex][1],
+				pImg->aucPalette[iIndex][2]);
+		}
+		(void)tSkipBytes(pFile, iPadding);
+	}
+} /* end of vDecode8bpp */
+
+/*
+ * vDecode24bpp - decode an uncompressed 24 bits per pixel image
+ */
+static void
+vDecode24bpp(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
+{
+	int	iX, iY, iTripleWidth, iByteWidth, iOffset, iPadding;
+	int	iRed, iGreen, iBlue;
+
+	DBG_MSG("vDecode24bpp");
+
+	fail(pFile == NULL);
+	fail(pucData == NULL);
+	fail(pImg == NULL);
+
+	iByteWidth = iGetByteWidth(pImg);
+
+	iTripleWidth = pImg->iWidth * 3;
+	iPadding = ROUND4(iTripleWidth) - iTripleWidth;
+
+	for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
+		for (iX = 0; iX < pImg->iWidth; iX++) {
+			iBlue = iNextByte(pFile);
+			if (iBlue == EOF) {
+				return;
+			}
+			iGreen = iNextByte(pFile);
+			if (iGreen == EOF) {
+				return;
+			}
+			iRed = iNextByte(pFile);
+			if (iRed == EOF) {
+				return;
+			}
+			iOffset = iY * iByteWidth + iX;
+			*(pucData + iOffset) =
+					iReduceColor(iRed, iGreen, iBlue);
+		}
+		(void)tSkipBytes(pFile, iPadding);
+	}
+} /* end of vDecode24bpp */
+
+/*
+ * vDecodeRle4 - decode a RLE compressed 4 bits per pixel image
+ */
+static void
+vDecodeRle4(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
+{
+	int	iX, iY, iByteWidth, iOffset, iTmp, iHalfWidth;
+	int	iRun, iRunLength, iHalfRun;
+	BOOL	bEOL;
+	UCHAR	ucTmp;
+
+	DBG_MSG("vDecodeRle4");
+
+	fail(pFile == NULL);
+	fail(pucData == NULL);
+	fail(pImg == NULL);
+	fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 16);
+
+	DBG_DEC(pImg->iWidth);
+	DBG_DEC(pImg->iHeight);
+
+	iByteWidth = iGetByteWidth(pImg);
+	iHalfWidth = (pImg->iWidth + 1) / 2;
+
+	for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
+		bEOL = FALSE;
+		iX = 0;
+		while (!bEOL) {
+			iRunLength = iNextByte(pFile);
+			if (iRunLength == EOF) {
+				return;
+			}
+			if (iRunLength != 0) {
+			  	/*
+				 * Encoded packet:
+				 * RunLength pixels, all the "same" value
+				 */
+				iTmp = iNextByte(pFile);
+				if (iTmp == EOF) {
+					return;
+				}
+				/* Reverse the nibble order */
+				ucTmp = (iTmp & 0xf0) >> 4;
+				ucTmp |= (iTmp & 0x0f) << 4;
+				iHalfRun = (iRunLength + 1) / 2;
+				for (iRun = 0; iRun < iHalfRun; iRun++) {
+					if (iX < iHalfWidth) {
+						iOffset = iY * iByteWidth + iX;
+						*(pucData + iOffset) = ucTmp;
+					}
+					iX++;
+				}
+				continue;
+			}
+			/* Literal or escape */
+			iRunLength = iNextByte(pFile);
+			if (iRunLength == EOF) {
+				return;
+			}
+			if (iRunLength == 0) {		/* End of line escape */
+				bEOL = TRUE;
+			} else if (iRunLength == 1) {	/* End of file escape */
+				return;
+			} else if (iRunLength == 2) {	/* Delta escape */
+				DBG_MSG("RLE4: encountered delta escape");
+				return;
+			} else {			/* Literal packet */
+				iHalfRun = (iRunLength + 1) / 2;
+				for (iRun = 0; iRun < iHalfRun; iRun++) {
+					iTmp = iNextByte(pFile);
+					if (iTmp == EOF) {
+						return;
+					}
+					/* Reverse the nibble order */
+					ucTmp = (iTmp & 0xf0) >> 4;
+					ucTmp |= (iTmp & 0x0f) << 4;
+					if (iX < iHalfWidth) {
+						iOffset = iY * iByteWidth + iX;
+						*(pucData + iOffset) = ucTmp;
+					}
+					iX++;
+				}
+				/* Padding if the number of bytes is odd */
+				if (odd(iHalfRun)) {
+					(void)tSkipBytes(pFile, 1);
+				}
+			}
+		}
+		DBG_DEC_C(iX != iHalfWidth, iX);
+	}
+} /* end of vDecodeRle4 */
+
+/*
+ * vDecodeRle8 - decode a RLE compressed 8 bits per pixel image
+ */
+static void
+vDecodeRle8(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
+{
+	int	iX, iY, iRun, iRunLength, iOffset, iIndex, iByteWidth;
+	BOOL	bEOL;
+
+	DBG_MSG("vDecodeRle8");
+
+	fail(pFile == NULL);
+	fail(pucData == NULL);
+	fail(pImg == NULL);
+	fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 256);
+
+	DBG_DEC(pImg->iWidth);
+	DBG_DEC(pImg->iHeight);
+
+	iByteWidth = iGetByteWidth(pImg);
+
+	for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
+		bEOL = FALSE;
+		iX = 0;
+		while (!bEOL) {
+			iRunLength = iNextByte(pFile);
+			if (iRunLength == EOF) {
+				return;
+			}
+			if (iRunLength != 0) {
+			  	/*
+				 * Encoded packet:
+				 * RunLength pixels, all the same value
+				 */
+				iIndex = iNextByte(pFile);
+				if (iIndex == EOF) {
+					return;
+				}
+				for (iRun = 0; iRun < iRunLength; iRun++) {
+					if (iX < pImg->iWidth) {
+						iOffset = iY * iByteWidth + iX;
+						*(pucData + iOffset) =
+							iReduceColor(
+							pImg->aucPalette[iIndex][0],
+							pImg->aucPalette[iIndex][1],
+							pImg->aucPalette[iIndex][2]);
+					}
+					iX++;
+				}
+				continue;
+			}
+			/* Literal or escape */
+			iRunLength = iNextByte(pFile);
+			if (iRunLength == EOF) {
+				return;
+			}
+			if (iRunLength == 0) {		/* End of line escape */
+				bEOL = TRUE;
+			} else if (iRunLength == 1) {	/* End of file escape */
+				return;
+			} else if (iRunLength == 2) {	/* Delta escape */
+				DBG_MSG("RLE8: encountered delta escape");
+				return;
+			} else {			/* Literal packet */
+				for (iRun = 0; iRun < iRunLength; iRun++) {
+					iIndex = iNextByte(pFile);
+					if (iIndex == EOF) {
+						return;
+					}
+					if (iX < pImg->iWidth) {
+						iOffset = iY * iByteWidth + iX;
+						*(pucData + iOffset) =
+							iReduceColor(
+							pImg->aucPalette[iIndex][0],
+							pImg->aucPalette[iIndex][1],
+							pImg->aucPalette[iIndex][2]);
+					}
+					iX++;
+				}
+				/* Padding if the number of bytes is odd */
+				if (odd(iRunLength)) {
+					(void)tSkipBytes(pFile, 1);
+				}
+			}
+		}
+		DBG_DEC_C(iX != pImg->iWidth, iX);
+	}
+} /* end of vDecodeRle8 */
+
+#if 0 /* defined(DEBUG) */
+static void
+vCopy2File(UCHAR *pucSprite, size_t tSpriteSize)
+{
+	FILE	*pOutFile;
+	int	iIndex;
+	char	szFilename[30];
+
+	sprintf(szFilename, "<Wimp$ScrapDir>.sprt%04d", ++iPicCounter);
+	pOutFile = fopen(szFilename, "wb");
+	if (pOutFile == NULL) {
+		return;
+	}
+	DBG_MSG(szFilename);
+	for (iIndex = 4; iIndex < (int)tSpriteSize; iIndex++) {
+		if (putc(pucSprite[iIndex], pOutFile) == EOF) {
+			break;
+		}
+	}
+	(void)fclose(pOutFile);
+	vSetFiletype(szFilename, FILETYPE_SPRITE);
+} /* end of vCopy2File */
+#endif /* DEBUG */
+
+/*
+ * vDecodeDIB - decode a dib picture
+ */
+static void
+vDecodeDIB(diagram_type *pDiag, FILE *pFile, const imagedata_type *pImg)
+{
+	sprite_areainfo	*pSprite;
+	UCHAR	*pucPalette, *pucData;
+	size_t	tSpriteSize;
+	int	iHeaderSize;
+
+	/* Skip the bitmap info header */
+	iHeaderSize = (int)ulNextLong(pFile);
+	(void)tSkipBytes(pFile, iHeaderSize - 4);
+	/* Skip the colortable */
+	if (pImg->uiBitsPerComponent <= 8) {
+		(void)tSkipBytes(pFile,
+			pImg->iColorsUsed * ((iHeaderSize > 12) ? 4 : 3));
+	}
+
+	/* Create an blank sprite */
+	pSprite = pCreateBlankSprite(pImg, &tSpriteSize);
+	pucPalette = (UCHAR *)pSprite +
+			pSprite->firstoffset + sizeof(sprite_header);
+
+	/* Add the pixel information */
+	switch (pImg->uiBitsPerComponent) {
+	case  1:
+		fail(pImg->eCompression != compression_none);
+		pucData = pucPalette + 2 * 8;
+		vDecode1bpp(pFile, pucData, pImg);
+		break;
+	case  4:
+		fail(pImg->eCompression != compression_none &&
+				pImg->eCompression != compression_rle4);
+		pucData = pucPalette + 16 * 8;
+		if (pImg->eCompression == compression_rle4) {
+			vDecodeRle4(pFile, pucData, pImg);
+		} else {
+			vDecode4bpp(pFile, pucData, pImg);
+		}
+		break;
+	case  8:
+		fail(pImg->eCompression != compression_none &&
+				pImg->eCompression != compression_rle8);
+		pucData = pucPalette + 0 * 8;
+		if (pImg->eCompression == compression_rle8) {
+			vDecodeRle8(pFile, pucData, pImg);
+		} else {
+			vDecode8bpp(pFile, pucData, pImg);
+		}
+		break;
+	case 24:
+		fail(pImg->eCompression != compression_none);
+		pucData = pucPalette + 0 * 8;
+		vDecode24bpp(pFile, pucData, pImg);
+		break;
+	default:
+		DBG_DEC(pImg->uiBitsPerComponent);
+		break;
+	}
+
+#if 0 /* defined(DEBUG) */
+	vCopy2File((UCHAR *)pSprite, tSpriteSize);
+#endif /* DEBUG */
+
+	/* Add the sprite to the Draw file */
+	vImage2Diagram(pDiag, pImg,
+		(UCHAR *)pSprite + pSprite->firstoffset,
+		tSpriteSize - pSprite->firstoffset);
+
+	/* Clean up before you leave */
+	pSprite = xfree(pSprite);
+} /* end of vDecodeDIB */
+
+/*
+ * bTranslateDIB - translate a DIB picture
+ *
+ * This function translates a picture from dib to sprite
+ *
+ * return TRUE when sucessful, otherwise FALSE
+ */
+BOOL
+bTranslateDIB(diagram_type *pDiag, FILE *pFile,
+	ULONG ulFileOffset, const imagedata_type *pImg)
+{
+	/* Seek to start position of DIB data */
+	if (!bSetDataOffset(pFile, ulFileOffset)) {
+		return FALSE;
+	}
+
+	vDecodeDIB(pDiag, pFile, pImg);
+
+	return TRUE;
+} /* end of bTranslateDIB */
diff --git a/doclist.c b/doclist.c
new file mode 100644
index 0000000..d4ac380
--- /dev/null
+++ b/doclist.c
@@ -0,0 +1,75 @@
+/*
+ * doclist.c
+ * Copyright (C) 2004 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Build, read and destroy list(s) of Word document information
+ *
+ * Note:
+ * There is no real list there is always one document per document
+ */
+
+#include "antiword.h"
+
+#define HALF_INCH	36000L  /* In millipoints */
+
+/* Variables needed to write the Document Information List */
+static document_block_type *pAnchor = NULL;
+static document_block_type tInfo;
+
+
+/*
+ * vDestroyDocumentInfoList - destroy the Document Information List
+ */
+void
+vDestroyDocumentInfoList(void)
+{
+        DBG_MSG("vDestroyDocumentInfoList");
+
+	pAnchor = NULL;
+} /* end of vDestoryDocumentInfoList */
+
+/*
+ * vCreateDocumentInfoList - create the Document Information List
+ */
+void
+vCreateDocumentInfoList(const document_block_type *pDocument)
+{
+	fail(pDocument == NULL);
+	fail(pAnchor != NULL);
+
+	tInfo = *pDocument;
+	pAnchor = &tInfo;
+} /* end of vCreateDocumentInfoList */
+
+/*
+ * lGetDefaultTabWidth - get the default tabwidth in millipoints
+ */
+long
+lGetDefaultTabWidth(void)
+{
+	long	lDefaultTabWidth;
+	USHORT	usTmp;
+
+	if (pAnchor == NULL) {
+		DBG_FIXME();
+		return HALF_INCH;
+	}
+	usTmp = pAnchor->usDefaultTabWidth;
+	lDefaultTabWidth = usTmp == 0 ? HALF_INCH : lTwips2MilliPoints(usTmp);
+	NO_DBG_DEC(lDefaultTabWidth);
+	return lDefaultTabWidth;
+} /* end of lGetDefaultTabWidth */
+
+/*
+ * ucGetDopHdrFtrSpecification - get the Heder/footer specification
+ */
+UCHAR
+ucGetDopHdrFtrSpecification(void)
+{
+	if (pAnchor == NULL) {
+		DBG_FIXME();
+		return 0x00;
+	}
+	return pAnchor->ucHdrFtrSpecification;
+} /* end of ucGetDopHdrFtrSpecification */
diff --git a/draw.c b/draw.c
new file mode 100644
index 0000000..f833d75
--- /dev/null
+++ b/draw.c
@@ -0,0 +1,1047 @@
+/*
+ * draw.c
+ * Copyright (C) 1998-2005 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Functions to deal with the Draw format
+ */
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include "DeskLib:KeyCodes.h"
+#include "DeskLib:Error.h"
+#include "DeskLib:Menu.h"
+#include "DeskLib:Template.h"
+#include "DeskLib:Window.h"
+#include "DeskLib:EventMsg.h"
+#include "flexlib:flex.h"
+#include "drawfile.h"
+#include "antiword.h"
+
+/* The work area must be a little bit larger than the diagram */
+#define WORKAREA_EXTENSION	    5
+/* Diagram memory */
+#define INITIAL_SIZE		32768	/* 32k */
+#define EXTENSION_SIZE		 4096	/*  4k */
+/* Main window title */
+#define WINDOW_TITLE_LEN	   28
+#define FILENAME_TITLE_LEN	(WINDOW_TITLE_LEN - 10)
+
+
+#if !defined(__GNUC__)
+int
+flex_alloc(flex_ptr anchor, int n)
+{
+	void	*pvTmp;
+
+	TRACE_MSG("flex_alloc");
+
+	if (anchor == NULL || n < 0) {
+		return 0;
+	}
+	if (n == 0) {
+		n = 1;
+	}
+	pvTmp = malloc(n);
+	if (pvTmp == NULL) {
+		return 0;
+	}
+	*anchor = pvTmp;
+	return 1;
+} /* end of flex_alloc */
+
+void
+flex_free(flex_ptr anchor)
+{
+	TRACE_MSG("flex_free");
+
+	if (anchor == NULL || *anchor == NULL) {
+		return;
+	}
+	free(*anchor);
+	*anchor = NULL;
+} /* end of flex_free */
+
+int
+flex_extend(flex_ptr anchor, int newsize)
+{
+	void	*pvTmp;
+
+	TRACE_MSG("flex_extend");
+
+	if (anchor == NULL || newsize < 0) {
+		return 0;
+	}
+	if (newsize == 0) {
+		newsize = 1;
+	}
+	pvTmp = realloc(*anchor, newsize);
+	if (pvTmp == NULL) {
+		return 0;
+	}
+	*anchor = pvTmp;
+	return 1;
+} /* end of flex_extend */
+#endif /* !__GNUC__ */
+
+/*
+ * vCreateMainWindow - create the Main window
+ *
+ * remark: does not return if the Main window can't be created
+ */
+static window_handle
+tCreateMainWindow(void)
+{
+	window_handle	tMainWindow;
+
+	TRACE_MSG("tCreateMainWindow");
+
+	tMainWindow = Window_Create("MainWindow", template_TITLEMIN);
+	if (tMainWindow == 0) {
+		werr(1, "I can't find the 'MainWindow' template");
+	}
+	return tMainWindow;
+} /* end of tCreateMainWindow */
+
+/*
+ * vCreateScaleWindow - create the Scale view window
+ *
+ * remark: does not return if the Scale view window can't be created
+ */
+static window_handle
+tCreateScaleWindow(void)
+{
+	window_handle	tScaleWindow;
+
+	TRACE_MSG("tCreateScaleWindow");
+
+	tScaleWindow = Window_Create("ScaleView", template_TITLEMIN);
+	if (tScaleWindow == 0) {
+		werr(1, "I can't find the 'ScaleView' template");
+	}
+	return tScaleWindow;
+} /* end of tCreateScaleWindow */
+
+/*
+ * pCreateDiagram - create and initialize a diagram
+ *
+ * remark: does not return if the diagram can't be created
+ */
+diagram_type *
+pCreateDiagram(const char *szTask, const char *szFilename)
+{
+	diagram_type	*pDiag;
+	options_type	tOptions;
+	window_handle	tMainWindow, tScaleWindow;
+	wimp_box	tBox;
+
+	TRACE_MSG("pCreateDiagram");
+
+	fail(szTask == NULL || szTask[0] == '\0');
+
+	/* Create the main window */
+	tMainWindow = tCreateMainWindow();
+
+	/* Create the scale view window */
+	tScaleWindow = tCreateScaleWindow();
+
+	/* Get the necessary memory */
+	pDiag = xmalloc(sizeof(diagram_type));
+	if (flex_alloc((flex_ptr)&pDiag->tInfo.data, INITIAL_SIZE) != 1) {
+		werr(1, "Memory allocation failed, unable to continue");
+	}
+
+	/* Initialize the diagram */
+	vGetOptions(&tOptions);
+	pDiag->tMainWindow = tMainWindow;
+	pDiag->tScaleWindow = tScaleWindow;
+	pDiag->iScaleFactorCurr = tOptions.iScaleFactor;
+	pDiag->iScaleFactorTemp = tOptions.iScaleFactor;
+	pDiag->tMemorySize = INITIAL_SIZE;
+	tBox.min.x = 0;
+	tBox.min.y = -(Drawfile_ScreenToDraw(32 + 3) * 8 + 1);
+	tBox.max.x = Drawfile_ScreenToDraw(16) * MIN_SCREEN_WIDTH + 1;
+	tBox.max.y = 0;
+	Error_CheckFatal(Drawfile_CreateDiagram(&pDiag->tInfo,
+					pDiag->tMemorySize, szTask, tBox));
+	DBG_DEC(pDiag->tInfo.length);
+	pDiag->lXleft = 0;
+	pDiag->lYtop = 0;
+	strncpy(pDiag->szFilename,
+			szBasename(szFilename), sizeof(pDiag->szFilename) - 1);
+	pDiag->szFilename[sizeof(pDiag->szFilename) - 1] = '\0';
+	/* Return success */
+	return pDiag;
+} /* end of pCreateDiagram */
+
+/*
+ * bDestroyDiagram - remove a diagram by freeing the memory it uses
+ */
+BOOL
+bDestroyDiagram(event_pollblock *pEvent, void *pvReference)
+{
+	diagram_type	*pDiag;
+	window_handle	tWindow;
+
+	TRACE_MSG("bDestroyDiagram");
+
+	fail(pEvent == NULL);
+	fail(pvReference == NULL);
+
+	if (pEvent == NULL || pvReference == NULL) {
+		return FALSE;
+	}
+
+	pDiag = (diagram_type *)pvReference;
+
+	switch (pEvent->type) {
+	case event_CLOSE:
+		tWindow = pEvent->data.openblock.window;
+		break;
+	case event_KEY:
+		tWindow = pEvent->data.key.caret.window;
+		break;
+	default:
+		DBG_DEC(pEvent->type);
+		return FALSE;
+	}
+	if (tWindow != pDiag->tMainWindow) {
+		return FALSE;
+	}
+
+	/* Delete the main window */
+	Window_Delete(pDiag->tMainWindow);
+	pDiag->tMainWindow = 0;
+
+	/* Delete the scale window */
+	Window_Delete(pDiag->tScaleWindow);
+	pDiag->tScaleWindow = 0;
+
+#if defined(__GNUC__)
+	/*
+	 * Remove all references to the diagram that will be free-ed
+	 * by undoing the EventMsg_Claim's from within the Menu_Warn's
+	 */
+	while (EventMsg_ReleaseSpecific(message_MENUWARNING, window_ANY,
+					bSaveTextfile, pDiag))
+		; /* EMPTY */
+	while (EventMsg_ReleaseSpecific(message_MENUWARNING, window_ANY,
+					bSaveDrawfile, pDiag))
+		; /* EMPTY */
+	while (EventMsg_ReleaseSpecific(message_MENUWARNING, window_ANY,
+					bScaleOpenAction, pDiag))
+		; /* EMPTY */
+#endif /* __GNUC__ */
+
+	/* Free the memory */
+	if (pDiag->tInfo.data != NULL && pDiag->tMemorySize != 0) {
+		flex_free((flex_ptr)&pDiag->tInfo.data);
+	}
+	/* Just to be on the save side */
+	pDiag->tInfo.data = NULL;
+	pDiag->tInfo.length = 0;
+	pDiag->tMemorySize = 0;
+
+	/* Destroy the diagram itself */
+	pDiag = xfree(pDiag);
+	return TRUE;
+} /* end of bDestroyDiagram */
+
+/*
+ * vExtendDiagramSize - make sure the diagram is big enough
+ */
+static void
+vExtendDiagramSize(diagram_type *pDiag, size_t tSize)
+{
+	TRACE_MSG("vExtendDiagramSize");
+
+	fail(pDiag == NULL || tSize % 4 != 0);
+
+	while (pDiag->tInfo.length + tSize > pDiag->tMemorySize) {
+		if (flex_extend((flex_ptr)&pDiag->tInfo.data,
+				pDiag->tMemorySize + EXTENSION_SIZE) != 1) {
+			werr(1, "Memory extend failed, unable to continue");
+		}
+		pDiag->tMemorySize += EXTENSION_SIZE;
+		NO_DBG_DEC(pDiag->tMemorySize);
+	}
+	TRACE_MSG("end of vExtendDiagramSize");
+} /* end of vExtendDiagramSize */
+
+/*
+ * vPrologue2 - prologue part 2; add a font list to a diagram
+ */
+void
+vPrologue2(diagram_type *pDiag, int iWordVersion)
+{
+	drawfile_object	*pNew;
+	const font_table_type	*pTmp;
+	char	*pcTmp;
+	size_t	tRealSize, tSize;
+	int	iCount;
+
+	TRACE_MSG("vPrologue2");
+
+	fail(pDiag == NULL);
+
+	if (tGetFontTableLength() == 0) {
+		return;
+	}
+	tRealSize = offsetof(drawfile_object, data);
+	pTmp = NULL;
+	while ((pTmp = pGetNextFontTableRecord(pTmp)) != NULL) {
+		tRealSize += 2 + strlen(pTmp->szOurFontname);
+	}
+	DBG_DEC(tRealSize);
+	tSize = ROUND4(tRealSize);
+	vExtendDiagramSize(pDiag, tSize);
+	pNew = xmalloc(tSize);
+	memset(pNew, 0, tSize);
+	pNew->type = drawfile_TYPE_FONT_TABLE;
+	pNew->size = tSize;
+	pcTmp = (char *)&pNew->data.font_table.font_def[0].font_ref;
+	iCount = 0;
+	pTmp = NULL;
+	while ((pTmp = pGetNextFontTableRecord(pTmp)) != NULL) {
+		*pcTmp = ++iCount;
+		pcTmp++;
+		strcpy(pcTmp, pTmp->szOurFontname);
+		pcTmp += 1 + strlen(pTmp->szOurFontname);
+	}
+	Error_CheckFatal(Drawfile_AppendObject(&pDiag->tInfo,
+			pDiag->tMemorySize, pNew, TRUE));
+	pNew = xfree(pNew);
+} /* end of vPrologue2 */
+
+/*
+ * vSubstring2Diagram - put a sub string into a diagram
+ */
+void
+vSubstring2Diagram(diagram_type *pDiag,
+	char *szString, size_t tStringLength, long lStringWidth,
+	UCHAR ucFontColor, USHORT usFontstyle, drawfile_fontref tFontRef,
+	USHORT usFontSize, USHORT usMaxFontSize)
+{
+	drawfile_object	*pNew;
+	long	lSizeX, lSizeY, lOffset, l20, lYMove;
+	size_t	tRealSize, tSize;
+
+	TRACE_MSG("vSubstring2Diagram");
+
+	fail(pDiag == NULL || szString == NULL);
+	fail(pDiag->lXleft < 0);
+	fail(tStringLength != strlen(szString));
+	fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
+	fail(usMaxFontSize < MIN_FONT_SIZE || usMaxFontSize > MAX_FONT_SIZE);
+	fail(usFontSize > usMaxFontSize);
+
+	if (szString[0] == '\0' || tStringLength == 0) {
+		return;
+	}
+
+	if (tFontRef == 0) {
+		lOffset = Drawfile_ScreenToDraw(2);
+		l20 = Drawfile_ScreenToDraw(32 + 3);
+		lSizeX = Drawfile_ScreenToDraw(16);
+		lSizeY = Drawfile_ScreenToDraw(32);
+	} else {
+		lOffset = lToBaseLine(usMaxFontSize);
+		l20 = lWord2DrawUnits20(usMaxFontSize);
+		lSizeX = lWord2DrawUnits00(usFontSize);
+		lSizeY = lWord2DrawUnits00(usFontSize);
+	}
+
+	lYMove = 0;
+
+	/* Up for superscript */
+	if (bIsSuperscript(usFontstyle)) {
+		lYMove = lMilliPoints2DrawUnits((((long)usFontSize + 1) / 2) * 375);
+	}
+	/* Down for subscript */
+	if (bIsSubscript(usFontstyle)) {
+		lYMove = -lMilliPoints2DrawUnits((long)usFontSize * 125);
+	}
+
+	tRealSize = offsetof(drawfile_object, data);
+	tRealSize += sizeof(drawfile_text) + tStringLength;
+	tSize = ROUND4(tRealSize);
+	vExtendDiagramSize(pDiag, tSize);
+	pNew = xmalloc(tSize);
+	memset(pNew, 0, tSize);
+	pNew->type = drawfile_TYPE_TEXT;
+	pNew->size = tSize;
+	pNew->data.text.bbox.min.x = (int)pDiag->lXleft;
+	pNew->data.text.bbox.min.y = (int)(pDiag->lYtop + lYMove);
+	pNew->data.text.bbox.max.x = (int)(pDiag->lXleft + lStringWidth);
+	pNew->data.text.bbox.max.y = (int)(pDiag->lYtop + l20 + lYMove);
+	pNew->data.text.fill.value = (int)ulColor2Color(ucFontColor);
+	pNew->data.text.bg_hint.value = 0xffffff00;	/* White */
+	pNew->data.text.style.font_ref = tFontRef;
+	pNew->data.text.style.reserved[0] = 0;
+	pNew->data.text.style.reserved[1] = 0;
+	pNew->data.text.style.reserved[2] = 0;
+	pNew->data.text.xsize = (int)lSizeX;
+	pNew->data.text.ysize = (int)lSizeY;
+	pNew->data.text.base.x = (int)pDiag->lXleft;
+	pNew->data.text.base.y = (int)(pDiag->lYtop + lOffset + lYMove);
+	strncpy(pNew->data.text.text, szString, tStringLength);
+	pNew->data.text.text[tStringLength] = '\0';
+	Error_CheckFatal(Drawfile_AppendObject(&pDiag->tInfo,
+			pDiag->tMemorySize, pNew, TRUE));
+	pNew = xfree(pNew);
+	/*draw_translateText(&pDiag->tInfo);*/
+	pDiag->lXleft += lStringWidth;
+	TRACE_MSG("leaving vSubstring2Diagram");
+} /* end of vSubstring2Diagram */
+
+/*
+ * vImage2Diagram - put an image into a diagram
+ */
+void
+vImage2Diagram(diagram_type *pDiag, const imagedata_type *pImg,
+	UCHAR *pucImage, size_t tImageSize)
+{
+  	drawfile_object	*pNew;
+	long	lWidth, lHeight;
+	size_t	tRealSize, tSize;
+
+	TRACE_MSG("vImage2Diagram");
+
+	fail(pDiag == NULL);
+	fail(pImg == NULL);
+	fail(pDiag->lXleft < 0);
+	fail(pImg->eImageType != imagetype_is_dib &&
+	     pImg->eImageType != imagetype_is_jpeg);
+
+	DBG_DEC_C(pDiag->lXleft != 0, pDiag->lXleft);
+
+	lWidth = lPoints2DrawUnits(pImg->iHorSizeScaled);
+	lHeight = lPoints2DrawUnits(pImg->iVerSizeScaled);
+	DBG_DEC(lWidth);
+	DBG_DEC(lHeight);
+
+	pDiag->lYtop -= lHeight;
+
+	tRealSize = offsetof(drawfile_object, data);
+	switch (pImg->eImageType) {
+	case imagetype_is_dib:
+		tRealSize += sizeof(drawfile_sprite) + tImageSize;
+		tSize = ROUND4(tRealSize);
+		vExtendDiagramSize(pDiag, tSize);
+		pNew = xmalloc(tSize);
+		memset(pNew, 0, tSize);
+		pNew->type = drawfile_TYPE_SPRITE;
+		pNew->size = tSize;
+		pNew->data.sprite.bbox.min.x = (int)pDiag->lXleft;
+		pNew->data.sprite.bbox.min.y = (int)pDiag->lYtop;
+		pNew->data.sprite.bbox.max.x = (int)(pDiag->lXleft + lWidth);
+		pNew->data.sprite.bbox.max.y = (int)(pDiag->lYtop + lHeight);
+		memcpy(&pNew->data.sprite.header, pucImage, tImageSize);
+		break;
+	case imagetype_is_jpeg:
+#if defined(DEBUG)
+		(void)bGetJpegInfo(pucImage, tImageSize);
+#endif /* DEBUG */
+		tRealSize += sizeof(drawfile_jpeg) + tImageSize;
+		tSize = ROUND4(tRealSize);
+		vExtendDiagramSize(pDiag, tSize);
+		pNew = xmalloc(tSize);
+		memset(pNew, 0, tSize);
+		pNew->type = drawfile_TYPE_JPEG;
+		pNew->size = tSize;
+		pNew->data.jpeg.bbox.min.x = (int)pDiag->lXleft;
+		pNew->data.jpeg.bbox.min.y = (int)pDiag->lYtop;
+		pNew->data.jpeg.bbox.max.x = (int)(pDiag->lXleft + lWidth);
+		pNew->data.jpeg.bbox.max.y = (int)(pDiag->lYtop + lHeight);
+		pNew->data.jpeg.width = (int)lWidth;
+		pNew->data.jpeg.height = (int)lHeight;
+		pNew->data.jpeg.xdpi = 90;
+		pNew->data.jpeg.ydpi = 90;
+		pNew->data.jpeg.trfm.entries[0][0] = 0x10000;
+		pNew->data.jpeg.trfm.entries[0][1] = 0;
+		pNew->data.jpeg.trfm.entries[1][0] = 0;
+		pNew->data.jpeg.trfm.entries[1][1] = 0x10000;
+		pNew->data.jpeg.trfm.entries[2][0] = (int)pDiag->lXleft;
+		pNew->data.jpeg.trfm.entries[2][1] = (int)pDiag->lYtop;
+		pNew->data.jpeg.len = tImageSize;
+		memcpy(pNew->data.jpeg.data, pucImage, tImageSize);
+		break;
+	default:
+		DBG_DEC(pImg->eImageType);
+		pNew = NULL;
+		break;
+	}
+
+	Error_CheckFatal(Drawfile_AppendObject(&pDiag->tInfo,
+					pDiag->tMemorySize, pNew, TRUE));
+	pNew = xfree(pNew);
+	pDiag->lXleft = 0;
+} /* end of vImage2Diagram */
+
+/*
+ * bAddDummyImage - add a dummy image
+ *
+ * return TRUE when successful, otherwise FALSE
+ */
+BOOL
+bAddDummyImage(diagram_type *pDiag, const imagedata_type *pImg)
+{
+  	drawfile_object	*pNew;
+	int	*piTmp;
+	long	lWidth, lHeight;
+	size_t	tRealSize, tSize;
+
+	TRACE_MSG("bAddDummyImage");
+
+	fail(pDiag == NULL);
+	fail(pImg == NULL);
+	fail(pDiag->lXleft < 0);
+
+	if (pImg->iVerSizeScaled <= 0 || pImg->iHorSizeScaled <= 0) {
+		return FALSE;
+	}
+
+	DBG_DEC_C(pDiag->lXleft != 0, pDiag->lXleft);
+
+	lWidth = lPoints2DrawUnits(pImg->iHorSizeScaled);
+	lHeight = lPoints2DrawUnits(pImg->iVerSizeScaled);
+
+	pDiag->lYtop -= lHeight;
+
+	tRealSize = offsetof(drawfile_object, data);
+	tRealSize += sizeof(drawfile_path) + (14 - 1) * sizeof(int);
+	tSize = ROUND4(tRealSize);
+	vExtendDiagramSize(pDiag, tSize);
+	pNew = xmalloc(tSize);
+	memset(pNew, 0, tSize);
+	pNew->type = drawfile_TYPE_PATH;
+	pNew->size = tSize;
+	pNew->data.path.bbox.min.x = (int)pDiag->lXleft;
+	pNew->data.path.bbox.min.y = (int)pDiag->lYtop;
+	pNew->data.path.bbox.max.x = (int)(pDiag->lXleft + lWidth);
+	pNew->data.path.bbox.max.y = (int)(pDiag->lYtop + lHeight);
+	pNew->data.path.fill.value = -1;
+	pNew->data.path.outline.value = 0x4d4d4d00;	/* Gray 70 percent */
+	pNew->data.path.width = (int)lMilliPoints2DrawUnits(500);
+	pNew->data.path.style.flags = 0;
+	pNew->data.path.style.reserved = 0;
+	pNew->data.path.style.cap_width = 0;
+	pNew->data.path.style.cap_length = 0;
+	piTmp = pNew->data.path.path;
+	*piTmp++ = drawfile_PATH_MOVE_TO;
+	*piTmp++ = pNew->data.path.bbox.min.x;
+	*piTmp++ = pNew->data.path.bbox.min.y;
+	*piTmp++ = drawfile_PATH_LINE_TO;
+	*piTmp++ = pNew->data.path.bbox.min.x;
+	*piTmp++ = pNew->data.path.bbox.max.y;
+	*piTmp++ = drawfile_PATH_LINE_TO;
+	*piTmp++ = pNew->data.path.bbox.max.x;
+	*piTmp++ = pNew->data.path.bbox.max.y;
+	*piTmp++ = drawfile_PATH_LINE_TO;
+	*piTmp++ = pNew->data.path.bbox.max.x;
+	*piTmp++ = pNew->data.path.bbox.min.y;
+	*piTmp++ = drawfile_PATH_CLOSE_LINE;
+	*piTmp++ = drawfile_PATH_END_PATH;
+
+	Error_CheckFatal(Drawfile_AppendObject(&pDiag->tInfo,
+					pDiag->tMemorySize, pNew, TRUE));
+	pNew = xfree(pNew);
+	pDiag->lXleft = 0;
+	return TRUE;
+} /* end of bAddDummyImage */
+
+/*
+ * vMove2NextLine - move to the next line
+ */
+void
+vMove2NextLine(diagram_type *pDiag, drawfile_fontref tFontRef,
+	USHORT usFontSize)
+{
+	long	l20;
+
+	TRACE_MSG("vMove2NextLine");
+
+	fail(pDiag == NULL);
+	fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
+
+	if (tFontRef == 0) {
+		l20 = Drawfile_ScreenToDraw(32 + 3);
+	} else {
+		l20 = lWord2DrawUnits20(usFontSize);
+	}
+	pDiag->lYtop -= l20;
+} /* end of vMove2NextLine */
+
+/*
+ * Create an start of paragraph (Phase 1)
+ */
+void
+vStartOfParagraph1(diagram_type *pDiag, long lBeforeIndentation)
+{
+	TRACE_MSG("vStartOfParagraph1");
+
+	fail(pDiag == NULL);
+	fail(lBeforeIndentation < 0);
+
+	pDiag->lXleft = 0;
+	pDiag->lYtop -= lMilliPoints2DrawUnits(lBeforeIndentation);
+} /* end of vStartOfParagraph1 */
+
+/*
+ * Create an start of paragraph (Phase 2)
+ * DUMMY function
+ */
+void
+vStartOfParagraph2(diagram_type *pDiag)
+{
+	TRACE_MSG("vStartOfParagraph2");
+} /* end of vStartOfParagraph2 */
+
+/*
+ * Create an end of paragraph
+ */
+void
+vEndOfParagraph(diagram_type *pDiag,
+	drawfile_fontref tFontRef, USHORT usFontSize, long lAfterIndentation)
+{
+	TRACE_MSG("vEndOfParagraph");
+
+	fail(pDiag == NULL);
+	fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
+	fail(lAfterIndentation < 0);
+
+	pDiag->lXleft = 0;
+	pDiag->lYtop -= lMilliPoints2DrawUnits(lAfterIndentation);
+} /* end of vEndOfParagraph */
+
+/*
+ * Create an end of page
+ */
+void
+vEndOfPage(diagram_type *pDiag, long lAfterIndentation, BOOL bNewSection)
+{
+	TRACE_MSG("vEndOfPage");
+
+	fail(pDiag == NULL);
+	fail(lAfterIndentation < 0);
+
+	pDiag->lXleft = 0;
+	pDiag->lYtop -= lMilliPoints2DrawUnits(lAfterIndentation);
+} /* end of vEndOfPage */
+
+/*
+ * vSetHeaders - set the headers
+ * DUMMY function
+ */
+void
+vSetHeaders(diagram_type *pDiag, USHORT usIstd)
+{
+	TRACE_MSG("vSetHeaders");
+} /* end of vSetHeaders */
+
+/*
+ * Create a start of list
+ * DUMMY function
+ */
+void
+vStartOfList(diagram_type *pDiag, UCHAR ucNFC, BOOL bIsEndOfTable)
+{
+	TRACE_MSG("vStartOfList");
+} /* end of vStartOfList */
+
+/*
+ * Create an end of list
+ * DUMMY function
+ */
+void
+vEndOfList(diagram_type *pDiag)
+{
+	TRACE_MSG("vEndOfList");
+} /* end of vEndOfList */
+
+/*
+ * Create a start of a list item
+ * DUMMY function
+ */
+void
+vStartOfListItem(diagram_type *pDiag, BOOL bNoMarks)
+{
+	TRACE_MSG("vStartOfListItem");
+} /* end of vStartOfListItem */
+
+/*
+ * Create an end of a table
+ * DUMMY function
+ */
+void
+vEndOfTable(diagram_type *pDiag)
+{
+	TRACE_MSG("vEndOfTable");
+} /* end of vEndTable */
+
+/*
+ * Add a table row
+ * DUMMY function
+ *
+ * Returns TRUE when conversion type is XML
+ */
+BOOL
+bAddTableRow(diagram_type *pDiag, char **aszColTxt,
+	int iNbrOfColumns, const short *asColumnWidth, UCHAR ucBorderInfo)
+{
+	TRACE_MSG("bAddTableRow");
+
+	return FALSE;
+} /* end of bAddTableRow */
+
+/*
+ * vForceRedraw - force a redraw of the main window
+ */
+static void
+vForceRedraw(diagram_type *pDiag)
+{
+	window_state		tWindowState;
+	window_redrawblock	tRedraw;
+	int	x0, y0, x1, y1;
+
+	TRACE_MSG("vForceRedraw");
+
+	fail(pDiag == NULL);
+
+	DBG_DEC(pDiag->iScaleFactorCurr);
+
+	/* Read the size of the current diagram */
+	Drawfile_QueryBox(&pDiag->tInfo, &tRedraw.rect, TRUE);
+	/* Adjust the size of the work area */
+	x0 = tRedraw.rect.min.x * pDiag->iScaleFactorCurr / 100 - 1;
+	y0 = tRedraw.rect.min.y * pDiag->iScaleFactorCurr / 100 - 1;
+	x1 = tRedraw.rect.max.x * pDiag->iScaleFactorCurr / 100 + 1;
+	y1 = tRedraw.rect.max.y * pDiag->iScaleFactorCurr / 100 + 1;
+	/* Work area extension */
+	x0 -= WORKAREA_EXTENSION;
+	y0 -= WORKAREA_EXTENSION;
+	x1 += WORKAREA_EXTENSION;
+	y1 += WORKAREA_EXTENSION;
+	Window_SetExtent(pDiag->tMainWindow, x0, y0, x1, y1);
+	/* Widen the box slightly to be sure all the edges are drawn */
+	x0 -= 5;
+	y0 -= 5;
+	x1 += 5;
+	y1 += 5;
+	/* Force the redraw */
+	Window_ForceRedraw(pDiag->tMainWindow, x0, y0, x1, y1);
+	/* Reopen the window to show the correct size */
+	Error_CheckFatal(Wimp_GetWindowState(pDiag->tMainWindow, &tWindowState));
+	tWindowState.openblock.behind = -1;
+	Error_CheckFatal(Wimp_OpenWindow(&tWindowState.openblock));
+} /* end of vForceRedraw */
+
+/*
+ * vShowDiagram - put the diagram on the screen
+ */
+void
+vShowDiagram(diagram_type *pDiag)
+{
+	wimp_box	tRect;
+	int	x0, y0, x1, y1;
+
+	TRACE_MSG("vShowDiagram");
+
+	fail(pDiag == NULL);
+
+	Window_Show(pDiag->tMainWindow, open_NEARLAST);
+	Drawfile_QueryBox(&pDiag->tInfo, &tRect, TRUE);
+	/* Work area extension */
+	x0 = tRect.min.x - WORKAREA_EXTENSION;
+	y0 = tRect.min.y - WORKAREA_EXTENSION;
+	x1 = tRect.max.x + WORKAREA_EXTENSION;
+	y1 = tRect.max.y + WORKAREA_EXTENSION;
+	Window_SetExtent(pDiag->tMainWindow, x0, y0, x1, y1);
+	vForceRedraw(pDiag);
+} /* end of vShowDiagram */
+
+/*
+ * vMainButtonClick - handle mouse buttons clicks for the main screen
+ */
+void
+vMainButtonClick(mouse_block *pMouse)
+{
+	caret_block	tCaret;
+	window_state	ws;
+
+	TRACE_MSG("vMainButtonClick");
+
+	fail(pMouse == NULL);
+
+	DBG_DEC(pMouse->button.data.select);
+	DBG_DEC(pMouse->button.data.adjust);
+	DBG_DEC(pMouse->window);
+	DBG_DEC(pMouse->icon);
+
+	if (pMouse->window >= 0 &&
+	    pMouse->icon == -1 &&
+	    (pMouse->button.data.select || pMouse->button.data.adjust)) {
+		/* Get the input focus */
+		Error_CheckFatal(Wimp_GetWindowState(pMouse->window, &ws));
+		tCaret.window = pMouse->window;
+		tCaret.icon = -1;
+		tCaret.offset.x = pMouse->pos.x - ws.openblock.screenrect.min.x;
+		tCaret.offset.y = pMouse->pos.y - ws.openblock.screenrect.max.y;
+		tCaret.height = (int)BIT(25);
+		tCaret.index = 0;
+		Error_CheckFatal(Wimp_SetCaretPosition(&tCaret));
+	}
+} /* end of vMainButtonClick */
+
+/*
+ * bMainKeyPressed - handle pressed keys for the main window
+ */
+BOOL
+bMainKeyPressed(event_pollblock *pEvent, void *pvReference)
+{
+	diagram_type 	*pDiag;
+
+	TRACE_MSG("bMainKeyPressed");
+
+	fail(pEvent == NULL);
+	fail(pEvent->type != event_KEY);
+	fail(pvReference == NULL);
+
+	pDiag = (diagram_type *)pvReference;
+
+	fail(pEvent->data.key.caret.window != pDiag->tMainWindow);
+
+
+	switch (pEvent->data.key.code) {
+	case keycode_CTRL_F2:		/* Ctrl F2 */
+		bDestroyDiagram(pEvent, pvReference);
+		break;
+	case keycode_F3:		/* F3 */
+		bSaveDrawfile(pEvent, pvReference);
+		break;
+	case keycode_SHIFT_F3:		/* Shift F3 */
+		bSaveTextfile(pEvent, pvReference);
+		break;
+	default:
+		DBG_DEC(pEvent->data.key.code);
+		Error_CheckFatal(Wimp_ProcessKey(pEvent->data.key.code));
+	}
+	return TRUE;
+} /* end of bMainKeyPressed */
+
+/*
+ * bRedrawMainWindow - redraw the main window
+ */
+BOOL
+bRedrawMainWindow(event_pollblock *pEvent, void *pvReference)
+{
+	window_redrawblock	tBlock;
+	diagram_type	*pDiag;
+	drawfile_info	*pInfo;
+	double		dScaleFactor;
+	BOOL		bMore;
+
+	TRACE_MSG("bRedrawMainWindow");
+
+	fail(pEvent == NULL);
+	fail(pEvent->type != event_REDRAW);
+	fail(pvReference == NULL);
+
+	pDiag = (diagram_type *)pvReference;
+
+	fail(pDiag->tMainWindow != pEvent->data.openblock.window);
+	fail(pDiag->iScaleFactorCurr < MIN_SCALE_FACTOR);
+	fail(pDiag->iScaleFactorCurr > MAX_SCALE_FACTOR);
+
+	dScaleFactor = (double)pDiag->iScaleFactorCurr / 100.0;
+	pInfo = &pDiag->tInfo;
+
+	tBlock.window = pEvent->data.openblock.window;
+	Error_CheckFatal(Wimp_RedrawWindow(&tBlock, &bMore));
+
+	/* If there is no real diagram just go thru the motions */
+	while (bMore) {
+		if (pInfo->data != NULL && pInfo->length != 0) {
+			Error_CheckFatal(Drawfile_RenderDiagram(pInfo,
+						&tBlock, dScaleFactor));
+		}
+		Error_CheckFatal(Wimp_GetRectangle(&tBlock, &bMore));
+	}
+	return TRUE;
+} /* end of bRedrawMainWindow */
+
+/*
+ * bScaleOpenAction - action to be taken when the Scale view window opens
+ */
+BOOL
+bScaleOpenAction(event_pollblock *pEvent, void *pvReference)
+{
+	window_state	tWindowState;
+	diagram_type	*pDiag;
+
+	TRACE_MSG("bScaleOpenAction");
+
+	fail(pEvent == NULL);
+	fail(pEvent->type != event_SEND);
+	fail(pEvent->data.message.header.action != message_MENUWARN);
+	fail(pvReference == NULL);
+
+	pDiag = (diagram_type *)pvReference;
+
+	if (menu_currentopen != pDiag->pSaveMenu ||
+	    pEvent->data.message.data.menuwarn.selection[0] != SAVEMENU_SCALEVIEW) {
+		return FALSE;
+	}
+
+	Error_CheckFatal(Wimp_GetWindowState(pDiag->tScaleWindow,
+						&tWindowState));
+	if (tWindowState.flags.data.open) {
+		/* The window is already open */
+		return TRUE;
+	}
+
+	DBG_MSG("vScaleOpenAction for real");
+
+	pDiag->iScaleFactorTemp = pDiag->iScaleFactorCurr;
+	vUpdateWriteableNumber(pDiag->tScaleWindow,
+			SCALE_SCALE_WRITEABLE, pDiag->iScaleFactorTemp);
+	Window_Show(pDiag->tScaleWindow, open_UNDERPOINTER);
+	return TRUE;
+} /* end of bScaleOpenAction */
+
+/*
+ * vSetTitle - set the title of a window
+ */
+void
+vSetTitle(diagram_type *pDiag)
+{
+	char	szTitle[WINDOW_TITLE_LEN];
+
+	TRACE_MSG("vSetTitle");
+
+	fail(pDiag == NULL);
+	fail(pDiag->szFilename[0] == '\0');
+
+	(void)sprintf(szTitle, "%.*s at %d%%",
+				FILENAME_TITLE_LEN,
+				pDiag->szFilename,
+				pDiag->iScaleFactorCurr % 1000);
+	if (strlen(pDiag->szFilename) > FILENAME_TITLE_LEN) {
+		szTitle[FILENAME_TITLE_LEN - 1] = OUR_ELLIPSIS;
+	}
+
+	Window_SetTitle(pDiag->tMainWindow, szTitle);
+} /* end of vSetTitle */
+
+/*
+ * vScaleButtonClick - handle a mouse button click in the Scale view window
+ */
+void
+vScaleButtonClick(mouse_block *pMouse, diagram_type *pDiag)
+{
+	BOOL	bCloseWindow, bRedraw;
+
+	TRACE_MSG("vScaleButtonClick");
+
+	fail(pMouse == NULL || pDiag == NULL);
+	fail(pMouse->window != pDiag->tScaleWindow);
+
+	bCloseWindow = FALSE;
+	bRedraw = FALSE;
+	switch (pMouse->icon) {
+	case SCALE_CANCEL_BUTTON:
+		bCloseWindow = TRUE;
+		pDiag->iScaleFactorTemp = pDiag->iScaleFactorCurr;
+		break;
+	case SCALE_SCALE_BUTTON:
+		bCloseWindow = TRUE;
+		bRedraw = pDiag->iScaleFactorCurr != pDiag->iScaleFactorTemp;
+		pDiag->iScaleFactorCurr = pDiag->iScaleFactorTemp;
+		break;
+	case SCALE_50_PCT:
+		pDiag->iScaleFactorTemp = 50;
+		break;
+	case SCALE_75_PCT:
+		pDiag->iScaleFactorTemp = 75;
+		break;
+	case SCALE_100_PCT:
+		pDiag->iScaleFactorTemp = 100;
+		break;
+	case SCALE_150_PCT:
+		pDiag->iScaleFactorTemp = 150;
+		break;
+	default:
+		DBG_DEC(pMouse->icon);
+		break;
+	}
+	if (bCloseWindow) {
+		/* Close the scale window */
+		Error_CheckFatal(Wimp_CloseWindow(pMouse->window));
+		if (bRedraw) {
+			/* Redraw the main window */
+			vSetTitle(pDiag);
+			vForceRedraw(pDiag);
+		}
+	} else {
+		vUpdateWriteableNumber(pMouse->window,
+				SCALE_SCALE_WRITEABLE,
+				pDiag->iScaleFactorTemp);
+	}
+} /* end of vScaleButtonClick */
+
+/*
+ * bScaleKeyPressed - handle pressed keys for the scale window
+ */
+BOOL
+bScaleKeyPressed(event_pollblock *pEvent, void *pvReference)
+{
+	icon_block	tIcon;
+	diagram_type	*pDiag;
+	caret_block	*pCaret;
+	char		*pcChar;
+	int		iTmp;
+
+	TRACE_MSG("bScaleKeyPressed");
+
+        fail(pEvent == NULL);
+        fail(pEvent->type != event_KEY);
+        fail(pvReference == NULL);
+
+	pCaret = &pEvent->data.key.caret;
+	pDiag = (diagram_type *)pvReference;
+
+        fail(pEvent->data.key.caret.window != pDiag->tScaleWindow);
+
+	DBG_DEC_C(pCaret->icon != SCALE_SCALE_WRITEABLE, pCaret->icon);
+	DBG_DEC_C(pCaret->icon == SCALE_SCALE_WRITEABLE, pEvent->data.key.code);
+
+	if (pEvent->data.key.code != '\r' ||
+	    pCaret->icon != SCALE_SCALE_WRITEABLE) {
+		Error_CheckFatal(Wimp_ProcessKey(pEvent->data.key.code));
+		return TRUE;
+	}
+
+	Error_CheckFatal(Wimp_GetIconState(pCaret->window, pCaret->icon, &tIcon));
+	if (!tIcon.flags.data.text || !tIcon.flags.data.indirected) {
+		werr(1, "Icon %d must be indirected text", (int)pCaret->icon);
+	}
+	iTmp = (int)strtol(tIcon.data.indirecttext.buffer, &pcChar, 10);
+	if (*pcChar != '\0' && *pcChar != '\r') {
+		DBG_DEC(*pcChar);
+	} else if (iTmp < MIN_SCALE_FACTOR) {
+		pDiag->iScaleFactorTemp = MIN_SCALE_FACTOR;
+	} else if (iTmp > MAX_SCALE_FACTOR) {
+		pDiag->iScaleFactorTemp = MAX_SCALE_FACTOR;
+	} else {
+		pDiag->iScaleFactorTemp = iTmp;
+	}
+	pDiag->iScaleFactorCurr = pDiag->iScaleFactorTemp;
+	/* Close the scale window */
+	Error_CheckFatal(Wimp_CloseWindow(pCaret->window));
+	/* Redraw the main window */
+	vSetTitle(pDiag);
+	vForceRedraw(pDiag);
+	return TRUE;
+} /* end of bScaleKeyPressed */
+
diff --git a/draw.h b/draw.h
new file mode 100644
index 0000000..839bbf0
--- /dev/null
+++ b/draw.h
@@ -0,0 +1,46 @@
+/*
+ * draw.h
+ * Copyright (C) 2001 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Constants and macros to deal with the Draw format
+ */
+
+#if !defined(__draw_h)
+#define __draw_h 1
+
+#include "drawftypes.h"
+
+typedef struct draw_jpegstrhdr_tag {
+	draw_tagtyp	tag;	/* 1 word  */
+	draw_sizetyp	size;	/* 1 word  */
+	draw_bboxtyp	bbox;	/* 4 words */
+	int	width;		/* 1 word  */
+	int	height;		/* 1 word  */
+	int	xdpi;		/* 1 word  */
+	int	ydpi;		/* 1 word  */
+	int	trfm[6];	/* 6 words */
+	int	len;		/* 1 word  */
+} draw_jpegstrhdr;
+
+typedef struct draw_jpegstr_tag {
+	draw_tagtyp	tag;	/* 1 word  */
+	draw_sizetyp	size;	/* 1 word  */
+	draw_bboxtyp	bbox;	/* 4 words */
+	int	width;		/* 1 word  */
+	int	height;		/* 1 word  */
+	int	xdpi;		/* 1 word  */
+	int	ydpi;		/* 1 word  */
+	int	trfm[6];	/* 6 words */
+	int	len;		/* 1 word  */
+	unsigned char	*jpeg;
+} draw_jpegstr;
+
+typedef union draw_imageType_tag {
+	draw_spristr	*sprite;
+	draw_jpegstr	*jpeg;
+	char		*bytep;
+	int		*wordp;
+} draw_imageType;
+
+#endif /* !__draw_h */
diff --git a/drawfile.c b/drawfile.c
new file mode 100644
index 0000000..5963644
--- /dev/null
+++ b/drawfile.c
@@ -0,0 +1,422 @@
+/*
+ * drawfile.c
+ * Copyright (C) 2005 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Functions to process with the Draw diagram
+ */
+
+#include <string.h>
+#include "DeskLib:Error.h"
+#include "DeskLib:SWI.h"
+#include "drawfile.h"
+#include "antiword.h"
+
+#define DRAWFILE_OBJECT_TOO_SMALL	200
+#define DRAWFILE_NO_TEXT		201
+#define DRAWFILE_BAD_CHARACTER		202
+#define DRAWFILE_SMALL_MEMORY		203
+#define DRAWFILE_PATH_WITHOUT_LINES	204
+#define DRAWFILE_BAD_PATH_TYPE		205
+#define DRAWFILE_PATH_WITHOUT_END	206
+#define DRAWFILE_BAD_SPRITE_SIZE	207
+#define DRAWFILE_BAD_JPEG_SIZE		208
+#define DRAWFILE_TOO_SMALL		209
+#define DRAWFILE_NOT_A_DRAWFILE		210
+#define DRAWFILE_OBJECT_SIZE		211
+#define DRAWFILE_MANY_FONTTABLES	212
+#define DRAWFILE_TEXT_NO_FONT		213
+#define DRAWFILE_OBJECT_UNEXPECTED	214
+#define DRAWFILE_SIZE_ERROR		215
+
+typedef struct drawfile_error_tag {
+	int		iErrorNumber;
+	const char	*szErrorText;
+} drawfile_error_type;
+
+static const drawfile_error_type atErrors[] = {
+	{ DRAWFILE_OBJECT_TOO_SMALL, "Object too small"},
+	{ DRAWFILE_NO_TEXT, "Text object without text"},
+	{ DRAWFILE_BAD_CHARACTER, "Bad character in string"},
+	{ DRAWFILE_SMALL_MEMORY, "Not enough memory reserved"},
+	{ DRAWFILE_PATH_WITHOUT_LINES, "This path has no lines"},
+	{ DRAWFILE_BAD_PATH_TYPE, "Bad path-type in path"},
+	{ DRAWFILE_PATH_WITHOUT_END, "No end of path seen"},
+	{ DRAWFILE_BAD_SPRITE_SIZE, "Bad sprite size"},
+	{ DRAWFILE_BAD_JPEG_SIZE, "Bad jpeg size"},
+	{ DRAWFILE_TOO_SMALL, "Too small to be a drawfile"},
+	{ DRAWFILE_NOT_A_DRAWFILE, "Not a drawfile"},
+	{ DRAWFILE_OBJECT_SIZE, "Object with incorrect size"},
+	{ DRAWFILE_MANY_FONTTABLES, "More than one font table"},
+	{ DRAWFILE_TEXT_NO_FONT, "Text, but no font table seen"},
+	{ DRAWFILE_OBJECT_UNEXPECTED, "Unexpected object type"},
+	{ DRAWFILE_SIZE_ERROR, "Sizes don't match"},
+};
+
+
+/*
+ * pFillError - error number to error struct
+ */
+static os_error *
+pFillError(int iErrorNumber)
+{
+	static os_error		tError;
+	const drawfile_error_type	*pTmp;
+	const char	*szErrorText;
+
+	szErrorText = "Unknown error";
+	for (pTmp = atErrors; pTmp < atErrors + elementsof(atErrors); pTmp++) {
+		if (iErrorNumber == pTmp->iErrorNumber) {
+			szErrorText = pTmp->szErrorText;
+			break;
+		}
+	}
+	tError.errnum = iErrorNumber;
+	strncpy(tError.errmess, szErrorText, sizeof(tError.errmess) - 1);
+	tError.errmess[sizeof(tError.errmess) - 1] = '\0';
+	DBG_DEC(tError.errnum);
+	DBG_MSG(tError.errmess);
+	return &tError;
+} /* end of pFillError */
+
+/*
+ * Drawfile_BBox - Find the bounding box of a diagram
+ */
+os_error *
+Drawfile_Bbox(drawfile_bbox_flags flags,
+	drawfile_diagram const *diagram,
+	int size,
+	os_trfm const *trfm,
+	wimp_box *bbox)
+{
+	return SWI(5, 0, DrawFile_BBox | XOS_Bit,
+		flags, diagram, size, trfm, bbox);
+} /* end of Drawfile_Bbox */
+
+/*
+ * Drawfile_CreateDiagram - create an empty drawfile diagram
+ */
+os_error *
+Drawfile_CreateDiagram(drawfile_info *pInfo, size_t tMemorySize,
+	const char *szCreator, wimp_box tBbox)
+{
+	drawfile_diagram	*pDiag;
+
+	if (tMemorySize < offsetof(drawfile_diagram, objects)) {
+		return pFillError(DRAWFILE_SMALL_MEMORY);
+	}
+	pDiag = (drawfile_diagram *)pInfo->data;
+	strncpy(pDiag->tag, "Draw", 4);
+	pDiag->major_version = 201;
+	pDiag->minor_version = 0;
+	strncpy(pDiag->source, szCreator, sizeof(pDiag->source));
+	pDiag->bbox = tBbox;
+	/* Memory in use */
+	pInfo->length = offsetof(drawfile_diagram, objects);
+	return NULL;
+} /* end of Drawfile_CreateDiagram */
+
+/*
+ * Drawfile_AppendObject - append an object to a diagram
+ */
+os_error *
+Drawfile_AppendObject(drawfile_info *pInfo, size_t tMemorySize,
+	const drawfile_object *pObject, BOOL bRebind)
+{
+	wimp_box	*pMainBbox;
+	const wimp_box	*pBbox;
+	byte		*pAfter;
+
+	if (tMemorySize < pInfo->length + pObject->size) {
+		return pFillError(DRAWFILE_OBJECT_TOO_SMALL);
+	}
+	/* After the last object */
+	pAfter = (byte *)pInfo->data + pInfo->length;
+	/* Copy in the new data */
+	memcpy(pAfter, pObject, pObject->size);
+	/* Rebind if needed */
+	if (bRebind) {
+		pMainBbox = &((drawfile_diagram *)pInfo->data)->bbox;
+		switch (pObject->type) {
+		case drawfile_TYPE_FONT_TABLE:
+			pBbox = NULL;
+			break;
+		case drawfile_TYPE_TEXT:
+			pBbox = &pObject->data.text.bbox;
+			break;
+		case drawfile_TYPE_PATH:
+			pBbox = &pObject->data.path.bbox;
+			break;
+		case drawfile_TYPE_SPRITE:
+			pBbox = &pObject->data.sprite.bbox;
+			break;
+		case drawfile_TYPE_GROUP:
+			pBbox = &pObject->data.group.bbox;
+			break;
+		case drawfile_TYPE_TAGGED:
+			pBbox = &pObject->data.tagged.bbox;
+			break;
+		case drawfile_TYPE_TEXT_AREA:
+			pBbox = &pObject->data.text_area.bbox;
+			break;
+		case drawfile_TYPE_TEXT_COLUMN:
+			pBbox = NULL;
+			break;
+		case drawfile_TYPE_OPTIONS:
+			pBbox = &pObject->data.options.bbox;
+			break;
+		case drawfile_TYPE_TRFM_TEXT:
+			pBbox = &pObject->data.trfm_text.bbox;
+			break;
+		case drawfile_TYPE_TRFM_SPRITE:
+			pBbox = &pObject->data.trfm_sprite.bbox;
+			break;
+		case drawfile_TYPE_JPEG:
+			pBbox = &pObject->data.jpeg.bbox;
+			break;
+		default:
+			pBbox = NULL;
+			break;
+		}
+		if (pBbox != NULL) {
+			if (pBbox->min.x < pMainBbox->min.x) {
+				pMainBbox->min.x = pBbox->min.x;
+			}
+			if (pBbox->min.y < pMainBbox->min.y) {
+				pMainBbox->min.y = pBbox->min.y;
+			}
+			if (pBbox->max.x > pMainBbox->max.x) {
+				pMainBbox->max.x = pBbox->max.x;
+			}
+			if (pBbox->max.y > pMainBbox->max.y) {
+				pMainBbox->max.y = pBbox->max.y;
+			}
+		}
+	}
+	/* Memory in use */
+	pInfo->length += pObject->size;
+	return NULL;
+} /* end of Drawfile_AppendObject */
+
+/*
+ * Replaces the draw_render_diag function from RISC_OSLib
+ */
+os_error *
+Drawfile_RenderDiagram(drawfile_info *pInfo, window_redrawblock *pRedraw,
+	double dScale)
+{
+	int	aiTransform[6];
+
+	fail(pInfo == NULL);
+	fail(pInfo->data == NULL);
+	fail(pRedraw == NULL);
+	fail(dScale < 0.01);
+
+	aiTransform[0] = (int)(dScale * 0x10000);
+	aiTransform[1] = 0;
+	aiTransform[2] = 0;
+	aiTransform[3] = (int)(dScale * 0x10000);
+	aiTransform[4] = (pRedraw->rect.min.x - pRedraw->scroll.x) * 256;
+	aiTransform[5] = (pRedraw->rect.max.y - pRedraw->scroll.y) * 256;
+
+	return SWI(6, 0, DrawFile_Render | XOS_Bit,
+		0, pInfo->data, pInfo->length, aiTransform, &pRedraw->rect, 0);
+} /* end of Drawfile_RenderDiagram */
+
+/*
+ * pVerifyText - verify a text object
+ */
+static os_error *
+pVerifyText(const drawfile_text *pText)
+{
+	const unsigned char	*pucTmp;
+
+	if (pText->text[0] == '\0') {
+		return pFillError(DRAWFILE_NO_TEXT);
+	}
+	pucTmp = (const unsigned char *)pText->text;
+	while (*pucTmp != '\0') {
+		if (*pucTmp < 0x20 || *pucTmp == 0x7f) {
+			return pFillError(DRAWFILE_BAD_CHARACTER);
+		}
+		pucTmp++;
+	}
+	return NULL;
+} /* end of pVerifyText */
+
+/*
+ * pVerifyPath - verify a path object
+ */
+static os_error *
+pVerifyPath(const drawfile_path *pPath, int iSize)
+{
+	const int	*piTmp;
+	int	iElements;
+	BOOL	bLine;
+
+	bLine = FALSE;
+	iElements = (iSize - offsetof(drawfile_path, path)) / 4;
+
+	for (piTmp = pPath->path; piTmp < pPath->path + iElements; piTmp++) {
+		switch(*piTmp) {
+		case drawfile_PATH_END_PATH:
+			if (bLine) {
+				return NULL;
+			}
+			return pFillError(DRAWFILE_PATH_WITHOUT_LINES);
+		case drawfile_PATH_LINE_TO:
+			bLine = TRUE;
+			piTmp += 2;
+			break;
+		case drawfile_PATH_MOVE_TO:
+			piTmp += 2;
+			break;
+		case drawfile_PATH_CLOSE_LINE:
+			bLine = TRUE;
+			break;
+		default:
+			return pFillError(DRAWFILE_BAD_PATH_TYPE);
+		}
+	}
+	return pFillError(DRAWFILE_PATH_WITHOUT_END);
+} /* end of pVerifyPath */
+
+/*
+ * pVerifySprite - verify a sprite object
+ */
+static os_error *
+pVerifySprite(const drawfile_sprite *pSprite, int iSize)
+{
+	iSize -= offsetof(drawfile_sprite, header);
+	if (iSize < pSprite->header.offset_next) {
+		DBG_DEC(iSize);
+		DBG_DEC(pSprite->header.offset_next);
+		return pFillError(DRAWFILE_BAD_SPRITE_SIZE);
+	}
+	return NULL;
+} /* end of pVerifySprite */
+
+/*
+ * pVerifyJpeg - verify a jpeg object
+ */
+static os_error *
+pVerifyJpeg(const drawfile_jpeg *pJpeg, int iSize)
+{
+	iSize -= offsetof(drawfile_jpeg, data);
+	if (iSize < pJpeg->len) {
+		DBG_DEC(iSize);
+		DBG_DEC(pJpeg->len);
+		return pFillError(DRAWFILE_BAD_JPEG_SIZE);
+	}
+	return NULL;
+} /* end of pVerifyJpeg */
+
+/*
+ * Drawfile_VerifyDiagram - Verify the diagram generated from the Word file
+ *
+ * returns NULL if the diagram is correct
+ */
+os_error *
+Drawfile_VerifyDiagram(drawfile_info *pInfo)
+{
+	drawfile_diagram	*pDiag;
+	drawfile_object	*pObj;
+	os_error	*pError;
+	const char	*pcTmp;
+	int		iToGo, iFontTables;
+	BOOL		bTypeFontTable;
+
+	TRACE_MSG("Drawfile_VerifyDiagram");
+
+	fail(pInfo == NULL);
+
+  	if (pInfo->length < offsetof(drawfile_diagram, objects)) {
+		return pFillError(DRAWFILE_TOO_SMALL);
+  	}
+
+	pDiag = (drawfile_diagram *)pInfo->data;
+	if (strncmp(pDiag->tag, "Draw", 4) != 0 ||
+	    pDiag->major_version != 201 ||
+	    pDiag->minor_version != 0) {
+		return pFillError(DRAWFILE_NOT_A_DRAWFILE);
+	}
+
+	iToGo = pInfo->length - offsetof(drawfile_diagram, objects);
+	pcTmp = (const char *)pInfo->data + offsetof(drawfile_diagram, objects);
+	iFontTables = 0;
+	bTypeFontTable = FALSE;
+
+	while (iToGo > 0) {
+		pObj = (drawfile_object *)pcTmp;
+		if (pObj->size < 0 || pObj->size % 4 != 0) {
+			return pFillError(DRAWFILE_OBJECT_SIZE);
+		}
+		switch (pObj->type) {
+		case drawfile_TYPE_FONT_TABLE:
+			if (bTypeFontTable) {
+				return pFillError(DRAWFILE_MANY_FONTTABLES);
+			}
+			bTypeFontTable = TRUE;
+			break;
+		case drawfile_TYPE_TEXT:
+			if (pObj->data.text.style.font_ref != 0 &&
+			    !bTypeFontTable) {
+				return pFillError(DRAWFILE_TEXT_NO_FONT);
+			}
+			pError = pVerifyText(&pObj->data.text);
+			if (pError != NULL) {
+				return pError;
+			}
+			break;
+		case drawfile_TYPE_PATH:
+			pError = pVerifyPath(&pObj->data.path,
+				pObj->size - offsetof(drawfile_object, data));
+			if (pError != NULL) {
+				return pError;
+			}
+			break;
+		case drawfile_TYPE_SPRITE:
+			pError = pVerifySprite(&pObj->data.sprite,
+				pObj->size - offsetof(drawfile_object, data));
+			if (pError != NULL) {
+				return pError;
+			}
+			break;
+		case drawfile_TYPE_JPEG:
+			pError = pVerifyJpeg(&pObj->data.jpeg,
+				pObj->size - offsetof(drawfile_object, data));
+			if (pError != NULL) {
+				return pError;
+			}
+			break;
+		default:
+			DBG_DEC(pObj->type);
+			return pFillError(DRAWFILE_OBJECT_UNEXPECTED);
+		}
+		pcTmp += pObj->size;
+		iToGo -= pObj->size;
+	}
+	if (iToGo < 0) {
+		return pFillError(DRAWFILE_SIZE_ERROR);
+	}
+	return NULL;
+} /* end of Drawfile_VerifyDiagram */
+
+/*
+ * Drawfile_QueryBox - Find the bounding box of a diagram
+ */
+void
+Drawfile_QueryBox(drawfile_info *pInfo, wimp_box *pRect, BOOL bScreenUnits)
+{
+	fail(pInfo == NULL);
+	fail(pRect == NULL);
+
+	Error_CheckFatal(Drawfile_Bbox(0,
+		pInfo->data, pInfo->length, NULL, pRect));
+	if (bScreenUnits) {
+		pRect->min.x = Drawfile_DrawToScreen(pRect->min.x);
+		pRect->min.y = Drawfile_DrawToScreen(pRect->min.y);
+		pRect->max.x = Drawfile_DrawToScreen(pRect->max.x);
+		pRect->max.y = Drawfile_DrawToScreen(pRect->max.y);
+	}
+} /* end of Drawfile_QueryBox */
diff --git a/drawfile.h b/drawfile.h
new file mode 100644
index 0000000..c9b76db
--- /dev/null
+++ b/drawfile.h
@@ -0,0 +1,433 @@
+/*
+ * drawfile.h
+ * Copyright (C) 2005 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Include file to deal with drawfiles
+ *
+ * Based on:
+ * C header file for DrawFile
+ * written by DefMod (May  4 2004) on Tue May  4 13:34:17 2004
+ * Jonathan Coxhead, jonathan@doves.demon.co.uk, 21 Aug 1995
+ * OSLib---efficient, type-safe, transparent, extensible,
+ * register-safe A P I coverage of RISC O S
+ * Copyright (C) 1994 Jonathan Coxhead
+ *
+ * All credit should go to him, but all the bugs are mine
+ */
+
+#if !defined(__drawfile_h)
+#define __drawfile_h
+
+#include "DeskLib:Sprite.h"
+#include "DeskLib:Wimp.h"
+
+#if !defined(BOOL)
+#define BOOL int
+#define TRUE 1
+#define FALSE 0
+#endif /* !BOOL */
+
+/*********************
+ * Conversion macros *
+ *********************/
+#define Drawfile_DrawToScreen(i) ((i) / 256)
+#define Drawfile_ScreenToDraw(i) ((i) * 256)
+
+/**********************************
+ * SWI names and SWI reason codes *
+ **********************************/
+#define DrawFile_Render                         0x45540
+#define DrawFile_BBox                           0x45541
+#define DrawFile_DeclareFonts                   0x45542
+
+/********************
+ * Type definitions *
+ ********************/
+typedef unsigned int                            bits;
+typedef unsigned char                           byte;
+
+typedef byte drawfile_fontref;
+
+typedef byte drawfile_path_style_flags;
+
+typedef bits drawfile_text_flags;
+
+typedef bits drawfile_render_flags;
+
+typedef bits drawfile_declare_fonts_flags;
+
+typedef bits drawfile_paper_options;
+
+typedef bits drawfile_entry_mode;
+
+typedef enum {
+  drawfile_TYPE_FONT_TABLE = 0,
+  drawfile_TYPE_TEXT = 1,
+  drawfile_TYPE_PATH = 2,
+  drawfile_TYPE_SPRITE = 5,
+  drawfile_TYPE_GROUP = 6,
+  drawfile_TYPE_TAGGED = 7,
+  drawfile_TYPE_TEXT_AREA = 9,
+  drawfile_TYPE_TEXT_COLUMN = 10,
+  drawfile_TYPE_OPTIONS = 11,
+  drawfile_TYPE_TRFM_TEXT = 12,
+  drawfile_TYPE_TRFM_SPRITE = 13,
+  drawfile_TYPE_JPEG = 16
+} drawfile_type;
+
+typedef enum {
+  drawfile_PATH_END_PATH = 0,
+  drawfile_PATH_CONTINUATION = 1,
+  drawfile_PATH_MOVE_TO = 2,
+  drawfile_PATH_SPECIAL_MOVE_TO = 3,
+  drawfile_PATH_CLOSE_GAP = 4,
+  drawfile_PATH_CLOSE_LINE = 5,
+  drawfile_PATH_BEZIER_TO = 6,
+  drawfile_PATH_GAP_TO = 7,
+  drawfile_PATH_LINE_TO = 8
+} drawfile_path_type;
+
+typedef struct {
+  int start;
+  int element_count;
+  int elements [6];
+} draw_dash_pattern;
+
+typedef struct {
+  int entries [3] [2];
+} os_trfm;
+
+typedef struct {
+  void *data;
+  size_t length;
+} drawfile_info;
+
+typedef struct {
+  drawfile_fontref font_ref;
+  char font_name [1];
+} drawfile_font_def;
+
+typedef struct {
+  drawfile_fontref font_ref;
+  byte reserved [3];
+} drawfile_text_style;
+
+typedef struct {
+  drawfile_path_style_flags flags;
+  byte reserved;
+  byte cap_width;
+  byte cap_length;
+} drawfile_path_style;
+
+typedef struct {
+  drawfile_font_def font_def[1];
+} drawfile_font_table;
+
+typedef struct {
+  wimp_box bbox;
+  palette_entry fill;
+  palette_entry bg_hint;
+  drawfile_text_style style;
+  int xsize;
+  int ysize;
+  wimp_coord base;
+  char text [1];
+} drawfile_text;
+
+typedef struct {
+  wimp_box bbox;
+  palette_entry fill;
+  palette_entry outline;
+  int width;
+  drawfile_path_style style;
+  int path [1];
+} drawfile_path;
+
+typedef struct {
+  wimp_box bbox;
+  palette_entry fill;
+  palette_entry outline;
+  int width;
+  drawfile_path_style style;
+  draw_dash_pattern pattern;
+  int path [1];
+} drawfile_path_with_pattern;
+
+typedef struct {
+  wimp_box bbox;
+  sprite_header header;
+  byte data [1];
+} drawfile_sprite;
+
+typedef struct  {
+  wimp_box bbox;
+  char name [12];
+  int objects [1];
+} drawfile_group;
+
+typedef struct {
+  wimp_box bbox;
+  drawfile_type tag;
+  int object [1];
+} drawfile_tagged;
+
+typedef struct {
+  wimp_box box;
+} drawfile_text_column;
+
+typedef struct {
+  struct {
+    drawfile_type type;
+    int size;
+    drawfile_text_column data;
+  } columns [1];
+} drawfile_text_column_list;
+
+typedef struct {
+  drawfile_type type;
+  int reserved [2];
+  palette_entry fill;
+  palette_entry bg_hint;
+  char text [1];
+} drawfile_area_text;
+
+typedef struct {
+  wimp_box bbox;
+  drawfile_text_column_list header;
+  drawfile_area_text area_text;
+} drawfile_text_area;
+
+typedef struct {
+  wimp_box bbox;
+  int paper_size;
+  drawfile_paper_options paper_options;
+  double grid_spacing;
+  int grid_division;
+  BOOL isometric;
+  BOOL auto_adjust;
+  BOOL show;
+  BOOL lock;
+  BOOL cm;
+  int zoom_mul;
+  int zoom_div;
+  BOOL zoom_lock;
+  BOOL toolbox;
+  drawfile_entry_mode entry_mode;
+  int undo_size;
+} drawfile_options;
+
+typedef struct {
+  wimp_box bbox;
+  os_trfm trfm;
+  drawfile_text_flags flags;
+  palette_entry fill;
+  palette_entry bg_hint;
+  drawfile_text_style style;
+  int xsize;
+  int ysize;
+  wimp_coord base;
+  char text [1];
+} drawfile_trfm_text;
+
+typedef struct {
+  wimp_box bbox;
+  os_trfm trfm;
+  sprite_header header;
+  byte data [1];
+} drawfile_trfm_sprite;
+
+typedef struct {
+  wimp_box bbox;
+  int width;
+  int height;
+  int xdpi;
+  int ydpi;
+  os_trfm trfm;
+  int len;
+  byte data [1];
+} drawfile_jpeg;
+
+/* ------------------------------------------------------------------------
+ * Type:          drawfile_object
+ *
+ * Description:   This type is used to declare pointers rather than objects
+ */
+
+typedef struct {
+  drawfile_type type;
+  int size;
+  union {
+    drawfile_font_table font_table;
+    drawfile_text text;
+    drawfile_path path;
+    drawfile_path_with_pattern path_with_pattern;
+    drawfile_sprite sprite;
+    drawfile_group group;
+    drawfile_tagged tagged;
+    drawfile_text_column text_column;
+    drawfile_text_area text_area;
+    drawfile_options options;
+    drawfile_trfm_text trfm_text;
+    drawfile_trfm_sprite trfm_sprite;
+    drawfile_jpeg jpeg;
+  } data;
+} drawfile_object;
+
+typedef struct {
+  char tag [4];
+  int major_version;
+  int minor_version;
+  char source [12];
+  wimp_box bbox;
+  drawfile_object objects [1];
+} drawfile_diagram;
+
+typedef bits drawfile_bbox_flags;
+
+typedef struct {
+  drawfile_object *object;
+  drawfile_diagram *diagram;
+  drawfile_object *font_table;
+  drawfile_declare_fonts_flags flags;
+  os_error *error;
+} drawfile_declare_fonts_state;
+
+/************************
+ * Constant definitions *
+ ************************/
+#define error_DRAW_FILE_NOT_DRAW                0x20C00u
+#define error_DRAW_FILE_VERSION                 0x20C01u
+#define error_DRAW_FILE_FONT_TAB                0x20C02u
+#define error_DRAW_FILE_BAD_FONT_NO             0x20C03u
+#define error_DRAW_FILE_BAD_MODE                0x20C04u
+#define error_DRAW_FILE_BAD_FILE                0x20C05u
+#define error_DRAW_FILE_BAD_GROUP               0x20C06u
+#define error_DRAW_FILE_BAD_TAG                 0x20C07u
+#define error_DRAW_FILE_SYNTAX                  0x20C08u
+#define error_DRAW_FILE_FONT_NO                 0x20C09u
+#define error_DRAW_FILE_AREA_VER                0x20C0Au
+#define error_DRAW_FILE_NO_AREA_VER             0x20C0Bu
+
+#define drawfile_PATH_MITRED                    ((drawfile_path_style_flags) 0x0u)
+#define drawfile_PATH_ROUND                     ((drawfile_path_style_flags) 0x1u)
+#define drawfile_PATH_BEVELLED                  ((drawfile_path_style_flags) 0x2u)
+#define drawfile_PATH_BUTT                      ((drawfile_path_style_flags) 0x0u)
+#define drawfile_PATH_SQUARE                    ((drawfile_path_style_flags) 0x2u)
+#define drawfile_PATH_TRIANGLE                  ((drawfile_path_style_flags) 0x3u)
+#define drawfile_PATH_JOIN_SHIFT                0
+#define drawfile_PATH_JOIN                      ((drawfile_path_style_flags) 0x3u)
+#define drawfile_PATH_END_SHIFT                 2
+#define drawfile_PATH_END                       ((drawfile_path_style_flags) 0xCu)
+#define drawfile_PATH_START_SHIFT               4
+#define drawfile_PATH_START                     ((drawfile_path_style_flags) 0x30u)
+#define drawfile_PATH_WINDING_EVEN_ODD          ((drawfile_path_style_flags) 0x40u)
+#define drawfile_PATH_DASHED                    ((drawfile_path_style_flags) 0x80u)
+#define drawfile_PATH_CAP_WIDTH_SHIFT           16
+#define drawfile_PATH_CAP_WIDTH                 ((drawfile_path_style_flags) 0xFF0000u)
+#define drawfile_PATH_CAP_LENGTH_SHIFT          24
+#define drawfile_PATH_CAP_LENGTH                ((drawfile_path_style_flags) 0xFF000000u)
+#define drawfile_TEXT_KERN                      ((drawfile_text_flags) 0x1u)
+#define drawfile_TEXT_RIGHT_TO_LEFT             ((drawfile_text_flags) 0x2u)
+#define drawfile_TEXT_UNDERLINE                 ((drawfile_text_flags) 0x4u)
+#define drawfile_RENDER_BBOXES                  ((drawfile_render_flags) 0x1u)
+#define drawfile_RENDER_SUPPRESS                ((drawfile_render_flags) 0x2u)
+#define drawfile_RENDER_GIVEN_FLATNESS          ((drawfile_render_flags) 0x4u)
+#define drawfile_RENDER_GIVEN_COLOUR_MAPPING    ((drawfile_render_flags) 0x8u)
+#define drawfile_NO_DOWNLOAD                    ((drawfile_declare_fonts_flags) 0x1u)
+#define drawfile_PAPER_SHOW                     ((drawfile_paper_options) 0x1u)
+#define drawfile_PAPER_LANDSCAPE                ((drawfile_paper_options) 0x10u)
+#define drawfile_PAPER_DEFAULT                  ((drawfile_paper_options) 0x100u)
+#define drawfile_ENTRY_MODE_LINE                ((drawfile_entry_mode) 0x1u)
+#define drawfile_ENTRY_MODE_CLOSED_LINE         ((drawfile_entry_mode) 0x2u)
+#define drawfile_ENTRY_MODE_CURVE               ((drawfile_entry_mode) 0x4u)
+#define drawfile_ENTRY_MODE_CLOSED_CURVE        ((drawfile_entry_mode) 0x8u)
+#define drawfile_ENTRY_MODE_RECTANGLE           ((drawfile_entry_mode) 0x10u)
+#define drawfile_ENTRY_MODE_ELLIPSE             ((drawfile_entry_mode) 0x20u)
+#define drawfile_ENTRY_MODE_TEXT_LINE           ((drawfile_entry_mode) 0x40u)
+#define drawfile_ENTRY_MODE_SELECT              ((drawfile_entry_mode) 0x80u)
+
+/*************************
+ * Function declarations *
+ *************************/
+
+#if defined(__cplusplus)
+   extern "C" {
+#endif /* __cplusplus */
+
+/* ------------------------------------------------------------------------
+ * Function:      drawfile_render()
+ *
+ * Description:   Calls SWI 0x45540
+ *
+ * Input:         flags - value of R0 on entry
+ *                diagram - value of R1 on entry
+ *                size - value of R2 on entry
+ *                trfm - value of R3 on entry
+ *                clip - value of R4 on entry
+ *                flatness - value of R5 on entry
+ */
+
+extern os_error *Drawfile_Render (drawfile_render_flags flags,
+      drawfile_diagram const *diagram,
+      int size,
+      os_trfm const *trfm,
+      wimp_box const *clip,
+      int flatness);
+
+/* ------------------------------------------------------------------------
+ * Function:      drawfile_bbox()
+ *
+ * Description:   Calls SWI 0x45541
+ *
+ * Input:         flags - value of R0 on entry
+ *                diagram - value of R1 on entry
+ *                size - value of R2 on entry
+ *                trfm - value of R3 on entry
+ *                bbox - value of R4 on entry
+ */
+
+extern os_error *Drawfile_Bbox (drawfile_bbox_flags flags,
+      drawfile_diagram const *diagram,
+      int size,
+      os_trfm const *trfm,
+      wimp_box *bbox);
+
+/* ------------------------------------------------------------------------
+ * Function:      Drawfile_DeclareFonts()
+ *
+ * Description:   Calls SWI 0x45542
+ *
+ * Input:         flags - value of R0 on entry
+ *                diagram - value of R1 on entry
+ *                size - value of R2 on entry
+ */
+
+extern os_error *Drawfile_DeclareFonts (drawfile_declare_fonts_flags flags,
+      drawfile_diagram const *diagram,
+      int size);
+
+/* ------------------------------------------------------------------------
+ * Function:      Drawfile_CreateDiagram()
+ *
+ */
+
+extern os_error * Drawfile_CreateDiagram(drawfile_info *info, size_t memory,
+	const char *creator, wimp_box box);
+
+extern os_error *Drawfile_AppendObject(drawfile_info *info, size_t memory,
+	const drawfile_object *object, BOOL rebind);
+
+extern os_error *Drawfile_RenderDiagram(drawfile_info *info,
+	window_redrawblock *redraw, double scale);
+
+extern os_error *Drawfile_VerifyDiagram(drawfile_info *info);
+
+extern void	Drawfile_QueryBox(drawfile_info *info,
+	wimp_box *rect, BOOL screenUnits);
+
+#if defined(__cplusplus)
+   }
+#endif /* __cplusplus */
+
+#endif /* __drawfile.h */
diff --git a/fail.c b/fail.c
new file mode 100644
index 0000000..b6c729f
--- /dev/null
+++ b/fail.c
@@ -0,0 +1,26 @@
+/*
+ * fail.c
+ * Copyright (C) 1998 A.J. van Os
+ *
+ * Description:
+ * An alternative form of assert()
+ */
+
+#include <stdlib.h>
+#include "antiword.h"
+
+#if !defined(NDEBUG)
+void
+__fail(char *szExpression, char *szFilename, int iLineNumber)
+{
+	if (szExpression == NULL || szFilename == NULL) {
+		werr(1, "Internal error: no expression");
+	}
+#if defined(DEBUG)
+	fprintf(stderr, "%s[%3d]: Internal error in '%s'\n",
+		szFilename, iLineNumber, szExpression);
+#endif /* DEBUG */
+	werr(1, "Internal error in '%s' in file %s at line %d",
+		szExpression, szFilename, iLineNumber);
+} /* end of __fail */
+#endif /* !NDEBUG */
diff --git a/fail.h b/fail.h
new file mode 100644
index 0000000..151a26a
--- /dev/null
+++ b/fail.h
@@ -0,0 +1,22 @@
+/*
+ * fail.h
+ * Copyright (C) 1998-2000 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Support for an alternative form of assert()
+ */
+
+#if !defined(__fail_h)
+#define __fail_h 1
+
+#undef fail
+
+#if defined(NDEBUG)
+#define fail(e)	((void)0)
+#else
+#define fail(e)	((e) ? __fail(#e, __FILE__, __LINE__) : (void)0)
+#endif /* NDEBUG */
+
+extern void	__fail(char *, char *, int);
+
+#endif /* __fail_h */
diff --git a/finddata.c b/finddata.c
new file mode 100644
index 0000000..441030c
--- /dev/null
+++ b/finddata.c
@@ -0,0 +1,154 @@
+/*
+ * finddata.c
+ * Copyright (C) 2000-2002 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Find the blocks that contain the data of MS Word files
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "antiword.h"
+
+
+/*
+ * bAddDataBlocks - Add the blocks to the data block list
+ *
+ * Returns TRUE when successful, otherwise FALSE
+ */
+BOOL
+bAddDataBlocks(ULONG ulDataPosFirst, ULONG ulTotalLength,
+	ULONG ulStartBlock, const ULONG *aulBBD, size_t tBBDLen)
+{
+	data_block_type	tDataBlock;
+	ULONG	ulDataPos, ulOffset, ulIndex;
+	long	lToGo;
+	BOOL	bSuccess;
+
+	fail(ulTotalLength > (ULONG)LONG_MAX);
+	fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
+	fail(aulBBD == NULL);
+
+	NO_DBG_HEX(ulDataPosFirst);
+	NO_DBG_DEC(ulTotalLength);
+
+	lToGo = (long)ulTotalLength;
+
+	ulDataPos = ulDataPosFirst;
+	ulOffset = ulDataPosFirst;
+	for (ulIndex = ulStartBlock;
+	     ulIndex != END_OF_CHAIN && lToGo > 0;
+	     ulIndex = aulBBD[ulIndex]) {
+		if (ulIndex == UNUSED_BLOCK || ulIndex >= (ULONG)tBBDLen) {
+			DBG_DEC(ulIndex);
+			DBG_DEC(tBBDLen);
+			return FALSE;
+		}
+		if (ulOffset >= BIG_BLOCK_SIZE) {
+			ulOffset -= BIG_BLOCK_SIZE;
+			continue;
+		}
+		tDataBlock.ulFileOffset =
+			(ulIndex + 1) * BIG_BLOCK_SIZE + ulOffset;
+		tDataBlock.ulDataPos = ulDataPos;
+		tDataBlock.ulLength = min(BIG_BLOCK_SIZE - ulOffset,
+						(ULONG)lToGo);
+		fail(tDataBlock.ulLength > BIG_BLOCK_SIZE);
+		ulOffset = 0;
+		if (!bAdd2DataBlockList(&tDataBlock)) {
+			DBG_HEX(tDataBlock.ulFileOffset);
+			DBG_HEX(tDataBlock.ulDataPos);
+			DBG_DEC(tDataBlock.ulLength);
+			return FALSE;
+		}
+		ulDataPos += tDataBlock.ulLength;
+		lToGo -= (long)tDataBlock.ulLength;
+	}
+	bSuccess = lToGo == 0 ||
+		(ulTotalLength == (ULONG)LONG_MAX && ulIndex == END_OF_CHAIN);
+	DBG_DEC_C(!bSuccess, lToGo);
+	DBG_DEC_C(!bSuccess, ulTotalLength);
+	DBG_DEC_C(!bSuccess, ulIndex);
+	return bSuccess;
+} /* end of bAddDataBlocks */
+
+/*
+ * bGet6DocumentData - make a list of the data blocks of Word 6/7 files
+ *
+ * Code for "fast saved" files.
+ *
+ * Returns TRUE when successful, otherwise FALSE
+ */
+BOOL
+bGet6DocumentData(FILE *pFile, ULONG ulStartBlock,
+	const ULONG *aulBBD, size_t tBBDLen, const UCHAR *aucHeader)
+{
+	UCHAR	*aucBuffer;
+	ULONG	ulBeginTextInfo, ulOffset, ulTotLength;
+	size_t	tTextInfoLen;
+	int	iIndex, iOff, iType, iLen, iPieces;
+
+	DBG_MSG("bGet6DocumentData");
+
+	fail(pFile == NULL);
+	fail(aulBBD == NULL);
+	fail(aucHeader == NULL);
+
+	ulBeginTextInfo = ulGetLong(0x160, aucHeader);
+	DBG_HEX(ulBeginTextInfo);
+	tTextInfoLen = (size_t)ulGetLong(0x164, aucHeader);
+	DBG_DEC(tTextInfoLen);
+
+	aucBuffer = xmalloc(tTextInfoLen);
+	if (!bReadBuffer(pFile, ulStartBlock,
+			aulBBD, tBBDLen, BIG_BLOCK_SIZE,
+			aucBuffer, ulBeginTextInfo, tTextInfoLen)) {
+		aucBuffer = xfree(aucBuffer);
+		return FALSE;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tTextInfoLen);
+
+	iOff = 0;
+	while (iOff < (int)tTextInfoLen) {
+		iType = (int)ucGetByte(iOff, aucBuffer);
+		iOff++;
+		if (iType == 0) {
+			iOff++;
+			continue;
+		}
+		iLen = (int)usGetWord(iOff, aucBuffer);
+		iOff += 2;
+		if (iType == 1) {
+			iOff += iLen;
+			continue;
+		}
+		if (iType != 2) {
+			werr(0, "Unknown type of 'fastsaved' format");
+			aucBuffer = xfree(aucBuffer);
+			return FALSE;
+		}
+		/* Type 2 */
+		NO_DBG_DEC(iLen);
+		iOff += 2;
+		iPieces = (iLen - 4) / 12;
+		DBG_DEC(iPieces);
+		for (iIndex = 0; iIndex < iPieces; iIndex++) {
+			ulOffset = ulGetLong(
+				iOff + (iPieces + 1) * 4 + iIndex * 8 + 2,
+				aucBuffer);
+			ulTotLength = ulGetLong(iOff + (iIndex + 1) * 4,
+						aucBuffer) -
+					ulGetLong(iOff + iIndex * 4,
+						aucBuffer);
+			if (!bAddDataBlocks(ulOffset, ulTotLength,
+					ulStartBlock,
+					aulBBD, tBBDLen)) {
+				aucBuffer = xfree(aucBuffer);
+				return FALSE;
+			}
+		}
+		break;
+	}
+	aucBuffer = xfree(aucBuffer);
+	return TRUE;
+} /* end of bGet6DocumentData */
diff --git a/findtext.c b/findtext.c
new file mode 100644
index 0000000..20724a5
--- /dev/null
+++ b/findtext.c
@@ -0,0 +1,289 @@
+/*
+ * findtext.c
+ * Copyright (C) 1998-2004 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Find the blocks that contain the text of MS Word files
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "antiword.h"
+
+
+/*
+ * bAddTextBlocks - Add the blocks to the text block list
+ *
+ * Returns TRUE when successful, FALSE if not
+ */
+BOOL
+bAddTextBlocks(ULONG ulCharPosFirst, ULONG ulTotalLength,
+	BOOL bUsesUnicode, USHORT usPropMod,
+	ULONG ulStartBlock, const ULONG *aulBBD, size_t tBBDLen)
+{
+	text_block_type	tTextBlock;
+	ULONG	ulCharPos, ulOffset, ulIndex;
+	long	lToGo;
+
+	fail(ulTotalLength > (ULONG)LONG_MAX / 2);
+	fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
+	fail(aulBBD == NULL);
+
+	NO_DBG_HEX(ulCharPosFirst);
+	NO_DBG_DEC(ulTotalLength);
+
+	if (bUsesUnicode) {
+		/* One character equals two bytes */
+		NO_DBG_MSG("Uses Unicode");
+		lToGo = (long)ulTotalLength * 2;
+	} else {
+		/* One character equals one byte */
+		NO_DBG_MSG("Uses ASCII");
+		lToGo = (long)ulTotalLength;
+	}
+
+	ulCharPos = ulCharPosFirst;
+	ulOffset = ulCharPosFirst;
+	for (ulIndex = ulStartBlock;
+	     ulIndex != END_OF_CHAIN && lToGo > 0;
+	     ulIndex = aulBBD[ulIndex]) {
+		if (ulIndex >= (ULONG)tBBDLen) {
+			DBG_DEC(ulIndex);
+			DBG_DEC(tBBDLen);
+			werr(1, "The Big Block Depot is damaged");
+		}
+		if (ulOffset >= BIG_BLOCK_SIZE) {
+			ulOffset -= BIG_BLOCK_SIZE;
+			continue;
+		}
+		tTextBlock.ulFileOffset =
+			(ulIndex + 1) * BIG_BLOCK_SIZE + ulOffset;
+		tTextBlock.ulCharPos = ulCharPos;
+		tTextBlock.ulLength = min(BIG_BLOCK_SIZE - ulOffset,
+						(ULONG)lToGo);
+		tTextBlock.bUsesUnicode = bUsesUnicode;
+		tTextBlock.usPropMod = usPropMod;
+		ulOffset = 0;
+		if (!bAdd2TextBlockList(&tTextBlock)) {
+			DBG_HEX(tTextBlock.ulFileOffset);
+			DBG_HEX(tTextBlock.ulCharPos);
+			DBG_DEC(tTextBlock.ulLength);
+			DBG_DEC(tTextBlock.bUsesUnicode);
+			DBG_DEC(tTextBlock.usPropMod);
+			return FALSE;
+		}
+		ulCharPos += tTextBlock.ulLength;
+		lToGo -= (long)tTextBlock.ulLength;
+	}
+	DBG_DEC_C(lToGo != 0, lToGo);
+	return lToGo == 0;
+} /* end of bAddTextBlocks */
+
+/*
+ * bGet6DocumentText - make a list of the text blocks of Word 6/7 files
+ *
+ * Code for "fast saved" files.
+ *
+ * Returns TRUE when successful, FALSE if not
+ */
+BOOL
+bGet6DocumentText(FILE *pFile, BOOL bUsesUnicode, ULONG ulStartBlock,
+	const ULONG *aulBBD, size_t tBBDLen, const UCHAR *aucHeader)
+{
+	UCHAR	*aucBuffer;
+	ULONG	ulBeginTextInfo, ulTextOffset, ulTotLength;
+	size_t	tTextInfoLen;
+	int	iIndex, iType, iOff, iLen, iPieces;
+	USHORT	usPropMod;
+
+	DBG_MSG("bGet6DocumentText");
+
+	fail(pFile == NULL);
+	fail(aulBBD == NULL);
+	fail(aucHeader == NULL);
+
+	ulBeginTextInfo = ulGetLong(0x160, aucHeader);	/* fcClx */
+	DBG_HEX(ulBeginTextInfo);
+	tTextInfoLen = (size_t)ulGetLong(0x164, aucHeader);	/* lcbClx */
+	DBG_DEC(tTextInfoLen);
+
+	aucBuffer = xmalloc(tTextInfoLen);
+	if (!bReadBuffer(pFile, ulStartBlock,
+			aulBBD, tBBDLen, BIG_BLOCK_SIZE,
+			aucBuffer, ulBeginTextInfo, tTextInfoLen)) {
+		aucBuffer = xfree(aucBuffer);
+		return FALSE;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tTextInfoLen);
+
+	iOff = 0;
+	while ((size_t)iOff < tTextInfoLen) {
+		iType = (int)ucGetByte(iOff, aucBuffer);
+		iOff++;
+		if (iType == 0) {
+			DBG_FIXME();
+			iOff++;
+			continue;
+		}
+		if (iType == 1) {
+			iLen = (int)usGetWord(iOff, aucBuffer);
+			vAdd2PropModList(aucBuffer + iOff);
+			iOff += iLen + 2;
+			continue;
+		}
+		if (iType != 2) {
+			werr(0, "Unknown type of 'fastsaved' format");
+			aucBuffer = xfree(aucBuffer);
+			return FALSE;
+		}
+		/* Type 2 */
+		iLen = (int)usGetWord(iOff, aucBuffer);
+		NO_DBG_DEC(iLen);
+		iOff += 4;
+		iPieces = (iLen - 4) / 12;
+		DBG_DEC(iPieces);
+		for (iIndex = 0; iIndex < iPieces; iIndex++) {
+			ulTextOffset = ulGetLong(
+				iOff + (iPieces + 1) * 4 + iIndex * 8 + 2,
+				aucBuffer);
+			usPropMod = usGetWord(
+				iOff + (iPieces + 1) * 4 + iIndex * 8 + 6,
+				aucBuffer);
+			ulTotLength = ulGetLong(iOff + (iIndex + 1) * 4,
+						aucBuffer) -
+					ulGetLong(iOff + iIndex * 4,
+						aucBuffer);
+			NO_DBG_HEX_C(usPropMod != 0, usPropMod);
+			if (!bAddTextBlocks(ulTextOffset, ulTotLength,
+					bUsesUnicode, usPropMod,
+					ulStartBlock,
+					aulBBD, tBBDLen)) {
+				aucBuffer = xfree(aucBuffer);
+				return FALSE;
+			}
+		}
+		break;
+	}
+	aucBuffer = xfree(aucBuffer);
+	return TRUE;
+} /* end of bGet6DocumentText */
+
+/*
+ * bGet8DocumentText - make a list of the text blocks of Word 8/97 files
+ *
+ * Returns TRUE when successful, FALSE if not
+ */
+BOOL
+bGet8DocumentText(FILE *pFile, const pps_info_type *pPPS,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const ULONG *aulSBD, size_t tSBDLen,
+	const UCHAR *aucHeader)
+{
+	const ULONG	*aulBlockDepot;
+	UCHAR	*aucBuffer;
+	ULONG	ulTextOffset, ulBeginTextInfo;
+	ULONG	ulTotLength, ulLen;
+	long	lIndex, lPieces, lOff;
+	size_t	tTextInfoLen, tBlockDepotLen, tBlockSize;
+	int	iType, iLen;
+	BOOL	bUsesUnicode;
+	USHORT	usPropMod;
+
+	DBG_MSG("bGet8DocumentText");
+
+	fail(pFile == NULL || pPPS == NULL);
+	fail(aulBBD == NULL || aulSBD == NULL);
+	fail(aucHeader == NULL);
+
+  	ulBeginTextInfo = ulGetLong(0x1a2, aucHeader);	/* fcClx */
+	DBG_HEX(ulBeginTextInfo);
+	tTextInfoLen = (size_t)ulGetLong(0x1a6, aucHeader);	/* lcbClx */
+	DBG_DEC(tTextInfoLen);
+
+	DBG_DEC(pPPS->tTable.ulSB);
+	DBG_HEX(pPPS->tTable.ulSize);
+	if (pPPS->tTable.ulSize == 0) {
+		return FALSE;
+	}
+
+	if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
+	  	/* Use the Small Block Depot */
+		aulBlockDepot = aulSBD;
+		tBlockDepotLen = tSBDLen;
+		tBlockSize = SMALL_BLOCK_SIZE;
+	} else {
+	  	/* Use the Big Block Depot */
+		aulBlockDepot = aulBBD;
+		tBlockDepotLen = tBBDLen;
+		tBlockSize = BIG_BLOCK_SIZE;
+	}
+	aucBuffer = xmalloc(tTextInfoLen);
+	if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
+			aulBlockDepot, tBlockDepotLen, tBlockSize,
+			aucBuffer, ulBeginTextInfo, tTextInfoLen)) {
+		aucBuffer = xfree(aucBuffer);
+		return FALSE;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tTextInfoLen);
+
+	lOff = 0;
+	while (lOff < (long)tTextInfoLen) {
+		iType = (int)ucGetByte(lOff, aucBuffer);
+		lOff++;
+		if (iType == 0) {
+			DBG_FIXME();
+			lOff++;
+			continue;
+		}
+		if (iType == 1) {
+			iLen = (int)usGetWord(lOff, aucBuffer);
+			vAdd2PropModList(aucBuffer + lOff);
+			lOff += (long)iLen + 2;
+			continue;
+		}
+		if (iType != 2) {
+			werr(0, "Unknown type of 'fastsaved' format");
+			aucBuffer = xfree(aucBuffer);
+			return FALSE;
+		}
+		/* Type 2 */
+		ulLen = ulGetLong(lOff, aucBuffer);
+		if (ulLen < 4) {
+			DBG_DEC(ulLen);
+			return FALSE;
+		}
+		lOff += 4;
+		lPieces = (long)((ulLen - 4) / 12);
+		DBG_DEC(lPieces);
+		for (lIndex = 0; lIndex < lPieces; lIndex++) {
+			ulTextOffset = ulGetLong(
+				lOff + (lPieces + 1) * 4 + lIndex * 8 + 2,
+				aucBuffer);
+			usPropMod = usGetWord(
+				lOff + (lPieces + 1) * 4 + lIndex * 8 + 6,
+				aucBuffer);
+			ulTotLength = ulGetLong(lOff + (lIndex + 1) * 4,
+						aucBuffer) -
+					ulGetLong(lOff + lIndex * 4,
+						aucBuffer);
+			if ((ulTextOffset & BIT(30)) == 0) {
+				bUsesUnicode = TRUE;
+			} else {
+				bUsesUnicode = FALSE;
+				ulTextOffset &= ~BIT(30);
+				ulTextOffset /= 2;
+			}
+			NO_DBG_HEX_C(usPropMod != 0, usPropMod);
+			if (!bAddTextBlocks(ulTextOffset, ulTotLength,
+					bUsesUnicode, usPropMod,
+					pPPS->tWordDocument.ulSB,
+					aulBBD, tBBDLen)) {
+				aucBuffer = xfree(aucBuffer);
+				return FALSE;
+			}
+		}
+		break;
+	}
+	aucBuffer = xfree(aucBuffer);
+	return TRUE;
+} /* end of bGet8DocumentText */
diff --git a/fmt_text.c b/fmt_text.c
new file mode 100644
index 0000000..db211e9
--- /dev/null
+++ b/fmt_text.c
@@ -0,0 +1,167 @@
+/*
+ * fmt_text.c
+ * Copyright (C) 2004 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Functions to deal with the Formatted Text format
+ *
+ * Based on patches send by: Ofir Reichenberg <ofir@qlusters.com>
+ *
+ * The credit should go to him, but all the bugs are mine.
+ */
+
+#include <string.h>
+#include "antiword.h"
+
+/* The character set */
+static encoding_type	eEncoding = encoding_neutral;
+/* Current vertical position information */
+static long		lYtopCurr = 0;
+/* Local representation of the non-breaking space */
+static UCHAR		ucNbsp = 0;
+
+
+/*
+ * vPrologueFMT - set options and perform the Formatted Text initialization
+ */
+void
+vPrologueFMT(diagram_type *pDiag, const options_type *pOptions)
+{
+	fail(pDiag == NULL);
+	fail(pOptions == NULL);
+
+	eEncoding = pOptions->eEncoding;
+	pDiag->lXleft = 0;
+	pDiag->lYtop = 0;
+	lYtopCurr = 0;
+} /* end of vPrologueFMT */
+
+/*
+ * vPrintFMT - print a Formatted Text string
+ */
+static void
+vPrintFMT(FILE *pFile,
+	const char *szString, size_t tStringLength, USHORT usFontstyle)
+{
+	const UCHAR	*pucByte, *pucStart, *pucLast, *pucNonSpace;
+
+	fail(szString == NULL);
+
+	if (szString == NULL || szString[0] == '\0' || tStringLength == 0) {
+		return;
+	}
+
+	if (eEncoding == encoding_utf_8) {
+		fprintf(pFile, "%.*s", (int)tStringLength, szString);
+		return;
+	}
+
+	if (ucNbsp == 0) {
+		ucNbsp = ucGetNbspCharacter();
+		DBG_HEX_C(ucNbsp != 0xa0, ucNbsp);
+	}
+
+	pucStart = (UCHAR *)szString;
+	pucLast = pucStart + tStringLength - 1;
+	pucNonSpace = pucLast;
+	while ((*pucNonSpace == (UCHAR)' ' || *pucNonSpace == ucNbsp) &&
+	       pucNonSpace > pucStart) {
+		pucNonSpace--;
+	}
+
+	/* 1: The spaces at the start */
+	pucByte = pucStart;
+	while ((*pucByte == (UCHAR)' ' || *pucByte == ucNbsp) &&
+	       pucByte <= pucLast) {
+		(void)putc(' ', pFile);
+		pucByte++;
+	}
+
+	if (pucByte > pucLast) {
+		/* There is no text, just spaces */
+		return;
+	}
+
+	/* 2: Start the *bold*, /italic/ and _underline_ */
+	if (bIsBold(usFontstyle)) {
+		(void)putc('*', pFile);
+	}
+	if (bIsItalic(usFontstyle)) {
+		(void)putc('/', pFile);
+	}
+	if (bIsUnderline(usFontstyle)) {
+		(void)putc('_', pFile);
+	}
+
+	/* 3: The text itself */
+	while (pucByte <= pucNonSpace) {
+		if (*pucByte == ucNbsp) {
+			(void)putc(' ', pFile);
+		} else {
+			(void)putc((char)*pucByte, pFile);
+		}
+		pucByte++;
+	}
+
+	/* 4: End the *bold*, /italic/ and _underline_ */
+	if (bIsUnderline(usFontstyle)) {
+		(void)putc('_', pFile);
+	}
+	if (bIsItalic(usFontstyle)) {
+		(void)putc('/', pFile);
+	}
+	if (bIsBold(usFontstyle)) {
+		(void)putc('*', pFile);
+	}
+
+	/* 5: The spaces at the end */
+	while (pucByte <= pucLast) {
+		(void)putc(' ', pFile);
+		pucByte++;
+	}
+} /* end of vPrintFMT */
+
+/*
+ * vMoveTo - move to the given X,Y coordinates
+ *
+ * Move the current position of the given diagram to its X,Y coordinates,
+ * start on a new page if needed
+ */
+static void
+vMoveTo(diagram_type *pDiag)
+{
+	int	iCount, iNbr;
+
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+
+	if (pDiag->lYtop != lYtopCurr) {
+		iNbr = iDrawUnits2Char(pDiag->lXleft);
+		for (iCount = 0; iCount < iNbr; iCount++) {
+			(void)putc(FILLER_CHAR, pDiag->pOutFile);
+		}
+		lYtopCurr = pDiag->lYtop;
+	}
+} /* end of vMoveTo */
+
+/*
+ * vSubstringFMT - print a sub string
+ */
+void
+vSubstringFMT(diagram_type *pDiag,
+	const char *szString, size_t tStringLength, long lStringWidth,
+	USHORT usFontstyle)
+{
+	fail(pDiag == NULL || szString == NULL);
+	fail(pDiag->pOutFile == NULL);
+	fail(pDiag->lXleft < 0);
+	fail(tStringLength != strlen(szString));
+
+	if (szString[0] == '\0' || tStringLength == 0) {
+		return;
+	}
+
+	vMoveTo(pDiag);
+	vPrintFMT(pDiag->pOutFile, szString, tStringLength, usFontstyle);
+	pDiag->lXleft += lStringWidth;
+} /* end of vSubstringFMT */
diff --git a/fontinfo.h b/fontinfo.h
new file mode 100644
index 0000000..8538dfa
--- /dev/null
+++ b/fontinfo.h
@@ -0,0 +1,2251 @@
+/* THIS FILE IS AUTOMATICALLY GENERATED - DO NOT EDIT! */
+static const char *szFontnames[32] = {
+	"Courier",
+	"Courier-Bold",
+	"Courier-Oblique",
+	"Courier-BoldOblique",
+	"Times-Roman",
+	"Times-Bold",
+	"Times-Italic",
+	"Times-BoldItalic",
+	"Helvetica",
+	"Helvetica-Bold",
+	"Helvetica-Oblique",
+	"Helvetica-BoldOblique",
+	"Palatino-Roman",
+	"Palatino-Bold",
+	"Palatino-Italic",
+	"Palatino-BoldItalic",
+	"Helvetica-Narrow",
+	"Helvetica-Narrow-Bold",
+	"Helvetica-Narrow-Oblique",
+	"Helvetica-Narrow-BoldOblique",
+	"Bookman-Light",
+	"Bookman-Demi",
+	"Bookman-LightItalic",
+	"Bookman-DemiItalic",
+	"AvantGarde-Book",
+	"AvantGarde-Demi",
+	"AvantGarde-BookOblique",
+	"AvantGarde-DemiOblique",
+	"NewCenturySchlbk-Roman",
+	"NewCenturySchlbk-Bold",
+	"NewCenturySchlbk-Italic",
+	"NewCenturySchlbk-BoldItalic",
+};
+static unsigned short ausCharacterWidths1[32][256] = {
+	{	/* Courier */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  40 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  48 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  56 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  64 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  72 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  80 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  88 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  96 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 104 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 112 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 120 */   600,  600,  600,  600,  600,  600,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,  600,  600,  600,  600,
+	/* 144 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 152 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 160 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 168 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 176 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 184 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 192 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 200 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 208 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 216 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 224 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 232 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 240 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 248 */   600,  600,  600,  600,  600,  600,  600,  600,
+	},
+	{	/* Courier-Bold */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  40 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  48 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  56 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  64 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  72 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  80 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  88 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  96 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 104 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 112 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 120 */   600,  600,  600,  600,  600,  600,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,  600,  600,  600,  600,
+	/* 144 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 152 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 160 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 168 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 176 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 184 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 192 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 200 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 208 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 216 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 224 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 232 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 240 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 248 */   600,  600,  600,  600,  600,  600,  600,  600,
+	},
+	{	/* Courier-Oblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  40 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  48 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  56 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  64 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  72 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  80 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  88 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  96 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 104 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 112 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 120 */   600,  600,  600,  600,  600,  600,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,  600,  600,  600,  600,
+	/* 144 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 152 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 160 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 168 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 176 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 184 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 192 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 200 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 208 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 216 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 224 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 232 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 240 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 248 */   600,  600,  600,  600,  600,  600,  600,  600,
+	},
+	{	/* Courier-BoldOblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  40 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  48 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  56 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  64 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  72 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  80 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  88 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  96 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 104 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 112 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 120 */   600,  600,  600,  600,  600,  600,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,  600,  600,  600,  600,
+	/* 144 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 152 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 160 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 168 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 176 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 184 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 192 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 200 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 208 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 216 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 224 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 232 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 240 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 248 */   600,  600,  600,  600,  600,  600,  600,  600,
+	},
+	{	/* Times-Roman */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  333,  408,  500,  500,  833,  778,  333,
+	/*  40 */   333,  333,  500,  564,  250,  333,  250,  278,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  278,  278,  564,  564,  564,  444,
+	/*  64 */   921,  722,  667,  667,  722,  611,  556,  722,
+	/*  72 */   722,  333,  389,  722,  611,  889,  722,  722,
+	/*  80 */   556,  722,  667,  556,  611,  722,  722,  944,
+	/*  88 */   722,  722,  611,  333,  278,  333,  469,  500,
+	/*  96 */   333,  444,  500,  444,  500,  444,  333,  500,
+	/* 104 */   500,  278,  278,  500,  278,  778,  500,  500,
+	/* 112 */   500,  500,  333,  389,  278,  500,  500,  722,
+	/* 120 */   500,  500,  444,  480,  200,  480,  541,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000,  980, 1000,  350,
+	/* 144 */   333,  333,  333,  333,  444,  444,  444,  500,
+	/* 152 */  1000,  564,  889,  722,  500,  500,  556,  556,
+	/* 160 */   250,  333,  500,  500,  500,  500,  200,  500,
+	/* 168 */   333,  760,  276,  500,  564,  333,  760,  333,
+	/* 176 */   400,  564,  300,  300,  333,  500,  453,  250,
+	/* 184 */   333,  300,  310,  500,  750,  750,  750,  444,
+	/* 192 */   722,  722,  722,  722,  722,  722,  889,  667,
+	/* 200 */   611,  611,  611,  611,  333,  333,  333,  333,
+	/* 208 */   722,  722,  722,  722,  722,  722,  722,  564,
+	/* 216 */   722,  722,  722,  722,  722,  722,  556,  500,
+	/* 224 */   444,  444,  444,  444,  444,  444,  667,  444,
+	/* 232 */   444,  444,  444,  444,  278,  278,  278,  278,
+	/* 240 */   500,  500,  500,  500,  500,  500,  500,  564,
+	/* 248 */   500,  500,  500,  500,  500,  500,  500,  500,
+	},
+	{	/* Times-Bold */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  333,  555,  500,  500, 1000,  833,  333,
+	/*  40 */   333,  333,  500,  570,  250,  333,  250,  278,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  333,  333,  570,  570,  570,  500,
+	/*  64 */   930,  722,  667,  722,  722,  667,  611,  778,
+	/*  72 */   778,  389,  500,  778,  667,  944,  722,  778,
+	/*  80 */   611,  778,  722,  556,  667,  722,  722, 1000,
+	/*  88 */   722,  722,  667,  333,  278,  333,  581,  500,
+	/*  96 */   333,  500,  556,  444,  556,  444,  333,  500,
+	/* 104 */   556,  278,  333,  556,  278,  833,  556,  500,
+	/* 112 */   556,  556,  444,  389,  333,  556,  500,  722,
+	/* 120 */   500,  500,  444,  394,  220,  394,  520,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1000,  350,
+	/* 144 */   333,  333,  333,  333,  500,  500,  500,  500,
+	/* 152 */  1000,  570, 1000,  722,  500,  500,  556,  556,
+	/* 160 */   250,  333,  500,  500,  500,  500,  220,  500,
+	/* 168 */   333,  747,  300,  500,  570,  333,  747,  333,
+	/* 176 */   400,  570,  300,  300,  333,  556,  540,  250,
+	/* 184 */   333,  300,  330,  500,  750,  750,  750,  500,
+	/* 192 */   722,  722,  722,  722,  722,  722, 1000,  722,
+	/* 200 */   667,  667,  667,  667,  389,  389,  389,  389,
+	/* 208 */   722,  722,  778,  778,  778,  778,  778,  570,
+	/* 216 */   778,  722,  722,  722,  722,  722,  611,  556,
+	/* 224 */   500,  500,  500,  500,  500,  500,  722,  444,
+	/* 232 */   444,  444,  444,  444,  278,  278,  278,  278,
+	/* 240 */   500,  556,  500,  500,  500,  500,  500,  570,
+	/* 248 */   500,  556,  556,  556,  556,  500,  556,  500,
+	},
+	{	/* Times-Italic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  333,  420,  500,  500,  833,  778,  333,
+	/*  40 */   333,  333,  500,  675,  250,  333,  250,  278,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  333,  333,  675,  675,  675,  500,
+	/*  64 */   920,  611,  611,  667,  722,  611,  611,  722,
+	/*  72 */   722,  333,  444,  667,  556,  833,  667,  722,
+	/*  80 */   611,  722,  611,  500,  556,  722,  611,  833,
+	/*  88 */   611,  556,  556,  389,  278,  389,  422,  500,
+	/*  96 */   333,  500,  500,  444,  500,  444,  278,  500,
+	/* 104 */   500,  278,  278,  444,  278,  722,  500,  500,
+	/* 112 */   500,  500,  389,  389,  278,  500,  444,  667,
+	/* 120 */   444,  444,  389,  400,  275,  400,  541,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,  889,  980, 1000,  350,
+	/* 144 */   333,  333,  333,  333,  556,  556,  556,  500,
+	/* 152 */   889,  675,  944,  667,  500,  500,  500,  500,
+	/* 160 */   250,  389,  500,  500,  500,  500,  275,  500,
+	/* 168 */   333,  760,  276,  500,  675,  333,  760,  333,
+	/* 176 */   400,  675,  300,  300,  333,  500,  523,  250,
+	/* 184 */   333,  300,  310,  500,  750,  750,  750,  500,
+	/* 192 */   611,  611,  611,  611,  611,  611,  889,  667,
+	/* 200 */   611,  611,  611,  611,  333,  333,  333,  333,
+	/* 208 */   722,  667,  722,  722,  722,  722,  722,  675,
+	/* 216 */   722,  722,  722,  722,  722,  556,  611,  500,
+	/* 224 */   500,  500,  500,  500,  500,  500,  667,  444,
+	/* 232 */   444,  444,  444,  444,  278,  278,  278,  278,
+	/* 240 */   500,  500,  500,  500,  500,  500,  500,  675,
+	/* 248 */   500,  500,  500,  500,  500,  444,  500,  444,
+	},
+	{	/* Times-BoldItalic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  389,  555,  500,  500,  833,  778,  333,
+	/*  40 */   333,  333,  500,  570,  250,  333,  250,  278,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  333,  333,  570,  570,  570,  500,
+	/*  64 */   832,  667,  667,  667,  722,  667,  667,  722,
+	/*  72 */   778,  389,  500,  667,  611,  889,  722,  722,
+	/*  80 */   611,  722,  667,  556,  611,  722,  667,  889,
+	/*  88 */   667,  611,  611,  333,  278,  333,  570,  500,
+	/*  96 */   333,  500,  500,  444,  500,  444,  333,  500,
+	/* 104 */   556,  278,  278,  500,  278,  778,  556,  500,
+	/* 112 */   500,  500,  389,  389,  278,  556,  444,  667,
+	/* 120 */   500,  444,  389,  348,  220,  348,  570,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1000,  350,
+	/* 144 */   333,  333,  333,  333,  500,  500,  500,  500,
+	/* 152 */  1000,  606,  944,  722,  500,  500,  556,  556,
+	/* 160 */   250,  389,  500,  500,  500,  500,  220,  500,
+	/* 168 */   333,  747,  266,  500,  606,  333,  747,  333,
+	/* 176 */   400,  570,  300,  300,  333,  576,  500,  250,
+	/* 184 */   333,  300,  300,  500,  750,  750,  750,  500,
+	/* 192 */   667,  667,  667,  667,  667,  667,  944,  667,
+	/* 200 */   667,  667,  667,  667,  389,  389,  389,  389,
+	/* 208 */   722,  722,  722,  722,  722,  722,  722,  570,
+	/* 216 */   722,  722,  722,  722,  722,  611,  611,  500,
+	/* 224 */   500,  500,  500,  500,  500,  500,  722,  444,
+	/* 232 */   444,  444,  444,  444,  278,  278,  278,  278,
+	/* 240 */   500,  556,  500,  500,  500,  500,  500,  570,
+	/* 248 */   500,  556,  556,  556,  556,  444,  500,  444,
+	},
+	{	/* Helvetica */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   278,  278,  355,  556,  556,  889,  667,  221,
+	/*  40 */   333,  333,  389,  584,  278,  333,  278,  278,
+	/*  48 */   556,  556,  556,  556,  556,  556,  556,  556,
+	/*  56 */   556,  556,  278,  278,  584,  584,  584,  556,
+	/*  64 */  1015,  667,  667,  722,  722,  667,  611,  778,
+	/*  72 */   722,  278,  500,  667,  556,  833,  722,  778,
+	/*  80 */   667,  778,  722,  667,  611,  722,  667,  944,
+	/*  88 */   667,  667,  611,  278,  278,  278,  469,  556,
+	/*  96 */   222,  556,  556,  500,  556,  556,  278,  556,
+	/* 104 */   556,  222,  222,  500,  222,  833,  556,  556,
+	/* 112 */   556,  556,  333,  500,  278,  556,  500,  722,
+	/* 120 */   500,  500,  500,  334,  260,  334,  584,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1000,  350,
+	/* 144 */   222,  221,  333,  333,  333,  333,  333,  556,
+	/* 152 */  1000,  584, 1000,  944,  556,  556,  500,  500,
+	/* 160 */   278,  333,  556,  556,  556,  556,  260,  556,
+	/* 168 */   333,  737,  370,  556,  584,  333,  737,  333,
+	/* 176 */   606,  584,  351,  351,  333,  556,  537,  278,
+	/* 184 */   333,  351,  365,  556,  869,  869,  869,  611,
+	/* 192 */   667,  667,  667,  667,  667,  667, 1000,  722,
+	/* 200 */   667,  667,  667,  667,  278,  278,  278,  278,
+	/* 208 */   722,  722,  778,  778,  778,  778,  778,  584,
+	/* 216 */   778,  722,  722,  722,  722,  666,  666,  611,
+	/* 224 */   556,  556,  556,  556,  556,  556,  889,  500,
+	/* 232 */   556,  556,  556,  556,  278,  278,  278,  278,
+	/* 240 */   556,  556,  556,  556,  556,  556,  556,  584,
+	/* 248 */   611,  556,  556,  556,  556,  500,  555,  500,
+	},
+	{	/* Helvetica-Bold */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   278,  333,  474,  556,  556,  889,  722,  278,
+	/*  40 */   333,  333,  389,  584,  278,  333,  278,  278,
+	/*  48 */   556,  556,  556,  556,  556,  556,  556,  556,
+	/*  56 */   556,  556,  333,  333,  584,  584,  584,  611,
+	/*  64 */   975,  722,  722,  722,  722,  667,  611,  778,
+	/*  72 */   722,  278,  556,  722,  611,  833,  722,  778,
+	/*  80 */   667,  778,  722,  667,  611,  722,  667,  944,
+	/*  88 */   667,  667,  611,  333,  278,  333,  584,  556,
+	/*  96 */   278,  556,  611,  556,  611,  556,  333,  611,
+	/* 104 */   611,  278,  278,  556,  278,  889,  611,  611,
+	/* 112 */   611,  611,  389,  556,  333,  611,  556,  778,
+	/* 120 */   556,  556,  500,  389,  280,  389,  584,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1000,  350,
+	/* 144 */   278,  278,  333,  333,  500,  500,  500,  556,
+	/* 152 */  1000,  584, 1000,  944,  556,  556,  611,  611,
+	/* 160 */   278,  333,  556,  556,  556,  556,  280,  556,
+	/* 168 */   333,  737,  370,  556,  584,  333,  737,  333,
+	/* 176 */   606,  584,  351,  351,  333,  611,  556,  278,
+	/* 184 */   333,  351,  365,  556,  869,  869,  869,  611,
+	/* 192 */   722,  722,  722,  722,  722,  722, 1000,  722,
+	/* 200 */   667,  667,  667,  667,  278,  278,  278,  278,
+	/* 208 */   722,  722,  778,  778,  778,  778,  778,  584,
+	/* 216 */   778,  722,  722,  722,  722,  667,  667,  611,
+	/* 224 */   556,  556,  556,  556,  556,  556,  889,  556,
+	/* 232 */   556,  556,  556,  556,  278,  278,  278,  278,
+	/* 240 */   611,  611,  611,  611,  611,  611,  611,  584,
+	/* 248 */   611,  611,  611,  611,  611,  556,  611,  556,
+	},
+	{	/* Helvetica-Oblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   278,  278,  355,  556,  556,  889,  667,  222,
+	/*  40 */   333,  333,  389,  584,  278,  333,  278,  278,
+	/*  48 */   556,  556,  556,  556,  556,  556,  556,  556,
+	/*  56 */   556,  556,  278,  278,  584,  584,  584,  556,
+	/*  64 */  1015,  667,  667,  722,  722,  667,  611,  778,
+	/*  72 */   722,  278,  500,  667,  556,  833,  722,  778,
+	/*  80 */   667,  778,  722,  667,  611,  722,  667,  944,
+	/*  88 */   667,  667,  611,  278,  278,  278,  469,  556,
+	/*  96 */   222,  556,  556,  500,  556,  556,  278,  556,
+	/* 104 */   556,  222,  222,  500,  222,  833,  556,  556,
+	/* 112 */   556,  556,  333,  500,  278,  556,  500,  722,
+	/* 120 */   500,  500,  500,  334,  260,  334,  584,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1000,  350,
+	/* 144 */   222,  222,  333,  333,  333,  333,  333,  556,
+	/* 152 */  1000,  584, 1000,  944,  556,  556,  500,  500,
+	/* 160 */   278,  333,  556,  556,  556,  556,  260,  556,
+	/* 168 */   333,  737,  370,  556,  584,  333,  737,  333,
+	/* 176 */   606,  584,  390,  390,  333,  556,  537,  278,
+	/* 184 */   333,  390,  365,  556,  947,  947,  947,  611,
+	/* 192 */   667,  667,  667,  667,  667,  667, 1000,  722,
+	/* 200 */   667,  667,  667,  667,  278,  278,  278,  278,
+	/* 208 */   722,  722,  778,  778,  778,  778,  778,  584,
+	/* 216 */   778,  722,  722,  722,  722,  667,  667,  611,
+	/* 224 */   556,  556,  556,  556,  556,  556,  889,  500,
+	/* 232 */   556,  556,  556,  556,  278,  278,  278,  278,
+	/* 240 */   556,  556,  556,  556,  556,  556,  556,  584,
+	/* 248 */   611,  556,  556,  556,  556,  500,  556,  500,
+	},
+	{	/* Helvetica-BoldOblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   278,  333,  474,  556,  556,  889,  722,  278,
+	/*  40 */   333,  333,  389,  584,  278,  333,  278,  278,
+	/*  48 */   556,  556,  556,  556,  556,  556,  556,  556,
+	/*  56 */   556,  556,  333,  333,  584,  584,  584,  611,
+	/*  64 */   975,  722,  722,  722,  722,  667,  611,  778,
+	/*  72 */   722,  278,  556,  722,  611,  833,  722,  778,
+	/*  80 */   667,  778,  722,  667,  611,  722,  667,  944,
+	/*  88 */   667,  667,  611,  333,  278,  333,  584,  556,
+	/*  96 */   278,  556,  611,  556,  611,  556,  333,  611,
+	/* 104 */   611,  278,  278,  556,  278,  889,  611,  611,
+	/* 112 */   611,  611,  389,  556,  333,  611,  556,  778,
+	/* 120 */   556,  556,  500,  389,  280,  389,  584,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1000,  350,
+	/* 144 */   278,  278,  333,  333,  500,  500,  500,  556,
+	/* 152 */  1000,  584, 1000,  944,  556,  556,  611,  611,
+	/* 160 */   278,  333,  556,  556,  556,  556,  280,  556,
+	/* 168 */   333,  737,  370,  556,  584,  333,  737,  333,
+	/* 176 */   606,  584,  444,  444,  333,  611,  556,  278,
+	/* 184 */   333,  444,  365,  556, 1055, 1055, 1055,  611,
+	/* 192 */   722,  722,  722,  722,  722,  722, 1000,  722,
+	/* 200 */   667,  667,  667,  667,  278,  278,  278,  278,
+	/* 208 */   722,  722,  778,  778,  778,  778,  778,  584,
+	/* 216 */   778,  722,  722,  722,  722,  667,  667,  611,
+	/* 224 */   556,  556,  556,  556,  556,  556,  889,  556,
+	/* 232 */   556,  556,  556,  556,  278,  278,  278,  278,
+	/* 240 */   611,  611,  611,  611,  611,  611,  611,  584,
+	/* 248 */   611,  611,  611,  611,  611,  556,  611,  556,
+	},
+	{	/* Palatino-Roman */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  278,  371,  500,  500,  840,  778,  278,
+	/*  40 */   333,  333,  389,  606,  250,  333,  250,  606,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  250,  250,  606,  606,  606,  444,
+	/*  64 */   747,  778,  611,  709,  774,  611,  556,  763,
+	/*  72 */   832,  337,  333,  726,  611,  946,  831,  786,
+	/*  80 */   604,  786,  668,  525,  613,  778,  722, 1000,
+	/*  88 */   667,  667,  667,  333,  606,  333,  606,  500,
+	/*  96 */   278,  500,  553,  444,  611,  479,  333,  556,
+	/* 104 */   582,  291,  234,  556,  291,  883,  582,  546,
+	/* 112 */   601,  560,  395,  424,  326,  603,  565,  834,
+	/* 120 */   516,  556,  500,  333,  606,  333,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000,  979, 1144,  606,
+	/* 144 */   278,  278,  331,  331,  500,  500,  500,  500,
+	/* 152 */  1000,  606,  998,  827,  500,  500,  605,  608,
+	/* 160 */   250,  278,  500,  500,  500,  500,  606,  500,
+	/* 168 */   333,  747,  333,  500,  606,  333,  747,  333,
+	/* 176 */   400,  606,  300,  300,  333,  603,  628,  250,
+	/* 184 */   333,  300,  333,  500,  750,  750,  750,  444,
+	/* 192 */   778,  778,  778,  778,  778,  778,  944,  709,
+	/* 200 */   611,  611,  611,  611,  337,  337,  337,  337,
+	/* 208 */   774,  831,  786,  786,  786,  786,  786,  606,
+	/* 216 */   833,  778,  778,  778,  778,  667,  604,  556,
+	/* 224 */   500,  500,  500,  500,  500,  500,  758,  444,
+	/* 232 */   479,  479,  479,  479,  287,  287,  287,  287,
+	/* 240 */   546,  582,  546,  546,  546,  546,  546,  606,
+	/* 248 */   556,  603,  603,  603,  603,  556,  601,  556,
+	},
+	{	/* Palatino-Bold */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  278,  402,  500,  500,  889,  833,  278,
+	/*  40 */   333,  333,  444,  606,  250,  333,  250,  296,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  250,  250,  606,  606,  606,  444,
+	/*  64 */   747,  778,  667,  722,  833,  611,  556,  833,
+	/*  72 */   833,  389,  389,  778,  611, 1000,  833,  833,
+	/*  80 */   611,  833,  722,  611,  667,  778,  778, 1000,
+	/*  88 */   667,  667,  667,  333,  606,  333,  606,  500,
+	/*  96 */   278,  500,  611,  444,  611,  500,  389,  556,
+	/* 104 */   611,  333,  333,  611,  333,  889,  611,  556,
+	/* 112 */   611,  611,  389,  444,  333,  611,  556,  833,
+	/* 120 */   500,  556,  500,  310,  606,  310,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000,  998, 1000,  606,
+	/* 144 */   278,  278,  389,  389,  500,  500,  500,  500,
+	/* 152 */  1000,  606, 1000,  833,  500,  500,  611,  611,
+	/* 160 */   250,  278,  500,  500,  500,  500,  606,  500,
+	/* 168 */   333,  747,  438,  500,  606,  333,  747,  333,
+	/* 176 */   400,  606,  300,  300,  333,  611,  641,  250,
+	/* 184 */   333,  300,  488,  500,  750,  750,  750,  444,
+	/* 192 */   778,  778,  778,  778,  778,  778, 1000,  722,
+	/* 200 */   611,  611,  611,  611,  389,  389,  389,  389,
+	/* 208 */   833,  833,  833,  833,  833,  833,  833,  606,
+	/* 216 */   833,  778,  778,  778,  778,  667,  611,  611,
+	/* 224 */   500,  500,  500,  500,  500,  500,  778,  444,
+	/* 232 */   500,  500,  500,  500,  333,  333,  333,  333,
+	/* 240 */   556,  611,  556,  556,  556,  556,  556,  606,
+	/* 248 */   556,  611,  611,  611,  611,  556,  611,  556,
+	},
+	{	/* Palatino-Italic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  333,  500,  500,  500,  889,  778,  278,
+	/*  40 */   333,  333,  389,  606,  250,  333,  250,  296,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  250,  250,  606,  606,  606,  500,
+	/*  64 */   747,  722,  611,  667,  778,  611,  556,  722,
+	/*  72 */   778,  333,  333,  667,  556,  944,  778,  778,
+	/*  80 */   611,  778,  667,  556,  611,  778,  722,  944,
+	/*  88 */   722,  667,  667,  333,  606,  333,  606,  500,
+	/*  96 */   278,  444,  463,  407,  500,  389,  278,  500,
+	/* 104 */   500,  278,  278,  444,  278,  778,  556,  444,
+	/* 112 */   500,  463,  389,  389,  333,  556,  500,  722,
+	/* 120 */   500,  500,  444,  333,  606,  333,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1000,  500,
+	/* 144 */   278,  278,  333,  333,  500,  500,  500,  500,
+	/* 152 */  1000,  606, 1028,  669,  500,  500,  528,  545,
+	/* 160 */   250,  333,  500,  500,  500,  500,  606,  500,
+	/* 168 */   333,  747,  333,  500,  606,  333,  747,  333,
+	/* 176 */   400,  606,  300,  300,  333,  556,  500,  250,
+	/* 184 */   333,  300,  333,  500,  750,  750,  750,  500,
+	/* 192 */   722,  722,  722,  722,  722,  722,  941,  667,
+	/* 200 */   611,  611,  611,  611,  333,  333,  333,  333,
+	/* 208 */   778,  778,  778,  778,  778,  778,  778,  606,
+	/* 216 */   778,  778,  778,  778,  778,  667,  611,  500,
+	/* 224 */   444,  444,  444,  444,  444,  444,  638,  407,
+	/* 232 */   389,  389,  389,  389,  278,  278,  278,  278,
+	/* 240 */   444,  556,  444,  444,  444,  444,  444,  606,
+	/* 248 */   444,  556,  556,  556,  556,  500,  500,  500,
+	},
+	{	/* Palatino-BoldItalic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  333,  500,  500,  500,  889,  833,  278,
+	/*  40 */   333,  333,  444,  606,  250,  389,  250,  315,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  250,  250,  606,  606,  606,  444,
+	/*  64 */   833,  722,  667,  685,  778,  611,  556,  778,
+	/*  72 */   778,  389,  389,  722,  611,  944,  778,  833,
+	/*  80 */   667,  833,  722,  556,  611,  778,  667, 1000,
+	/*  88 */   722,  611,  667,  333,  606,  333,  606,  500,
+	/*  96 */   278,  556,  537,  444,  556,  444,  333,  500,
+	/* 104 */   556,  333,  333,  556,  333,  833,  556,  556,
+	/* 112 */   556,  537,  389,  444,  389,  556,  556,  833,
+	/* 120 */   500,  556,  500,  333,  606,  333,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1000,  606,
+	/* 144 */   278,  278,  333,  333,  500,  500,  500,  500,
+	/* 152 */  1000,  606,  944,  778,  556,  556,  611,  611,
+	/* 160 */   250,  333,  500,  500,  500,  500,  606,  556,
+	/* 168 */   333,  747,  333,  500,  606,  389,  747,  333,
+	/* 176 */   400,  606,  300,  300,  333,  556,  556,  250,
+	/* 184 */   333,  300,  333,  500,  750,  750,  750,  444,
+	/* 192 */   722,  722,  722,  722,  722,  722,  944,  685,
+	/* 200 */   611,  611,  611,  611,  389,  389,  389,  389,
+	/* 208 */   778,  778,  833,  833,  833,  833,  833,  606,
+	/* 216 */   833,  778,  778,  778,  778,  611,  667,  556,
+	/* 224 */   556,  556,  556,  556,  556,  556,  738,  444,
+	/* 232 */   444,  444,  444,  444,  333,  333,  333,  333,
+	/* 240 */   556,  556,  556,  556,  556,  556,  556,  606,
+	/* 248 */   556,  556,  556,  556,  556,  556,  556,  556,
+	},
+	{	/* Helvetica-Narrow */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   228,  228,  291,  456,  456,  729,  547,  182,
+	/*  40 */   273,  273,  319,  479,  228,  273,  228,  228,
+	/*  48 */   456,  456,  456,  456,  456,  456,  456,  456,
+	/*  56 */   456,  456,  228,  228,  479,  479,  479,  456,
+	/*  64 */   832,  547,  547,  592,  592,  547,  501,  638,
+	/*  72 */   592,  228,  410,  547,  456,  683,  592,  638,
+	/*  80 */   547,  638,  592,  547,  501,  592,  547,  774,
+	/*  88 */   547,  547,  501,  228,  228,  228,  385,  456,
+	/*  96 */   182,  456,  456,  410,  456,  456,  228,  456,
+	/* 104 */   456,  182,  182,  410,  182,  683,  456,  456,
+	/* 112 */   456,  456,  273,  410,  228,  456,  410,  592,
+	/* 120 */   410,  410,  410,  274,  213,  274,  479,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,  820,  820,  820,  287,
+	/* 144 */   182,  182,  273,  273,  273,  273,  273,  456,
+	/* 152 */   820,  479,  820,  774,  456,  456,  410,  410,
+	/* 160 */   228,  273,  456,  456,  456,  456,  213,  456,
+	/* 168 */   273,  604,  303,  456,  479,  273,  604,  273,
+	/* 176 */   328,  479,  273,  273,  273,  456,  440,  228,
+	/* 184 */   273,  273,  299,  456,  684,  684,  684,  501,
+	/* 192 */   547,  547,  547,  547,  547,  547,  820,  592,
+	/* 200 */   547,  547,  547,  547,  228,  228,  228,  228,
+	/* 208 */   592,  592,  638,  638,  638,  638,  638,  479,
+	/* 216 */   638,  592,  592,  592,  592,  547,  547,  501,
+	/* 224 */   456,  456,  456,  456,  456,  456,  729,  410,
+	/* 232 */   456,  456,  456,  456,  228,  228,  228,  228,
+	/* 240 */   456,  456,  456,  456,  456,  456,  456,  479,
+	/* 248 */   501,  456,  456,  456,  456,  410,  456,  410,
+	},
+	{	/* Helvetica-Narrow-Bold */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   228,  273,  389,  456,  456,  729,  592,  228,
+	/*  40 */   273,  273,  319,  479,  228,  273,  228,  228,
+	/*  48 */   456,  456,  456,  456,  456,  456,  456,  456,
+	/*  56 */   456,  456,  273,  273,  479,  479,  479,  501,
+	/*  64 */   800,  592,  592,  592,  592,  547,  501,  638,
+	/*  72 */   592,  228,  456,  592,  501,  683,  592,  638,
+	/*  80 */   547,  638,  592,  547,  501,  592,  547,  774,
+	/*  88 */   547,  547,  501,  273,  228,  273,  479,  456,
+	/*  96 */   228,  456,  501,  456,  501,  456,  273,  501,
+	/* 104 */   501,  228,  228,  456,  228,  729,  501,  501,
+	/* 112 */   501,  501,  319,  456,  273,  501,  456,  638,
+	/* 120 */   456,  456,  410,  319,  230,  319,  479,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,  820,  820,  820,  287,
+	/* 144 */   228,  228,  273,  273,  410,  410,  410,  456,
+	/* 152 */   820,  479,  820,  774,  456,  456,  501,  501,
+	/* 160 */   228,  273,  456,  456,  456,  456,  230,  456,
+	/* 168 */   273,  604,  303,  456,  479,  273,  604,  273,
+	/* 176 */   328,  479,  273,  273,  273,  501,  456,  228,
+	/* 184 */   273,  273,  299,  456,  684,  684,  684,  501,
+	/* 192 */   592,  592,  592,  592,  592,  592,  820,  592,
+	/* 200 */   547,  547,  547,  547,  228,  228,  228,  228,
+	/* 208 */   592,  592,  638,  638,  638,  638,  638,  479,
+	/* 216 */   638,  592,  592,  592,  592,  547,  547,  501,
+	/* 224 */   456,  456,  456,  456,  456,  456,  729,  456,
+	/* 232 */   456,  456,  456,  456,  228,  228,  228,  228,
+	/* 240 */   501,  501,  501,  501,  501,  501,  501,  479,
+	/* 248 */   501,  501,  501,  501,  501,  456,  501,  456,
+	},
+	{	/* Helvetica-Narrow-Oblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   228,  228,  291,  456,  456,  729,  547,  182,
+	/*  40 */   273,  273,  319,  479,  228,  273,  228,  228,
+	/*  48 */   456,  456,  456,  456,  456,  456,  456,  456,
+	/*  56 */   456,  456,  228,  228,  479,  479,  479,  456,
+	/*  64 */   832,  547,  547,  592,  592,  547,  501,  638,
+	/*  72 */   592,  228,  410,  547,  456,  683,  592,  638,
+	/*  80 */   547,  638,  592,  547,  501,  592,  547,  774,
+	/*  88 */   547,  547,  501,  228,  228,  228,  385,  456,
+	/*  96 */   182,  456,  456,  410,  456,  456,  228,  456,
+	/* 104 */   456,  182,  182,  410,  182,  683,  456,  456,
+	/* 112 */   456,  456,  273,  410,  228,  456,  410,  592,
+	/* 120 */   410,  410,  410,  274,  213,  274,  479,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,  820,  820,  820,  287,
+	/* 144 */   182,  182,  273,  273,  273,  273,  273,  456,
+	/* 152 */   820,  479,  820,  774,  456,  456,  410,  410,
+	/* 160 */   228,  273,  456,  456,  456,  456,  213,  456,
+	/* 168 */   273,  604,  303,  456,  479,  273,  604,  273,
+	/* 176 */   328,  479,  273,  273,  273,  456,  440,  228,
+	/* 184 */   273,  273,  299,  456,  684,  684,  684,  501,
+	/* 192 */   547,  547,  547,  547,  547,  547,  820,  592,
+	/* 200 */   547,  547,  547,  547,  228,  228,  228,  228,
+	/* 208 */   592,  592,  638,  638,  638,  638,  638,  479,
+	/* 216 */   638,  592,  592,  592,  592,  547,  547,  501,
+	/* 224 */   456,  456,  456,  456,  456,  456,  729,  410,
+	/* 232 */   456,  456,  456,  456,  228,  228,  228,  228,
+	/* 240 */   456,  456,  456,  456,  456,  456,  456,  479,
+	/* 248 */   501,  456,  456,  456,  456,  410,  456,  410,
+	},
+	{	/* Helvetica-Narrow-BoldOblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   228,  273,  389,  456,  456,  729,  592,  228,
+	/*  40 */   273,  273,  319,  479,  228,  273,  228,  228,
+	/*  48 */   456,  456,  456,  456,  456,  456,  456,  456,
+	/*  56 */   456,  456,  273,  273,  479,  479,  479,  501,
+	/*  64 */   800,  592,  592,  592,  592,  547,  501,  638,
+	/*  72 */   592,  228,  456,  592,  501,  683,  592,  638,
+	/*  80 */   547,  638,  592,  547,  501,  592,  547,  774,
+	/*  88 */   547,  547,  501,  273,  228,  273,  479,  456,
+	/*  96 */   228,  456,  501,  456,  501,  456,  273,  501,
+	/* 104 */   501,  228,  228,  456,  228,  729,  501,  501,
+	/* 112 */   501,  501,  319,  456,  273,  501,  456,  638,
+	/* 120 */   456,  456,  410,  319,  230,  319,  479,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,  820,  820,  820,  287,
+	/* 144 */   228,  228,  273,  273,  410,  410,  410,  456,
+	/* 152 */   820,  479,  820,  774,  456,  456,  501,  501,
+	/* 160 */   228,  273,  456,  456,  456,  456,  230,  456,
+	/* 168 */   273,  604,  303,  456,  479,  273,  604,  273,
+	/* 176 */   328,  479,  273,  273,  273,  501,  456,  228,
+	/* 184 */   273,  273,  299,  456,  684,  684,  684,  501,
+	/* 192 */   592,  592,  592,  592,  592,  592,  820,  592,
+	/* 200 */   547,  547,  547,  547,  228,  228,  228,  228,
+	/* 208 */   592,  592,  638,  638,  638,  638,  638,  479,
+	/* 216 */   638,  592,  592,  592,  592,  547,  547,  501,
+	/* 224 */   456,  456,  456,  456,  456,  456,  729,  456,
+	/* 232 */   456,  456,  456,  456,  228,  228,  228,  228,
+	/* 240 */   501,  501,  501,  501,  501,  501,  501,  479,
+	/* 248 */   501,  501,  501,  501,  501,  456,  501,  456,
+	},
+	{	/* Bookman-Light */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   320,  300,  380,  620,  620,  900,  800,  220,
+	/*  40 */   300,  300,  440,  600,  320,  400,  320,  600,
+	/*  48 */   620,  620,  620,  620,  620,  620,  620,  620,
+	/*  56 */   620,  620,  320,  320,  600,  600,  600,  540,
+	/*  64 */   820,  680,  740,  740,  800,  720,  640,  800,
+	/*  72 */   800,  340,  600,  720,  600,  920,  740,  800,
+	/*  80 */   620,  820,  720,  660,  620,  780,  700,  960,
+	/*  88 */   720,  640,  640,  300,  600,  300,  600,  500,
+	/*  96 */   220,  580,  620,  520,  620,  520,  320,  540,
+	/* 104 */   660,  300,  300,  620,  300,  940,  660,  560,
+	/* 112 */   620,  580,  440,  520,  380,  680,  520,  780,
+	/* 120 */   560,  540,  480,  280,  600,  280,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000,  980, 1280,  460,
+	/* 144 */   220,  220,  240,  240,  400,  400,  400,  500,
+	/* 152 */  1000,  600, 1240,  900,  540,  540,  620,  620,
+	/* 160 */   320,  300,  620,  620,  620,  620,  600,  520,
+	/* 168 */   420,  740,  420,  360,  600,  400,  740,  440,
+	/* 176 */   400,  600,  372,  372,  340,  680,  600,  320,
+	/* 184 */   320,  372,  420,  360,  930,  930,  930,  540,
+	/* 192 */   680,  680,  680,  680,  680,  680, 1260,  740,
+	/* 200 */   720,  720,  720,  720,  340,  340,  340,  340,
+	/* 208 */   800,  740,  800,  800,  800,  800,  800,  600,
+	/* 216 */   800,  780,  780,  780,  780,  640,  620,  660,
+	/* 224 */   580,  580,  580,  580,  580,  580,  860,  520,
+	/* 232 */   520,  520,  520,  520,  300,  300,  300,  300,
+	/* 240 */   560,  660,  560,  560,  560,  560,  560,  600,
+	/* 248 */   560,  680,  680,  680,  680,  540,  620,  540,
+	},
+	{	/* Bookman-Demi */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   340,  360,  420,  660,  660,  940,  800,  320,
+	/*  40 */   320,  320,  460,  600,  340,  360,  340,  600,
+	/*  48 */   660,  660,  660,  660,  660,  660,  660,  660,
+	/*  56 */   660,  660,  340,  340,  600,  600,  600,  660,
+	/*  64 */   820,  720,  720,  740,  780,  720,  680,  780,
+	/*  72 */   820,  400,  640,  800,  640,  940,  740,  800,
+	/*  80 */   660,  800,  780,  660,  700,  740,  720,  940,
+	/*  88 */   780,  700,  640,  300,  600,  300,  600,  500,
+	/*  96 */   320,  580,  600,  580,  640,  580,  380,  580,
+	/* 104 */   680,  360,  340,  660,  340, 1000,  680,  620,
+	/* 112 */   640,  620,  460,  520,  460,  660,  600,  800,
+	/* 120 */   600,  620,  560,  320,  600,  320,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000,  980, 1360,  460,
+	/* 144 */   320,  320,  220,  220,  540,  540,  540,  500,
+	/* 152 */  1000,  600, 1220,  940,  440,  380,  740,  740,
+	/* 160 */   340,  360,  660,  660,  660,  660,  600,  600,
+	/* 168 */   500,  740,  400,  400,  600,  360,  740,  460,
+	/* 176 */   400,  600,  396,  396,  400,  660,  800,  340,
+	/* 184 */   360,  396,  400,  400,  990,  990,  990,  660,
+	/* 192 */   720,  720,  720,  720,  720,  720, 1140,  740,
+	/* 200 */   720,  720,  720,  720,  400,  400,  400,  400,
+	/* 208 */   780,  740,  800,  800,  800,  800,  800,  600,
+	/* 216 */   800,  740,  740,  740,  740,  700,  660,  660,
+	/* 224 */   580,  580,  580,  580,  580,  580,  880,  580,
+	/* 232 */   580,  580,  580,  580,  360,  360,  360,  360,
+	/* 240 */   620,  680,  620,  620,  620,  620,  620,  600,
+	/* 248 */   620,  660,  660,  660,  660,  620,  640,  620,
+	},
+	{	/* Bookman-LightItalic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   300,  320,  360,  620,  620,  800,  820,  280,
+	/*  40 */   280,  280,  440,  600,  300,  320,  300,  600,
+	/*  48 */   620,  620,  620,  620,  620,  620,  620,  620,
+	/*  56 */   620,  620,  300,  300,  600,  600,  600,  540,
+	/*  64 */   780,  700,  720,  720,  740,  680,  620,  760,
+	/*  72 */   800,  320,  560,  720,  580,  860,  720,  760,
+	/*  80 */   600,  780,  700,  640,  600,  720,  680,  960,
+	/*  88 */   700,  660,  580,  260,  600,  260,  600,  500,
+	/*  96 */   280,  620,  600,  480,  640,  540,  340,  560,
+	/* 104 */   620,  280,  280,  600,  280,  880,  620,  540,
+	/* 112 */   600,  560,  400,  540,  340,  620,  540,  880,
+	/* 120 */   540,  600,  520,  360,  600,  380,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000,  980, 1180,  460,
+	/* 144 */   280,  280,  180,  180,  440,  440,  480,  500,
+	/* 152 */  1000,  600, 1180,  900,  620,  620,  640,  660,
+	/* 160 */   300,  320,  620,  620,  620,  620,  600,  620,
+	/* 168 */   420,  740,  440,  300,  600,  320,  740,  440,
+	/* 176 */   400,  600,  372,  372,  320,  620,  620,  300,
+	/* 184 */   320,  372,  400,  300,  930,  930,  930,  540,
+	/* 192 */   700,  700,  700,  700,  700,  700, 1220,  720,
+	/* 200 */   680,  680,  680,  680,  320,  320,  320,  320,
+	/* 208 */   740,  720,  760,  760,  760,  760,  760,  600,
+	/* 216 */   760,  720,  720,  720,  720,  660,  600,  620,
+	/* 224 */   620,  620,  620,  620,  620,  620,  880,  480,
+	/* 232 */   540,  540,  540,  540,  280,  280,  280,  280,
+	/* 240 */   540,  620,  540,  540,  540,  540,  540,  600,
+	/* 248 */   540,  620,  620,  620,  620,  600,  600,  600,
+	},
+	{	/* Bookman-DemiItalic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   340,  320,  380,  680,  680,  880,  980,  320,
+	/*  40 */   260,  260,  460,  600,  340,  280,  340,  360,
+	/*  48 */   680,  680,  680,  680,  680,  680,  680,  680,
+	/*  56 */   680,  680,  340,  340,  620,  600,  620,  620,
+	/*  64 */   780,  720,  720,  700,  760,  720,  660,  760,
+	/*  72 */   800,  380,  620,  780,  640,  860,  740,  760,
+	/*  80 */   640,  760,  740,  700,  700,  740,  660, 1000,
+	/*  88 */   740,  660,  680,  260,  580,  260,  620,  500,
+	/*  96 */   320,  680,  600,  560,  680,  560,  420,  620,
+	/* 104 */   700,  380,  320,  700,  380,  960,  680,  600,
+	/* 112 */   660,  620,  500,  540,  440,  680,  540,  860,
+	/* 120 */   620,  600,  560,  300,  620,  300,  620,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000,  940, 1360,  360,
+	/* 144 */   320,  320,  220,  220,  520,  520,  520,  500,
+	/* 152 */  1000,  600, 1180,  920,  420,  420,  820,  820,
+	/* 160 */   340,  320,  680,  680,  680,  680,  620,  620,
+	/* 168 */   520,  780,  440,  380,  620,  280,  780,  480,
+	/* 176 */   400,  600,  408,  408,  340,  680,  680,  340,
+	/* 184 */   360,  408,  440,  380, 1020, 1020, 1020,  620,
+	/* 192 */   720,  720,  720,  720,  720,  720, 1140,  700,
+	/* 200 */   720,  720,  720,  720,  380,  380,  380,  380,
+	/* 208 */   760,  740,  760,  760,  760,  760,  760,  600,
+	/* 216 */   760,  740,  740,  740,  740,  660,  640,  660,
+	/* 224 */   680,  680,  680,  680,  680,  680,  880,  560,
+	/* 232 */   560,  560,  560,  560,  380,  380,  380,  380,
+	/* 240 */   600,  680,  600,  600,  600,  600,  600,  600,
+	/* 248 */   600,  680,  680,  680,  680,  600,  660,  600,
+	},
+	{	/* AvantGarde-Book */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   277,  295,  309,  554,  554,  775,  757,  351,
+	/*  40 */   369,  369,  425,  606,  277,  332,  277,  437,
+	/*  48 */   554,  554,  554,  554,  554,  554,  554,  554,
+	/*  56 */   554,  554,  277,  277,  606,  606,  606,  591,
+	/*  64 */   867,  740,  574,  813,  744,  536,  485,  872,
+	/*  72 */   683,  226,  482,  591,  462,  919,  740,  869,
+	/*  80 */   592,  871,  607,  498,  426,  655,  702,  960,
+	/*  88 */   609,  592,  480,  351,  605,  351,  606,  500,
+	/*  96 */   351,  683,  682,  647,  685,  650,  314,  673,
+	/* 104 */   610,  200,  203,  502,  200,  938,  610,  655,
+	/* 112 */   682,  682,  301,  388,  339,  608,  554,  831,
+	/* 120 */   480,  536,  425,  351,  672,  351,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1174,  606,
+	/* 144 */   351,  351,  251,  251,  502,  484,  502,  500,
+	/* 152 */  1000,  606, 1194, 1137,  553,  553,  487,  485,
+	/* 160 */   277,  295,  554,  554,  554,  554,  672,  615,
+	/* 168 */   369,  747,  369,  425,  606,  332,  747,  485,
+	/* 176 */   400,  606,  332,  332,  375,  608,  564,  277,
+	/* 184 */   324,  332,  369,  425,  831,  831,  831,  591,
+	/* 192 */   740,  740,  740,  740,  740,  740,  992,  813,
+	/* 200 */   536,  536,  536,  536,  226,  226,  226,  226,
+	/* 208 */   790,  740,  869,  869,  869,  869,  869,  606,
+	/* 216 */   868,  655,  655,  655,  655,  592,  592,  554,
+	/* 224 */   683,  683,  683,  683,  683,  683, 1157,  647,
+	/* 232 */   650,  650,  650,  650,  200,  200,  200,  200,
+	/* 240 */   655,  610,  655,  655,  655,  655,  655,  606,
+	/* 248 */   653,  608,  608,  608,  608,  536,  682,  536,
+	},
+	{	/* AvantGarde-Demi */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   280,  280,  360,  560,  560,  860,  680,  280,
+	/*  40 */   380,  380,  440,  600,  280,  420,  280,  460,
+	/*  48 */   560,  560,  560,  560,  560,  560,  560,  560,
+	/*  56 */   560,  560,  280,  280,  600,  600,  600,  560,
+	/*  64 */   740,  740,  580,  780,  700,  520,  480,  840,
+	/*  72 */   680,  280,  480,  620,  440,  900,  740,  840,
+	/*  80 */   560,  840,  580,  520,  420,  640,  700,  900,
+	/*  88 */   680,  620,  500,  320,  640,  320,  600,  500,
+	/*  96 */   280,  660,  660,  640,  660,  640,  280,  660,
+	/* 104 */   600,  240,  260,  580,  240,  940,  600,  640,
+	/* 112 */   660,  660,  320,  440,  300,  600,  560,  800,
+	/* 120 */   560,  580,  460,  340,  600,  340,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1280,  600,
+	/* 144 */   280,  280,  240,  240,  480,  480,  480,  500,
+	/* 152 */  1000,  600, 1060, 1080,  560,  560,  520,  520,
+	/* 160 */   280,  280,  560,  560,  560,  560,  600,  560,
+	/* 168 */   500,  740,  360,  460,  600,  420,  740,  420,
+	/* 176 */   400,  600,  336,  336,  420,  576,  600,  280,
+	/* 184 */   340,  336,  360,  460,  840,  840,  840,  560,
+	/* 192 */   740,  740,  740,  740,  740,  740,  900,  780,
+	/* 200 */   520,  520,  520,  520,  280,  280,  280,  280,
+	/* 208 */   742,  740,  840,  840,  840,  840,  840,  600,
+	/* 216 */   840,  640,  640,  640,  640,  620,  560,  600,
+	/* 224 */   660,  660,  660,  660,  660,  660, 1080,  640,
+	/* 232 */   640,  640,  640,  640,  240,  240,  240,  240,
+	/* 240 */   640,  600,  640,  640,  640,  640,  640,  600,
+	/* 248 */   660,  600,  600,  600,  600,  580,  660,  580,
+	},
+	{	/* AvantGarde-BookOblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   277,  295,  309,  554,  554,  775,  757,  351,
+	/*  40 */   369,  369,  425,  606,  277,  332,  277,  437,
+	/*  48 */   554,  554,  554,  554,  554,  554,  554,  554,
+	/*  56 */   554,  554,  277,  277,  606,  606,  606,  591,
+	/*  64 */   867,  740,  574,  813,  744,  536,  485,  872,
+	/*  72 */   683,  226,  482,  591,  462,  919,  740,  869,
+	/*  80 */   592,  871,  607,  498,  426,  655,  702,  960,
+	/*  88 */   609,  592,  480,  351,  605,  351,  606,  500,
+	/*  96 */   351,  683,  682,  647,  685,  650,  314,  673,
+	/* 104 */   610,  200,  203,  502,  200,  938,  610,  655,
+	/* 112 */   682,  682,  301,  388,  339,  608,  554,  831,
+	/* 120 */   480,  536,  425,  351,  672,  351,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1174,  606,
+	/* 144 */   351,  351,  251,  251,  502,  484,  502,  500,
+	/* 152 */  1000,  606, 1194, 1137,  553,  553,  487,  485,
+	/* 160 */   277,  295,  554,  554,  554,  554,  672,  615,
+	/* 168 */   369,  747,  369,  425,  606,  332,  747,  485,
+	/* 176 */   400,  606,  332,  332,  375,  608,  564,  277,
+	/* 184 */   324,  332,  369,  425,  831,  831,  831,  591,
+	/* 192 */   740,  740,  740,  740,  740,  740,  992,  813,
+	/* 200 */   536,  536,  536,  536,  226,  226,  226,  226,
+	/* 208 */   790,  740,  869,  869,  869,  869,  869,  606,
+	/* 216 */   868,  655,  655,  655,  655,  592,  592,  554,
+	/* 224 */   683,  683,  683,  683,  683,  683, 1157,  647,
+	/* 232 */   650,  650,  650,  650,  200,  200,  200,  200,
+	/* 240 */   655,  610,  655,  655,  655,  655,  655,  606,
+	/* 248 */   653,  608,  608,  608,  608,  536,  682,  536,
+	},
+	{	/* AvantGarde-DemiOblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   280,  280,  360,  560,  560,  860,  680,  280,
+	/*  40 */   380,  380,  440,  600,  280,  420,  280,  460,
+	/*  48 */   560,  560,  560,  560,  560,  560,  560,  560,
+	/*  56 */   560,  560,  280,  280,  600,  600,  600,  560,
+	/*  64 */   740,  740,  580,  780,  700,  520,  480,  840,
+	/*  72 */   680,  280,  480,  620,  440,  900,  740,  840,
+	/*  80 */   560,  840,  580,  520,  420,  640,  700,  900,
+	/*  88 */   680,  620,  500,  320,  640,  320,  600,  500,
+	/*  96 */   280,  660,  660,  640,  660,  640,  280,  660,
+	/* 104 */   600,  240,  260,  580,  240,  940,  600,  640,
+	/* 112 */   660,  660,  320,  440,  300,  600,  560,  800,
+	/* 120 */   560,  580,  460,  340,  600,  340,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1280,  600,
+	/* 144 */   280,  280,  240,  240,  480,  480,  480,  500,
+	/* 152 */  1000,  600, 1060, 1080,  560,  560,  520,  520,
+	/* 160 */   280,  280,  560,  560,  560,  560,  600,  560,
+	/* 168 */   500,  740,  360,  460,  600,  420,  740,  420,
+	/* 176 */   400,  600,  336,  336,  420,  576,  600,  280,
+	/* 184 */   340,  336,  360,  460,  840,  840,  840,  560,
+	/* 192 */   740,  740,  740,  740,  740,  740,  900,  780,
+	/* 200 */   520,  520,  520,  520,  280,  280,  280,  280,
+	/* 208 */   742,  740,  840,  840,  840,  840,  840,  600,
+	/* 216 */   840,  640,  640,  640,  640,  620,  560,  600,
+	/* 224 */   660,  660,  660,  660,  660,  660, 1080,  640,
+	/* 232 */   640,  640,  640,  640,  240,  240,  240,  240,
+	/* 240 */   640,  600,  640,  640,  640,  640,  640,  600,
+	/* 248 */   660,  600,  600,  600,  600,  580,  660,  580,
+	},
+	{	/* NewCenturySchlbk-Roman */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   278,  296,  389,  556,  556,  833,  815,  204,
+	/*  40 */   333,  333,  500,  606,  278,  333,  278,  278,
+	/*  48 */   556,  556,  556,  556,  556,  556,  556,  556,
+	/*  56 */   556,  556,  278,  278,  606,  606,  606,  444,
+	/*  64 */   737,  722,  722,  722,  778,  722,  667,  778,
+	/*  72 */   833,  407,  556,  778,  667,  944,  815,  778,
+	/*  80 */   667,  778,  722,  630,  667,  815,  722,  981,
+	/*  88 */   704,  704,  611,  333,  606,  333,  606,  500,
+	/*  96 */   204,  556,  556,  444,  574,  500,  333,  537,
+	/* 104 */   611,  315,  296,  593,  315,  889,  611,  500,
+	/* 112 */   574,  556,  444,  463,  389,  611,  537,  778,
+	/* 120 */   537,  537,  481,  333,  606,  333,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1000,  606,
+	/* 144 */   204,  204,  259,  259,  389,  389,  389,  556,
+	/* 152 */  1000,  606, 1000,  833,  500,  500,  611,  611,
+	/* 160 */   278,  296,  556,  556,  556,  556,  606,  500,
+	/* 168 */   333,  737,  334,  426,  606,  333,  737,  333,
+	/* 176 */   400,  606,  333,  333,  333,  611,  606,  278,
+	/* 184 */   333,  333,  300,  426,  834,  834,  834,  444,
+	/* 192 */   722,  722,  722,  722,  722,  722, 1000,  722,
+	/* 200 */   722,  722,  722,  722,  407,  407,  407,  407,
+	/* 208 */   778,  815,  778,  778,  778,  778,  778,  606,
+	/* 216 */   778,  815,  815,  815,  815,  704,  667,  574,
+	/* 224 */   556,  556,  556,  556,  556,  556,  796,  444,
+	/* 232 */   500,  500,  500,  500,  315,  315,  315,  315,
+	/* 240 */   500,  611,  500,  500,  500,  500,  500,  606,
+	/* 248 */   500,  611,  611,  611,  611,  537,  574,  537,
+	},
+	{	/* NewCenturySchlbk-Bold */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   287,  296,  333,  574,  574,  833,  852,  241,
+	/*  40 */   389,  389,  500,  606,  278,  333,  278,  278,
+	/*  48 */   574,  574,  574,  574,  574,  574,  574,  574,
+	/*  56 */   574,  574,  278,  278,  606,  606,  606,  500,
+	/*  64 */   747,  759,  778,  778,  833,  759,  722,  833,
+	/*  72 */   870,  444,  648,  815,  722,  981,  833,  833,
+	/*  80 */   759,  833,  815,  667,  722,  833,  759,  981,
+	/*  88 */   722,  722,  667,  389,  606,  389,  606,  500,
+	/*  96 */   241,  611,  648,  556,  667,  574,  389,  611,
+	/* 104 */   685,  370,  352,  667,  352,  963,  685,  611,
+	/* 112 */   667,  648,  519,  500,  426,  685,  611,  889,
+	/* 120 */   611,  611,  537,  389,  606,  389,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000, 1000, 1000,  606,
+	/* 144 */   241,  241,  333,  333,  481,  481,  481,  500,
+	/* 152 */  1000,  606, 1000,  907,  500,  500,  685,  685,
+	/* 160 */   287,  296,  574,  574,  574,  574,  606,  500,
+	/* 168 */   333,  747,  367,  500,  606,  333,  747,  333,
+	/* 176 */   400,  606,  344,  344,  333,  685,  747,  278,
+	/* 184 */   333,  344,  367,  500,  861,  861,  861,  500,
+	/* 192 */   759,  759,  759,  759,  759,  759,  981,  778,
+	/* 200 */   759,  759,  759,  759,  444,  444,  444,  444,
+	/* 208 */   833,  833,  833,  833,  833,  833,  833,  606,
+	/* 216 */   833,  833,  833,  833,  833,  722,  759,  611,
+	/* 224 */   611,  611,  611,  611,  611,  611,  870,  556,
+	/* 232 */   574,  574,  574,  574,  370,  370,  370,  370,
+	/* 240 */   611,  685,  611,  611,  611,  611,  611,  606,
+	/* 248 */   611,  685,  685,  685,  685,  611,  667,  611,
+	},
+	{	/* NewCenturySchlbk-Italic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   278,  333,  400,  556,  556,  833,  852,  204,
+	/*  40 */   333,  333,  500,  606,  278,  333,  278,  606,
+	/*  48 */   556,  556,  556,  556,  556,  556,  556,  556,
+	/*  56 */   556,  556,  278,  278,  606,  606,  606,  444,
+	/*  64 */   747,  704,  722,  722,  778,  722,  667,  778,
+	/*  72 */   833,  407,  611,  741,  667,  944,  815,  778,
+	/*  80 */   667,  778,  741,  667,  685,  815,  704,  926,
+	/*  88 */   704,  685,  667,  333,  606,  333,  606,  500,
+	/*  96 */   204,  574,  556,  444,  611,  444,  333,  537,
+	/* 104 */   611,  333,  315,  556,  333,  889,  611,  500,
+	/* 112 */   574,  556,  444,  444,  352,  611,  519,  778,
+	/* 120 */   500,  500,  463,  333,  606,  333,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000,  950, 1000,  606,
+	/* 144 */   204,  204,  333,  333,  389,  389,  389,  500,
+	/* 152 */  1000,  606,  981,  778,  500,  500,  611,  611,
+	/* 160 */   278,  333,  556,  556,  556,  556,  606,  500,
+	/* 168 */   333,  747,  422,  426,  606,  333,  747,  333,
+	/* 176 */   400,  606,  333,  333,  333,  611,  650,  278,
+	/* 184 */   333,  333,  372,  426,  834,  834,  834,  444,
+	/* 192 */   704,  704,  704,  704,  704,  704,  870,  722,
+	/* 200 */   722,  722,  722,  722,  407,  407,  407,  407,
+	/* 208 */   778,  815,  778,  778,  778,  778,  778,  606,
+	/* 216 */   778,  815,  815,  815,  815,  685,  667,  556,
+	/* 224 */   574,  574,  574,  574,  574,  574,  722,  444,
+	/* 232 */   444,  444,  444,  444,  333,  333,  333,  333,
+	/* 240 */   500,  611,  500,  500,  500,  500,  500,  606,
+	/* 248 */   500,  611,  611,  611,  611,  500,  574,  500,
+	},
+	{	/* NewCenturySchlbk-BoldItalic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   287,  333,  400,  574,  574,  889,  889,  259,
+	/*  40 */   407,  407,  500,  606,  287,  333,  287,  278,
+	/*  48 */   574,  574,  574,  574,  574,  574,  574,  574,
+	/*  56 */   574,  574,  287,  287,  606,  606,  606,  481,
+	/*  64 */   747,  741,  759,  759,  833,  741,  704,  815,
+	/*  72 */   870,  444,  667,  778,  704,  944,  852,  833,
+	/*  80 */   741,  833,  796,  685,  722,  833,  741,  944,
+	/*  88 */   741,  704,  704,  407,  606,  407,  606,  500,
+	/*  96 */   259,  667,  611,  537,  667,  519,  389,  611,
+	/* 104 */   685,  389,  370,  648,  389,  944,  685,  574,
+	/* 112 */   648,  630,  519,  481,  407,  685,  556,  833,
+	/* 120 */   574,  519,  519,  407,  606,  407,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0, 1000,  950, 1167,  606,
+	/* 144 */   259,  259,  278,  278,  481,  481,  481,  500,
+	/* 152 */  1000,  606,  963,  852,  500,  500,  685,  685,
+	/* 160 */   287,  333,  574,  574,  574,  574,  606,  500,
+	/* 168 */   333,  747,  412,  481,  606,  333,  747,  333,
+	/* 176 */   400,  606,  344,  344,  333,  685,  650,  287,
+	/* 184 */   333,  344,  356,  481,  861,  861,  861,  481,
+	/* 192 */   741,  741,  741,  741,  741,  741,  889,  759,
+	/* 200 */   741,  741,  741,  741,  444,  444,  444,  444,
+	/* 208 */   833,  852,  833,  833,  833,  833,  833,  606,
+	/* 216 */   833,  833,  833,  833,  833,  704,  741,  574,
+	/* 224 */   667,  667,  667,  667,  667,  667,  815,  537,
+	/* 232 */   519,  519,  519,  519,  389,  389,  389,  389,
+	/* 240 */   574,  685,  574,  574,  574,  574,  574,  606,
+	/* 248 */   574,  685,  685,  685,  685,  519,  648,  519,
+	},
+};
+static unsigned short ausCharacterWidths2[32][256] = {
+	{	/* Courier */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  40 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  48 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  56 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  64 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  72 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  80 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  88 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  96 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 104 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 112 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 120 */   600,  600,  600,  600,  600,  600,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 168 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 176 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 184 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 192 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 200 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 208 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 216 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 224 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 232 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 240 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 248 */   600,  600,  600,  600,  600,  600,  600,  600,
+	},
+	{	/* Courier-Bold */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  40 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  48 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  56 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  64 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  72 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  80 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  88 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  96 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 104 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 112 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 120 */   600,  600,  600,  600,  600,  600,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 168 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 176 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 184 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 192 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 200 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 208 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 216 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 224 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 232 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 240 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 248 */   600,  600,  600,  600,  600,  600,  600,  600,
+	},
+	{	/* Courier-Oblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  40 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  48 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  56 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  64 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  72 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  80 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  88 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  96 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 104 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 112 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 120 */   600,  600,  600,  600,  600,  600,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 168 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 176 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 184 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 192 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 200 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 208 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 216 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 224 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 232 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 240 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 248 */   600,  600,  600,  600,  600,  600,  600,  600,
+	},
+	{	/* Courier-BoldOblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  40 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  48 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  56 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  64 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  72 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  80 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  88 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/*  96 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 104 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 112 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 120 */   600,  600,  600,  600,  600,  600,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 168 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 176 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 184 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 192 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 200 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 208 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 216 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 224 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 232 */   600,  600,  600,  600,  600,  600,  600,  740,
+	/* 240 */   600,  600,  600,  600,  600,  600,  600,  600,
+	/* 248 */   600,  600,  600,  600,  600,  600,  600,  600,
+	},
+	{	/* Times-Roman */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  333,  408,  500,  500,  833,  778,  180,
+	/*  40 */   333,  333,  500,  564,  250,  333,  250,  278,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  278,  278,  564,  564,  564,  444,
+	/*  64 */   921,  722,  667,  667,  722,  611,  556,  722,
+	/*  72 */   722,  333,  389,  722,  611,  889,  722,  722,
+	/*  80 */   556,  722,  667,  556,  611,  722,  722,  944,
+	/*  88 */   722,  722,  611,  333,  278,  333,  469,  500,
+	/*  96 */   333,  444,  500,  444,  500,  444,  333,  500,
+	/* 104 */   500,  278,  278,  500,  278,  778,  500,  500,
+	/* 112 */   500,  500,  333,  389,  278,  500,  500,  722,
+	/* 120 */   500,  500,  444,  480,  200,  480,  541,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   250,  722,  333,  611,  500,  611,  556,  500,
+	/* 168 */   333,  556,  556,  611,  611,  333,  611,  611,
+	/* 176 */   333,  444,  333,  278,  333,  348,  389,  333,
+	/* 184 */   333,  389,  389,  278,  444,  333,  444,  444,
+	/* 192 */   667,  722,  722,  722,  722,  611,  667,  667,
+	/* 200 */   667,  611,  611,  611,  611,  333,  333,  722,
+	/* 208 */   722,  722,  722,  722,  722,  722,  722,  564,
+	/* 216 */   667,  722,  722,  722,  722,  722,  611,  500,
+	/* 224 */   333,  444,  444,  444,  444,  278,  444,  444,
+	/* 232 */   444,  444,  444,  444,  444,  278,  278,  600,
+	/* 240 */   500,  500,  500,  500,  500,  500,  500,  564,
+	/* 248 */   333,  500,  500,  500,  500,  500,  278,  333,
+	},
+	{	/* Times-Bold */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  333,  555,  500,  500, 1000,  833,  278,
+	/*  40 */   333,  333,  500,  570,  250,  333,  250,  278,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  333,  333,  570,  570,  570,  500,
+	/*  64 */   930,  722,  667,  722,  722,  667,  611,  778,
+	/*  72 */   778,  389,  500,  778,  667,  944,  722,  778,
+	/*  80 */   611,  778,  722,  556,  667,  722,  722, 1000,
+	/*  88 */   722,  722,  667,  333,  278,  333,  581,  500,
+	/*  96 */   333,  500,  556,  444,  556,  444,  333,  500,
+	/* 104 */   556,  278,  333,  556,  278,  833,  556,  500,
+	/* 112 */   556,  556,  444,  389,  333,  556,  500,  722,
+	/* 120 */   500,  500,  444,  394,  220,  394,  520,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   250,  722,  333,  667,  500,  667,  556,  500,
+	/* 168 */   333,  556,  556,  667,  667,  333,  667,  667,
+	/* 176 */   333,  500,  333,  278,  333,  396,  389,  333,
+	/* 184 */   333,  389,  389,  400,  444,  333,  444,  444,
+	/* 192 */   722,  722,  722,  722,  722,  667,  722,  722,
+	/* 200 */   722,  667,  667,  667,  667,  389,  389,  722,
+	/* 208 */   722,  722,  722,  778,  778,  778,  778,  570,
+	/* 216 */   722,  722,  722,  722,  722,  722,  667,  556,
+	/* 224 */   444,  500,  500,  500,  500,  278,  444,  444,
+	/* 232 */   444,  444,  444,  444,  444,  278,  278,  665,
+	/* 240 */   556,  556,  556,  500,  500,  500,  500,  570,
+	/* 248 */   444,  556,  556,  556,  556,  500,  333,  333,
+	},
+	{	/* Times-Italic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  333,  420,  500,  500,  833,  778,  214,
+	/*  40 */   333,  333,  500,  675,  250,  333,  250,  278,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  333,  333,  675,  675,  675,  500,
+	/*  64 */   920,  611,  611,  667,  722,  611,  611,  722,
+	/*  72 */   722,  333,  444,  667,  556,  833,  667,  722,
+	/*  80 */   611,  722,  611,  500,  556,  722,  611,  833,
+	/*  88 */   611,  556,  556,  389,  278,  389,  422,  500,
+	/*  96 */   333,  500,  500,  444,  500,  444,  278,  500,
+	/* 104 */   500,  278,  278,  444,  278,  722,  500,  500,
+	/* 112 */   500,  500,  389,  389,  278,  500,  444,  667,
+	/* 120 */   444,  444,  389,  400,  275,  400,  541,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   250,  611,  333,  556,  500,  556,  500,  500,
+	/* 168 */   333,  500,  500,  556,  556,  333,  556,  556,
+	/* 176 */   333,  500,  333,  278,  333,  278,  389,  333,
+	/* 184 */   333,  389,  389,  278,  389,  333,  389,  389,
+	/* 192 */   611,  611,  611,  611,  611,  556,  667,  667,
+	/* 200 */   667,  611,  611,  611,  611,  333,  333,  722,
+	/* 208 */   722,  667,  667,  722,  722,  722,  722,  675,
+	/* 216 */   611,  722,  722,  722,  722,  556,  556,  500,
+	/* 224 */   389,  500,  500,  500,  500,  278,  444,  444,
+	/* 232 */   444,  444,  444,  444,  444,  278,  278,  521,
+	/* 240 */   500,  500,  500,  500,  500,  500,  500,  675,
+	/* 248 */   389,  500,  500,  500,  500,  444,  278,  333,
+	},
+	{	/* Times-BoldItalic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  389,  555,  500,  500,  833,  778,  278,
+	/*  40 */   333,  333,  500,  570,  250,  333,  250,  278,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  333,  333,  570,  570,  570,  500,
+	/*  64 */   832,  667,  667,  667,  722,  667,  667,  722,
+	/*  72 */   778,  389,  500,  667,  611,  889,  722,  722,
+	/*  80 */   611,  722,  667,  556,  611,  722,  667,  889,
+	/*  88 */   667,  611,  611,  333,  278,  333,  570,  500,
+	/*  96 */   333,  500,  500,  444,  500,  444,  333,  500,
+	/* 104 */   556,  278,  278,  500,  278,  778,  556,  500,
+	/* 112 */   500,  500,  389,  389,  278,  556,  444,  667,
+	/* 120 */   500,  444,  389,  348,  220,  348,  570,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   250,  667,  333,  611,  500,  611,  556,  500,
+	/* 168 */   333,  556,  556,  611,  611,  333,  611,  611,
+	/* 176 */   333,  500,  333,  278,  333,  382,  389,  333,
+	/* 184 */   333,  389,  389,  345,  389,  333,  389,  389,
+	/* 192 */   667,  667,  667,  667,  667,  611,  667,  667,
+	/* 200 */   667,  667,  667,  667,  667,  389,  389,  722,
+	/* 208 */   722,  722,  722,  722,  722,  722,  722,  570,
+	/* 216 */   667,  722,  722,  722,  722,  611,  611,  500,
+	/* 224 */   389,  500,  500,  500,  500,  278,  444,  444,
+	/* 232 */   444,  444,  444,  444,  444,  278,  278,  600,
+	/* 240 */   500,  556,  556,  500,  500,  500,  500,  570,
+	/* 248 */   389,  556,  556,  556,  556,  444,  278,  333,
+	},
+	{	/* Helvetica */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   278,  278,  355,  556,  556,  889,  667,  191,
+	/*  40 */   333,  333,  389,  584,  278,  333,  278,  278,
+	/*  48 */   556,  556,  556,  556,  556,  556,  556,  556,
+	/*  56 */   556,  556,  278,  278,  584,  584,  584,  556,
+	/*  64 */  1015,  667,  667,  722,  722,  667,  611,  778,
+	/*  72 */   722,  278,  500,  667,  556,  833,  722,  778,
+	/*  80 */   667,  778,  722,  667,  611,  722,  667,  944,
+	/*  88 */   667,  667,  611,  278,  278,  278,  469,  556,
+	/*  96 */   333,  556,  556,  500,  556,  556,  278,  556,
+	/* 104 */   556,  222,  222,  500,  222,  833,  556,  556,
+	/* 112 */   556,  556,  333,  500,  278,  556,  500,  722,
+	/* 120 */   500,  500,  500,  334,  260,  334,  584,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   278,  667,  333,  556,  556,  556,  667,  556,
+	/* 168 */   333,  667,  667,  611,  611,  333,  611,  611,
+	/* 176 */   333,  556,  333,  222,  333,  292,  500,  333,
+	/* 184 */   333,  500,  500,  308,  500,  333,  500,  500,
+	/* 192 */   722,  667,  667,  667,  667,  556,  722,  722,
+	/* 200 */   722,  667,  667,  667,  667,  278,  278,  722,
+	/* 208 */   722,  722,  722,  778,  778,  778,  778,  584,
+	/* 216 */   722,  722,  722,  722,  722,  666,  611,  611,
+	/* 224 */   333,  556,  556,  556,  556,  222,  500,  500,
+	/* 232 */   500,  556,  556,  556,  556,  278,  278,  635,
+	/* 240 */   556,  556,  556,  556,  556,  556,  556,  584,
+	/* 248 */   333,  556,  556,  556,  556,  500,  278,  333,
+	},
+	{	/* Helvetica-Bold */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   278,  333,  474,  556,  556,  889,  722,  238,
+	/*  40 */   333,  333,  389,  584,  278,  333,  278,  278,
+	/*  48 */   556,  556,  556,  556,  556,  556,  556,  556,
+	/*  56 */   556,  556,  333,  333,  584,  584,  584,  611,
+	/*  64 */   975,  722,  722,  722,  722,  667,  611,  778,
+	/*  72 */   722,  278,  556,  722,  611,  833,  722,  778,
+	/*  80 */   667,  778,  722,  667,  611,  722,  667,  944,
+	/*  88 */   667,  667,  611,  333,  278,  333,  584,  556,
+	/*  96 */   333,  556,  611,  556,  611,  556,  333,  611,
+	/* 104 */   611,  278,  278,  556,  278,  889,  611,  611,
+	/* 112 */   611,  611,  389,  556,  333,  611,  556,  778,
+	/* 120 */   556,  556,  500,  389,  280,  389,  584,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   278,  722,  333,  611,  556,  611,  667,  556,
+	/* 168 */   333,  667,  667,  611,  611,  333,  611,  611,
+	/* 176 */   333,  556,  333,  278,  333,  369,  556,  333,
+	/* 184 */   333,  556,  556,  385,  500,  333,  500,  500,
+	/* 192 */   722,  722,  722,  722,  722,  611,  722,  722,
+	/* 200 */   722,  667,  667,  667,  667,  278,  278,  722,
+	/* 208 */   722,  722,  722,  778,  778,  778,  778,  584,
+	/* 216 */   722,  722,  722,  722,  722,  667,  611,  611,
+	/* 224 */   389,  556,  556,  556,  556,  278,  556,  556,
+	/* 232 */   556,  556,  556,  556,  556,  278,  278,  707,
+	/* 240 */   611,  611,  611,  611,  611,  611,  611,  584,
+	/* 248 */   389,  611,  611,  611,  611,  556,  333,  333,
+	},
+	{	/* Helvetica-Oblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   278,  278,  355,  556,  556,  889,  667,  191,
+	/*  40 */   333,  333,  389,  584,  278,  333,  278,  278,
+	/*  48 */   556,  556,  556,  556,  556,  556,  556,  556,
+	/*  56 */   556,  556,  278,  278,  584,  584,  584,  556,
+	/*  64 */  1015,  667,  667,  722,  722,  667,  611,  778,
+	/*  72 */   722,  278,  500,  667,  556,  833,  722,  778,
+	/*  80 */   667,  778,  722,  667,  611,  722,  667,  944,
+	/*  88 */   667,  667,  611,  278,  278,  278,  469,  556,
+	/*  96 */   333,  556,  556,  500,  556,  556,  278,  556,
+	/* 104 */   556,  222,  222,  500,  222,  833,  556,  556,
+	/* 112 */   556,  556,  333,  500,  278,  556,  500,  722,
+	/* 120 */   500,  500,  500,  334,  260,  334,  584,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   278,  667,  333,  556,  556,  556,  667,  556,
+	/* 168 */   333,  667,  667,  611,  611,  333,  611,  611,
+	/* 176 */   333,  556,  333,  222,  333,  307,  500,  333,
+	/* 184 */   333,  500,  500,  319,  500,  333,  500,  500,
+	/* 192 */   722,  667,  667,  667,  667,  556,  722,  722,
+	/* 200 */   722,  667,  667,  667,  667,  278,  278,  722,
+	/* 208 */   722,  722,  722,  778,  778,  778,  778,  584,
+	/* 216 */   722,  722,  722,  722,  722,  667,  611,  611,
+	/* 224 */   333,  556,  556,  556,  556,  222,  500,  500,
+	/* 232 */   500,  556,  556,  556,  556,  278,  278,  650,
+	/* 240 */   556,  556,  556,  556,  556,  556,  556,  584,
+	/* 248 */   333,  556,  556,  556,  556,  500,  278,  333,
+	},
+	{	/* Helvetica-BoldOblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   278,  333,  474,  556,  556,  889,  722,  238,
+	/*  40 */   333,  333,  389,  584,  278,  333,  278,  278,
+	/*  48 */   556,  556,  556,  556,  556,  556,  556,  556,
+	/*  56 */   556,  556,  333,  333,  584,  584,  584,  611,
+	/*  64 */   975,  722,  722,  722,  722,  667,  611,  778,
+	/*  72 */   722,  278,  556,  722,  611,  833,  722,  778,
+	/*  80 */   667,  778,  722,  667,  611,  722,  667,  944,
+	/*  88 */   667,  667,  611,  333,  278,  333,  584,  556,
+	/*  96 */   333,  556,  611,  556,  611,  556,  333,  611,
+	/* 104 */   611,  278,  278,  556,  278,  889,  611,  611,
+	/* 112 */   611,  611,  389,  556,  333,  611,  556,  778,
+	/* 120 */   556,  556,  500,  389,  280,  389,  584,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   278,  722,  333,  611,  556,  611,  667,  556,
+	/* 168 */   333,  667,  667,  611,  611,  333,  611,  611,
+	/* 176 */   333,  556,  333,  278,  333,  384,  556,  333,
+	/* 184 */   333,  556,  556,  404,  500,  333,  500,  500,
+	/* 192 */   722,  722,  722,  722,  722,  611,  722,  722,
+	/* 200 */   722,  667,  667,  667,  667,  278,  278,  722,
+	/* 208 */   722,  722,  722,  778,  778,  778,  778,  584,
+	/* 216 */   722,  722,  722,  722,  722,  667,  611,  611,
+	/* 224 */   389,  556,  556,  556,  556,  278,  556,  556,
+	/* 232 */   556,  556,  556,  556,  556,  278,  278,  722,
+	/* 240 */   611,  611,  611,  611,  611,  611,  611,  584,
+	/* 248 */   389,  611,  611,  611,  611,  556,  333,  333,
+	},
+	{	/* Palatino-Roman */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  278,  371,  500,  500,  840,  778,  208,
+	/*  40 */   333,  333,  389,  606,  250,  333,  250,  606,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  250,  250,  606,  606,  606,  444,
+	/*  64 */   747,  778,  611,  709,  774,  611,  556,  763,
+	/*  72 */   832,  337,  333,  726,  611,  946,  831,  786,
+	/*  80 */   604,  786,  668,  525,  613,  778,  722, 1000,
+	/*  88 */   667,  667,  667,  333,  606,  333,  606,  500,
+	/*  96 */   333,  500,  553,  444,  611,  479,  333,  556,
+	/* 104 */   582,  291,  234,  556,  291,  883,  582,  546,
+	/* 112 */   601,  560,  395,  424,  326,  603,  565,  834,
+	/* 120 */   516,  556,  500,  333,  606,  333,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   250,  778,  333,  611,  500,  611,  525,  500,
+	/* 168 */   333,  525,  525,  613,  667,  333,  667,  667,
+	/* 176 */   333,  500,  313,  291,  333,  375,  424,  333,
+	/* 184 */   333,  424,  424,  375,  500,  380,  500,  500,
+	/* 192 */   668,  778,  778,  778,  778,  611,  709,  709,
+	/* 200 */   709,  611,  611,  611,  611,  337,  337,  774,
+	/* 208 */   774,  831,  831,  786,  786,  786,  786,  606,
+	/* 216 */   668,  778,  778,  778,  778,  667,  613,  556,
+	/* 224 */   395,  500,  500,  500,  500,  291,  444,  444,
+	/* 232 */   444,  479,  479,  479,  479,  287,  287,  671,
+	/* 240 */   611,  582,  582,  546,  546,  546,  546,  606,
+	/* 248 */   395,  603,  603,  603,  603,  556,  326,  250,
+	},
+	{	/* Palatino-Bold */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  278,  402,  500,  500,  889,  833,  227,
+	/*  40 */   333,  333,  444,  606,  250,  333,  250,  296,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  250,  250,  606,  606,  606,  444,
+	/*  64 */   747,  778,  667,  722,  833,  611,  556,  833,
+	/*  72 */   833,  389,  389,  778,  611, 1000,  833,  833,
+	/*  80 */   611,  833,  722,  611,  667,  778,  778, 1000,
+	/*  88 */   667,  667,  667,  333,  606,  333,  606,  500,
+	/*  96 */   333,  500,  611,  444,  611,  500,  389,  556,
+	/* 104 */   611,  333,  333,  611,  333,  889,  611,  556,
+	/* 112 */   611,  611,  389,  444,  333,  611,  556,  833,
+	/* 120 */   500,  556,  500,  310,  606,  310,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   250,  778,  333,  611,  500,  611,  611,  500,
+	/* 168 */   333,  611,  611,  667,  667,  333,  667,  667,
+	/* 176 */   333,  500,  333,  333,  333,  433,  444,  333,
+	/* 184 */   333,  444,  444,  402,  500,  333,  500,  500,
+	/* 192 */   722,  778,  778,  778,  778,  611,  722,  722,
+	/* 200 */   722,  611,  611,  611,  611,  389,  389,  833,
+	/* 208 */   833,  833,  833,  833,  833,  833,  833,  606,
+	/* 216 */   722,  778,  778,  778,  778,  667,  667,  611,
+	/* 224 */   389,  500,  500,  500,  500,  333,  444,  444,
+	/* 232 */   444,  500,  500,  500,  500,  333,  333,  711,
+	/* 240 */   611,  611,  611,  556,  556,  556,  556,  606,
+	/* 248 */   389,  611,  611,  611,  611,  556,  333,  333,
+	},
+	{	/* Palatino-Italic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  333,  500,  500,  500,  889,  778,  333,
+	/*  40 */   333,  333,  389,  606,  250,  333,  250,  296,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  250,  250,  606,  606,  606,  500,
+	/*  64 */   747,  722,  611,  667,  778,  611,  556,  722,
+	/*  72 */   778,  333,  333,  667,  556,  944,  778,  778,
+	/*  80 */   611,  778,  667,  556,  611,  778,  722,  944,
+	/*  88 */   722,  667,  667,  333,  606,  333,  606,  500,
+	/*  96 */   333,  444,  463,  407,  500,  389,  278,  500,
+	/* 104 */   500,  278,  278,  444,  278,  778,  556,  444,
+	/* 112 */   500,  463,  389,  389,  333,  556,  500,  722,
+	/* 120 */   500,  500,  444,  333,  606,  333,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   250,  722,  333,  556,  500,  556,  556,  500,
+	/* 168 */   333,  556,  556,  611,  667,  333,  667,  667,
+	/* 176 */   333,  444,  333,  278,  333,  346,  389,  333,
+	/* 184 */   333,  389,  389,  361,  444,  333,  444,  444,
+	/* 192 */   667,  722,  722,  722,  722,  556,  667,  667,
+	/* 200 */   667,  611,  611,  611,  611,  333,  333,  778,
+	/* 208 */   778,  778,  778,  778,  778,  778,  778,  606,
+	/* 216 */   667,  778,  778,  778,  778,  667,  611,  500,
+	/* 224 */   389,  444,  444,  444,  444,  278,  407,  407,
+	/* 232 */   407,  389,  389,  389,  389,  278,  278,  577,
+	/* 240 */   500,  556,  556,  444,  444,  444,  444,  606,
+	/* 248 */   389,  556,  556,  556,  556,  500,  333,  333,
+	},
+	{	/* Palatino-BoldItalic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   250,  333,  500,  500,  500,  889,  833,  250,
+	/*  40 */   333,  333,  444,  606,  250,  389,  250,  315,
+	/*  48 */   500,  500,  500,  500,  500,  500,  500,  500,
+	/*  56 */   500,  500,  250,  250,  606,  606,  606,  444,
+	/*  64 */   833,  722,  667,  685,  778,  611,  556,  778,
+	/*  72 */   778,  389,  389,  722,  611,  944,  778,  833,
+	/*  80 */   667,  833,  722,  556,  611,  778,  667, 1000,
+	/*  88 */   722,  611,  667,  333,  606,  333,  606,  500,
+	/*  96 */   333,  556,  537,  444,  556,  444,  333,  500,
+	/* 104 */   556,  333,  333,  556,  333,  833,  556,  556,
+	/* 112 */   556,  537,  389,  444,  389,  556,  556,  833,
+	/* 120 */   500,  556,  500,  333,  606,  333,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   250,  722,  333,  611,  500,  611,  556,  556,
+	/* 168 */   333,  556,  556,  611,  667,  389,  667,  667,
+	/* 176 */   556,  556,  333,  333,  333,  429,  444,  333,
+	/* 184 */   333,  444,  444,  389,  500,  333,  500,  500,
+	/* 192 */   722,  722,  722,  722,  722,  611,  685,  685,
+	/* 200 */   685,  611,  611,  611,  611,  389,  389,  778,
+	/* 208 */   778,  778,  778,  833,  833,  833,  833,  606,
+	/* 216 */   722,  778,  778,  778,  778,  611,  611,  556,
+	/* 224 */   389,  556,  556,  556,  556,  333,  444,  444,
+	/* 232 */   444,  444,  444,  444,  444,  333,  333,  667,
+	/* 240 */   556,  556,  556,  556,  556,  556,  556,  606,
+	/* 248 */   389,  556,  556,  556,  556,  556,  389,  333,
+	},
+	{	/* Helvetica-Narrow */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   228,  228,  291,  456,  456,  729,  547,  157,
+	/*  40 */   273,  273,  319,  479,  228,  273,  228,  228,
+	/*  48 */   456,  456,  456,  456,  456,  456,  456,  456,
+	/*  56 */   456,  456,  228,  228,  479,  479,  479,  456,
+	/*  64 */   832,  547,  547,  592,  592,  547,  501,  638,
+	/*  72 */   592,  228,  410,  547,  456,  683,  592,  638,
+	/*  80 */   547,  638,  592,  547,  501,  592,  547,  774,
+	/*  88 */   547,  547,  501,  228,  228,  228,  385,  456,
+	/*  96 */   273,  456,  456,  410,  456,  456,  228,  456,
+	/* 104 */   456,  182,  182,  410,  182,  683,  456,  456,
+	/* 112 */   456,  456,  273,  410,  228,  456,  410,  592,
+	/* 120 */   410,  410,  410,  274,  213,  274,  479,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   228,  547,  273,  456,  456,  456,  547,  456,
+	/* 168 */   273,  547,  547,  501,  501,  273,  501,  501,
+	/* 176 */   273,  456,  273,  182,  273,  212,  410,  273,
+	/* 184 */   273,  410,  410,  248,  410,  273,  410,  410,
+	/* 192 */   592,  547,  547,  547,  547,  456,  592,  592,
+	/* 200 */   592,  547,  547,  547,  547,  228,  228,  592,
+	/* 208 */   592,  592,  592,  638,  638,  638,  638,  479,
+	/* 216 */   592,  592,  592,  592,  592,  547,  501,  501,
+	/* 224 */   273,  456,  456,  456,  456,  182,  410,  410,
+	/* 232 */   410,  456,  456,  456,  456,  228,  228,  496,
+	/* 240 */   456,  456,  456,  456,  456,  456,  456,  479,
+	/* 248 */   273,  456,  456,  456,  456,  410,  228,  273,
+	},
+	{	/* Helvetica-Narrow-Bold */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   228,  273,  389,  456,  456,  729,  592,  195,
+	/*  40 */   273,  273,  319,  479,  228,  273,  228,  228,
+	/*  48 */   456,  456,  456,  456,  456,  456,  456,  456,
+	/*  56 */   456,  456,  273,  273,  479,  479,  479,  501,
+	/*  64 */   800,  592,  592,  592,  592,  547,  501,  638,
+	/*  72 */   592,  228,  456,  592,  501,  683,  592,  638,
+	/*  80 */   547,  638,  592,  547,  501,  592,  547,  774,
+	/*  88 */   547,  547,  501,  273,  228,  273,  479,  456,
+	/*  96 */   273,  456,  501,  456,  501,  456,  273,  501,
+	/* 104 */   501,  228,  228,  456,  228,  729,  501,  501,
+	/* 112 */   501,  501,  319,  456,  273,  501,  456,  638,
+	/* 120 */   456,  456,  410,  319,  230,  319,  479,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   228,  592,  273,  501,  456,  501,  547,  456,
+	/* 168 */   273,  547,  547,  501,  501,  273,  501,  501,
+	/* 176 */   273,  456,  273,  228,  273,  280,  456,  273,
+	/* 184 */   273,  456,  456,  338,  410,  273,  410,  410,
+	/* 192 */   592,  592,  592,  592,  592,  501,  592,  592,
+	/* 200 */   592,  547,  547,  547,  547,  228,  228,  592,
+	/* 208 */   592,  592,  592,  638,  638,  638,  638,  479,
+	/* 216 */   592,  592,  592,  592,  592,  547,  501,  501,
+	/* 224 */   319,  456,  456,  456,  456,  228,  456,  456,
+	/* 232 */   456,  456,  456,  456,  456,  228,  228,  561,
+	/* 240 */   501,  501,  501,  501,  501,  501,  501,  479,
+	/* 248 */   319,  501,  501,  501,  501,  456,  273,  273,
+	},
+	{	/* Helvetica-Narrow-Oblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   228,  228,  291,  456,  456,  729,  547,  157,
+	/*  40 */   273,  273,  319,  479,  228,  273,  228,  228,
+	/*  48 */   456,  456,  456,  456,  456,  456,  456,  456,
+	/*  56 */   456,  456,  228,  228,  479,  479,  479,  456,
+	/*  64 */   832,  547,  547,  592,  592,  547,  501,  638,
+	/*  72 */   592,  228,  410,  547,  456,  683,  592,  638,
+	/*  80 */   547,  638,  592,  547,  501,  592,  547,  774,
+	/*  88 */   547,  547,  501,  228,  228,  228,  385,  456,
+	/*  96 */   273,  456,  456,  410,  456,  456,  228,  456,
+	/* 104 */   456,  182,  182,  410,  182,  683,  456,  456,
+	/* 112 */   456,  456,  273,  410,  228,  456,  410,  592,
+	/* 120 */   410,  410,  410,  274,  213,  274,  479,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   228,  547,  273,  456,  456,  456,  547,  456,
+	/* 168 */   273,  547,  547,  501,  501,  273,  501,  501,
+	/* 176 */   273,  456,  273,  182,  273,  217,  410,  273,
+	/* 184 */   273,  410,  410,  254,  410,  273,  410,  410,
+	/* 192 */   592,  547,  547,  547,  547,  456,  592,  592,
+	/* 200 */   592,  547,  547,  547,  547,  228,  228,  592,
+	/* 208 */   592,  592,  592,  638,  638,  638,  638,  479,
+	/* 216 */   592,  592,  592,  592,  592,  547,  501,  501,
+	/* 224 */   273,  456,  456,  456,  456,  182,  410,  410,
+	/* 232 */   410,  456,  456,  456,  456,  228,  228,  503,
+	/* 240 */   456,  456,  456,  456,  456,  456,  456,  479,
+	/* 248 */   273,  456,  456,  456,  456,  410,  228,  273,
+	},
+	{	/* Helvetica-Narrow-BoldOblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   228,  273,  389,  456,  456,  729,  592,  195,
+	/*  40 */   273,  273,  319,  479,  228,  273,  228,  228,
+	/*  48 */   456,  456,  456,  456,  456,  456,  456,  456,
+	/*  56 */   456,  456,  273,  273,  479,  479,  479,  501,
+	/*  64 */   800,  592,  592,  592,  592,  547,  501,  638,
+	/*  72 */   592,  228,  456,  592,  501,  683,  592,  638,
+	/*  80 */   547,  638,  592,  547,  501,  592,  547,  774,
+	/*  88 */   547,  547,  501,  273,  228,  273,  479,  456,
+	/*  96 */   273,  456,  501,  456,  501,  456,  273,  501,
+	/* 104 */   501,  228,  228,  456,  228,  729,  501,  501,
+	/* 112 */   501,  501,  319,  456,  273,  501,  456,  638,
+	/* 120 */   456,  456,  410,  319,  230,  319,  479,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   228,  592,  273,  501,  456,  501,  547,  456,
+	/* 168 */   273,  547,  547,  501,  501,  273,  501,  501,
+	/* 176 */   273,  456,  273,  228,  273,  283,  456,  273,
+	/* 184 */   273,  456,  456,  312,  410,  273,  410,  410,
+	/* 192 */   592,  592,  592,  592,  592,  501,  592,  592,
+	/* 200 */   592,  547,  547,  547,  547,  228,  228,  592,
+	/* 208 */   592,  592,  592,  638,  638,  638,  638,  479,
+	/* 216 */   592,  592,  592,  592,  592,  547,  501,  501,
+	/* 224 */   319,  456,  456,  456,  456,  228,  456,  456,
+	/* 232 */   456,  456,  456,  456,  456,  228,  228,  561,
+	/* 240 */   501,  501,  501,  501,  501,  501,  501,  479,
+	/* 248 */   319,  501,  501,  501,  501,  456,  273,  273,
+	},
+	{	/* Bookman-Light */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   320,  300,  380,  620,  620,  900,  800,  220,
+	/*  40 */   300,  300,  440,  600,  320,  400,  320,  600,
+	/*  48 */   620,  620,  620,  620,  620,  620,  620,  620,
+	/*  56 */   620,  620,  320,  320,  600,  600,  600,  540,
+	/*  64 */   820,  680,  740,  740,  800,  720,  640,  800,
+	/*  72 */   800,  340,  600,  720,  600,  920,  740,  800,
+	/*  80 */   620,  820,  720,  660,  620,  780,  700,  960,
+	/*  88 */   720,  640,  640,  300,  600,  300,  600,  500,
+	/*  96 */   340,  580,  620,  520,  620,  520,  320,  540,
+	/* 104 */   660,  300,  300,  620,  300,  940,  660,  560,
+	/* 112 */   620,  580,  440,  520,  380,  680,  520,  780,
+	/* 120 */   560,  540,  480,  280,  600,  280,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   320,  680,  460,  600,  620,  600,  660,  520,
+	/* 168 */   420,  660,  660,  620,  640,  400,  640,  640,
+	/* 176 */   320,  580,  320,  320,  340,  336,  520,  420,
+	/* 184 */   320,  520,  520,  380,  480,  380,  480,  480,
+	/* 192 */   720,  680,  680,  680,  680,  600,  740,  740,
+	/* 200 */   740,  720,  720,  720,  720,  340,  340,  800,
+	/* 208 */   800,  740,  740,  800,  800,  800,  800,  600,
+	/* 216 */   720,  780,  780,  780,  780,  640,  620,  660,
+	/* 224 */   440,  580,  580,  580,  580,  300,  520,  520,
+	/* 232 */   520,  520,  520,  520,  520,  300,  300,  620,
+	/* 240 */   620,  660,  660,  560,  560,  560,  560,  600,
+	/* 248 */   440,  680,  680,  680,  680,  540,  380,  260,
+	},
+	{	/* Bookman-Demi */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   340,  360,  420,  660,  660,  940,  800,  240,
+	/*  40 */   320,  320,  460,  600,  340,  360,  340,  600,
+	/*  48 */   660,  660,  660,  660,  660,  660,  660,  660,
+	/*  56 */   660,  660,  340,  340,  600,  600,  600,  660,
+	/*  64 */   820,  720,  720,  740,  780,  720,  680,  780,
+	/*  72 */   820,  400,  640,  800,  640,  940,  740,  800,
+	/*  80 */   660,  800,  780,  660,  700,  740,  720,  940,
+	/*  88 */   780,  700,  640,  300,  600,  300,  600,  500,
+	/*  96 */   400,  580,  600,  580,  640,  580,  380,  580,
+	/* 104 */   680,  360,  340,  660,  340, 1000,  680,  620,
+	/* 112 */   640,  620,  460,  520,  460,  660,  600,  800,
+	/* 120 */   600,  620,  560,  320,  600,  320,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   340,  720,  500,  640,  660,  640,  660,  600,
+	/* 168 */   500,  660,  660,  700,  640,  360,  640,  640,
+	/* 176 */   340,  580,  320,  340,  400,  430,  520,  500,
+	/* 184 */   360,  520,  520,  470,  560,  440,  560,  560,
+	/* 192 */   780,  720,  720,  720,  720,  640,  740,  740,
+	/* 200 */   740,  720,  720,  720,  720,  400,  400,  780,
+	/* 208 */   780,  740,  740,  800,  800,  800,  800,  600,
+	/* 216 */   780,  740,  740,  740,  740,  700,  700,  660,
+	/* 224 */   460,  580,  580,  580,  580,  340,  580,  580,
+	/* 232 */   580,  580,  580,  580,  580,  360,  360,  720,
+	/* 240 */   640,  680,  680,  620,  620,  620,  620,  600,
+	/* 248 */   460,  660,  660,  660,  660,  620,  460,  320,
+	},
+	{	/* Bookman-LightItalic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   300,  320,  360,  620,  620,  800,  820,  200,
+	/*  40 */   280,  280,  440,  600,  300,  320,  300,  600,
+	/*  48 */   620,  620,  620,  620,  620,  620,  620,  620,
+	/*  56 */   620,  620,  300,  300,  600,  600,  600,  540,
+	/*  64 */   780,  700,  720,  720,  740,  680,  620,  760,
+	/*  72 */   800,  320,  560,  720,  580,  860,  720,  760,
+	/*  80 */   600,  780,  700,  640,  600,  720,  680,  960,
+	/*  88 */   700,  660,  580,  260,  600,  260,  600,  500,
+	/*  96 */   340,  620,  600,  480,  640,  540,  340,  560,
+	/* 104 */   620,  280,  280,  600,  280,  880,  620,  540,
+	/* 112 */   600,  560,  400,  540,  340,  620,  540,  880,
+	/* 120 */   540,  600,  520,  360,  600,  380,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   300,  700,  440,  580,  620,  580,  640,  620,
+	/* 168 */   420,  640,  640,  600,  580,  320,  580,  580,
+	/* 176 */   300,  620,  260,  340,  320,  380,  540,  440,
+	/* 184 */   320,  540,  540,  340,  520,  340,  520,  520,
+	/* 192 */   700,  700,  700,  700,  700,  580,  720,  720,
+	/* 200 */   720,  680,  680,  680,  680,  320,  320,  740,
+	/* 208 */   740,  720,  720,  760,  760,  760,  760,  600,
+	/* 216 */   700,  720,  720,  720,  720,  660,  600,  620,
+	/* 224 */   400,  620,  620,  620,  620,  280,  480,  480,
+	/* 232 */   480,  540,  540,  540,  540,  280,  280,  730,
+	/* 240 */   640,  620,  620,  540,  540,  540,  540,  600,
+	/* 248 */   400,  620,  620,  620,  620,  600,  340,  260,
+	},
+	{	/* Bookman-DemiItalic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   340,  320,  380,  680,  680,  880,  980,  180,
+	/*  40 */   260,  260,  460,  600,  340,  280,  340,  360,
+	/*  48 */   680,  680,  680,  680,  680,  680,  680,  680,
+	/*  56 */   680,  680,  340,  340,  620,  600,  620,  620,
+	/*  64 */   780,  720,  720,  700,  760,  720,  660,  760,
+	/*  72 */   800,  380,  620,  780,  640,  860,  740,  760,
+	/*  80 */   640,  760,  740,  700,  700,  740,  660, 1000,
+	/*  88 */   740,  660,  680,  260,  580,  260,  620,  500,
+	/*  96 */   380,  680,  600,  560,  680,  560,  420,  620,
+	/* 104 */   700,  380,  320,  700,  380,  960,  680,  600,
+	/* 112 */   660,  620,  500,  540,  440,  680,  540,  860,
+	/* 120 */   620,  600,  560,  300,  620,  300,  620,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   340,  720,  460,  640,  680,  640,  700,  620,
+	/* 168 */   520,  700,  700,  700,  680,  280,  680,  680,
+	/* 176 */   360,  680,  320,  380,  340,  509,  540,  480,
+	/* 184 */   360,  540,  540,  520,  560,  560,  560,  560,
+	/* 192 */   740,  720,  720,  720,  720,  640,  700,  700,
+	/* 200 */   700,  720,  720,  720,  720,  380,  380,  760,
+	/* 208 */   760,  740,  740,  760,  760,  760,  760,  600,
+	/* 216 */   740,  740,  740,  740,  740,  660,  700,  660,
+	/* 224 */   500,  680,  680,  680,  680,  380,  560,  560,
+	/* 232 */   560,  560,  560,  560,  560,  380,  380,  810,
+	/* 240 */   680,  680,  680,  600,  600,  600,  600,  600,
+	/* 248 */   500,  680,  680,  680,  680,  600,  440,  380,
+	},
+	{	/* AvantGarde-Book */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   277,  295,  309,  554,  554,  775,  757,  198,
+	/*  40 */   369,  369,  425,  606,  277,  332,  277,  437,
+	/*  48 */   554,  554,  554,  554,  554,  554,  554,  554,
+	/*  56 */   554,  554,  277,  277,  606,  606,  606,  591,
+	/*  64 */   867,  740,  574,  813,  744,  536,  485,  872,
+	/*  72 */   683,  226,  482,  591,  462,  919,  740,  869,
+	/*  80 */   592,  871,  607,  498,  426,  655,  702,  960,
+	/*  88 */   609,  592,  480,  351,  605,  351,  606,  500,
+	/*  96 */   378,  683,  682,  647,  685,  650,  314,  673,
+	/* 104 */   610,  200,  203,  502,  200,  938,  610,  655,
+	/* 112 */   682,  682,  301,  388,  339,  608,  554,  831,
+	/* 120 */   480,  536,  425,  351,  672,  351,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   277,  740,  453,  517,  554,  462,  498,  615,
+	/* 168 */   369,  498,  498,  426,  480,  332,  480,  480,
+	/* 176 */   332,  683,  302,  300,  375,  245,  388,  502,
+	/* 184 */   324,  388,  388,  339,  425,  552,  425,  425,
+	/* 192 */   607,  740,  740,  740,  740,  462,  813,  813,
+	/* 200 */   813,  536,  536,  536,  536,  226,  226,  744,
+	/* 208 */   790,  740,  740,  869,  869,  869,  869,  606,
+	/* 216 */   607,  655,  655,  655,  655,  592,  426,  554,
+	/* 224 */   301,  683,  683,  683,  683,  200,  647,  647,
+	/* 232 */   647,  650,  650,  650,  650,  200,  200,  725,
+	/* 240 */   685,  610,  610,  655,  655,  655,  655,  606,
+	/* 248 */   301,  608,  608,  608,  608,  536,  339,  222,
+	},
+	{	/* AvantGarde-Demi */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   280,  280,  360,  560,  560,  860,  680,  220,
+	/*  40 */   380,  380,  440,  600,  280,  420,  280,  460,
+	/*  48 */   560,  560,  560,  560,  560,  560,  560,  560,
+	/*  56 */   560,  560,  280,  280,  600,  600,  600,  560,
+	/*  64 */   740,  740,  580,  780,  700,  520,  480,  840,
+	/*  72 */   680,  280,  480,  620,  440,  900,  740,  840,
+	/*  80 */   560,  840,  580,  520,  420,  640,  700,  900,
+	/*  88 */   680,  620,  500,  320,  640,  320,  600,  500,
+	/*  96 */   420,  660,  660,  640,  660,  640,  280,  660,
+	/* 104 */   600,  240,  260,  580,  240,  940,  600,  640,
+	/* 112 */   660,  660,  320,  440,  300,  600,  560,  800,
+	/* 120 */   560,  580,  460,  340,  600,  340,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   280,  740,  480,  480,  560,  440,  520,  560,
+	/* 168 */   500,  520,  520,  420,  500,  420,  500,  500,
+	/* 176 */   360,  660,  340,  320,  420,  330,  440,  540,
+	/* 184 */   340,  440,  440,  369,  460,  700,  460,  460,
+	/* 192 */   580,  740,  740,  740,  740,  440,  780,  780,
+	/* 200 */   780,  520,  520,  520,  520,  280,  280,  700,
+	/* 208 */   742,  740,  740,  840,  840,  840,  840,  600,
+	/* 216 */   580,  640,  640,  640,  640,  620,  420,  600,
+	/* 224 */   320,  660,  660,  660,  660,  240,  640,  640,
+	/* 232 */   640,  640,  640,  640,  640,  240,  240,  754,
+	/* 240 */   660,  600,  600,  640,  640,  640,  640,  600,
+	/* 248 */   320,  600,  600,  600,  600,  580,  300,  280,
+	},
+	{	/* AvantGarde-BookOblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   277,  295,  309,  554,  554,  775,  757,  198,
+	/*  40 */   369,  369,  425,  606,  277,  332,  277,  437,
+	/*  48 */   554,  554,  554,  554,  554,  554,  554,  554,
+	/*  56 */   554,  554,  277,  277,  606,  606,  606,  591,
+	/*  64 */   867,  740,  574,  813,  744,  536,  485,  872,
+	/*  72 */   683,  226,  482,  591,  462,  919,  740,  869,
+	/*  80 */   592,  871,  607,  498,  426,  655,  702,  960,
+	/*  88 */   609,  592,  480,  351,  605,  351,  606,  500,
+	/*  96 */   378,  683,  682,  647,  685,  650,  314,  673,
+	/* 104 */   610,  200,  203,  502,  200,  938,  610,  655,
+	/* 112 */   682,  682,  301,  388,  339,  608,  554,  831,
+	/* 120 */   480,  536,  425,  351,  672,  351,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   277,  740,  453,  517,  554,  462,  498,  615,
+	/* 168 */   369,  498,  498,  426,  480,  332,  480,  480,
+	/* 176 */   332,  683,  302,  300,  375,  231,  388,  502,
+	/* 184 */   324,  388,  388,  339,  425,  552,  425,  425,
+	/* 192 */   607,  740,  740,  740,  740,  462,  813,  813,
+	/* 200 */   813,  536,  536,  536,  536,  226,  226,  744,
+	/* 208 */   790,  740,  740,  869,  869,  869,  869,  606,
+	/* 216 */   607,  655,  655,  655,  655,  592,  426,  554,
+	/* 224 */   301,  683,  683,  683,  683,  200,  647,  647,
+	/* 232 */   647,  650,  650,  650,  650,  200,  200,  714,
+	/* 240 */   685,  610,  610,  655,  655,  655,  655,  606,
+	/* 248 */   301,  608,  608,  608,  608,  536,  339,  222,
+	},
+	{	/* AvantGarde-DemiOblique */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   280,  280,  360,  560,  560,  860,  680,  220,
+	/*  40 */   380,  380,  440,  600,  280,  420,  280,  460,
+	/*  48 */   560,  560,  560,  560,  560,  560,  560,  560,
+	/*  56 */   560,  560,  280,  280,  600,  600,  600,  560,
+	/*  64 */   740,  740,  580,  780,  700,  520,  480,  840,
+	/*  72 */   680,  280,  480,  620,  440,  900,  740,  840,
+	/*  80 */   560,  840,  580,  520,  420,  640,  700,  900,
+	/*  88 */   680,  620,  500,  320,  640,  320,  600,  500,
+	/*  96 */   420,  660,  660,  640,  660,  640,  280,  660,
+	/* 104 */   600,  240,  260,  580,  240,  940,  600,  640,
+	/* 112 */   660,  660,  320,  440,  300,  600,  560,  800,
+	/* 120 */   560,  580,  460,  340,  600,  340,  600,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   280,  740,  480,  480,  560,  440,  520,  560,
+	/* 168 */   500,  520,  520,  420,  500,  420,  500,  500,
+	/* 176 */   360,  660,  340,  320,  420,  326,  440,  540,
+	/* 184 */   340,  440,  440,  364,  460,  700,  460,  460,
+	/* 192 */   580,  740,  740,  740,  740,  440,  780,  780,
+	/* 200 */   780,  520,  520,  520,  520,  280,  280,  700,
+	/* 208 */   742,  740,  740,  840,  840,  840,  840,  600,
+	/* 216 */   580,  640,  640,  640,  640,  620,  420,  600,
+	/* 224 */   320,  660,  660,  660,  660,  240,  640,  640,
+	/* 232 */   640,  640,  640,  640,  640,  240,  240,  752,
+	/* 240 */   660,  600,  600,  640,  640,  640,  640,  600,
+	/* 248 */   320,  600,  600,  600,  600,  580,  300,  280,
+	},
+	{	/* NewCenturySchlbk-Roman */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   278,  296,  389,  556,  556,  833,  815,  204,
+	/*  40 */   333,  333,  500,  606,  278,  333,  278,  278,
+	/*  48 */   556,  556,  556,  556,  556,  556,  556,  556,
+	/*  56 */   556,  556,  278,  278,  606,  606,  606,  444,
+	/*  64 */   737,  722,  722,  722,  778,  722,  667,  778,
+	/*  72 */   833,  407,  556,  778,  667,  944,  815,  778,
+	/*  80 */   667,  778,  722,  630,  667,  815,  722,  981,
+	/*  88 */   704,  704,  611,  333,  606,  333,  606,  500,
+	/*  96 */   333,  556,  556,  444,  574,  500,  333,  537,
+	/* 104 */   611,  315,  296,  593,  315,  889,  611,  500,
+	/* 112 */   574,  556,  444,  463,  389,  611,  537,  778,
+	/* 120 */   537,  537,  481,  333,  606,  333,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   278,  722,  333,  667,  556,  667,  630,  500,
+	/* 168 */   333,  630,  630,  667,  611,  333,  611,  611,
+	/* 176 */   333,  556,  333,  315,  333,  339,  463,  333,
+	/* 184 */   333,  463,  463,  389,  481,  333,  481,  481,
+	/* 192 */   722,  722,  722,  722,  722,  667,  722,  722,
+	/* 200 */   722,  722,  722,  722,  722,  407,  407,  778,
+	/* 208 */   778,  815,  815,  778,  778,  778,  778,  606,
+	/* 216 */   722,  815,  815,  815,  815,  704,  667,  574,
+	/* 224 */   444,  556,  556,  556,  556,  315,  444,  444,
+	/* 232 */   444,  500,  500,  500,  500,  315,  315,  606,
+	/* 240 */   574,  611,  611,  500,  500,  500,  500,  606,
+	/* 248 */   444,  611,  611,  611,  611,  537,  389,  333,
+	},
+	{	/* NewCenturySchlbk-Bold */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   287,  296,  333,  574,  574,  833,  852,  241,
+	/*  40 */   389,  389,  500,  606,  278,  333,  278,  278,
+	/*  48 */   574,  574,  574,  574,  574,  574,  574,  574,
+	/*  56 */   574,  574,  278,  278,  606,  606,  606,  500,
+	/*  64 */   747,  759,  778,  778,  833,  759,  722,  833,
+	/*  72 */   870,  444,  648,  815,  722,  981,  833,  833,
+	/*  80 */   759,  833,  815,  667,  722,  833,  759,  981,
+	/*  88 */   722,  722,  667,  389,  606,  389,  606,  500,
+	/*  96 */   333,  611,  648,  556,  667,  574,  389,  611,
+	/* 104 */   685,  370,  352,  667,  352,  963,  685,  611,
+	/* 112 */   667,  648,  519,  500,  426,  685,  611,  889,
+	/* 120 */   611,  611,  537,  389,  606,  389,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   287,  759,  333,  722,  574,  722,  667,  500,
+	/* 168 */   333,  667,  667,  722,  667,  333,  667,  667,
+	/* 176 */   333,  611,  333,  352,  333,  436,  500,  333,
+	/* 184 */   333,  500,  500,  446,  537,  333,  537,  537,
+	/* 192 */   815,  759,  759,  759,  759,  722,  778,  778,
+	/* 200 */   778,  759,  759,  759,  759,  444,  444,  833,
+	/* 208 */   833,  833,  833,  833,  833,  833,  833,  606,
+	/* 216 */   815,  833,  833,  833,  833,  722,  722,  611,
+	/* 224 */   519,  611,  611,  611,  611,  352,  556,  556,
+	/* 232 */   556,  574,  574,  574,  574,  370,  370,  747,
+	/* 240 */   667,  685,  685,  611,  611,  611,  611,  606,
+	/* 248 */   519,  685,  685,  685,  685,  611,  426,  333,
+	},
+	{	/* NewCenturySchlbk-Italic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   278,  333,  400,  556,  556,  833,  852,  278,
+	/*  40 */   333,  333,  500,  606,  278,  333,  278,  606,
+	/*  48 */   556,  556,  556,  556,  556,  556,  556,  556,
+	/*  56 */   556,  556,  278,  278,  606,  606,  606,  444,
+	/*  64 */   747,  704,  722,  722,  778,  722,  667,  778,
+	/*  72 */   833,  407,  611,  741,  667,  944,  815,  778,
+	/*  80 */   667,  778,  741,  667,  685,  815,  704,  926,
+	/*  88 */   704,  685,  667,  333,  606,  333,  606,  500,
+	/*  96 */   333,  574,  556,  444,  611,  444,  333,  537,
+	/* 104 */   611,  333,  315,  556,  333,  889,  611,  500,
+	/* 112 */   574,  556,  444,  444,  352,  611,  519,  778,
+	/* 120 */   500,  500,  463,  333,  606,  333,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   278,  704,  333,  667,  556,  667,  667,  500,
+	/* 168 */   333,  667,  667,  685,  667,  333,  667,  667,
+	/* 176 */   333,  574,  333,  333,  333,  359,  444,  333,
+	/* 184 */   333,  444,  444,  368,  463,  333,  463,  463,
+	/* 192 */   741,  704,  704,  704,  704,  667,  722,  722,
+	/* 200 */   722,  722,  722,  722,  722,  407,  407,  778,
+	/* 208 */   778,  815,  815,  778,  778,  778,  778,  606,
+	/* 216 */   741,  815,  815,  815,  815,  685,  685,  556,
+	/* 224 */   444,  574,  574,  574,  574,  333,  444,  444,
+	/* 232 */   444,  444,  444,  444,  444,  333,  333,  651,
+	/* 240 */   611,  611,  611,  500,  500,  500,  500,  606,
+	/* 248 */   444,  611,  611,  611,  611,  500,  352,  333,
+	},
+	{	/* NewCenturySchlbk-BoldItalic */
+	/*   0 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*   8 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  16 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  24 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/*  32 */   287,  333,  400,  574,  574,  889,  889,  287,
+	/*  40 */   407,  407,  500,  606,  287,  333,  287,  278,
+	/*  48 */   574,  574,  574,  574,  574,  574,  574,  574,
+	/*  56 */   574,  574,  287,  287,  606,  606,  606,  481,
+	/*  64 */   747,  741,  759,  759,  833,  741,  704,  815,
+	/*  72 */   870,  444,  667,  778,  704,  944,  852,  833,
+	/*  80 */   741,  833,  796,  685,  722,  833,  741,  944,
+	/*  88 */   741,  704,  704,  407,  606,  407,  606,  500,
+	/*  96 */   333,  667,  611,  537,  667,  519,  389,  611,
+	/* 104 */   685,  389,  370,  648,  389,  944,  685,  574,
+	/* 112 */   648,  630,  519,  481,  407,  685,  556,  833,
+	/* 120 */   574,  519,  519,  407,  606,  407,  606,    0,
+	/* 128 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 136 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 144 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 152 */     0,    0,    0,    0,    0,    0,    0,    0,
+	/* 160 */   287,  741,  333,  704,  574,  704,  685,  500,
+	/* 168 */   333,  685,  685,  722,  704,  333,  704,  704,
+	/* 176 */   333,  667,  333,  389,  333,  486,  481,  333,
+	/* 184 */   333,  481,  481,  483,  519,  333,  519,  519,
+	/* 192 */   796,  741,  741,  741,  741,  704,  759,  759,
+	/* 200 */   759,  741,  741,  741,  741,  444,  444,  833,
+	/* 208 */   833,  852,  852,  833,  833,  833,  833,  606,
+	/* 216 */   796,  833,  833,  833,  833,  704,  722,  574,
+	/* 224 */   519,  667,  667,  667,  667,  389,  537,  537,
+	/* 232 */   537,  519,  519,  519,  519,  389,  389,  780,
+	/* 240 */   667,  685,  685,  574,  574,  574,  574,  606,
+	/* 248 */   519,  685,  685,  685,  685,  519,  407,  333,
+	},
+};
+#if 0 /* Until this array is needed */
+static int aiUnderlineInfo[32][2] = {
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -151, 50 },
+	{ -155, 69 },
+	{ -151, 50 },
+	{ -111, 69 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -100, 50 },
+	{ -125, 60 },
+	{ -125, 60 },
+	{ -125, 60 },
+	{ -125, 60 },
+	{ -96, 58 },
+	{ -93, 90 },
+	{ -96, 58 },
+	{ -93, 90 },
+	{ -104, 61 },
+	{ -103, 90 },
+	{ -102, 42 },
+	{ -102, 54 },
+};
+#endif /* 0 */
diff --git a/fontlist.c b/fontlist.c
new file mode 100644
index 0000000..d55efbb
--- /dev/null
+++ b/fontlist.c
@@ -0,0 +1,173 @@
+/*
+ * fontlist.c
+ * Copyright (C) 1998-2004 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Build, read and destroy a list of Word font information
+ */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include "antiword.h"
+
+
+/*
+ * Private structure to hide the way the information
+ * is stored from the rest of the program
+ */
+typedef struct font_desc_tag {
+	font_block_type tInfo;
+	struct font_desc_tag    *pNext;
+} font_mem_type;
+
+/* Variables needed to write the Font Information List */
+static font_mem_type	*pAnchor = NULL;
+static font_mem_type	*pFontLast = NULL;
+
+
+/*
+ * vDestroyFontInfoList - destroy the Font Information List
+ */
+void
+vDestroyFontInfoList(void)
+{
+	font_mem_type	*pCurr, *pNext;
+
+	DBG_MSG("vDestroyFontInfoList");
+
+	/* Free the Font Information List */
+	pCurr = pAnchor;
+	while (pCurr != NULL) {
+		pNext = pCurr->pNext;
+		pCurr = xfree(pCurr);
+		pCurr = pNext;
+	}
+	pAnchor = NULL;
+	/* Reset all control variables */
+	pFontLast = NULL;
+} /* end of vDestroyFontInfoList */
+
+/*
+ * vCorrectFontValues - correct font values to values Antiword can use
+ */
+void
+vCorrectFontValues(font_block_type *pFontBlock)
+{
+	UINT	uiRealSize;
+	USHORT	usRealStyle;
+
+	uiRealSize = pFontBlock->usFontSize;
+	usRealStyle = pFontBlock->usFontStyle;
+	if (bIsSmallCapitals(pFontBlock->usFontStyle)) {
+		/* Small capitals become normal capitals in a smaller font */
+		uiRealSize = (uiRealSize * 4 + 2) / 5;
+		usRealStyle &= ~FONT_SMALL_CAPITALS;
+		usRealStyle |= FONT_CAPITALS;
+	}
+	if (bIsSuperscript(pFontBlock->usFontStyle) ||
+	    bIsSubscript(pFontBlock->usFontStyle)) {
+		/* Superscript and subscript use a smaller fontsize */
+		uiRealSize = (uiRealSize * 2 + 1) / 3;
+	}
+
+	if (uiRealSize < MIN_FONT_SIZE) {
+		DBG_DEC(uiRealSize);
+		uiRealSize = MIN_FONT_SIZE;
+	} else if (uiRealSize > MAX_FONT_SIZE) {
+		DBG_DEC(uiRealSize);
+		uiRealSize = MAX_FONT_SIZE;
+	}
+
+	pFontBlock->usFontSize = (USHORT)uiRealSize;
+	if (pFontBlock->ucFontColor == 8) {
+		/* White text to light gray text */
+		pFontBlock->ucFontColor = 16;
+	}
+	pFontBlock->usFontStyle = usRealStyle;
+} /* end of vCorrectFontValues */
+
+/*
+ * vAdd2FontInfoList - Add an element to the Font Information List
+ */
+void
+vAdd2FontInfoList(const font_block_type *pFontBlock)
+{
+	font_mem_type	*pListMember;
+
+	fail(pFontBlock == NULL);
+
+	NO_DBG_MSG("bAdd2FontInfoList");
+
+	if (pFontBlock->ulFileOffset == FC_INVALID) {
+		/*
+		 * This offset is really past the end of the file,
+		 * so don't waste any memory by storing it.
+		 */
+		return;
+	}
+
+	NO_DBG_HEX(pFontBlock->ulFileOffset);
+	NO_DBG_DEC_C(pFontBlock->ucFontNumber != 0,
+					pFontBlock->ucFontNumber);
+	NO_DBG_DEC_C(pFontBlock->usFontSize != DEFAULT_FONT_SIZE,
+					pFontBlock->usFontSize);
+	NO_DBG_DEC_C(pFontBlock->ucFontColor != 0,
+					pFontBlock->ucFontColor);
+	NO_DBG_HEX_C(pFontBlock->usFontStyle != 0x00,
+					pFontBlock->usFontStyle);
+
+	if (pFontLast != NULL &&
+	    pFontLast->tInfo.ulFileOffset == pFontBlock->ulFileOffset) {
+		/*
+		 * If two consecutive fonts share the same
+		 * offset, remember only the last font
+		 */
+		fail(pFontLast->pNext != NULL);
+		pFontLast->tInfo = *pFontBlock;
+		return;
+	}
+
+	/* Create list member */
+	pListMember = xmalloc(sizeof(font_mem_type));
+	/* Fill the list member */
+	pListMember->tInfo = *pFontBlock;
+	pListMember->pNext = NULL;
+	/* Correct the values where needed */
+	vCorrectFontValues(&pListMember->tInfo);
+	/* Add the new member to the list */
+	if (pAnchor == NULL) {
+		pAnchor = pListMember;
+	} else {
+		fail(pFontLast == NULL);
+		pFontLast->pNext = pListMember;
+	}
+	pFontLast = pListMember;
+} /* end of vAdd2FontInfoList */
+
+/*
+ * Get the record that follows the given recored in the Font Information List
+ */
+const font_block_type *
+pGetNextFontInfoListItem(const font_block_type *pCurr)
+{
+	const font_mem_type	*pRecord;
+	size_t	tOffset;
+
+	if (pCurr == NULL) {
+		if (pAnchor == NULL) {
+			/* There are no records */
+			return NULL;
+		}
+		/* The first record is the only one without a predecessor */
+		return &pAnchor->tInfo;
+	}
+	tOffset = offsetof(font_mem_type, tInfo);
+	/* Many casts to prevent alignment warnings */
+	pRecord = (font_mem_type *)(void *)((char *)pCurr - tOffset);
+	fail(pCurr != &pRecord->tInfo);
+	if (pRecord->pNext == NULL) {
+		/* The last record has no successor */
+		return NULL;
+	}
+	return &pRecord->pNext->tInfo;
+} /* end of pGetNextFontInfoListItem */
diff --git a/fonts.c b/fonts.c
new file mode 100644
index 0000000..77fde74
--- /dev/null
+++ b/fonts.c
@@ -0,0 +1,1018 @@
+/*
+ * fonts.c
+ * Copyright (C) 1998-2004 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Functions to deal with fonts (generic)
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include "antiword.h"
+
+/* Maximum line length in the font file */
+#define FONT_LINE_LENGTH	81
+
+/* Pitch */
+#define PITCH_UNKNOWN		0
+#define PITCH_FIXED		1
+#define PITCH_VARIABLE		2
+
+/* Font Family */
+#define FAMILY_UNKNOWN		0
+#define FAMILY_ROMAN		1
+#define FAMILY_SWISS		2
+#define FAMILY_MODERN		3
+#define FAMILY_SCRIPT		4
+#define FAMILY_DECORATIVE	5
+
+/* Font Translation Table */
+static size_t		tFontTableRecords = 0;
+static font_table_type	*pFontTable = NULL;
+
+/*
+ * Find the given font in the font table
+ *
+ * returns the index into the FontTable, -1 if not found
+ */
+int
+iGetFontByNumber(UCHAR ucWordFontNumber, USHORT usFontStyle)
+{
+	int	iIndex;
+
+	for (iIndex = 0; iIndex < (int)tFontTableRecords; iIndex++) {
+		if (ucWordFontNumber == pFontTable[iIndex].ucWordFontNumber &&
+		    usFontStyle == pFontTable[iIndex].usFontStyle &&
+		    pFontTable[iIndex].szOurFontname[0] != '\0') {
+			return iIndex;
+		}
+	}
+	DBG_DEC(ucWordFontNumber);
+	DBG_HEX(usFontStyle);
+	return -1;
+} /* end of iGetFontByNumber */
+
+/*
+ * szGetOurFontname - Get our font name
+ *
+ * return our font name from the given index, NULL if not found
+ */
+const char *
+szGetOurFontname(int iIndex)
+{
+	if (iIndex < 0 || iIndex >= (int)tFontTableRecords) {
+		return NULL;
+	}
+	return pFontTable[iIndex].szOurFontname;
+} /* end of szGetOurFontname */
+
+/*
+ * Find the given font in the font table
+ *
+ * returns the Word font number, -1 if not found
+ */
+int
+iFontname2Fontnumber(const char *szOurFontname, USHORT usFontStyle)
+{
+	int	iIndex;
+
+	for (iIndex = 0; iIndex < (int)tFontTableRecords; iIndex++) {
+		if (pFontTable[iIndex].usFontStyle == usFontStyle &&
+		    STREQ(pFontTable[iIndex].szOurFontname, szOurFontname)) {
+			return (int)pFontTable[iIndex].ucWordFontNumber;
+		}
+	}
+	return -1;
+} /* end of iFontname2Fontnumber */
+
+/*
+ * szGetDefaultFont - get the default font that matches the parameters
+ */
+static const char *
+szGetDefaultFont(UCHAR ucFFN, int iEmphasis)
+{
+	UCHAR	ucPrq, ucFf;
+
+	fail(iEmphasis < 0 || iEmphasis > 3);
+
+	ucPrq = ucFFN & 0x03;
+	ucFf = (ucFFN & 0x70) >> 4;
+	NO_DBG_DEC(ucPrq);
+	NO_DBG_DEC(ucFf);
+	if (ucPrq == PITCH_FIXED) {
+		/* Set to the default monospaced font */
+		switch (iEmphasis) {
+		case 1: return FONT_MONOSPACED_BOLD;
+		case 2: return FONT_MONOSPACED_ITALIC;
+		case 3: return FONT_MONOSPACED_BOLDITALIC;
+		default: return FONT_MONOSPACED_PLAIN;
+		}
+	} else if (ucFf == FAMILY_ROMAN) {
+		/* Set to the default serif font */
+		switch (iEmphasis) {
+		case 1: return FONT_SERIF_BOLD;
+		case 2: return FONT_SERIF_ITALIC;
+		case 3: return FONT_SERIF_BOLDITALIC;
+		default: return FONT_SERIF_PLAIN;
+		}
+	} else if (ucFf == FAMILY_SWISS) {
+		/* Set to the default sans serif font */
+		switch (iEmphasis) {
+		case 1: return FONT_SANS_SERIF_BOLD;
+		case 2: return FONT_SANS_SERIF_ITALIC;
+		case 3: return FONT_SANS_SERIF_BOLDITALIC;
+		default: return FONT_SANS_SERIF_PLAIN;
+		}
+	} else {
+		/* Set to the default default font */
+		switch (iEmphasis) {
+		case 1: return FONT_SERIF_BOLD;
+		case 2: return FONT_SERIF_ITALIC;
+		case 3: return FONT_SERIF_BOLDITALIC;
+		default: return FONT_SERIF_PLAIN;
+		}
+	}
+} /* end of szGetDefaultFont */
+
+/*
+ * See if the fontname from the Word file matches the fontname from the
+ * font translation file.
+ * If iBytesPerChar is one than aucWord is in ISO-8859-x (Word 2/6/7),
+ * if iBytesPerChar is two than aucWord is in Unicode (Word 8/9/10).
+ */
+static BOOL
+bFontEqual(const UCHAR *aucWord, const char *szTable, int iBytesPerChar)
+{
+	const UCHAR	*pucTmp;
+	const char	*pcTmp;
+
+	fail(aucWord == NULL || szTable == NULL);
+	fail(iBytesPerChar != 1 && iBytesPerChar != 2);
+
+	for (pucTmp = aucWord, pcTmp = szTable;
+	     *pucTmp != 0;
+	     pucTmp += iBytesPerChar, pcTmp++) {
+		if (ulToUpper((ULONG)*pucTmp) !=
+		    ulToUpper((ULONG)(UCHAR)*pcTmp)) {
+			return FALSE;
+		}
+	}
+	return *pcTmp == '\0';
+} /* end of bFontEqual */
+
+/*
+ * vFontname2Table - add fontnames to the font table
+ */
+static void
+vFontname2Table(const UCHAR *aucFont, const UCHAR *aucAltFont,
+	int iBytesPerChar, int iEmphasis, UCHAR ucFFN,
+	const char *szWordFont, const char *szOurFont,
+	font_table_type *pFontTableRecord)
+{
+	BOOL	bMatchFound;
+
+	fail(aucFont == NULL || aucFont[0] == 0);
+	fail(aucAltFont != NULL && aucAltFont[0] == 0);
+	fail(iBytesPerChar != 1 && iBytesPerChar != 2);
+	fail(iEmphasis < 0 || iEmphasis > 3);
+	fail(szWordFont == NULL || szWordFont[0] == '\0');
+	fail(szOurFont == NULL || szOurFont[0] == '\0');
+	fail(pFontTableRecord == NULL);
+
+	bMatchFound = bFontEqual(aucFont, szWordFont, iBytesPerChar);
+
+	if (!bMatchFound && aucAltFont != NULL) {
+		bMatchFound = bFontEqual(aucAltFont, szWordFont, iBytesPerChar);
+	}
+
+	if (!bMatchFound &&
+	    pFontTableRecord->szWordFontname[0] == '\0' &&
+	    szWordFont[0] == '*' &&
+	    szWordFont[1] == '\0') {
+		/*
+		 * szWordFont contains a "*", so szOurFont will contain the
+		 * "default default" font. See if we can do better than that.
+		 */
+		szOurFont = szGetDefaultFont(ucFFN, iEmphasis);
+		bMatchFound = TRUE;
+	}
+
+	if (bMatchFound) {
+		switch (iBytesPerChar) {
+		case 1:
+			(void)strncpy(pFontTableRecord->szWordFontname,
+				(const char *)aucFont,
+				sizeof(pFontTableRecord->szWordFontname) - 1);
+			break;
+		case 2:
+			(void)unincpy(pFontTableRecord->szWordFontname,
+				aucFont,
+				sizeof(pFontTableRecord->szWordFontname) - 1);
+			break;
+		default:
+			DBG_FIXME();
+			pFontTableRecord->szWordFontname[0] = '\0';
+			break;
+		}
+		pFontTableRecord->szWordFontname[
+			sizeof(pFontTableRecord->szWordFontname) - 1] = '\0';
+		(void)strncpy(pFontTableRecord->szOurFontname, szOurFont,
+			sizeof(pFontTableRecord->szOurFontname) - 1);
+		pFontTableRecord->szOurFontname[
+			sizeof(pFontTableRecord->szOurFontname) - 1] = '\0';
+		NO_DBG_MSG(pFontTableRecord->szWordFontname);
+		NO_DBG_MSG(pFontTableRecord->szOurFontname);
+		pFontTableRecord->ucFFN = ucFFN;
+		pFontTableRecord->ucEmphasis = (UCHAR)iEmphasis;
+	}
+} /* end of vFontname2Table */
+
+/*
+ * vCreateFontTable - Create and initialize the internal font table
+ */
+static void
+vCreateFontTable(void)
+{
+	font_table_type	*pTmp;
+	int	iNbr;
+
+	if (tFontTableRecords == 0) {
+		pFontTable = xfree(pFontTable);
+		return;
+	}
+
+	/* Create the font table */
+	pFontTable = xcalloc(tFontTableRecords, sizeof(*pFontTable));
+
+	/* Initialize the font table */
+	for (iNbr = 0, pTmp = pFontTable;
+	     pTmp < pFontTable + tFontTableRecords;
+	     iNbr++, pTmp++) {
+		pTmp->ucWordFontNumber = (UCHAR)(iNbr / 4);
+		switch (iNbr % 4) {
+		case 0:
+			pTmp->usFontStyle = FONT_REGULAR;
+			break;
+		case 1:
+			pTmp->usFontStyle = FONT_BOLD;
+			break;
+		case 2:
+			pTmp->usFontStyle = FONT_ITALIC;
+			break;
+		case 3:
+			pTmp->usFontStyle = FONT_BOLD|FONT_ITALIC;
+			break;
+		default:
+			DBG_DEC(iNbr);
+			break;
+		}
+	}
+} /* end of vCreateFontTable */
+
+/*
+ * vMinimizeFontTable - make the font table as small as possible
+ */
+static void
+vMinimizeFontTable(void)
+{
+	font_block_type		tFontNext;
+	const style_block_type	*pStyle;
+	const font_block_type	*pFont;
+	font_table_type		*pTmp;
+	int	iUnUsed;
+	BOOL	bMustAddTableFont;
+
+	NO_DBG_MSG("vMinimizeFontTable");
+
+	if (tFontTableRecords == 0) {
+		pFontTable = xfree(pFontTable);
+		return;
+	}
+
+	/* See if we must add a font for our tables */
+	bMustAddTableFont = TRUE;
+
+#if 0
+	DBG_MSG("Before");
+	DBG_DEC(tFontTableRecords);
+	for (pTmp = pFontTable;
+	     pTmp < pFontTable + tFontTableRecords;
+	     pTmp++) {
+		DBG_DEC(pTmp->ucWordFontNumber);
+		DBG_HEX(pTmp->usFontStyle);
+		DBG_MSG(pTmp->szWordFontname);
+		DBG_MSG(pTmp->szOurFontname);
+	}
+#endif /* DEBUG */
+
+	/* See which fonts/styles we really need */
+
+	/* Default font/style is by definition in use */
+	pFontTable[0].ucInUse = 1;
+
+	/* Make InUse 1 for all the fonts/styles that WILL be used */
+	pFont = NULL;
+	while((pFont = pGetNextFontInfoListItem(pFont)) != NULL) {
+		pTmp = pFontTable + 4 * (int)pFont->ucFontNumber;
+		if (bIsBold(pFont->usFontStyle)) {
+			pTmp++;
+		}
+		if (bIsItalic(pFont->usFontStyle)) {
+			pTmp += 2;
+		}
+		if (pTmp >= pFontTable + tFontTableRecords) {
+			continue;
+		}
+		if (STREQ(pTmp->szOurFontname, TABLE_FONT)) {
+			/* The table font is already present */
+			bMustAddTableFont = FALSE;
+		}
+		pTmp->ucInUse = 1;
+	}
+
+	/* Make InUse 1 for all the fonts/styles that MIGHT be used */
+	pStyle = NULL;
+	while((pStyle = pGetNextStyleInfoListItem(pStyle)) != NULL) {
+		vFillFontFromStylesheet(pStyle->usIstdNext, &tFontNext);
+		vCorrectFontValues(&tFontNext);
+		pTmp = pFontTable + 4 * (int)tFontNext.ucFontNumber;
+		if (bIsBold(tFontNext.usFontStyle)) {
+			pTmp++;
+		}
+		if (bIsItalic(tFontNext.usFontStyle)) {
+			pTmp += 2;
+		}
+		if (pTmp >= pFontTable + tFontTableRecords) {
+			continue;
+		}
+		if (STREQ(pTmp->szOurFontname, TABLE_FONT)) {
+			/* The table font is already present */
+			bMustAddTableFont = FALSE;
+		}
+		pTmp->ucInUse = 1;
+	}
+
+	/* Remove the unused font entries from the font table */
+	iUnUsed = 0;
+	for (pTmp = pFontTable;
+	     pTmp < pFontTable + tFontTableRecords;
+	     pTmp++) {
+		if (pTmp->ucInUse == 0) {
+			iUnUsed++;
+			continue;
+		}
+		if (iUnUsed > 0) {
+			fail(pTmp - iUnUsed <= pFontTable);
+			*(pTmp - iUnUsed) = *pTmp;
+		}
+	}
+	fail(iUnUsed < 0);
+	fail(tFontTableRecords <= (size_t)iUnUsed);
+	tFontTableRecords -= (size_t)iUnUsed;
+
+	if (bMustAddTableFont) {
+		pTmp = pFontTable + tFontTableRecords;
+		fail(pTmp <= pFontTable);
+		pTmp->ucWordFontNumber = (pTmp - 1)->ucWordFontNumber + 1;
+		pTmp->usFontStyle = FONT_REGULAR;
+		pTmp->ucInUse = 1;
+		strcpy(pTmp->szWordFontname, "Extra Table Font");
+		strcpy(pTmp->szOurFontname, TABLE_FONT);
+		tFontTableRecords++;
+		iUnUsed--;
+	}
+	if (iUnUsed > 0) {
+		/* Resize the font table */
+		pFontTable = xrealloc(pFontTable,
+				tFontTableRecords * sizeof(*pFontTable));
+	}
+#if defined(DEBUG)
+	DBG_MSG("After");
+	DBG_DEC(tFontTableRecords);
+	for (pTmp = pFontTable;
+	     pTmp < pFontTable + tFontTableRecords;
+	     pTmp++) {
+		DBG_DEC(pTmp->ucWordFontNumber);
+		DBG_HEX(pTmp->usFontStyle);
+		DBG_MSG(pTmp->szWordFontname);
+		DBG_MSG(pTmp->szOurFontname);
+	}
+#endif /* DEBUG */
+} /* end of vMinimizeFontTable */
+
+/*
+ * bReadFontFile - read and check a line from the font translation file
+ *
+ * returns TRUE when a correct line has been read, otherwise FALSE
+ */
+static BOOL
+bReadFontFile(FILE *pFontTableFile, char *szWordFont,
+	int *piItalic, int *piBold, char *szOurFont, int *piSpecial)
+{
+	char	*pcTmp;
+	int	iFields;
+	char	szLine[FONT_LINE_LENGTH];
+
+	fail(szWordFont == NULL || szOurFont == NULL);
+	fail(piItalic == NULL || piBold == NULL || piSpecial == NULL);
+
+	while (fgets(szLine, (int)sizeof(szLine), pFontTableFile) != NULL) {
+		if (szLine[0] == '#' ||
+		    szLine[0] == '\n' ||
+		    szLine[0] == '\r') {
+			continue;
+		}
+		iFields = sscanf(szLine, "%[^,],%d,%d,%1s%[^,],%d",
+			szWordFont, piItalic, piBold,
+			&szOurFont[0], &szOurFont[1], piSpecial);
+		if (iFields != 6) {
+			pcTmp = strchr(szLine, '\r');
+			if (pcTmp != NULL) {
+				*pcTmp = '\0';
+			}
+			pcTmp = strchr(szLine, '\n');
+			if (pcTmp != NULL) {
+				*pcTmp = '\0';
+			}
+			DBG_DEC(iFields);
+			werr(0, "Syntax error in: '%s'", szLine);
+			continue;
+		}
+		if (strlen(szWordFont) >=
+				sizeof(pFontTable[0].szWordFontname)) {
+			werr(0, "Word fontname too long: '%s'", szWordFont);
+			continue;
+		}
+		if (strlen(szOurFont) >=
+				sizeof(pFontTable[0].szOurFontname)) {
+			werr(0, "Local fontname too long: '%s'", szOurFont);
+			continue;
+		}
+		/* The current line passed all the tests */
+		return TRUE;
+	}
+	return FALSE;
+} /* end of bReadFontFile */
+
+/*
+ * vCreate0FontTable - create a font table from Word for DOS
+ */
+void
+vCreate0FontTable(void)
+{
+	FILE	*pFontTableFile;
+	font_table_type	*pTmp;
+	UCHAR	*aucFont;
+	int	iBold, iItalic, iSpecial, iEmphasis, iFtc;
+	UCHAR	ucPrq, ucFf, ucFFN;
+	char	szWordFont[FONT_LINE_LENGTH], szOurFont[FONT_LINE_LENGTH];
+
+	tFontTableRecords = 0;
+	pFontTable = xfree(pFontTable);
+
+	pFontTableFile = pOpenFontTableFile();
+	if (pFontTableFile == NULL) {
+		/* No translation table file, no translation table */
+		return;
+	}
+
+	/* Get the maximum number of entries in the font table */
+	tFontTableRecords = 64;
+	tFontTableRecords *= 4;	/* Plain, Bold, Italic and Bold/italic */
+	tFontTableRecords++;	/* One extra for the table-font */
+	vCreateFontTable();
+
+	/* Read the font translation file */
+	iItalic = 0;
+	iBold = 0;
+	iSpecial = 0;
+	while (bReadFontFile(pFontTableFile, szWordFont,
+			&iItalic, &iBold, szOurFont, &iSpecial)) {
+		iEmphasis = 0;
+		if (iBold != 0) {
+			iEmphasis++;
+		}
+		if (iItalic != 0) {
+			iEmphasis += 2;
+		}
+		for (iFtc = 0, pTmp = pFontTable + iEmphasis;
+		     pTmp < pFontTable + tFontTableRecords;
+		     iFtc++, pTmp += 4) {
+			if (iFtc >= 16 && iFtc <= 55) {
+				ucPrq = PITCH_VARIABLE;
+				ucFf = FAMILY_ROMAN;
+				aucFont = (UCHAR *)"Times";
+			} else {
+				ucPrq = PITCH_FIXED;
+				ucFf = FAMILY_MODERN;
+				aucFont = (UCHAR *)"Courier";
+			}
+			ucFFN = (ucFf << 4) | ucPrq;
+			vFontname2Table(aucFont, NULL, 1, iEmphasis,
+					ucFFN, szWordFont, szOurFont, pTmp);
+		}
+	}
+	(void)fclose(pFontTableFile);
+	vMinimizeFontTable();
+} /* end of vCreate0FontTable */
+
+/*
+ * vCreate2FontTable - create a font table from WinWord 1/2
+ */
+void
+vCreate2FontTable(FILE *pFile, int iWordVersion, const UCHAR *aucHeader)
+{
+	FILE	*pFontTableFile;
+	font_table_type	*pTmp;
+	UCHAR	*aucFont;
+	UCHAR	*aucBuffer;
+	ULONG	ulBeginFontInfo;
+	size_t	tFontInfoLen;
+	int	iPos, iOff, iRecLen;
+	int	iBold, iItalic, iSpecial, iEmphasis;
+	UCHAR	ucFFN;
+	char	szWordFont[FONT_LINE_LENGTH], szOurFont[FONT_LINE_LENGTH];
+
+	fail(pFile == NULL || aucHeader == NULL);
+	fail(iWordVersion != 1 && iWordVersion != 2);
+
+	tFontTableRecords = 0;
+	pFontTable = xfree(pFontTable);
+
+	pFontTableFile = pOpenFontTableFile();
+	if (pFontTableFile == NULL) {
+		/* No translation table file, no translation table */
+		return;
+	}
+
+	ulBeginFontInfo = ulGetLong(0xb2, aucHeader); /* fcSttbfffn */
+	DBG_HEX(ulBeginFontInfo);
+	tFontInfoLen = (size_t)usGetWord(0xb6, aucHeader); /* cbSttbfffn */
+	DBG_DEC(tFontInfoLen);
+
+	if (ulBeginFontInfo > (ULONG)LONG_MAX || tFontInfoLen == 0) {
+		/* Don't ask me why this is needed */
+		DBG_HEX_C(tFontInfoLen != 0, ulBeginFontInfo);
+		(void)fclose(pFontTableFile);
+		return;
+	}
+
+	aucBuffer = xmalloc(tFontInfoLen);
+	if (!bReadBytes(aucBuffer, tFontInfoLen, ulBeginFontInfo, pFile)) {
+		aucBuffer = xfree(aucBuffer);
+		(void)fclose(pFontTableFile);
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tFontInfoLen);
+	DBG_DEC(usGetWord(0, aucBuffer));
+
+	/* Compute the maximum number of entries in the font table */
+	if (iWordVersion == 1) {
+		fail(tFontInfoLen < 2);
+		/* WinWord 1 has three implicit fonts */
+		tFontTableRecords = 3;
+		iOff = 2;
+	} else {
+		fail(tFontInfoLen < 6);
+		/* WinWord 2 and up have no implicit fonts */
+		tFontTableRecords = 0;
+		iOff = 3;
+	}
+	iPos = 2;
+	while (iPos + iOff < (int)tFontInfoLen) {
+		iRecLen = (int)ucGetByte(iPos, aucBuffer);
+		NO_DBG_DEC(iRecLen);
+		NO_DBG_MSG(aucBuffer + iPos + iOff);
+		iPos += iRecLen + 1;
+		tFontTableRecords++;
+	}
+	tFontTableRecords *= 4;	/* Plain, Bold, Italic and Bold/Italic */
+	tFontTableRecords++;	/* One extra for the table-font */
+	vCreateFontTable();
+
+	/* Add the tree implicit fonts (in four variations) */
+	if (iWordVersion == 1) {
+		fail(tFontTableRecords < 13);
+		vFontname2Table((UCHAR *)"Tms Rmn", NULL, 1, 0,
+			(UCHAR)((FAMILY_ROMAN << 4) | PITCH_VARIABLE),
+			"*", "Times-Roman", pFontTable + 0);
+		vFontname2Table((UCHAR *)"Tms Rmn", NULL, 1, 1,
+			(UCHAR)((FAMILY_ROMAN << 4) | PITCH_VARIABLE),
+			"*", "Times-Bold", pFontTable + 1);
+		vFontname2Table((UCHAR *)"Tms Rmn", NULL, 1, 2,
+			(UCHAR)((FAMILY_ROMAN << 4) | PITCH_VARIABLE),
+			"*", "Times-Italic", pFontTable + 2);
+		vFontname2Table((UCHAR *)"Tms Rmn", NULL, 1, 3,
+			(UCHAR)((FAMILY_ROMAN << 4) | PITCH_VARIABLE),
+			"*", "Times-BoldItalic", pFontTable + 3);
+		vFontname2Table((UCHAR *)"Symbol", NULL, 1, 0,
+			(UCHAR)((FAMILY_ROMAN << 4) | PITCH_VARIABLE),
+			"*", "Times-Roman", pFontTable + 4);
+		vFontname2Table((UCHAR *)"Symbol", NULL, 1, 1,
+			(UCHAR)((FAMILY_ROMAN << 4) | PITCH_VARIABLE),
+			"*", "Times-Bold", pFontTable + 5);
+		vFontname2Table((UCHAR *)"Symbol", NULL, 1, 2,
+			(UCHAR)((FAMILY_ROMAN << 4) | PITCH_VARIABLE),
+			"*", "Times-Italic", pFontTable + 6);
+		vFontname2Table((UCHAR *)"Symbol", NULL, 1, 3,
+			(UCHAR)((FAMILY_ROMAN << 4) | PITCH_VARIABLE),
+			"*", "Times-BoldItalic", pFontTable + 7);
+		vFontname2Table((UCHAR *)"Helv", NULL, 1, 0,
+			(UCHAR)((FAMILY_SWISS << 4) | PITCH_VARIABLE),
+			"*", "Helvetica", pFontTable + 8);
+		vFontname2Table((UCHAR *)"Helv", NULL, 1, 1,
+			(UCHAR)((FAMILY_SWISS << 4) | PITCH_VARIABLE),
+			"*", "Helvetica-Bold", pFontTable + 9);
+		vFontname2Table((UCHAR *)"Helv", NULL, 1, 2,
+			(UCHAR)((FAMILY_SWISS << 4) | PITCH_VARIABLE),
+			"*", "Helvetica-Oblique", pFontTable + 10);
+		vFontname2Table((UCHAR *)"Helv", NULL, 1, 3,
+			(UCHAR)((FAMILY_SWISS << 4) | PITCH_VARIABLE),
+			"*", "Helvetica-BoldOblique", pFontTable + 11);
+	}
+
+	/* Read the font translation file */
+	iItalic = 0;
+	iBold = 0;
+	iSpecial = 0;
+	while (bReadFontFile(pFontTableFile, szWordFont,
+			&iItalic, &iBold, szOurFont, &iSpecial)) {
+		iEmphasis = 0;
+		if (iBold != 0) {
+			iEmphasis++;
+		}
+		if (iItalic != 0) {
+			iEmphasis += 2;
+		}
+		pTmp = pFontTable + iEmphasis;
+		iPos = 2;
+		while (iPos + iOff < (int)tFontInfoLen) {
+			iRecLen = (int)ucGetByte(iPos, aucBuffer);
+			ucFFN = ucGetByte(iPos + 1, aucBuffer);
+			aucFont = aucBuffer + iPos + iOff;
+			vFontname2Table(aucFont, NULL, 1, iEmphasis,
+					ucFFN, szWordFont, szOurFont, pTmp);
+			pTmp += 4;
+			iPos += iRecLen + 1;
+		}
+	}
+	(void)fclose(pFontTableFile);
+	aucBuffer = xfree(aucBuffer);
+	vMinimizeFontTable();
+} /* end of vCreate2FontTable */
+
+/*
+ * vCreate6FontTable - create a font table from Word 6/7
+ */
+void
+vCreate6FontTable(FILE *pFile, ULONG ulStartBlock,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const UCHAR *aucHeader)
+{
+	FILE	*pFontTableFile;
+	font_table_type	*pTmp;
+	UCHAR	*aucFont, *aucAltFont;
+	UCHAR	*aucBuffer;
+	ULONG	ulBeginFontInfo;
+	size_t	tFontInfoLen;
+	int	iPos, iRecLen, iOffsetAltName;
+	int	iBold, iItalic, iSpecial, iEmphasis;
+	UCHAR	ucFFN;
+	char	szWordFont[FONT_LINE_LENGTH], szOurFont[FONT_LINE_LENGTH];
+
+	fail(pFile == NULL || aucHeader == NULL);
+	fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
+	fail(aulBBD == NULL);
+
+	tFontTableRecords = 0;
+	pFontTable = xfree(pFontTable);
+
+	pFontTableFile = pOpenFontTableFile();
+	if (pFontTableFile == NULL) {
+		/* No translation table file, no translation table */
+		return;
+	}
+
+	ulBeginFontInfo = ulGetLong(0xd0, aucHeader); /* fcSttbfffn */
+	DBG_HEX(ulBeginFontInfo);
+	tFontInfoLen = (size_t)ulGetLong(0xd4, aucHeader); /* lcbSttbfffn */
+	DBG_DEC(tFontInfoLen);
+	fail(tFontInfoLen < 9);
+
+	aucBuffer = xmalloc(tFontInfoLen);
+	if (!bReadBuffer(pFile, ulStartBlock,
+			aulBBD, tBBDLen, BIG_BLOCK_SIZE,
+			aucBuffer, ulBeginFontInfo, tFontInfoLen)) {
+		aucBuffer = xfree(aucBuffer);
+		(void)fclose(pFontTableFile);
+		return;
+	}
+	DBG_DEC(usGetWord(0, aucBuffer));
+
+	/* Compute the maximum number of entries in the font table */
+	tFontTableRecords = 0;
+	iPos = 2;
+	while (iPos + 6 < (int)tFontInfoLen) {
+		iRecLen = (int)ucGetByte(iPos, aucBuffer);
+		NO_DBG_DEC(iRecLen);
+		iOffsetAltName = (int)ucGetByte(iPos + 5, aucBuffer);
+		NO_DBG_MSG(aucBuffer + iPos + 6);
+		NO_DBG_MSG_C(iOffsetAltName > 0,
+				aucBuffer + iPos + 6 + iOffsetAltName);
+		iPos += iRecLen + 1;
+		tFontTableRecords++;
+	}
+	tFontTableRecords *= 4;	/* Plain, Bold, Italic and Bold/italic */
+	tFontTableRecords++;	/* One extra for the table-font */
+	vCreateFontTable();
+
+	/* Read the font translation file */
+	iItalic = 0;
+	iBold = 0;
+	iSpecial = 0;
+	while (bReadFontFile(pFontTableFile, szWordFont,
+			&iItalic, &iBold, szOurFont, &iSpecial)) {
+		iEmphasis = 0;
+		if (iBold != 0) {
+			iEmphasis++;
+		}
+		if (iItalic != 0) {
+			iEmphasis += 2;
+		}
+		pTmp = pFontTable + iEmphasis;
+		iPos = 2;
+		while (iPos + 6 < (int)tFontInfoLen) {
+			iRecLen = (int)ucGetByte(iPos, aucBuffer);
+			ucFFN = ucGetByte(iPos + 1, aucBuffer);
+			aucFont = aucBuffer + iPos + 6;
+			iOffsetAltName = (int)ucGetByte(iPos + 5, aucBuffer);
+			if (iOffsetAltName <= 0) {
+				aucAltFont = NULL;
+			} else {
+				aucAltFont = aucFont + iOffsetAltName;
+				NO_DBG_MSG(aucFont);
+				NO_DBG_MSG(aucAltFont);
+			}
+			vFontname2Table(aucFont, aucAltFont, 1, iEmphasis,
+					ucFFN, szWordFont, szOurFont, pTmp);
+			pTmp += 4;
+			iPos += iRecLen + 1;
+		}
+	}
+	(void)fclose(pFontTableFile);
+	aucBuffer = xfree(aucBuffer);
+	vMinimizeFontTable();
+} /* end of vCreate6FontTable */
+
+/*
+ * vCreate8FontTable - create a font table from Word 8/9/10
+ */
+void
+vCreate8FontTable(FILE *pFile, const pps_info_type *pPPS,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const ULONG *aulSBD, size_t tSBDLen,
+	const UCHAR *aucHeader)
+{
+	FILE	*pFontTableFile;
+	font_table_type	*pTmp;
+	const ULONG	*aulBlockDepot;
+	UCHAR	*aucFont, *aucAltFont;
+	UCHAR	*aucBuffer;
+	ULONG	ulBeginFontInfo;
+	size_t	tFontInfoLen, tBlockDepotLen, tBlockSize;
+	int	iPos, iRecLen, iOffsetAltName;
+	int	iBold, iItalic, iSpecial, iEmphasis;
+	UCHAR	ucFFN;
+	char	szWordFont[FONT_LINE_LENGTH], szOurFont[FONT_LINE_LENGTH];
+
+	fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
+	fail(aulBBD == NULL || aulSBD == NULL);
+
+	tFontTableRecords = 0;
+	pFontTable = xfree(pFontTable);
+
+	pFontTableFile = pOpenFontTableFile();
+	if (pFontTableFile == NULL) {
+		/* No translation table file, no translation table */
+		return;
+	}
+
+	ulBeginFontInfo = ulGetLong(0x112, aucHeader); /* fcSttbfffn */
+	DBG_HEX(ulBeginFontInfo);
+	tFontInfoLen = (size_t)ulGetLong(0x116, aucHeader); /* lcbSttbfffn */
+	DBG_DEC(tFontInfoLen);
+	fail(tFontInfoLen < 46);
+
+	DBG_DEC(pPPS->tTable.ulSB);
+	DBG_HEX(pPPS->tTable.ulSize);
+	if (pPPS->tTable.ulSize == 0) {
+		DBG_MSG("No fontname table");
+		(void)fclose(pFontTableFile);
+		return;
+	}
+
+	if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
+		/* Use the Small Block Depot */
+		aulBlockDepot = aulSBD;
+		tBlockDepotLen = tSBDLen;
+		tBlockSize = SMALL_BLOCK_SIZE;
+	} else {
+		/* Use the Big Block Depot */
+		aulBlockDepot = aulBBD;
+		tBlockDepotLen = tBBDLen;
+		tBlockSize = BIG_BLOCK_SIZE;
+	}
+	aucBuffer = xmalloc(tFontInfoLen);
+	if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
+			aulBlockDepot, tBlockDepotLen, tBlockSize,
+			aucBuffer, ulBeginFontInfo, tFontInfoLen)) {
+		aucBuffer = xfree(aucBuffer);
+		(void)fclose(pFontTableFile);
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tFontInfoLen);
+
+	/* Get the maximum number of entries in the font table */
+	tFontTableRecords = (size_t)usGetWord(0, aucBuffer);
+	tFontTableRecords *= 4;	/* Plain, Bold, Italic and Bold/italic */
+	tFontTableRecords++;	/* One extra for the table-font */
+	vCreateFontTable();
+
+	/* Read the font translation file */
+	iItalic = 0;
+	iBold = 0;
+	iSpecial = 0;
+	while (bReadFontFile(pFontTableFile, szWordFont,
+			&iItalic, &iBold, szOurFont, &iSpecial)) {
+		iEmphasis = 0;
+		if (iBold != 0) {
+			iEmphasis++;
+		}
+		if (iItalic != 0) {
+			iEmphasis += 2;
+		}
+		pTmp = pFontTable + iEmphasis;
+		iPos = 4;
+		while (iPos + 40 < (int)tFontInfoLen) {
+			iRecLen = (int)ucGetByte(iPos, aucBuffer);
+			ucFFN = ucGetByte(iPos + 1, aucBuffer);
+			aucFont = aucBuffer + iPos + 40;
+			iOffsetAltName = (int)unilen(aucFont);
+			if (iPos + 40 + iOffsetAltName + 4 >= iRecLen) {
+				aucAltFont = NULL;
+			} else {
+				aucAltFont = aucFont + iOffsetAltName + 2;
+				NO_DBG_UNICODE(aucFont);
+				NO_DBG_UNICODE(aucAltFont);
+			}
+			vFontname2Table(aucFont, aucAltFont, 2, iEmphasis,
+					ucFFN, szWordFont, szOurFont, pTmp);
+			pTmp += 4;
+			iPos += iRecLen + 1;
+		}
+	}
+	(void)fclose(pFontTableFile);
+	aucBuffer = xfree(aucBuffer);
+	vMinimizeFontTable();
+} /* end of vCreate8FontTable */
+
+/*
+ * Destroy the internal font table by freeing its memory
+ */
+void
+vDestroyFontTable(void)
+{
+	DBG_MSG("vDestroyFontTable");
+
+	tFontTableRecords = 0;
+	pFontTable = xfree(pFontTable);
+} /* end of vDestroyFontTable */
+
+/*
+ * pGetNextFontTableRecord
+ *
+ * returns the next record in the table or NULL if there is no next record
+ */
+const font_table_type *
+pGetNextFontTableRecord(const font_table_type *pRecordCurr)
+{
+	size_t	tIndexCurr;
+
+	if (pRecordCurr == NULL) {
+		/* No current record, so start with the first one */
+		return &pFontTable[0];
+	}
+
+	if (pRecordCurr < pFontTable ||
+	    pRecordCurr >= pFontTable + tFontTableRecords) {
+		/* Not a pointer in the array */
+		DBG_HEX(pRecordCurr);
+		DBG_HEX(pFontTable);
+		return NULL;
+	}
+
+	tIndexCurr = (size_t)(pRecordCurr - pFontTable);
+	if (tIndexCurr + 1 < tFontTableRecords) {
+		/* There is a next record, so return it */
+		return &pFontTable[tIndexCurr + 1];
+	}
+	/* There is no next record */
+	return NULL;
+} /* end of pGetNextFontTableRecord */
+
+/*
+ * tGetFontTableLength
+ *
+ * returns the number of records in the internal font table
+ */
+size_t
+tGetFontTableLength(void)
+{
+	return tFontTableRecords;
+} /* end of tGetFontTableLength */
+
+#if !defined(__riscos)
+/*
+ * vCorrect4PDF - only include PDF default fonts
+ */
+static void
+vCorrect4PDF(void)
+{
+	font_table_type	*pTmp;
+	const char	*szOurFont;
+
+	for (pTmp = pFontTable; pTmp < pFontTable + tFontTableRecords; pTmp++) {
+		if (STRCEQ(pTmp->szOurFontname, FONT_MONOSPACED_PLAIN) ||
+		    STRCEQ(pTmp->szOurFontname, FONT_MONOSPACED_BOLD) ||
+		    STRCEQ(pTmp->szOurFontname, FONT_MONOSPACED_ITALIC) ||
+		    STRCEQ(pTmp->szOurFontname, FONT_MONOSPACED_BOLDITALIC) ||
+		    STRCEQ(pTmp->szOurFontname, FONT_SERIF_PLAIN) ||
+		    STRCEQ(pTmp->szOurFontname, FONT_SERIF_BOLD) ||
+		    STRCEQ(pTmp->szOurFontname, FONT_SERIF_ITALIC) ||
+		    STRCEQ(pTmp->szOurFontname, FONT_SERIF_BOLDITALIC) ||
+		    STRCEQ(pTmp->szOurFontname, FONT_SANS_SERIF_PLAIN) ||
+		    STRCEQ(pTmp->szOurFontname, FONT_SANS_SERIF_BOLD) ||
+		    STRCEQ(pTmp->szOurFontname, FONT_SANS_SERIF_ITALIC) ||
+		    STRCEQ(pTmp->szOurFontname, FONT_SANS_SERIF_BOLDITALIC)) {
+			/* Already a default font */
+			continue;
+		}
+		szOurFont =
+			szGetDefaultFont(pTmp->ucFFN, (int)pTmp->ucEmphasis);
+		(void)strncpy(pTmp->szOurFontname, szOurFont,
+			sizeof(pTmp->szOurFontname) - 1);
+		pTmp->szOurFontname[sizeof(pTmp->szOurFontname) - 1] = '\0';
+	}
+} /* end of vCorrect4PDF */
+
+/*
+ * vCorrect4CyrPS - only include monospaced fonts
+ */
+static void
+vCorrect4CyrPS(void)
+{
+	font_table_type	*pTmp;
+	const char	*szOurFont;
+	UCHAR	ucFFN;
+
+	ucFFN = (FAMILY_UNKNOWN << 4) | PITCH_FIXED;
+	for (pTmp = pFontTable; pTmp < pFontTable + tFontTableRecords; pTmp++) {
+		szOurFont = szGetDefaultFont(ucFFN, (int)pTmp->ucEmphasis);
+		(void)strncpy(pTmp->szOurFontname, szOurFont,
+			sizeof(pTmp->szOurFontname) - 1);
+		pTmp->szOurFontname[sizeof(pTmp->szOurFontname) - 1] = '\0';
+	}
+} /* end of vCorrect4CyrPS */
+#endif /* __riscos */
+
+/*
+ * vCorrectFontTable - correct the font table in special cases
+ */
+void
+vCorrectFontTable(conversion_type eConversionType, encoding_type eEncoding)
+{
+#if !defined(__riscos)
+	if (eConversionType == conversion_pdf) {
+		vCorrect4PDF();
+	}
+	if (eConversionType == conversion_ps &&
+	    eEncoding == encoding_cyrillic) {
+		vCorrect4CyrPS();
+	}
+#endif /* __riscos */
+} /* end of vCorrectFontTable */
+
+/*
+ * lComputeSpaceWidth - compute the width of a space character
+ *
+ * Returns the space width in millipoints
+ */
+long
+lComputeSpaceWidth(drawfile_fontref tFontRef, USHORT usFontSize)
+{
+	char	szSpace[] = " ";
+
+	fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
+
+        return lComputeStringWidth(szSpace, 1, tFontRef, usFontSize);
+} /* end of lComputeSpaceWidth */
diff --git a/fonts_r.c b/fonts_r.c
new file mode 100644
index 0000000..0898d4f
--- /dev/null
+++ b/fonts_r.c
@@ -0,0 +1,251 @@
+/*
+ * fonts_r.c
+ * Copyright (C) 1999-2002 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Functions to deal with fonts (RiscOs version)
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "DeskLib:Font.h"
+#include "drawfile.h"
+#include "antiword.h"
+
+static font_handle	tFontCurr = (font_handle)-1;
+
+/*
+ * pOpenFontTableFile - open the Font translation file
+ * Copy the file to the proper place if necessary.
+ *
+ * Returns the file pointer or NULL
+ */
+FILE *
+pOpenFontTableFile(void)
+{
+	FILE	*pFileR, *pFileW;
+	char	*szFontNamesFile;
+	size_t	tSize;
+	BOOL	bFailed;
+	char	acBuffer[256];
+
+	pFileR = fopen("<AntiWord$FontNamesFile>", "r");
+	if (pFileR != NULL) {
+		/* The font table is already in the right directory */
+		return pFileR;
+	}
+
+	szFontNamesFile = getenv("AntiWord$FontNamesSave");
+	if (szFontNamesFile == NULL) {
+		werr(0, "Warning: Name of the FontNames file not found");
+		return NULL;
+	}
+	DBG_MSG(szFontNamesFile);
+
+	pFileR = fopen("<AntiWord$Dir>.Resources.Default", "r");
+	if (pFileR == NULL) {
+		werr(0, "I can't find 'Resources.Default'");
+		return NULL;
+	}
+	/* Here the default font translation table is known to exist */
+
+	if (!bMakeDirectory(szFontNamesFile)) {
+		werr(0,
+		"I can't make a directory for the FontNames file");
+		return NULL;
+	}
+	/* Here the proper directory is known to exist */
+
+	pFileW = fopen(szFontNamesFile, "w");
+	if (pFileW == NULL) {
+		(void)fclose(pFileR);
+		werr(0, "I can't create a default FontNames file");
+		return NULL;
+	}
+	/* Here the proper directory is known to be writeable */
+
+	/* Copy the default FontNames file */
+	bFailed = FALSE;
+	while (!feof(pFileR)) {
+		tSize = fread(acBuffer, 1, sizeof(acBuffer), pFileR);
+		if (ferror(pFileR)) {
+			DBG_MSG("Read error");
+			bFailed = TRUE;
+			break;
+		}
+		if (fwrite(acBuffer, 1, tSize, pFileW) != tSize) {
+			DBG_MSG("Write error");
+			bFailed = TRUE;
+			break;
+		}
+	}
+	(void)fclose(pFileW);
+	(void)fclose(pFileR);
+	if (bFailed) {
+		DBG_MSG("Copying the FontNames file failed");
+		(void)remove(szFontNamesFile);
+		return NULL;
+	}
+	return fopen(szFontNamesFile, "r");
+} /* end of pOpenFontTableFile */
+
+/*
+ * vCloseFont - close the current font, if any
+ */
+void
+vCloseFont(void)
+{
+	os_error	*e;
+
+	NO_DBG_MSG("vCloseFont");
+
+	if (tFontCurr == (font_handle)-1) {
+		return;
+	}
+	e = Font_LoseFont(tFontCurr);
+	if (e != NULL) {
+		werr(0, "Close font error %d: %s", e->errnum, e->errmess);
+	}
+	tFontCurr = (font_handle)-1;
+} /* end of vCloseFont */
+
+/*
+ * tOpenFont - make the specified font the current font
+ *
+ * Returns the font reference number for use in a draw file
+ */
+drawfile_fontref
+tOpenFont(UCHAR ucWordFontNumber, USHORT usFontStyle, USHORT usWordFontSize)
+{
+	os_error	*e;
+	const char	*szOurFontname;
+	font_handle	tFont;
+	int	iFontnumber;
+
+	NO_DBG_MSG("tOpenFont");
+	NO_DBG_DEC(ucWordFontNumber);
+	NO_DBG_HEX(usFontStyle);
+	NO_DBG_DEC(usWordFontSize);
+
+	/* Keep the relevant bits */
+	usFontStyle &= FONT_BOLD|FONT_ITALIC;
+	NO_DBG_HEX(usFontStyle);
+
+	iFontnumber = iGetFontByNumber(ucWordFontNumber, usFontStyle);
+	szOurFontname = szGetOurFontname(iFontnumber);
+	if (szOurFontname == NULL || szOurFontname[0] == '\0') {
+		tFontCurr = (font_handle)-1;
+		return (byte)0;
+	}
+	NO_DBG_MSG(szOurFontname);
+	e = Font_FindFont(&tFont, (char *)szOurFontname,
+			(int)usWordFontSize * 8, (int)usWordFontSize * 8,
+			0, 0);
+	if (e != NULL) {
+		switch (e->errnum) {
+		case 523:
+			werr(0, "%s", e->errmess);
+			break;
+		default:
+			werr(0, "Open font error %d: %s",
+				e->errnum, e->errmess);
+			break;
+		}
+		tFontCurr = (font_handle)-1;
+		return (drawfile_fontref)0;
+	}
+	tFontCurr = tFont;
+	NO_DBG_DEC(tFontCurr);
+	return (drawfile_fontref)(iFontnumber + 1);
+} /* end of tOpenFont */
+
+/*
+ * tOpenTableFont - make the table font the current font
+ *
+ * Returns the font reference number for use in a draw file
+ */
+drawfile_fontref
+tOpenTableFont(USHORT usWordFontSize)
+{
+	int	iWordFontnumber;
+
+	NO_DBG_MSG("tOpenTableFont");
+
+	iWordFontnumber = iFontname2Fontnumber(TABLE_FONT, FONT_REGULAR);
+	if (iWordFontnumber < 0 || iWordFontnumber > (int)UCHAR_MAX) {
+		DBG_DEC(iWordFontnumber);
+		tFontCurr = (font_handle)-1;
+		return (drawfile_fontref)0;
+	}
+
+	return tOpenFont((UCHAR)iWordFontnumber, FONT_REGULAR, usWordFontSize);
+} /* end of tOpenTableFont */
+
+/*
+ * lComputeStringWidth - compute the string width
+ *
+ * Returns the string width in millipoints
+ */
+long
+lComputeStringWidth(const char *szString, size_t tStringLength,
+	drawfile_fontref tFontRef, USHORT usFontSize)
+{
+	font_string	tStr;
+	os_error	*e;
+
+	fail(szString == NULL);
+	fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
+
+	if (szString[0] == '\0' || tStringLength == 0) {
+		/* Empty string */
+		return 0;
+	}
+	if (tStringLength == 1 && szString[0] == TABLE_SEPARATOR) {
+		/* Font_strwidth doesn't like control characters */
+		return 0;
+	}
+	if (tFontCurr == (font_handle)-1) {
+		/* No current font, use systemfont */
+		return lChar2MilliPoints(tStringLength);
+	}
+	tStr.s = (char *)szString;
+	tStr.x = INT_MAX;
+	tStr.y = INT_MAX;
+	tStr.split = -1;
+	tStr.term = tStringLength;
+	e = Font_StringWidth(&tStr);
+	if (e == NULL) {
+		return (long)tStr.x;
+	}
+	DBG_DEC(e->errnum);
+	DBG_MSG(e->errmess);
+	DBG_DEC(tStringLength);
+	DBG_MSG(szString);
+	werr(0, "String width error %d: %s", e->errnum, e->errmess);
+	return lChar2MilliPoints(tStringLength);
+} /* end of lComputeStringWidth */
+
+/*
+ * tCountColumns - count the number of columns in a string
+ *
+ * Returns the number of columns
+ */
+size_t
+tCountColumns(const char *szString, size_t tLength)
+{
+	fail(szString == NULL);
+
+	/* One byte, one character, one column */
+	return tLength;
+} /* end of tCountColumns */
+
+/*
+ * tGetCharacterLength - the length of the specified character in bytes
+ *
+ * Returns the length in bytes
+ */
+size_t
+tGetCharacterLength(const char *szString)
+{
+	return 1;
+} /* end of tGetCharacterLength */
diff --git a/fonts_u.c b/fonts_u.c
new file mode 100644
index 0000000..a99f7d2
--- /dev/null
+++ b/fonts_u.c
@@ -0,0 +1,305 @@
+/*
+ * fonts_u.c
+ * Copyright (C) 1999-2004 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Functions to deal with fonts (Unix version)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "antiword.h"
+#include "fontinfo.h"
+
+/* Don't use fonts, just plain text */
+static BOOL		bUsePlainText = TRUE;
+/* Which character set should be used */
+static encoding_type	eEncoding = encoding_neutral;
+
+
+/*
+ * pOpenFontTableFile - open the Font translation file
+ *
+ * Returns the file pointer or NULL
+ */
+FILE *
+pOpenFontTableFile(void)
+{
+	FILE		*pFile;
+	const char	*szHome, *szAntiword, *szGlobalFile;
+	char		szEnvironmentFile[PATH_MAX+1];
+	char		szLocalFile[PATH_MAX+1];
+
+	szEnvironmentFile[0] = '\0';
+	szLocalFile[0] = '\0';
+
+	/* Try the environment version of the fontnames file */
+	szAntiword = szGetAntiwordDirectory();
+	if (szAntiword != NULL && szAntiword[0] != '\0') {
+		if (strlen(szAntiword) +
+		    sizeof(FILE_SEPARATOR FONTNAMES_FILE) >=
+		    sizeof(szEnvironmentFile)) {
+			werr(0,
+			"The name of your ANTIWORDHOME directory is too long");
+			return NULL;
+		}
+		sprintf(szEnvironmentFile, "%s%s",
+			szAntiword,
+			FILE_SEPARATOR FONTNAMES_FILE);
+		DBG_MSG(szEnvironmentFile);
+
+		pFile = fopen(szEnvironmentFile, "r");
+		if (pFile != NULL) {
+			return pFile;
+		}
+	}
+
+	/* Try the local version of the fontnames file */
+	szHome = szGetHomeDirectory();
+	if (strlen(szHome) +
+	    sizeof(FILE_SEPARATOR ANTIWORD_DIR FILE_SEPARATOR FONTNAMES_FILE) >=
+	    sizeof(szLocalFile)) {
+		werr(0, "The name of your HOME directory is too long");
+		return NULL;
+	}
+
+	sprintf(szLocalFile, "%s%s",
+		szHome,
+		FILE_SEPARATOR ANTIWORD_DIR FILE_SEPARATOR FONTNAMES_FILE);
+	DBG_MSG(szLocalFile);
+
+	pFile = fopen(szLocalFile, "r");
+	if (pFile != NULL) {
+		return pFile;
+	}
+
+	/* Try the global version of the fontnames file */
+	szGlobalFile = GLOBAL_ANTIWORD_DIR FILE_SEPARATOR FONTNAMES_FILE;
+	DBG_MSG(szGlobalFile);
+
+	pFile = fopen(szGlobalFile, "r");
+	if (pFile != NULL) {
+		return pFile;
+	}
+
+	if (szEnvironmentFile[0] != '\0') {
+		werr(0, "I can not open your fontnames file.\n"
+			"Neither '%s' nor\n"
+			"'%s' nor\n"
+			"'%s' can be opened for reading.",
+			szEnvironmentFile, szLocalFile, szGlobalFile);
+	} else {
+		werr(0, "I can not open your fontnames file.\n"
+			"Neither '%s' nor\n"
+			"'%s' can be opened for reading.",
+			szLocalFile, szGlobalFile);
+	}
+	return NULL;
+} /* end of pOpenFontTableFile */
+
+/*
+ * vCloseFont - close the current font, if any
+ */
+void
+vCloseFont(void)
+{
+	NO_DBG_MSG("vCloseFont");
+	/* For safety: to be overwritten at the next call of tOpenfont() */
+	eEncoding = encoding_neutral;
+	bUsePlainText = TRUE;
+} /* end of vCloseFont */
+
+/*
+ * tOpenFont - make the specified font the current font
+ *
+ * Returns the font reference number
+ */
+drawfile_fontref
+tOpenFont(UCHAR ucWordFontNumber, USHORT usFontStyle, USHORT usWordFontSize)
+{
+	options_type	tOptions;
+	const char	*szOurFontname;
+	size_t	tIndex;
+	int	iFontnumber;
+
+	NO_DBG_MSG("tOpenFont");
+	NO_DBG_DEC(ucWordFontNumber);
+	NO_DBG_HEX(usFontStyle);
+	NO_DBG_DEC(usWordFontSize);
+
+	/* Keep the relevant bits */
+	usFontStyle &= FONT_BOLD|FONT_ITALIC;
+	NO_DBG_HEX(usFontStyle);
+
+	vGetOptions(&tOptions);
+	eEncoding = tOptions.eEncoding;
+	bUsePlainText = tOptions.eConversionType != conversion_draw &&
+			tOptions.eConversionType != conversion_ps &&
+			tOptions.eConversionType != conversion_pdf;
+
+	if (bUsePlainText) {
+		/* Plain text, no fonts */
+		return (drawfile_fontref)0;
+	}
+
+	iFontnumber = iGetFontByNumber(ucWordFontNumber, usFontStyle);
+	szOurFontname = szGetOurFontname(iFontnumber);
+	if (szOurFontname == NULL || szOurFontname[0] == '\0') {
+		DBG_DEC(iFontnumber);
+		return (drawfile_fontref)0;
+	}
+	NO_DBG_MSG(szOurFontname);
+
+	for (tIndex = 0; tIndex < elementsof(szFontnames); tIndex++) {
+		if (STREQ(szFontnames[tIndex], szOurFontname)) {
+			NO_DBG_DEC(tIndex);
+			return (drawfile_fontref)tIndex;
+		}
+	}
+	return (drawfile_fontref)0;
+} /* end of tOpenFont */
+
+/*
+ * tOpenTableFont - make the table font the current font
+ *
+ * Returns the font reference number
+ */
+drawfile_fontref
+tOpenTableFont(USHORT usWordFontSize)
+{
+	options_type	tOptions;
+	int	iWordFontnumber;
+
+	NO_DBG_MSG("tOpenTableFont");
+
+	vGetOptions(&tOptions);
+	eEncoding = tOptions.eEncoding;
+	bUsePlainText = tOptions.eConversionType != conversion_draw &&
+			tOptions.eConversionType != conversion_ps &&
+			tOptions.eConversionType != conversion_pdf;
+
+	if (bUsePlainText) {
+		/* Plain text, no fonts */
+		return (drawfile_fontref)0;
+	}
+
+	iWordFontnumber = iFontname2Fontnumber(TABLE_FONT, FONT_REGULAR);
+	if (iWordFontnumber < 0 || iWordFontnumber > (int)UCHAR_MAX) {
+		DBG_DEC(iWordFontnumber);
+		return (drawfile_fontref)0;
+	}
+
+	return tOpenFont((UCHAR)iWordFontnumber, FONT_REGULAR, usWordFontSize);
+} /* end of tOpenTableFont */
+
+/*
+ * szGetFontname - get the fontname
+ */
+const char *
+szGetFontname(drawfile_fontref tFontRef)
+{
+	fail((size_t)(UCHAR)tFontRef >= elementsof(szFontnames));
+	return szFontnames[(int)(UCHAR)tFontRef];
+} /* end of szGetFontname */
+
+/*
+ * lComputeStringWidth - compute the string width
+ *
+ * Note: the fontsize is specified in half-points!
+ *       the stringlength is specified in bytes, not characters!
+ *
+ * Returns the string width in millipoints
+ */
+long
+lComputeStringWidth(const char *szString, size_t tStringLength,
+	drawfile_fontref tFontRef, USHORT usFontSize)
+{
+	USHORT	*ausCharWidths;
+	UCHAR	*pucChar;
+	long	lRelWidth;
+	size_t	tIndex;
+	int	iFontRef;
+
+	fail(szString == NULL);
+	fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
+
+	if (szString[0] == '\0' || tStringLength == 0) {
+		/* Empty string */
+		return 0;
+	}
+
+	if (eEncoding == encoding_utf_8) {
+		fail(!bUsePlainText);
+		return lChar2MilliPoints(
+			utf8_strwidth(szString, tStringLength));
+	}
+
+	if (bUsePlainText) {
+		/* No current font, use "systemfont" */
+		return lChar2MilliPoints(tStringLength);
+	}
+
+	if (eEncoding == encoding_cyrillic) {
+		/* FIXME: until the character tables are available */
+		return (tStringLength * 600L * (long)usFontSize + 1) / 2;
+	}
+
+	DBG_DEC_C(eEncoding != encoding_latin_1 &&
+		eEncoding != encoding_latin_2, eEncoding);
+	fail(eEncoding != encoding_latin_1 &&
+		eEncoding != encoding_latin_2);
+
+	/* Compute the relative string width */
+	iFontRef = (int)(UCHAR)tFontRef;
+	if (eEncoding == encoding_latin_2) {
+		ausCharWidths = ausCharacterWidths2[iFontRef];
+	} else {
+		ausCharWidths = ausCharacterWidths1[iFontRef];
+	}
+	lRelWidth = 0;
+	for (tIndex = 0, pucChar = (UCHAR *)szString;
+	     tIndex < tStringLength;
+	     tIndex++, pucChar++) {
+		lRelWidth += (long)ausCharWidths[(int)*pucChar];
+	}
+
+	/* Compute the absolute string width */
+	return (lRelWidth * (long)usFontSize + 1) / 2;
+} /* end of lComputeStringWidth */
+
+/*
+ * tCountColumns - count the number of columns in a string
+ *
+ * Note: the length is specified in bytes!
+ *       A UTF-8 a character can be 0, 1 or 2 columns wide.
+ *
+ * Returns the number of columns
+ */
+size_t
+tCountColumns(const char *szString, size_t tLength)
+{
+	fail(szString == NULL);
+
+	if (eEncoding != encoding_utf_8) {
+		/* One byte, one character, one column */
+		return tLength;
+	}
+	return (size_t)utf8_strwidth(szString, tLength);
+} /* end of tCountColumns */
+
+/*
+ * tGetCharacterLength - the length of the specified character in bytes
+ *
+ * Returns the length in bytes
+ */
+size_t
+tGetCharacterLength(const char *szString)
+{
+	fail(szString == NULL);
+
+	if (eEncoding != encoding_utf_8) {
+		return 1;
+	}
+	return (size_t)utf8_chrlength(szString);
+} /* end of tGetCharacterLength */
diff --git a/hdrftrlist.c b/hdrftrlist.c
new file mode 100644
index 0000000..c164188
--- /dev/null
+++ b/hdrftrlist.c
@@ -0,0 +1,371 @@
+/*
+ * hdrftrlist.c
+ * Copyright (C) 2004,2005 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Build, read and destroy list(s) of Word Header/footer information
+ */
+
+#include <string.h>
+#include "antiword.h"
+
+
+#define HDR_EVEN_PAGES	0
+#define HDR_ODD_PAGES	1
+#define FTR_EVEN_PAGES	2
+#define FTR_ODD_PAGES	3
+#define HDR_FIRST_PAGE	4
+#define FTR_FIRST_PAGE	5
+
+/*
+ * Private structures to hide the way the information
+ * is stored from the rest of the program
+ */
+typedef struct hdrftr_local_tag {
+	hdrftr_block_type	tInfo;
+	ULONG			ulCharPosStart;
+	ULONG			ulCharPosNext;
+	BOOL			bUseful;
+	BOOL			bTextOriginal;
+} hdrftr_local_type;
+typedef struct hdrftr_mem_tag {
+	hdrftr_local_type	atElement[6];
+} hdrftr_mem_type;
+
+/* Variables needed to write the Header/footer Information List */
+static hdrftr_mem_type	*pHdrFtrList = NULL;
+static size_t		tHdrFtrLen = 0;
+
+
+/*
+ * vDestroyHdrFtrInfoList - destroy the Header/footer Information List
+ */
+void
+vDestroyHdrFtrInfoList(void)
+{
+	hdrftr_mem_type *pRecord;
+	output_type	*pCurr, *pNext;
+	size_t		tHdrFtr, tIndex;
+
+	DBG_MSG("vDestroyHdrFtrInfoList");
+
+	/* Free the Header/footer Information List */
+	for (tHdrFtr = 0; tHdrFtr < tHdrFtrLen; tHdrFtr++) {
+		pRecord = pHdrFtrList + tHdrFtr;
+		for (tIndex = 0;
+		     tIndex < elementsof(pRecord->atElement);
+		     tIndex++) {
+			if (!pRecord->atElement[tIndex].bTextOriginal) {
+				continue;
+			}
+			pCurr = pRecord->atElement[tIndex].tInfo.pText;
+			while (pCurr != NULL) {
+				pCurr->szStorage = xfree(pCurr->szStorage);
+				pNext = pCurr->pNext;
+				pCurr = xfree(pCurr);
+				pCurr = pNext;
+			}
+		}
+	}
+	pHdrFtrList = xfree(pHdrFtrList);
+	/* Reset all control variables */
+	tHdrFtrLen = 0;
+} /* end of vDestroyHdrFtrInfoList */
+
+/*
+ * vCreat8HdrFtrInfoList - Create the Header/footer Information List
+ */
+void
+vCreat8HdrFtrInfoList(const ULONG *aulCharPos, size_t tLength)
+{
+	hdrftr_mem_type	*pListMember;
+	size_t	tHdrFtr, tIndex, tMainIndex;
+
+	fail(aulCharPos == NULL);
+
+	DBG_DEC(tLength);
+	if (tLength <= 1) {
+		return;
+	}
+	tHdrFtrLen = tLength / 12;
+	if (tLength % 12 != 0 && tLength % 12 != 1) {
+		tHdrFtrLen++;
+	}
+	DBG_DEC(tHdrFtrLen);
+
+	pHdrFtrList = xcalloc(tHdrFtrLen, sizeof(hdrftr_mem_type));
+
+	for (tHdrFtr = 0; tHdrFtr < tHdrFtrLen; tHdrFtr++) {
+		pListMember = pHdrFtrList + tHdrFtr;
+		for (tIndex = 0, tMainIndex = tHdrFtr * 12;
+		     tIndex < 6 && tMainIndex < tLength;
+		     tIndex++, tMainIndex++) {
+			pListMember->atElement[tIndex].tInfo.pText = NULL;
+			pListMember->atElement[tIndex].ulCharPosStart =
+						aulCharPos[tMainIndex];
+			if (tMainIndex + 1 < tLength) {
+				pListMember->atElement[tIndex].ulCharPosNext =
+					aulCharPos[tMainIndex + 1];
+			} else {
+				pListMember->atElement[tIndex].ulCharPosNext =
+					aulCharPos[tMainIndex];
+			}
+		}
+	}
+} /* end of vCreat8HdrFtrInfoList */
+
+/*
+ * vCreat6HdrFtrInfoList - Create the Header/footer Information List
+ */
+void
+vCreat6HdrFtrInfoList(const ULONG *aulCharPos, size_t tLength)
+{
+	static const size_t	atIndex[] =
+		{ SIZE_T_MAX, SIZE_T_MAX, FTR_FIRST_PAGE, HDR_FIRST_PAGE,
+		  FTR_ODD_PAGES, FTR_EVEN_PAGES, HDR_ODD_PAGES, HDR_EVEN_PAGES,
+		};
+	hdrftr_mem_type	*pListMember;
+	size_t	tHdrFtr, tTmp, tIndex, tMainIndex, tBit;
+	UCHAR	ucDopSpecification, ucSepSpecification;
+
+	fail(aulCharPos == NULL);
+
+	DBG_DEC(tLength);
+	if (tLength <= 1) {
+		return;
+	}
+	tHdrFtrLen = tGetNumberOfSections();
+	if (tHdrFtrLen == 0) {
+		tHdrFtrLen = 1;
+	}
+	DBG_DEC(tHdrFtrLen);
+
+	pHdrFtrList = xcalloc(tHdrFtrLen, sizeof(hdrftr_mem_type));
+
+	/* Get the start index in aulCharPos */
+	ucDopSpecification = ucGetDopHdrFtrSpecification();
+	DBG_HEX(ucDopSpecification & 0xe0);
+	tMainIndex = 0;
+	for (tBit = 7; tBit >= 5; tBit--) {
+		if ((ucDopSpecification & BIT(tBit)) != 0) {
+			tMainIndex++;
+		}
+	}
+	DBG_DEC(tMainIndex);
+
+	for (tHdrFtr = 0; tHdrFtr < tHdrFtrLen; tHdrFtr++) {
+		ucSepSpecification = ucGetSepHdrFtrSpecification(tHdrFtr);
+		DBG_HEX(ucSepSpecification & 0xfc);
+		pListMember = pHdrFtrList + tHdrFtr;
+		for (tTmp = 0;
+		     tTmp < elementsof(pListMember->atElement);
+		     tTmp++) {
+			pListMember->atElement[tTmp].tInfo.pText = NULL;
+		}
+		for (tBit = 7; tBit >= 2; tBit--) {
+			if (tMainIndex >= tLength) {
+				break;
+			}
+			if ((ucSepSpecification & BIT(tBit)) == 0) {
+				continue;
+			}
+			tIndex = atIndex[tBit];
+			fail(tIndex >= 6);
+			pListMember->atElement[tIndex].ulCharPosStart =
+				aulCharPos[tMainIndex];
+			if (tMainIndex + 1 < tLength) {
+				pListMember->atElement[tIndex].ulCharPosNext =
+					aulCharPos[tMainIndex + 1];
+			} else {
+				pListMember->atElement[tIndex].ulCharPosNext =
+					aulCharPos[tMainIndex];
+			}
+			tMainIndex++;
+		}
+	}
+} /* end of vCreat6HdrFtrInfoList */
+
+/*
+ * vCreat2HdrFtrInfoList - Create the Header/footer Information List
+ */
+void
+vCreat2HdrFtrInfoList(const ULONG *aulCharPos, size_t tLength)
+{
+	vCreat6HdrFtrInfoList(aulCharPos, tLength);
+} /* end of vCreat2HdrFtrInfoList */
+
+/*
+ * pGetHdrFtrInfo - get the Header/footer information
+ */
+const hdrftr_block_type *
+pGetHdrFtrInfo(int iSectionIndex,
+	BOOL bWantHeader, BOOL bOddPage, BOOL bFirstInSection)
+{
+	hdrftr_mem_type	*pCurr;
+
+	fail(iSectionIndex < 0);
+	fail(pHdrFtrList == NULL && tHdrFtrLen != 0);
+
+	if (pHdrFtrList == NULL || tHdrFtrLen == 0) {
+		/* No information */
+		return NULL;
+	}
+
+	if (iSectionIndex < 0) {
+		iSectionIndex = 0;
+	} else if (iSectionIndex >= (int)tHdrFtrLen) {
+		iSectionIndex = (int)(tHdrFtrLen - 1);
+	}
+
+	pCurr = pHdrFtrList + iSectionIndex;
+
+	if (bFirstInSection) {
+		if (bWantHeader) {
+			return &pCurr->atElement[HDR_FIRST_PAGE].tInfo;
+		} else {
+			return &pCurr->atElement[FTR_FIRST_PAGE].tInfo;
+		}
+	} else {
+		if (bWantHeader) {
+			if (bOddPage) {
+				return &pCurr->atElement[HDR_ODD_PAGES].tInfo;
+			} else {
+				return &pCurr->atElement[HDR_EVEN_PAGES].tInfo;
+			}
+		} else {
+			if (bOddPage) {
+				return &pCurr->atElement[FTR_ODD_PAGES].tInfo;
+			} else {
+				return &pCurr->atElement[FTR_EVEN_PAGES].tInfo;
+			}
+		}
+	}
+} /* end of pGetHdrFtrInfo */
+
+/*
+ * lComputeHdrFtrHeight - compute the height of a header or footer
+ *
+ * Returns the height in DrawUnits
+ */
+static long
+lComputeHdrFtrHeight(const output_type *pAnchor)
+{
+	const output_type *pCurr;
+	long	lTotal;
+	USHORT	usFontSizeMax;
+
+	lTotal = 0;
+	usFontSizeMax = 0;
+	for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
+		if (pCurr->tNextFree == 1) {
+			if (pCurr->szStorage[0] == PAR_END) {
+				/* End of a paragraph */
+				lTotal += lComputeLeading(usFontSizeMax);
+				lTotal += lMilliPoints2DrawUnits(
+						(long)pCurr->usFontSize * 200);
+				usFontSizeMax = 0;
+				continue;
+			}
+			if (pCurr->szStorage[0] == HARD_RETURN) {
+				/* End of a line */
+				lTotal += lComputeLeading(usFontSizeMax);
+				usFontSizeMax = 0;
+				continue;
+			}
+		}
+		if (pCurr->usFontSize > usFontSizeMax) {
+			usFontSizeMax = pCurr->usFontSize;
+		}
+	}
+	if (usFontSizeMax != 0) {
+		/* Height of the last paragraph */
+		lTotal += lComputeLeading(usFontSizeMax);
+	}
+	return lTotal;
+} /* end of lComputeHdrFtrHeight */
+
+/*
+ * vPrepareHdrFtrText - prepare the header/footer text
+ */
+void
+vPrepareHdrFtrText(FILE *pFile)
+{
+	hdrftr_mem_type		*pCurr, *pPrev;
+	hdrftr_local_type	*pTmp;
+	output_type		*pText;
+	size_t		tHdrFtr, tIndex;
+
+	fail(pFile == NULL);
+	fail(pHdrFtrList == NULL && tHdrFtrLen != 0);
+
+	if (pHdrFtrList == NULL || tHdrFtrLen == 0) {
+		/* No information */
+		return;
+	}
+
+	/* Fill text, text height and useful-ness */
+	for (tHdrFtr = 0; tHdrFtr < tHdrFtrLen; tHdrFtr++) {
+		pCurr = pHdrFtrList + tHdrFtr;
+		for (tIndex = 0;
+		     tIndex < elementsof(pHdrFtrList->atElement);
+		     tIndex++) {
+			pTmp = &pCurr->atElement[tIndex];
+			pTmp->bUseful =
+				pTmp->ulCharPosStart != pTmp->ulCharPosNext;
+			if (pTmp->bUseful) {
+				pText = pHdrFtrDecryptor(pFile,
+						pTmp->ulCharPosStart,
+						pTmp->ulCharPosNext);
+				pTmp->tInfo.pText = pText;
+				pTmp->tInfo.lHeight =
+						lComputeHdrFtrHeight(pText);
+				pTmp->bTextOriginal = pText != NULL;
+			} else {
+				pTmp->tInfo.pText = NULL;
+				pTmp->tInfo.lHeight = 0;
+				pTmp->bTextOriginal = FALSE;
+			}
+		}
+	}
+
+	/* Replace not-useful records by using inheritance */
+	if (pHdrFtrList->atElement[HDR_FIRST_PAGE].bUseful) {
+		pTmp = &pHdrFtrList->atElement[HDR_ODD_PAGES];
+		if (!pTmp->bUseful) {
+			*pTmp = pHdrFtrList->atElement[HDR_FIRST_PAGE];
+			pTmp->bTextOriginal = FALSE;
+		}
+		pTmp = &pHdrFtrList->atElement[HDR_EVEN_PAGES];
+		if (!pTmp->bUseful) {
+			*pTmp = pHdrFtrList->atElement[HDR_FIRST_PAGE];
+			pTmp->bTextOriginal = FALSE;
+		}
+	}
+	if (pHdrFtrList->atElement[FTR_FIRST_PAGE].bUseful) {
+		pTmp = &pHdrFtrList->atElement[FTR_ODD_PAGES];
+		if (!pTmp->bUseful) {
+			*pTmp = pHdrFtrList->atElement[FTR_FIRST_PAGE];
+			pTmp->bTextOriginal = FALSE;
+		}
+		pTmp = &pHdrFtrList->atElement[FTR_EVEN_PAGES];
+		if (!pTmp->bUseful) {
+			*pTmp = pHdrFtrList->atElement[FTR_FIRST_PAGE];
+			pTmp->bTextOriginal = FALSE;
+		}
+	}
+	for (tHdrFtr = 1, pCurr = &pHdrFtrList[1];
+	     tHdrFtr < tHdrFtrLen;
+	     tHdrFtr++, pCurr++) {
+		pPrev = pCurr - 1;
+		for (tIndex = 0;
+		     tIndex < elementsof(pHdrFtrList->atElement);
+		     tIndex++) {
+			if (!pCurr->atElement[tIndex].bUseful &&
+			    pPrev->atElement[tIndex].bUseful) {
+				pCurr->atElement[tIndex] =
+						pPrev->atElement[tIndex];
+				pCurr->atElement[tIndex].bTextOriginal = FALSE;
+			}
+		}
+	}
+} /* end of vPrepareHdrFtrText */
diff --git a/icons.c b/icons.c
new file mode 100644
index 0000000..dd88c00
--- /dev/null
+++ b/icons.c
@@ -0,0 +1,96 @@
+/*
+ * icons.c
+ * Copyright (C) 1998-2001 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Update window icons
+ */
+
+#include <string.h>
+#include "DeskLib:Error.h"
+#include "DeskLib:WimpSWIs.h"
+#include "antiword.h"
+
+void
+vUpdateIcon(window_handle tWindow, icon_block *pIcon)
+{
+	window_redrawblock	tRedraw;
+	BOOL		bMore;
+
+	tRedraw.window = tWindow;
+	tRedraw.rect = pIcon->workarearect;
+	Error_CheckFatal(Wimp_UpdateWindow(&tRedraw, &bMore));
+	while (bMore) {
+		Error_CheckFatal(Wimp_PlotIcon(pIcon));
+		Error_CheckFatal(Wimp_GetRectangle(&tRedraw, &bMore));
+	}
+} /* end of vUpdateIcon */
+
+void
+vUpdateRadioButton(window_handle tWindow, icon_handle tIconNumber,
+	BOOL bSelected)
+{
+	icon_block	tIcon;
+
+	Error_CheckFatal(Wimp_GetIconState(tWindow, tIconNumber, &tIcon));
+	DBG_DEC(tIconNumber);
+	DBG_HEX(tIcon.flags.data.selected);
+	if (bSelected == (tIcon.flags.data.selected == 1)) {
+		/* No update needed */
+		return;
+	}
+	Error_CheckFatal(Wimp_SetIconState(tWindow, tIconNumber,
+			bSelected ? 0x00200000 : 0, 0x00200000));
+	vUpdateIcon(tWindow, &tIcon);
+} /* end of vUpdateRadioButton */
+
+/*
+ * vUpdateWriteable - update a writeable icon with a string
+ */
+void
+vUpdateWriteable(window_handle tWindow, icon_handle tIconNumber,
+	const char *szString)
+{
+	icon_block	tIcon;
+	caret_block	tCaret;
+	int		iLen;
+
+	fail(szString == NULL);
+
+	NO_DBG_DEC(tIconNumber);
+	NO_DBG_MSG(szString);
+
+	Error_CheckFatal(Wimp_GetIconState(tWindow, tIconNumber, &tIcon));
+	NO_DBG_HEX(tIcon.flags);
+	if (!tIcon.flags.data.text || !tIcon.flags.data.indirected) {
+		werr(1, "Icon %d must be indirected text", (int)tIconNumber);
+		return;
+	}
+	strncpy(tIcon.data.indirecttext.buffer,
+		szString,
+		tIcon.data.indirecttext.bufflen - 1);
+	/* Ensure the caret is behind the last character of the text */
+	Error_CheckFatal(Wimp_GetCaretPosition(&tCaret));
+	if (tCaret.window == tWindow && tCaret.icon == tIconNumber) {
+		iLen = strlen(tIcon.data.indirecttext.buffer);
+		if (tCaret.index != iLen) {
+			tCaret.index = iLen;
+			Error_CheckFatal(Wimp_SetCaretPosition(&tCaret));
+		}
+	}
+	Error_CheckFatal(Wimp_SetIconState(tWindow, tIconNumber, 0, 0));
+	vUpdateIcon(tWindow, &tIcon);
+} /* end of vUpdateWriteable */
+
+/*
+ * vUpdateWriteableNumber - update a writeable icon with a number
+ */
+void
+vUpdateWriteableNumber(window_handle tWindow, icon_handle tIconNumber,
+	int iNumber)
+{
+	char	szTmp[1+3*sizeof(int)+1];
+
+	(void)sprintf(szTmp, "%d", iNumber);
+	vUpdateWriteable(tWindow, tIconNumber, szTmp);
+} /* end of vUpdateWriteableNumber */
diff --git a/imgexam.c b/imgexam.c
new file mode 100644
index 0000000..2b8384a
--- /dev/null
+++ b/imgexam.c
@@ -0,0 +1,1044 @@
+/*
+ * imgexam.c
+ * Copyright (C) 2000-2004 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Functions to examine image headers
+ *
+ *================================================================
+ * Part of this software is based on:
+ * jpeg2ps - convert JPEG compressed images to PostScript Level 2
+ * Copyright (C) 1994-99 Thomas Merz (tm@muc.de)
+ *================================================================
+ * The credit should go to him, but all the bugs are mine.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include "antiword.h"
+
+/* BMP compression types */
+#define BI_RGB		0
+#define BI_RLE8		1
+#define BI_RLE4		2
+
+/* PNG colortype bits */
+#define PNG_CB_PALETTE		0x01
+#define PNG_CB_COLOR		0x02
+#define PNG_CB_ALPHA		0x04
+
+/* Instance signature */
+#define MSOBI_WMF	0x0216
+#define MSOBI_EMF	0x03d4
+#define MSOBI_PICT	0x0542
+#define MSOBI_PNG	0x06e0
+#define MSOBI_JPEG	0x046a
+#define MSOBI_DIB	0x07a8
+
+/* The following enum is stolen from the IJG JPEG library */
+typedef enum {		/* JPEG marker codes			*/
+	M_SOF0	= 0xc0,	/* baseline DCT				*/
+	M_SOF1	= 0xc1,	/* extended sequential DCT		*/
+	M_SOF2	= 0xc2,	/* progressive DCT			*/
+	M_SOF3	= 0xc3,	/* lossless (sequential)		*/
+
+	M_SOF5	= 0xc5,	/* differential sequential DCT		*/
+	M_SOF6	= 0xc6,	/* differential progressive DCT		*/
+	M_SOF7	= 0xc7,	/* differential lossless		*/
+
+	M_JPG	= 0xc8,	/* JPEG extensions			*/
+	M_SOF9	= 0xc9,	/* extended sequential DCT		*/
+	M_SOF10	= 0xca,	/* progressive DCT			*/
+	M_SOF11	= 0xcb,	/* lossless (sequential)		*/
+
+	M_SOF13	= 0xcd,	/* differential sequential DCT		*/
+	M_SOF14	= 0xce,	/* differential progressive DCT		*/
+	M_SOF15	= 0xcf,	/* differential lossless		*/
+
+	M_DHT	= 0xc4,	/* define Huffman tables		*/
+
+	M_DAC	= 0xcc,	/* define arithmetic conditioning table	*/
+
+	M_RST0	= 0xd0,	/* restart				*/
+	M_RST1	= 0xd1,	/* restart				*/
+	M_RST2	= 0xd2,	/* restart				*/
+	M_RST3	= 0xd3,	/* restart				*/
+	M_RST4	= 0xd4,	/* restart				*/
+	M_RST5	= 0xd5,	/* restart				*/
+	M_RST6	= 0xd6,	/* restart				*/
+	M_RST7	= 0xd7,	/* restart				*/
+
+	M_SOI	= 0xd8,	/* start of image			*/
+	M_EOI	= 0xd9,	/* end of image				*/
+	M_SOS	= 0xda,	/* start of scan			*/
+	M_DQT	= 0xdb,	/* define quantization tables		*/
+	M_DNL	= 0xdc,	/* define number of lines		*/
+	M_DRI	= 0xdd,	/* define restart interval		*/
+	M_DHP	= 0xde,	/* define hierarchical progression	*/
+	M_EXP	= 0xdf,	/* expand reference image(s)		*/
+
+	M_APP0	= 0xe0,	/* application marker, used for JFIF	*/
+	M_APP1	= 0xe1,	/* application marker			*/
+	M_APP2	= 0xe2,	/* application marker			*/
+	M_APP3	= 0xe3,	/* application marker			*/
+	M_APP4	= 0xe4,	/* application marker			*/
+	M_APP5	= 0xe5,	/* application marker			*/
+	M_APP6	= 0xe6,	/* application marker			*/
+	M_APP7	= 0xe7,	/* application marker			*/
+	M_APP8	= 0xe8,	/* application marker			*/
+	M_APP9	= 0xe9,	/* application marker			*/
+	M_APP10	= 0xea,	/* application marker			*/
+	M_APP11	= 0xeb,	/* application marker			*/
+	M_APP12	= 0xec,	/* application marker			*/
+	M_APP13	= 0xed,	/* application marker			*/
+	M_APP14	= 0xee,	/* application marker, used by Adobe	*/
+	M_APP15	= 0xef,	/* application marker			*/
+
+	M_JPG0	= 0xf0,	/* reserved for JPEG extensions		*/
+	M_JPG13	= 0xfd,	/* reserved for JPEG extensions		*/
+	M_COM	= 0xfe,	/* comment				*/
+
+	M_TEM	= 0x01	/* temporary use			*/
+} JPEG_MARKER;
+
+
+/*
+ * bFillPaletteDIB - fill the palette part of the imagesdata
+ *
+ * returns TRUE if the images must be a color image, otherwise FALSE;
+ */
+static BOOL
+bFillPaletteDIB(FILE *pFile, imagedata_type *pImg, BOOL bNewFormat)
+{
+	int	iIndex;
+	BOOL	bIsColorPalette;
+
+	fail(pFile == NULL);
+	fail(pImg == NULL);
+
+	if (pImg->uiBitsPerComponent > 8) {
+		/* No palette, image uses more than 256 colors */
+		return TRUE;
+	}
+
+	if (pImg->iColorsUsed <= 0) {
+		/* Not specified, so compute the number of colors used */
+		pImg->iColorsUsed = 1 << pImg->uiBitsPerComponent;
+	}
+
+	fail(pImg->iColorsUsed > 256);
+	if (pImg->iColorsUsed > 256) {
+		pImg->iColorsUsed = 256;
+	}
+
+	bIsColorPalette = FALSE;
+	for (iIndex = 0; iIndex < pImg->iColorsUsed; iIndex++) {
+		/* From BGR order to RGB order */
+		pImg->aucPalette[iIndex][2] = (UCHAR)iNextByte(pFile);
+		pImg->aucPalette[iIndex][1] = (UCHAR)iNextByte(pFile);
+		pImg->aucPalette[iIndex][0] = (UCHAR)iNextByte(pFile);
+		if (bNewFormat) {
+			(void)iNextByte(pFile);
+		}
+		NO_DBG_PRINT_BLOCK(pImg->aucPalette[iIndex], 3);
+		if (pImg->aucPalette[iIndex][0] !=
+		     pImg->aucPalette[iIndex][1] ||
+		    pImg->aucPalette[iIndex][1] !=
+		     pImg->aucPalette[iIndex][2]) {
+			bIsColorPalette = TRUE;
+		}
+	}
+
+	return bIsColorPalette;
+} /* end of bFillPaletteDIB */
+
+/*
+ * bExamineDIB - Examine a DIB header
+ *
+ * return TRUE if successful, otherwise FALSE
+ */
+static BOOL
+bExamineDIB(FILE *pFile, imagedata_type *pImg)
+{
+	size_t	tHeaderSize;
+	int	iPlanes, iCompression;
+
+	tHeaderSize = (size_t)ulNextLong(pFile);
+	switch (tHeaderSize) {
+	case 12:
+		pImg->iWidth = (int)usNextWord(pFile);
+		pImg->iHeight = (int)usNextWord(pFile);
+		iPlanes = (int)usNextWord(pFile);
+		pImg->uiBitsPerComponent = (UINT)usNextWord(pFile);
+		iCompression = BI_RGB;
+		pImg->iColorsUsed = 0;
+		break;
+	case 40:
+	case 64:
+		pImg->iWidth = (int)ulNextLong(pFile);
+		pImg->iHeight = (int)ulNextLong(pFile);
+		iPlanes = (int)usNextWord(pFile);
+		pImg->uiBitsPerComponent = (UINT)usNextWord(pFile);
+		iCompression = (int)ulNextLong(pFile);
+		(void)tSkipBytes(pFile, 12);
+		pImg->iColorsUsed = (int)ulNextLong(pFile);
+		(void)tSkipBytes(pFile, tHeaderSize - 36);
+		break;
+	default:
+		DBG_DEC(tHeaderSize);
+		return FALSE;
+	}
+	DBG_DEC(pImg->iWidth);
+	DBG_DEC(pImg->iHeight);
+	DBG_DEC(pImg->uiBitsPerComponent);
+	DBG_DEC(iCompression);
+	DBG_DEC(pImg->iColorsUsed);
+
+	/* Do some sanity checks with the parameters */
+	if (iPlanes != 1) {
+		DBG_DEC(iPlanes);
+		return FALSE;
+	}
+	if (pImg->iWidth <= 0 || pImg->iHeight <= 0) {
+		DBG_DEC(pImg->iWidth);
+		DBG_DEC(pImg->iHeight);
+		return FALSE;
+	}
+	if (pImg->uiBitsPerComponent != 1 && pImg->uiBitsPerComponent != 4 &&
+	    pImg->uiBitsPerComponent != 8 && pImg->uiBitsPerComponent != 24) {
+		DBG_DEC(pImg->uiBitsPerComponent);
+		return FALSE;
+	}
+	if (iCompression != BI_RGB &&
+	    (pImg->uiBitsPerComponent == 1 || pImg->uiBitsPerComponent == 24)) {
+		return FALSE;
+	}
+	if (iCompression == BI_RLE8 && pImg->uiBitsPerComponent == 4) {
+		return FALSE;
+	}
+	if (iCompression == BI_RLE4 && pImg->uiBitsPerComponent == 8) {
+		return FALSE;
+	}
+
+	switch (iCompression) {
+	case BI_RGB:
+		pImg->eCompression = compression_none;
+		break;
+	case BI_RLE4:
+		pImg->eCompression = compression_rle4;
+		break;
+	case BI_RLE8:
+		pImg->eCompression = compression_rle8;
+		break;
+	default:
+		DBG_DEC(iCompression);
+		return FALSE;
+	}
+
+	pImg->bColorImage = bFillPaletteDIB(pFile, pImg, tHeaderSize > 12);
+
+	if (pImg->uiBitsPerComponent <= 8) {
+		pImg->iComponents = 1;
+	} else {
+		pImg->iComponents = (int)(pImg->uiBitsPerComponent / 8);
+	}
+
+	return TRUE;
+} /* end of bExamineDIB */
+
+/*
+ * iNextMarker - read the next JPEG marker
+ */
+static int
+iNextMarker(FILE *pFile)
+{
+	int	iMarker;
+
+	do {
+		do {
+			iMarker = iNextByte(pFile);
+		} while (iMarker != 0xff && iMarker != EOF);
+		if (iMarker == EOF) {
+			return EOF;
+		}
+		do {
+			iMarker = iNextByte(pFile);
+		} while (iMarker == 0xff);
+	} while (iMarker == 0x00);			/* repeat if ff/00 */
+
+	return iMarker;
+} /* end of iNextMarker */
+
+/*
+ * bExamineJPEG - Examine a JPEG header
+ *
+ * return TRUE if successful, otherwise FALSE
+ */
+static BOOL
+bExamineJPEG(FILE *pFile, imagedata_type *pImg)
+{
+	size_t	tLength;
+	int	iMarker, iIndex;
+	char	appstring[10];
+	BOOL	bSOFDone;
+
+	tLength = 0;
+	bSOFDone = FALSE;
+
+	/* process JPEG markers */
+	while (!bSOFDone && (iMarker = iNextMarker(pFile)) != (int)M_EOI) {
+		switch (iMarker) {
+		case EOF:
+			DBG_MSG("Error: unexpected end of JPEG file");
+			return FALSE;
+	/* The following are not officially supported in PostScript level 2 */
+		case M_SOF2:
+		case M_SOF3:
+		case M_SOF5:
+		case M_SOF6:
+		case M_SOF7:
+		case M_SOF9:
+		case M_SOF10:
+		case M_SOF11:
+		case M_SOF13:
+		case M_SOF14:
+		case M_SOF15:
+			DBG_HEX(iMarker);
+			return FALSE;
+		case M_SOF0:
+		case M_SOF1:
+			tLength = (size_t)usNextWordBE(pFile);
+			pImg->uiBitsPerComponent = (UINT)iNextByte(pFile);
+			pImg->iHeight = (int)usNextWordBE(pFile);
+			pImg->iWidth = (int)usNextWordBE(pFile);
+			pImg->iComponents = iNextByte(pFile);
+			bSOFDone = TRUE;
+			break;
+		case M_APP14:
+		/*
+		 * Check for Adobe application marker. It is known (per Adobe's
+		 * TN5116) to contain the string "Adobe" at the start of the
+		 * APP14 marker.
+		 */
+			tLength = (size_t)usNextWordBE(pFile);
+			if (tLength < 12) {
+				(void)tSkipBytes(pFile, tLength - 2);
+			} else {
+				for (iIndex = 0; iIndex < 5; iIndex++) {
+					appstring[iIndex] =
+							(char)iNextByte(pFile);
+				}
+				appstring[5] = '\0';
+				if (STREQ(appstring, "Adobe")) {
+					pImg->bAdobe = TRUE;
+				}
+				(void)tSkipBytes(pFile, tLength - 7);
+			}
+			break;
+		case M_SOI:		/* ignore markers without parameters */
+		case M_EOI:
+		case M_TEM:
+		case M_RST0:
+		case M_RST1:
+		case M_RST2:
+		case M_RST3:
+		case M_RST4:
+		case M_RST5:
+		case M_RST6:
+		case M_RST7:
+			break;
+		default:		/* skip variable length markers */
+			tLength = (size_t)usNextWordBE(pFile);
+			(void)tSkipBytes(pFile, tLength - 2);
+			break;
+		}
+	}
+
+	DBG_DEC(pImg->iWidth);
+	DBG_DEC(pImg->iHeight);
+	DBG_DEC(pImg->uiBitsPerComponent);
+	DBG_DEC(pImg->iComponents);
+
+	/* Do some sanity checks with the parameters */
+	if (pImg->iHeight <= 0 ||
+	    pImg->iWidth <= 0 ||
+	    pImg->iComponents <= 0) {
+		DBG_DEC(pImg->iHeight);
+		DBG_DEC(pImg->iWidth);
+		DBG_DEC(pImg->iComponents);
+		return FALSE;
+	}
+
+	/* Some broken JPEG files have this but they print anyway... */
+	if (pImg->iComponents * 3 + 8 != (int)tLength) {
+		DBG_MSG("Warning: SOF marker has incorrect length - ignored");
+	}
+
+	if (pImg->uiBitsPerComponent != 8) {
+		DBG_DEC(pImg->uiBitsPerComponent);
+		DBG_MSG("Not supported in PostScript level 2");
+		return FALSE;
+	}
+
+	if (pImg->iComponents != 1 &&
+	    pImg->iComponents != 3 &&
+	    pImg->iComponents != 4) {
+		DBG_DEC(pImg->iComponents);
+		return FALSE;
+	}
+
+	pImg->bColorImage = pImg->iComponents >= 3;
+	pImg->iColorsUsed = 0;
+	pImg->eCompression = compression_jpeg;
+
+	return TRUE;
+} /* end of bExamineJPEG */
+
+/*
+ * bFillPalettePNG - fill the palette part of the imagesdata
+ *
+ * returns TRUE if sucessful, otherwise FALSE;
+ */
+static BOOL
+bFillPalettePNG(FILE *pFile, imagedata_type *pImg, size_t tLength)
+{
+	int	iIndex, iEntries;
+
+	fail(pFile == NULL);
+	fail(pImg == NULL);
+
+	if (pImg->uiBitsPerComponent > 8) {
+		/* No palette, image uses more than 256 colors */
+		return TRUE;
+	}
+
+	if (!pImg->bColorImage) {
+		/* Only color images can have a palette */
+		return FALSE;
+	}
+
+	if (tLength % 3 != 0) {
+		/* Each palette entry takes three bytes */
+		DBG_DEC(tLength);
+		return FALSE;
+	}
+
+	iEntries = (int)(tLength / 3);
+	DBG_DEC(iEntries);
+	pImg->iColorsUsed = 1 << pImg->uiBitsPerComponent;
+	DBG_DEC(pImg->iColorsUsed);
+
+	if (iEntries > 256) {
+		DBG_DEC(iEntries);
+		return FALSE;
+	}
+
+	for (iIndex = 0; iIndex < iEntries; iIndex++) {
+		pImg->aucPalette[iIndex][0] = (UCHAR)iNextByte(pFile);
+		pImg->aucPalette[iIndex][1] = (UCHAR)iNextByte(pFile);
+		pImg->aucPalette[iIndex][2] = (UCHAR)iNextByte(pFile);
+		NO_DBG_PRINT_BLOCK(pImg->aucPalette[iIndex], 3);
+	}
+	for (;iIndex < pImg->iColorsUsed; iIndex++) {
+		pImg->aucPalette[iIndex][0] = 0;
+		pImg->aucPalette[iIndex][1] = 0;
+		pImg->aucPalette[iIndex][2] = 0;
+	}
+
+	return TRUE;
+} /* end of bFillPalettePNG */
+
+/*
+ * bExaminePNG - Examine a PNG header
+ *
+ * return TRUE if successful, otherwise FALSE
+ */
+static BOOL
+bExaminePNG(FILE *pFile, imagedata_type *pImg)
+{
+	size_t		tLength;
+	ULONG		ulLong1, ulLong2, ulName;
+	int		iIndex, iTmp;
+	int		iCompressionMethod, iFilterMethod, iInterlaceMethod;
+	int		iColor, iIncrement;
+	BOOL		bHasPalette, bHasAlpha;
+	UCHAR	aucBuf[4];
+
+	/* Check signature */
+	ulLong1 = ulNextLongBE(pFile);
+	ulLong2 = ulNextLongBE(pFile);
+	if (ulLong1 != 0x89504e47UL || ulLong2 != 0x0d0a1a0aUL) {
+		DBG_HEX(ulLong1);
+		DBG_HEX(ulLong2);
+		return FALSE;
+	}
+
+	ulName = 0x00;
+	bHasPalette = FALSE;
+
+	/* Examine chunks */
+	while (ulName != PNG_CN_IEND) {
+		tLength = (size_t)ulNextLongBE(pFile);
+		ulName = 0x00;
+		for (iIndex = 0; iIndex < (int)elementsof(aucBuf); iIndex++) {
+			aucBuf[iIndex] = (UCHAR)iNextByte(pFile);
+			if (!isalpha(aucBuf[iIndex])) {
+				DBG_HEX(aucBuf[iIndex]);
+				return FALSE;
+			}
+			ulName <<= 8;
+			ulName |= aucBuf[iIndex];
+		}
+
+		switch (ulName) {
+		case PNG_CN_IHDR:
+			/* Header chunck */
+			if (tLength < 13) {
+				DBG_DEC(tLength);
+				return FALSE;
+			}
+			pImg->iWidth = (int)ulNextLongBE(pFile);
+			pImg->iHeight = (int)ulNextLongBE(pFile);
+			pImg->uiBitsPerComponent = (UINT)iNextByte(pFile);
+			iTmp = iNextByte(pFile);
+			NO_DBG_HEX(iTmp);
+			pImg->bColorImage = (iTmp & PNG_CB_COLOR) != 0;
+			bHasPalette = (iTmp & PNG_CB_PALETTE) != 0;
+			bHasAlpha = (iTmp & PNG_CB_ALPHA) != 0;
+			if (bHasPalette && pImg->uiBitsPerComponent > 8) {
+				/* This should not happen */
+				return FALSE;
+			}
+			pImg->iComponents =
+				(bHasPalette || !pImg->bColorImage) ? 1 : 3;
+			if (bHasAlpha) {
+				pImg->iComponents++;
+			}
+			iCompressionMethod = iNextByte(pFile);
+			if (iCompressionMethod != 0) {
+				DBG_DEC(iCompressionMethod);
+				return FALSE;
+			}
+			iFilterMethod = iNextByte(pFile);
+			if (iFilterMethod != 0) {
+				DBG_DEC(iFilterMethod);
+				return FALSE;
+			}
+			iInterlaceMethod = iNextByte(pFile);
+			if (iInterlaceMethod != 0) {
+				DBG_DEC(iInterlaceMethod);
+				return FALSE;
+			}
+			pImg->iColorsUsed = 0;
+			(void)tSkipBytes(pFile, tLength - 13 + 4);
+			break;
+		case PNG_CN_PLTE:
+			if (!bHasPalette) {
+				return FALSE;
+			}
+			if (!bFillPalettePNG(pFile, pImg, tLength)) {
+				return FALSE;
+			}
+			(void)tSkipBytes(pFile, 4);
+			break;
+		default:
+			(void)tSkipBytes(pFile, tLength + 4);
+			break;
+		}
+	}
+
+	DBG_DEC(pImg->iWidth);
+	DBG_DEC(pImg->iHeight);
+	DBG_DEC(pImg->uiBitsPerComponent);
+	DBG_DEC(pImg->iColorsUsed);
+	DBG_DEC(pImg->iComponents);
+
+	/* Do some sanity checks with the parameters */
+	if (pImg->iWidth <= 0 || pImg->iHeight <= 0) {
+		return FALSE;
+	}
+
+	if (pImg->uiBitsPerComponent != 1 && pImg->uiBitsPerComponent != 2 &&
+	    pImg->uiBitsPerComponent != 4 && pImg->uiBitsPerComponent != 8 &&
+	    pImg->uiBitsPerComponent != 16) {
+		DBG_DEC(pImg->uiBitsPerComponent);
+		return  FALSE;
+	}
+
+	if (pImg->iComponents != 1 && pImg->iComponents != 3) {
+		/* Not supported */
+		DBG_DEC(pImg->iComponents);
+		return FALSE;
+	}
+
+	if (pImg->uiBitsPerComponent > 8) {
+		/* Not supported */
+		DBG_DEC(pImg->uiBitsPerComponent);
+		return FALSE;
+	}
+
+	if (pImg->iColorsUsed == 0 &&
+	    pImg->iComponents == 1 &&
+	    pImg->uiBitsPerComponent <= 4) {
+		/*
+		 * No palette is supplied, but PostScript needs one in these
+		 * cases, so we add a default palette here
+		 */
+		pImg->iColorsUsed = 1 << pImg->uiBitsPerComponent;
+		iIncrement = 0xff / (pImg->iColorsUsed - 1);
+		for (iIndex = 0, iColor = 0x00;
+		     iIndex < pImg->iColorsUsed;
+		     iIndex++, iColor += iIncrement) {
+			pImg->aucPalette[iIndex][0] = (UCHAR)iColor;
+			pImg->aucPalette[iIndex][1] = (UCHAR)iColor;
+			pImg->aucPalette[iIndex][2] = (UCHAR)iColor;
+		}
+		/* Just to be sure */
+		pImg->bColorImage = FALSE;
+	}
+
+	pImg->eCompression = compression_zlib;
+
+	return TRUE;
+} /* end of bExaminePNG */
+
+/*
+ * bExamineWMF - Examine a WMF header
+ *
+ * return TRUE if successful, otherwise FALSE
+ */
+static BOOL
+bExamineWMF(FILE *pFile, imagedata_type *pImg)
+{
+	ULONG	ulFileSize, ulMaxRecord, ulMagic;
+	USHORT	usType, usHeaderSize, usVersion, usNoObjects;
+
+	usType = usNextWord(pFile);
+	usHeaderSize = usNextWord(pFile);
+	ulMagic = ((ULONG)usHeaderSize << 16) | (ULONG)usType;
+	usVersion = usNextWord(pFile);
+	ulFileSize = ulNextLong(pFile);
+	usNoObjects = usNextWord(pFile);
+	ulMaxRecord = ulNextLong(pFile);
+
+	DBG_HEX(ulMagic);
+	DBG_DEC(usType);
+	DBG_DEC(usHeaderSize);
+	DBG_HEX(usVersion);
+	DBG_DEC(ulFileSize);
+	DBG_DEC(usNoObjects);
+	DBG_DEC(ulMaxRecord);
+
+	return FALSE;
+} /* end of bExamineWMF */
+
+#if !defined(__riscos)
+/*
+ * vImage2Papersize - make sure the image fits on the paper
+ *
+ * This function should not be needed if Word would do a proper job
+ */
+static void
+vImage2Papersize(imagedata_type *pImg)
+{
+	static int	iNetPageHeight = -1;
+	static int	iNetPageWidth = -1;
+	options_type	tOptions;
+        double  dVerFactor, dHorFactor, dFactor;
+
+	DBG_MSG("vImage2Papersize");
+
+	fail(pImg == NULL);
+
+	if (iNetPageHeight < 0 || iNetPageWidth < 0) {
+		/* Get the page dimensions from the options */
+		vGetOptions(&tOptions);
+		/* Add 999 to err on the save side */
+		iNetPageHeight = tOptions.iPageHeight -
+				(lDrawUnits2MilliPoints(
+					PS_TOP_MARGIN + PS_BOTTOM_MARGIN) +
+					999) / 1000;
+		iNetPageWidth = tOptions.iPageWidth -
+				(lDrawUnits2MilliPoints(
+					PS_LEFT_MARGIN + PS_RIGHT_MARGIN) +
+					999) / 1000;
+		DBG_DEC(iNetPageHeight);
+		DBG_DEC(iNetPageWidth);
+	}
+
+	if (pImg->iVerSizeScaled < iNetPageHeight &&
+	    pImg->iHorSizeScaled < iNetPageWidth) {
+		/* The image fits on the paper */
+		return;
+	}
+
+	dVerFactor = (double)iNetPageHeight / (double)pImg->iVerSizeScaled;
+	dHorFactor = (double)iNetPageWidth / (double)pImg->iHorSizeScaled;
+        dFactor = min(dVerFactor, dHorFactor);
+        DBG_FLT(dFactor);
+        /* Round down, just to be on the save side */
+        pImg->iVerSizeScaled = (int)(pImg->iVerSizeScaled * dFactor);
+        pImg->iHorSizeScaled = (int)(pImg->iHorSizeScaled * dFactor);
+} /* end of vImage2Papersize */
+#endif /* !__riscos */
+
+/*
+ * tFind6Image - skip until the image is found
+ *
+ * Find the image in Word 6/7 files
+ *
+ * returns the new position when a image is found, otherwise -1
+ */
+static size_t
+tFind6Image(FILE *pFile, size_t tPosition, size_t tLength,
+	imagetype_enum *peImageType)
+{
+	ULONG	ulMarker;
+	size_t	tRecordLength, tToSkip;
+	USHORT	usMarker;
+
+	fail(pFile == NULL);
+	fail(peImageType == NULL);
+
+	*peImageType = imagetype_is_unknown;
+	if (tPosition + 18 >= tLength) {
+		return (size_t)-1;
+	}
+
+	ulMarker = ulNextLong(pFile);
+	if (ulMarker != 0x00090001) {
+		DBG_HEX(ulMarker);
+		return (size_t)-1;
+	}
+	usMarker = usNextWord(pFile);
+	if (usMarker != 0x0300) {
+		DBG_HEX(usMarker);
+		return (size_t)-1;
+	}
+	(void)tSkipBytes(pFile, 10);
+	usMarker = usNextWord(pFile);
+	if (usMarker != 0x0000) {
+		DBG_HEX(usMarker);
+		return (size_t)-1;
+	}
+	tPosition += 18;
+
+	while (tPosition + 6 <= tLength) {
+		tRecordLength = (size_t)ulNextLong(pFile);
+		usMarker = usNextWord(pFile);
+		tPosition += 6;
+		NO_DBG_DEC(tRecordLength);
+		NO_DBG_HEX(usMarker);
+		switch (usMarker) {
+		case 0x0000:
+			DBG_HEX(ulGetDataOffset(pFile));
+			return (size_t)-1;
+		case 0x0b41:
+			DBG_MSG("DIB");
+			*peImageType = imagetype_is_dib;
+			tPosition += tSkipBytes(pFile, 20);
+			return tPosition;
+		case 0x0f43:
+			DBG_MSG("DIB");
+			*peImageType = imagetype_is_dib;
+			tPosition += tSkipBytes(pFile, 22);
+			return tPosition;
+		default:
+			if (tRecordLength < 3) {
+				break;
+			}
+			if (tRecordLength > SIZE_T_MAX / 2) {
+				/*
+				 * No need to compute the number of bytes
+				 * to skip
+				 */
+				DBG_DEC(tRecordLength);
+				DBG_HEX(tRecordLength);
+				DBG_FIXME();
+				return (size_t)-1;
+			}
+			tToSkip = tRecordLength * 2 - 6;
+			if (tToSkip > tLength - tPosition) {
+				/* You can't skip this number of bytes */
+				DBG_DEC(tToSkip);
+				DBG_DEC(tLength - tPosition);
+				return (size_t)-1;
+			}
+			tPosition += tSkipBytes(pFile, tToSkip);
+			break;
+		}
+	}
+
+	return (size_t)-1;
+} /* end of tFind6Image */
+
+/*
+ * tFind8Image - skip until the image is found
+ *
+ * Find the image in Word 8/9/10 files
+ *
+ * returns the new position when a image is found, otherwise -1
+ */
+static size_t
+tFind8Image(FILE *pFile, size_t tPosition, size_t tLength,
+	imagetype_enum *peImageType)
+{
+	size_t	tRecordLength, tNameLen;
+	USHORT	usRecordVersion, usRecordType, usRecordInstance;
+	USHORT	usTmp;
+
+	fail(pFile == NULL);
+	fail(peImageType == NULL);
+
+	*peImageType = imagetype_is_unknown;
+	while (tPosition + 8 <= tLength) {
+		usTmp = usNextWord(pFile);
+		usRecordVersion = usTmp & 0x000f;
+		usRecordInstance = usTmp >> 4;
+		usRecordType = usNextWord(pFile);
+		tRecordLength = (size_t)ulNextLong(pFile);
+		tPosition += 8;
+		NO_DBG_HEX(usRecordVersion);
+		NO_DBG_HEX(usRecordInstance);
+		NO_DBG_HEX(usRecordType);
+		NO_DBG_DEC(tRecordLength);
+		switch (usRecordType) {
+		case 0xf000: case 0xf001: case 0xf002: case 0xf003:
+		case 0xf004: case 0xf005:
+			break;
+		case 0xf007:
+			tPosition += tSkipBytes(pFile, 33);
+			tNameLen = (size_t)iNextByte(pFile);
+			tPosition++;
+			DBG_DEC_C(tNameLen != 0, tNameLen);
+			tPosition += tSkipBytes(pFile, 2 + tNameLen * 2);
+			break;
+		case 0xf008:
+			tPosition += tSkipBytes(pFile, 8);
+			break;
+		case 0xf009:
+			tPosition += tSkipBytes(pFile, 16);
+			break;
+		case 0xf006: case 0xf00a: case 0xf00b: case 0xf00d:
+		case 0xf00e: case 0xf00f: case 0xf010: case 0xf011:
+		case 0xf122:
+			tPosition += tSkipBytes(pFile, tRecordLength);
+			break;
+		case 0xf01a:
+			DBG_MSG("EMF");
+			*peImageType = imagetype_is_emf;
+			tPosition += tSkipBytes(pFile, 50);
+			if ((usRecordInstance ^ MSOBI_EMF) == 1) {
+				tPosition += tSkipBytes(pFile, 16);
+			}
+			return tPosition;
+		case 0xf01b:
+			DBG_MSG("WMF");
+			*peImageType = imagetype_is_wmf;
+			tPosition += tSkipBytes(pFile, 50);
+			if ((usRecordInstance ^ MSOBI_WMF) == 1) {
+				tPosition += tSkipBytes(pFile, 16);
+			}
+			return tPosition;
+		case 0xf01c:
+			DBG_MSG("PICT");
+			*peImageType = imagetype_is_pict;
+			tPosition += tSkipBytes(pFile, 50);
+			if ((usRecordInstance ^ MSOBI_PICT) == 1) {
+				tPosition += tSkipBytes(pFile, 16);
+			}
+			return tPosition;
+		case 0xf01d:
+			DBG_MSG("JPEG");
+			*peImageType = imagetype_is_jpeg;
+			tPosition += tSkipBytes(pFile, 17);
+			if ((usRecordInstance ^ MSOBI_JPEG) == 1) {
+				tPosition += tSkipBytes(pFile, 16);
+			}
+			return tPosition;
+		case 0xf01e:
+			DBG_MSG("PNG");
+			*peImageType = imagetype_is_png;
+			tPosition += tSkipBytes(pFile, 17);
+			if ((usRecordInstance ^ MSOBI_PNG) == 1) {
+				tPosition += tSkipBytes(pFile, 16);
+			}
+			return tPosition;
+		case 0xf01f:
+			DBG_MSG("DIB");
+			/* DIB is a BMP minus its 14 byte header */
+			*peImageType = imagetype_is_dib;
+			tPosition += tSkipBytes(pFile, 17);
+			if ((usRecordInstance ^ MSOBI_DIB) == 1) {
+				tPosition += tSkipBytes(pFile, 16);
+			}
+			return tPosition;
+		case 0xf00c:
+		default:
+			DBG_HEX(usRecordType);
+			DBG_DEC_C(tRecordLength % 4 != 0, tRecordLength);
+			DBG_FIXME();
+			return (size_t)-1;
+		}
+	}
+
+	return (size_t)-1;
+} /* end of tFind8Image */
+
+/*
+ * eExamineImage - Examine the image
+ *
+ * Returns an indication of the amount of information found
+ */
+image_info_enum
+eExamineImage(FILE *pFile, ULONG ulFileOffsetImage, imagedata_type *pImg)
+{
+	long	lTmp;
+	size_t	tWordHeaderLen, tLength, tPos;
+	int	iType, iHorSize, iVerSize;
+	USHORT	usHorScalingFactor, usVerScalingFactor;
+
+	if (ulFileOffsetImage == FC_INVALID) {
+		return image_no_information;
+	}
+	DBG_HEX(ulFileOffsetImage);
+
+	if (!bSetDataOffset(pFile, ulFileOffsetImage)) {
+		return image_no_information;
+	}
+
+	tLength = (size_t)ulNextLong(pFile);
+	DBG_DEC(tLength);
+	if (tLength < 46) {
+		/* Smaller than the smallest known header */
+		DBG_FIXME();
+		return image_no_information;
+	}
+	tWordHeaderLen = (size_t)usNextWord(pFile);
+	DBG_DEC(tWordHeaderLen);
+	fail(tWordHeaderLen != 46 &&
+		tWordHeaderLen != 58 &&
+		tWordHeaderLen != 68);
+
+	if (tLength < tWordHeaderLen) {
+		/* Smaller than the current header */
+		return image_no_information;
+	}
+	iType = (int)usNextWord(pFile);
+	DBG_DEC(iType);
+	(void)tSkipBytes(pFile, 28 - 8);
+
+	lTmp = lTwips2MilliPoints(usNextWord(pFile));
+	iHorSize = (int)(lTmp / 1000);
+	if (lTmp % 1000 != 0) {
+		iHorSize++;
+	}
+	DBG_DEC(iHorSize);
+	lTmp = lTwips2MilliPoints(usNextWord(pFile));
+	iVerSize = (int)(lTmp / 1000);
+	if (lTmp % 1000 != 0) {
+		iVerSize++;
+	}
+	DBG_DEC(iVerSize);
+
+	usHorScalingFactor = usNextWord(pFile);
+	DBG_DEC(usHorScalingFactor);
+	usVerScalingFactor = usNextWord(pFile);
+	DBG_DEC(usVerScalingFactor);
+
+	/* Sanity checks */
+	lTmp = (long)iHorSize * (long)usHorScalingFactor;
+	if (lTmp < 2835) {
+		/* This image would be less than 1 millimeter wide */
+		DBG_DEC(lTmp);
+		return image_no_information;
+	}
+	lTmp = (long)iVerSize * (long)usVerScalingFactor;
+	if (lTmp < 2835) {
+		/* This image would be less than 1 millimeter high */
+		DBG_DEC(lTmp);
+		return image_no_information;
+	}
+
+	/* Skip the rest of the header */
+	(void)tSkipBytes(pFile, tWordHeaderLen - 36);
+	tPos = tWordHeaderLen;
+
+	(void)memset(pImg, 0, sizeof(*pImg));
+
+	switch (iType) {
+	case   7:
+	case   8:
+		tPos = tFind6Image(pFile, tPos, tLength, &pImg->eImageType);
+		if (tPos == (size_t)-1) {
+			/* No image found */
+			return image_no_information;
+		}
+		DBG_HEX(tPos);
+		break;
+	case  94:	/* Word 6/7, no image just a pathname */
+		pImg->eImageType = imagetype_is_external;
+		DBG_HEX(ulFileOffsetImage + tPos);
+		break;
+	case 100:
+		tPos = tFind8Image(pFile, tPos, tLength, &pImg->eImageType);
+		if (tPos == (size_t)-1) {
+			/* No image found */
+			return image_no_information;
+		}
+		DBG_HEX(tPos);
+		break;
+	case 102:	/* Word 8/9/10, no image just a pathname or URL */
+		pImg->eImageType = imagetype_is_external;
+		DBG_HEX(ulFileOffsetImage + tPos);
+		break;
+	default:
+		DBG_DEC(iType);
+		DBG_HEX(ulFileOffsetImage + tPos);
+		DBG_FIXME();
+		return image_no_information;
+	}
+
+	/* Minimal information is now available */
+	pImg->tLength = tLength;
+	pImg->tPosition = tPos;
+	pImg->iHorSizeScaled =
+		(int)(((long)iHorSize * (long)usHorScalingFactor + 500) / 1000);
+	pImg->iVerSizeScaled =
+		(int)(((long)iVerSize * (long)usVerScalingFactor + 500) / 1000);
+#if !defined(__riscos)
+	vImage2Papersize(pImg);
+#endif /* !__riscos */
+
+	/* Image type specific examinations */
+	switch (pImg->eImageType) {
+	case imagetype_is_dib:
+		if (bExamineDIB(pFile, pImg)) {
+			return image_full_information;
+		}
+		return image_minimal_information;
+	case imagetype_is_jpeg:
+		if (bExamineJPEG(pFile, pImg)) {
+			return image_full_information;
+		}
+		return image_minimal_information;
+	case imagetype_is_png:
+		if (bExaminePNG(pFile, pImg)) {
+			return image_full_information;
+		}
+		return image_minimal_information;
+	case imagetype_is_wmf:
+		if (bExamineWMF(pFile, pImg)) {
+			return image_full_information;
+		}
+		return image_minimal_information;
+	case imagetype_is_emf:
+	case imagetype_is_pict:
+	case imagetype_is_external:
+		return image_minimal_information;
+	case imagetype_is_unknown:
+	default:
+		return image_no_information;
+	}
+} /* end of eExamineImage */
diff --git a/imgtrans.c b/imgtrans.c
new file mode 100644
index 0000000..1b284c4
--- /dev/null
+++ b/imgtrans.c
@@ -0,0 +1,71 @@
+/*
+ * imgtrans.c
+ * Copyright (C) 2000-2002 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Generic functions to translate Word images
+ */
+
+#include <stdio.h>
+#include "antiword.h"
+
+
+/*
+ * bTranslateImage - translate the image
+ *
+ * This function reads the type of the given image and and gets it translated.
+ *
+ * return TRUE when sucessful, otherwise FALSE
+ */
+BOOL
+bTranslateImage(diagram_type *pDiag, FILE *pFile, BOOL bMinimalInformation,
+	ULONG ulFileOffsetImage, const imagedata_type *pImg)
+{
+	options_type	tOptions;
+
+	DBG_MSG("bTranslateImage");
+
+	fail(pDiag == NULL);
+	fail(pFile == NULL);
+	fail(ulFileOffsetImage == FC_INVALID);
+	fail(pImg == NULL);
+	fail(pImg->iHorSizeScaled <= 0);
+	fail(pImg->iVerSizeScaled <= 0);
+
+	vGetOptions(&tOptions);
+	fail(tOptions.eImageLevel == level_no_images);
+
+	if (bMinimalInformation) {
+		return bAddDummyImage(pDiag, pImg);
+	}
+
+	switch (pImg->eImageType) {
+	case imagetype_is_dib:
+		return bTranslateDIB(pDiag, pFile,
+				ulFileOffsetImage + pImg->tPosition,
+				pImg);
+	case imagetype_is_jpeg:
+		return bTranslateJPEG(pDiag, pFile,
+				ulFileOffsetImage + pImg->tPosition,
+				pImg->tLength - pImg->tPosition,
+				pImg);
+	case imagetype_is_png:
+		if (tOptions.eImageLevel == level_ps_2) {
+			return bAddDummyImage(pDiag, pImg);
+		}
+		return bTranslatePNG(pDiag, pFile,
+				ulFileOffsetImage + pImg->tPosition,
+				pImg->tLength - pImg->tPosition,
+				pImg);
+	case imagetype_is_emf:
+	case imagetype_is_wmf:
+	case imagetype_is_pict:
+	case imagetype_is_external:
+		/* FIXME */
+		return bAddDummyImage(pDiag, pImg);
+	case imagetype_is_unknown:
+	default:
+		DBG_DEC(pImg->eImageType);
+		return bAddDummyImage(pDiag, pImg);
+	}
+} /* end of bTranslateImage */
diff --git a/jpeg2eps.c b/jpeg2eps.c
new file mode 100644
index 0000000..ee438ce
--- /dev/null
+++ b/jpeg2eps.c
@@ -0,0 +1,74 @@
+/*
+ * jpeg2eps.c
+ * Copyright (C) 2000-2002 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Functions to translate jpeg pictures into eps
+ *
+ */
+
+#include <stdio.h>
+#include "antiword.h"
+
+#if defined(DEBUG)
+static int	iPicCounter = 0;
+#endif /* DEBUG */
+
+
+#if defined(DEBUG)
+/*
+ * vCopy2File
+ */
+static void
+vCopy2File(FILE *pFile, ULONG ulFileOffset, size_t tPictureLen)
+{
+	FILE	*pOutFile;
+	size_t	tIndex;
+	int	iTmp;
+	char	szFilename[30];
+
+	if (!bSetDataOffset(pFile, ulFileOffset)) {
+		return;
+	}
+
+	sprintf(szFilename, "/tmp/pic/pic%04d.jpg", ++iPicCounter);
+	pOutFile = fopen(szFilename, "wb");
+	if (pOutFile == NULL) {
+		return;
+	}
+	for (tIndex = 0; tIndex < tPictureLen; tIndex++) {
+		iTmp = iNextByte(pFile);
+		if (putc(iTmp, pOutFile) == EOF) {
+			break;
+		}
+	}
+	(void)fclose(pOutFile);
+} /* end of vCopy2File */
+#endif /* DEBUG */
+
+/*
+ * bTranslateJPEG - translate a JPEG picture
+ *
+ * This function translates a picture from jpeg to eps
+ *
+ * return TRUE when sucessful, otherwise FALSE
+ */
+BOOL
+bTranslateJPEG(diagram_type *pDiag, FILE *pFile,
+	ULONG ulFileOffset, size_t tPictureLen, const imagedata_type *pImg)
+{
+#if defined(DEBUG)
+	vCopy2File(pFile, ulFileOffset, tPictureLen);
+#endif /* DEBUG */
+
+	/* Seek to start position of JPEG data */
+	if (!bSetDataOffset(pFile, ulFileOffset)) {
+		return FALSE;
+	}
+
+	vImagePrologue(pDiag, pImg);
+	vASCII85EncodeFile(pFile, pDiag->pOutFile, tPictureLen);
+	vImageEpilogue(pDiag);
+
+	return TRUE;
+} /* end of bTranslateJPEG */
diff --git a/jpeg2sprt.c b/jpeg2sprt.c
new file mode 100644
index 0000000..28bd6cd
--- /dev/null
+++ b/jpeg2sprt.c
@@ -0,0 +1,97 @@
+/*
+ * jpeg2sprt.c
+ * Copyright (C) 2000-2002 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Functions to translate jpeg pictures into sprites
+ */
+
+#include <stdio.h>
+#include "antiword.h"
+
+#if 0 /* defined(DEBUG) */
+static int iPicCounter = 0;
+#endif /* DEBUG */
+
+
+#if 0 /* defined(DEBUG) */
+static void
+vCopy2File(UCHAR *pucJpeg, size_t tJpegSize)
+{
+	FILE	*pOutFile;
+	size_t	tIndex;
+	char	szFilename[30];
+
+	sprintf(szFilename, "<Wimp$ScrapDir>.jpeg%04d", ++iPicCounter);
+	pOutFile = fopen(szFilename, "wb");
+	if (pOutFile == NULL) {
+		return;
+	}
+	DBG_MSG(szFilename);
+	for (tIndex = 0; tIndex < tJpegSize; tIndex++) {
+		if (putc(pucJpeg[tIndex], pOutFile) == EOF) {
+			break;
+		}
+	}
+	(void)fclose(pOutFile);
+	vSetFiletype(szFilename, FILETYPE_JPEG);
+} /* end of vCopy2File */
+#endif /* DEBUG */
+
+/*
+ * bSave2Draw - save the JPEG picture to the Draw file
+ *
+ * This function puts a JPEG picture in a Draw file
+ *
+ * return TRUE when sucessful, otherwise FALSE
+ */
+BOOL
+bSave2Draw(diagram_type *pDiag, FILE *pFile,
+	size_t tJpegSize, const imagedata_type *pImg)
+{
+	UCHAR	*pucJpeg, *pucTmp;
+	size_t	tLen;
+	int	iByte;
+
+	pucJpeg = xmalloc(tJpegSize);
+	for (pucTmp = pucJpeg, tLen = 0; tLen < tJpegSize; pucTmp++, tLen++) {
+		iByte = iNextByte(pFile);
+		if (iByte == EOF) {
+			return FALSE;
+		}
+		*pucTmp = (UCHAR)iByte;
+	}
+
+#if 0 /* defined(DEBUG) */
+	vCopy2File(pucJpeg, tJpegSize);
+#endif /* DEBUG */
+
+	/* Add the JPEG to the Draw file */
+	vImage2Diagram(pDiag, pImg, pucJpeg, tJpegSize);
+
+	xfree(pucJpeg);
+	return TRUE;
+} /* end of bSave2Draw */
+
+/*
+ * bTranslateJPEG - translate a JPEG picture
+ *
+ * This function translates a picture from jpeg to sprite
+ *
+ * return TRUE when sucessful, otherwise FALSE
+ */
+BOOL
+bTranslateJPEG(diagram_type *pDiag, FILE *pFile,
+	ULONG ulFileOffset, size_t tPictureLen, const imagedata_type *pImg)
+{
+  	/* Seek to start position of JPEG data */
+	if (!bSetDataOffset(pFile, ulFileOffset)) {
+		return FALSE;
+	}
+
+	if (iGetRiscOsVersion() >= 360) {
+		return bSave2Draw(pDiag, pFile, tPictureLen, pImg);
+	}
+  	/* JPEG is not supported until RISC OS 3.6 */
+	return bAddDummyImage(pDiag, pImg);
+} /* end of bTranslateJPEG */
diff --git a/listlist.c b/listlist.c
new file mode 100644
index 0000000..eb86589
--- /dev/null
+++ b/listlist.c
@@ -0,0 +1,330 @@
+/*
+ * listlist.c
+ * Copyright (C) 2002,2003 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Build, read and destroy a list of Word list information
+ *
+ * Note:
+ * This list only exists when the Word document is saved by Word 8 or later
+ */
+
+#include "antiword.h"
+
+/*
+ * Private structure to hide the way the information
+ * is stored from the rest of the program
+ */
+typedef struct list_desc_tag {
+	list_block_type		tInfo;
+	ULONG			ulListID;
+	USHORT			usIstd;
+	UCHAR			ucListLevel;
+	struct list_desc_tag	*pNext;
+} list_desc_type;
+
+typedef struct list_value_tag {
+	USHORT			usValue;
+	USHORT			usListIndex;
+	UCHAR			ucListLevel;
+	struct list_value_tag	*pNext;
+} list_value_type;
+
+/* Variables needed to describe the LFO list (pllfo) */
+static ULONG		*aulLfoList = NULL;
+static USHORT		usLfoLen = 0;
+/* Variables needed to write the List Information List */
+static list_desc_type	*pAnchor = NULL;
+static list_desc_type	*pBlockLast = NULL;
+/* Variable needed for numbering new lists */
+static list_value_type	*pValues = NULL;
+/* Variables needed for numbering old lists */
+static int	iOldListSeqNumber = 0;
+static USHORT	usOldListValue = 0;
+
+
+/*
+ * vDestroyListInfoList - destroy the List Information List
+ */
+void
+vDestroyListInfoList(void)
+{
+	list_desc_type	*pCurr, *pNext;
+	list_value_type	*pValueCurr, *pValueNext;
+
+	DBG_MSG("vDestroyListInfoList");
+
+	/* Free the LFO list */
+	usLfoLen = 0;
+	aulLfoList = xfree(aulLfoList);
+
+	/* Free the List Information List */
+	pCurr = pAnchor;
+	while (pCurr != NULL) {
+		pNext = pCurr->pNext;
+		pCurr = xfree(pCurr);
+		pCurr = pNext;
+	}
+	pAnchor = NULL;
+	/* Reset all control variables */
+	pBlockLast = NULL;
+
+	/* Free the values list */
+	pValueCurr = pValues;
+	while (pValueCurr != NULL) {
+		pValueNext = pValueCurr->pNext;
+		pValueCurr = xfree(pValueCurr);
+		pValueCurr = pValueNext;
+	}
+	pValues = NULL;
+	/* Reset the values for the old lists */
+	iOldListSeqNumber = 0;
+	usOldListValue = 0;
+} /* end of vDestroyListInfoList */
+
+/*
+ * vBuildLfoList - build the LFO list (pllfo)
+ */
+void
+vBuildLfoList(const UCHAR *aucBuffer, size_t tBufLen)
+{
+	size_t	tRecords;
+	int	iIndex;
+
+	fail(aucBuffer == NULL);
+
+	if (tBufLen < 4) {
+		return;
+	}
+	tRecords = (size_t)ulGetLong(0, aucBuffer);
+	NO_DBG_DEC(tRecords);
+	if (4 + 16 * tRecords > tBufLen || tRecords >= 0x7fff) {
+		/* Just a sanity check */
+		DBG_DEC(tRecords);
+		DBG_DEC(4 + 16 * tRecords);
+		DBG_DEC(tBufLen);
+		return;
+	}
+	aulLfoList = xcalloc(tRecords, sizeof(ULONG));
+	for (iIndex = 0; iIndex < (int)tRecords; iIndex++) {
+		aulLfoList[iIndex] = ulGetLong(4 + 16 * iIndex, aucBuffer);
+		NO_DBG_HEX(aulLfoList[iIndex]);
+	}
+	usLfoLen = (USHORT)tRecords;
+} /* end of vBuildLfoList */
+
+/*
+ * vAdd2ListInfoList - add an element to the List Information list
+ */
+void
+vAdd2ListInfoList(ULONG ulListID, USHORT usIstd, UCHAR ucListLevel,
+	const list_block_type *pListBlock)
+{
+	list_desc_type	*pListMember;
+
+	fail(pListBlock == NULL);
+
+	NO_DBG_HEX(ulListID);
+	NO_DBG_DEC(usIstd);
+	NO_DBG_DEC(ucListLevel);
+	NO_DBG_DEC(pListBlock->ulStartAt);
+	NO_DBG_DEC(pListBlock->bNoRestart);
+	NO_DBG_DEC(pListBlock->sLeftIndent);
+	NO_DBG_HEX(pListBlock->ucNFC);
+	NO_DBG_HEX(pListBlock->usListChar);
+
+	/* Create list member */
+	pListMember = xmalloc(sizeof(list_desc_type));
+	/* Fill the list member */
+	pListMember->tInfo = *pListBlock;
+	pListMember->ulListID = ulListID;
+	pListMember->usIstd = usIstd;
+	pListMember->ucListLevel = ucListLevel;
+	pListMember->pNext = NULL;
+	/* Correct the values where needed */
+	if (pListMember->tInfo.ulStartAt > 0xffff) {
+		DBG_DEC(pListMember->tInfo.ulStartAt);
+		pListMember->tInfo.ulStartAt = 1;
+	}
+	/* Add the new member to the list */
+	if (pAnchor == NULL) {
+		pAnchor = pListMember;
+	} else {
+		fail(pBlockLast == NULL);
+		pBlockLast->pNext = pListMember;
+	}
+	pBlockLast = pListMember;
+} /* end of vAdd2ListInfoList */
+
+/*
+ * Get a matching record from the List Information List
+ *
+ * Returns NULL if no matching records is found
+ */
+const list_block_type *
+pGetListInfo(USHORT usListIndex, UCHAR ucListLevel)
+{
+	list_desc_type	*pCurr;
+	list_block_type	*pNearMatch;
+	ULONG	ulListID;
+
+	if (usListIndex == 0) {
+		return NULL;
+	}
+	if (usListIndex - 1 >= usLfoLen || ucListLevel > 8) {
+		DBG_DEC(usListIndex);
+		DBG_DEC(ucListLevel);
+		return NULL;
+	}
+	fail(aulLfoList == NULL);
+	ulListID = aulLfoList[usListIndex - 1];
+	NO_DBG_HEX(ulListID);
+
+	pNearMatch = NULL;
+	for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
+		if (pCurr->ulListID != ulListID) {
+			/* No match */
+			continue;
+		}
+		if (pCurr->ucListLevel == ucListLevel) {
+			/* Exact match */
+			return &pCurr->tInfo;
+		}
+		if (pCurr->ucListLevel == 0) {
+			/* Near match */
+			pNearMatch = &pCurr->tInfo;
+		}
+	}
+	/* No exact match, use a near match if any */
+	return pNearMatch;
+} /* end of pGetListInfo */
+
+/*
+ * Get a matching record from the List Information List
+ *
+ * Returns NULL if no matching records is found
+ */
+const list_block_type *
+pGetListInfoByIstd(USHORT usIstd)
+{
+	list_desc_type	*pCurr;
+
+	if (usIstd == ISTD_INVALID || usIstd == STI_NIL || usIstd == STI_USER) {
+		return NULL;
+	}
+
+	for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
+		if (pCurr->usIstd == usIstd) {
+			return &pCurr->tInfo;
+		}
+	}
+	return NULL;
+} /* end of pGetListInfoByIstd */
+
+/*
+ * vRestartListValues - reset the less significant list levels
+ */
+static void
+vRestartListValues(USHORT usListIndex, UCHAR ucListLevel)
+{
+	list_value_type	*pPrev, *pCurr, *pNext;
+	int		iCounter;
+
+	iCounter = 0;
+	pPrev = NULL;
+	pCurr = pValues;
+
+	while (pCurr != NULL) {
+		if (pCurr->usListIndex != usListIndex ||
+		    pCurr->ucListLevel <= ucListLevel) {
+			pPrev = pCurr;
+			pCurr = pCurr->pNext;
+			continue;
+		}
+		/* Reset the level by deleting the record */
+		pNext = pCurr->pNext;
+		if (pPrev == NULL) {
+			pValues = pNext;
+		} else {
+			pPrev->pNext = pNext;
+		}
+		DBG_DEC(pCurr->usListIndex);
+		DBG_DEC(pCurr->ucListLevel);
+		pCurr = xfree(pCurr);
+		pCurr = pNext;
+		iCounter++;
+	}
+	DBG_DEC_C(iCounter > 0, iCounter);
+} /* end of vRestartListValues */
+
+/*
+ * usGetListValue - Get the current value of the given list
+ *
+ * Returns the value of the given list
+ */
+USHORT
+usGetListValue(int iListSeqNumber, int iWordVersion,
+	const style_block_type *pStyle)
+{
+	list_value_type	*pCurr;
+	USHORT		usValue;
+
+	fail(iListSeqNumber < 0);
+	fail(iListSeqNumber < iOldListSeqNumber);
+	fail(iWordVersion < 0);
+	fail(pStyle == NULL);
+
+	if (iListSeqNumber <= 0) {
+		return 0;
+	}
+
+	if (iWordVersion < 8) {
+		/* Old style list */
+		if (iListSeqNumber == iOldListSeqNumber ||
+		    (iListSeqNumber == iOldListSeqNumber + 1 &&
+		     eGetNumType(pStyle->ucNumLevel) == level_type_sequence)) {
+			if (!pStyle->bNumPause) {
+				usOldListValue++;
+			}
+		} else {
+			usOldListValue = pStyle->usStartAt;
+		}
+		iOldListSeqNumber = iListSeqNumber;
+		return usOldListValue;
+	}
+
+	/* New style list */
+	if (pStyle->usListIndex == 0 ||
+	    pStyle->usListIndex - 1 >= usLfoLen ||
+	    pStyle->ucListLevel > 8) {
+		/* Out of range; no need to search */
+		return 0;
+	}
+
+	for (pCurr = pValues; pCurr != NULL; pCurr = pCurr->pNext) {
+		if (pCurr->usListIndex == pStyle->usListIndex &&
+		    pCurr->ucListLevel == pStyle->ucListLevel) {
+			/* Record found; increment and return the value */
+			pCurr->usValue++;
+			usValue = pCurr->usValue;
+			if (!pStyle->bNoRestart) {
+				vRestartListValues(pStyle->usListIndex,
+						pStyle->ucListLevel);
+			}
+			return usValue;
+		}
+	}
+
+	/* Record not found; create it and add it to the front of the list */
+	pCurr = xmalloc(sizeof(list_value_type));
+	pCurr->usValue = pStyle->usStartAt;
+	pCurr->usListIndex = pStyle->usListIndex;
+	pCurr->ucListLevel = pStyle->ucListLevel;
+	pCurr->pNext = pValues;
+	pValues = pCurr;
+	usValue = pCurr->usValue;
+	if (!pStyle->bNoRestart) {
+		vRestartListValues(pStyle->usListIndex, pStyle->ucListLevel);
+	}
+	return usValue;
+} /* end of usGetListValue */
diff --git a/main_ros.c b/main_ros.c
new file mode 100644
index 0000000..8f4f316
--- /dev/null
+++ b/main_ros.c
@@ -0,0 +1,520 @@
+/*
+ * main_ros.c
+ *
+ * Released under GPL
+ *
+ * Copyright (C) 1998-2005 A.J. van Os
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * Description:
+ * The main program of !Antiword (RISC OS version)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "DeskLib:Dialog2.h"
+#include "DeskLib:Error.h"
+#include "DeskLib:Event.h"
+#include "DeskLib:EventMsg.h"
+#include "DeskLib:Handler.h"
+#include "DeskLib:Menu.h"
+#include "DeskLib:Resource.h"
+#include "DeskLib:Screen.h"
+#include "DeskLib:Template.h"
+#include "DeskLib:Window.h"
+#if defined(__GNUC__)
+#include "flexlib:flex.h"
+#endif /* __GNUC__ */
+#include "version.h"
+#include "antiword.h"
+
+
+/* The name of this program */
+static char	*szTask = "!Antiword";
+
+/* The window handle of the choices window */
+static window_handle	tChoicesWindow = 0;
+
+/* Dummy diagram with the iconbar menu pointer */
+static diagram_type	tDummyDiagram;
+
+/* Program information Box */
+static dialog2_block	*pInfoBox = NULL;
+
+/* Info box fields */
+#define PURPOSE_INFO_FIELD	2
+#define AUTHOR_INFO_FIELD	3
+#define VERSION_INFO_FIELD	4
+#define STATUS_INFO_FIELD	5
+
+/* Iconbar menu fields */
+#define ICONBAR_INFO_FIELD	0
+#define ICONBAR_CHOICES_FIELD	1
+#define ICONBAR_QUIT_FIELD	2
+
+
+/*
+ * bBarInfo - Show iconbar information
+ */
+static BOOL
+bBarInfo(event_pollblock *pEvent, void *pvReference)
+{
+	diagram_type	*pDiag;
+
+	TRACE_MSG("bBarInfo");
+
+	fail(pEvent == NULL);
+	fail(pEvent->type != event_SEND);
+	fail(pEvent->data.message.header.action != message_MENUWARN);
+	fail(pvReference == NULL);
+
+	pDiag = (diagram_type *)pvReference;
+
+	if (menu_currentopen != pDiag->pSaveMenu ||
+	    pEvent->data.message.data.menuwarn.selection[0] != ICONBAR_INFO_FIELD) {
+		return FALSE;
+	}
+
+	Dialog2_OpenDialogMenuLeaf(pEvent, pInfoBox);
+	return TRUE;
+} /* end of bBarInfo */
+
+/*
+ * vBarInfoSetText - Set the iconbar infobox text
+ */
+static void
+vBarInfoSetText(dialog2_block *pBox)
+{
+	TRACE_MSG("vBarInfoSetText");
+
+	fail(pBox == NULL);
+	fail(pBox != pInfoBox);
+
+	Icon_SetText(pBox->window, PURPOSE_INFO_FIELD, PURPOSESTRING);
+	Icon_SetText(pBox->window, AUTHOR_INFO_FIELD, AUTHORSTRING);
+	Icon_SetText(pBox->window, VERSION_INFO_FIELD, VERSIONSTRING);
+	Icon_SetText(pBox->window, STATUS_INFO_FIELD, STATUSSTRING);
+} /* end of vBarInfoSetText */
+
+/*
+ * bMouseButtonClick - respond to mouse button click
+ */
+static BOOL
+bMouseButtonClick(event_pollblock *pEvent, void *pvReference)
+{
+	diagram_type	*pDiag;
+	menu_ptr	pMenu;
+	int		iPosY;
+
+	TRACE_MSG("bMouseButtonClick");
+
+	fail(pEvent == NULL);
+	fail(pEvent->type != event_CLICK);
+	fail(pvReference == NULL);
+
+	pDiag = (diagram_type *)pvReference;
+
+	if (pEvent->data.mouse.button.data.menu) {
+		pMenu = pDiag->pSaveMenu;
+		iPosY = (pMenu == tDummyDiagram.pSaveMenu) ?
+					-1 : pEvent->data.mouse.pos.y;
+		Menu_Show(pMenu, pEvent->data.mouse.pos.x, iPosY);
+		return TRUE;
+	}
+	if (pEvent->data.mouse.window == pDiag->tMainWindow &&
+	    pEvent->data.mouse.icon == -1) {
+		vMainButtonClick(&pEvent->data.mouse);
+		return TRUE;
+	}
+	if (pEvent->data.mouse.window == pDiag->tScaleWindow &&
+	    pEvent->data.mouse.icon >= 0) {
+		vScaleButtonClick(&pEvent->data.mouse, pDiag);
+		return TRUE;
+	}
+	return FALSE;
+} /* end of bMouseButtonClick */
+
+/*
+ * bAutoRedrawWindow - the redraw is handled by the WIMP
+ */
+static BOOL
+bAutoRedrawWindow(event_pollblock *pEvent, void *pvReference)
+{
+	return TRUE;
+} /* end of bAutoRedrawWindow */
+
+static BOOL
+bSaveSelect(event_pollblock *pEvent, void *pvReference)
+{
+	TRACE_MSG("bSaveSelect");
+
+	fail(pEvent == NULL);
+	fail(pEvent->type != event_MENU);
+	fail(pvReference == NULL);
+
+	DBG_DEC(pEvent->data.selection[0]);
+
+	switch (pEvent->data.selection[0]) {
+	case SAVEMENU_SCALEVIEW:
+		return bScaleOpenAction(pEvent, pvReference);
+	case SAVEMENU_SAVEDRAW:
+		return bSaveDrawfile(pEvent, pvReference);
+	case SAVEMENU_SAVETEXT:
+		return bSaveTextfile(pEvent, pvReference);
+	default:
+		DBG_DEC(pEvent->data.selection[0]);
+		return FALSE;
+	}
+} /* end of bSaveSelect */
+
+/*
+ * Create the window for the text from the given file
+ */
+static diagram_type *
+pCreateTextWindow(const char *szFilename)
+{
+	diagram_type	*pDiag;
+
+	TRACE_MSG("pCreateTextWindow");
+
+	fail(szFilename == NULL || szFilename[0] == '\0');
+
+	/* Create the diagram */
+	pDiag = pCreateDiagram(szTask+1, szFilename);
+	if (pDiag == NULL) {
+		werr(0, "Sorry, no new diagram object");
+		return NULL;
+	}
+
+	/* Prepare a save menu for this diagram */
+	pDiag->pSaveMenu = Menu_New(szTask+1,
+		">Scale view,"
+		">Save (Drawfile)   F3,"
+		">Save (Text only) \213F3");
+	if (pDiag->pSaveMenu == NULL) {
+		werr(1, "Sorry, no Savemenu object");
+	}
+	Menu_Warn(pDiag->pSaveMenu, SAVEMENU_SCALEVIEW,
+					TRUE, bScaleOpenAction, pDiag);
+	Menu_Warn(pDiag->pSaveMenu, SAVEMENU_SAVEDRAW,
+					TRUE, bSaveDrawfile, pDiag);
+	Menu_Warn(pDiag->pSaveMenu, SAVEMENU_SAVETEXT,
+					TRUE, bSaveTextfile, pDiag);
+
+	/* Claim events for the main window */
+        Event_Claim(event_REDRAW, pDiag->tMainWindow, icon_ANY,
+                                        bRedrawMainWindow, pDiag);
+        Event_Claim(event_CLOSE, pDiag->tMainWindow, icon_ANY,
+                                        bDestroyDiagram, pDiag);
+        Event_Claim(event_CLICK, pDiag->tMainWindow, icon_ANY,
+                                        bMouseButtonClick, pDiag);
+        Event_Claim(event_KEY, pDiag->tMainWindow, icon_ANY,
+                                        bMainKeyPressed, pDiag);
+
+	/* Claim events for the scale window */
+	Event_Claim(event_REDRAW, pDiag->tScaleWindow, icon_ANY,
+					bAutoRedrawWindow, NULL);
+        Event_Claim(event_CLICK, pDiag->tScaleWindow, icon_ANY,
+                                        bMouseButtonClick, pDiag);
+        Event_Claim(event_KEY, pDiag->tScaleWindow, icon_ANY,
+                                        bScaleKeyPressed, pDiag);
+
+	/* Set the window title */
+	vSetTitle(pDiag);
+	return pDiag;
+} /* end of pCreateTextWindow */
+
+/*
+ * vProcessFile - process one file
+ */
+static void
+vProcessFile(const char *szFilename, int iFiletype)
+{
+	options_type	tOptions;
+	FILE		*pFile;
+	diagram_type	*pDiag;
+	long		lFilesize;
+	int		iWordVersion;
+
+	TRACE_MSG("vProcessFile");
+
+	fail(szFilename == NULL || szFilename[0] == '\0');
+
+	DBG_MSG(szFilename);
+
+	pFile = fopen(szFilename, "rb");
+	if (pFile == NULL) {
+		werr(0, "I can't open '%s' for reading", szFilename);
+		return;
+	}
+
+	lFilesize = lGetFilesize(szFilename);
+	if (lFilesize < 0) {
+		(void)fclose(pFile);
+		werr(0, "I can't get the size of '%s'", szFilename);
+		return;
+	}
+
+	iWordVersion = iGuessVersionNumber(pFile, lFilesize);
+	if (iWordVersion < 0 || iWordVersion == 3) {
+		if (bIsRtfFile(pFile)) {
+			werr(0, "%s is not a Word Document."
+				" It is probably a Rich Text Format file",
+				szFilename);
+		} if (bIsWordPerfectFile(pFile)) {
+			werr(0, "%s is not a Word Document."
+				" It is probably a Word Perfect file",
+				szFilename);
+		} else {
+			werr(0, "%s is not a Word Document.", szFilename);
+		}
+		(void)fclose(pFile);
+		return;
+	}
+	/* Reset any reading done during file-testing */
+	rewind(pFile);
+
+	if (iFiletype != FILETYPE_MSWORD) {
+		vGetOptions(&tOptions);
+		if (tOptions.bAutofiletypeAllowed) {
+			vSetFiletype(szFilename, FILETYPE_MSWORD);
+		}
+	}
+
+	pDiag = pCreateTextWindow(szFilename);
+	if (pDiag == NULL) {
+		(void)fclose(pFile);
+		return;
+	}
+
+	(void)bWordDecryptor(pFile, lFilesize, pDiag);
+	Error_CheckFatal(Drawfile_VerifyDiagram(&pDiag->tInfo));
+	vShowDiagram(pDiag);
+	TRACE_MSG("After vShowDiagram");
+
+	TRACE_MSG("before debug print");
+	DBG_HEX(pFile);
+	TRACE_MSG("before fclose");
+	(void)fclose(pFile);
+	TRACE_MSG("after fclose");
+} /* end of vProcessFile */
+
+/*
+ * vSendAck - send an acknowledge
+ */
+static void
+vSendAck(event_pollblock *pEvent)
+{
+	message_block	tMessage;
+
+	TRACE_MSG("vSendAck");
+
+	fail(pEvent == NULL);
+	fail(pEvent->type != event_SEND && pEvent->type != event_SENDWANTACK);
+	fail(pEvent->data.message.header.action != message_DATALOAD &&
+		pEvent->data.message.header.action != message_DATAOPEN);
+
+	tMessage.header.action = message_DATALOADACK;
+	tMessage.header.size = sizeof(tMessage);
+	tMessage.header.yourref = pEvent->data.message.header.myref;
+	Error_CheckFatal(Wimp_SendMessage(event_SEND, &tMessage,
+				pEvent->data.message.header.sender, 0));
+} /* end of vSendAck */
+
+static BOOL
+bEventMsgHandler(event_pollblock *pEvent, void *pvReference)
+{
+	TRACE_MSG("bEventMsgHandler");
+
+	fail(pEvent == NULL);
+
+	switch (pEvent->type) {
+	case event_SEND:
+	case event_SENDWANTACK:
+		switch (pEvent->data.message.header.action) {
+		case message_CLOSEDOWN:
+			exit(EXIT_SUCCESS);
+			break;
+		case message_DATALOAD:
+		case message_DATAOPEN:
+			vProcessFile(
+				pEvent->data.message.data.dataload.filename,
+				pEvent->data.message.data.dataload.filetype);
+			vSendAck(pEvent);
+			break;
+		default:
+			DBG_DEC(pEvent->data.message.header.action);
+			break;
+		}
+		return TRUE;
+	default:
+		DBG_DEC(pEvent->type);
+		return FALSE;
+	}
+} /* end of bEventMsgHandler */
+
+/*
+ * bMenuSelect - select from the iconbar menu
+ */
+static BOOL
+bMenuSelect(event_pollblock *pEvent, void *pvReference)
+{
+	TRACE_MSG("bMenuSelect");
+
+	fail(pEvent == NULL);
+	fail(pEvent->type != event_MENU);
+
+	DBG_DEC(pEvent->data.selection[0]);
+
+	switch (pEvent->data.selection[0]) {
+	case ICONBAR_INFO_FIELD:
+		return bBarInfo(pEvent, pvReference);
+	case ICONBAR_CHOICES_FIELD:
+		vChoicesOpenAction(tChoicesWindow);
+		Window_BringToFront(tChoicesWindow);
+		break;
+	case ICONBAR_QUIT_FIELD:
+		TRACE_MSG("before exit");
+		exit(EXIT_SUCCESS);
+		break;
+	default:
+		DBG_DEC(pEvent->data.selection[0]);
+		break;
+	}
+	return TRUE;
+} /* end of bMenuSelect */
+
+/*
+ * bMenuClick - respond to an menu click
+ */
+static BOOL
+bMenuClick(event_pollblock *pEvent, void *pvReference)
+{
+	TRACE_MSG("bMenuClick");
+
+	fail(pEvent == NULL);
+	fail(pEvent->type != event_MENU);
+
+	if (menu_currentopen == tDummyDiagram.pSaveMenu) {
+		return bMenuSelect(pEvent, pvReference);
+	} else if (pvReference == NULL) {
+		return FALSE;
+	}
+	return bSaveSelect(pEvent, pvReference);
+} /* end of bMenuClick */
+
+static void
+vTemplates(void)
+{
+	TRACE_MSG("vTemplates");
+
+	Template_Initialise();
+	Template_LoadFile("Templates");
+
+	tChoicesWindow = Window_Create("Choices", template_TITLEMIN);
+	if (tChoicesWindow == 0) {
+		werr(1, "I can't find the 'Choices' template");
+	}
+
+	/* Claim events for the choices window */
+	Event_Claim(event_REDRAW, tChoicesWindow, icon_ANY,
+					bAutoRedrawWindow, NULL);
+	Event_Claim(event_CLICK, tChoicesWindow, icon_ANY,
+					bChoicesMouseClick, NULL);
+	Event_Claim(event_KEY, tChoicesWindow, icon_ANY,
+					bChoicesKeyPressed, NULL);
+} /* end of vTemplates */
+
+static void
+vInitialise(void)
+{
+	int	aiMessages[] = {0};
+	icon_handle	tBarIcon;
+
+
+	TRACE_MSG("vInitialise");
+
+	Resource_Initialise(szTask+1);
+	Event_Initialise3(szTask+1, 310, aiMessages);
+	EventMsg_Initialise();
+	Screen_CacheModeInfo();
+#if defined(__GNUC__)
+	flex_init(szTask+1, 0, 0);
+	flex_set_budge(1);
+#endif /* __GNUC__ */
+	vTemplates();
+
+	/* Prepare iconbar menu */
+	tDummyDiagram.tInfo.data = NULL;
+	tDummyDiagram.tInfo.length = 0;
+	tDummyDiagram.pSaveMenu = Menu_New(szTask+1, ">Info,Choices...,Quit");
+	if (tDummyDiagram.pSaveMenu == NULL) {
+		werr(1, "Sorry, no Barmenu object");
+	}
+	pInfoBox = Dialog2_CreateDialogBlock("ProgInfo", -1, -1,
+					vBarInfoSetText, NULL, NULL);
+
+	if (pInfoBox == NULL) {
+		werr(1, "Sorry, no Infobox object");
+	}
+	Menu_Warn(tDummyDiagram.pSaveMenu, ICONBAR_INFO_FIELD,
+					TRUE, bBarInfo, &tDummyDiagram);
+
+	/* Create an icon on the icon bar */
+	tBarIcon = Icon_BarIcon(szTask, iconbar_RIGHT);
+	Event_Claim(event_CLICK, window_ICONBAR, tBarIcon,
+					bMouseButtonClick, &tDummyDiagram);
+
+	/* Generic claims */
+	Event_Claim(event_OPEN, window_ANY, icon_ANY,
+					Handler_OpenWindow, NULL);
+	Event_Claim(event_CLOSE, window_ANY, icon_ANY,
+					Handler_CloseWindow, NULL);
+	Event_Claim(event_MENU, window_ANY, icon_ANY,
+					bMenuClick, NULL);
+	EventMsg_Claim(message_DATALOAD, window_ICONBAR,
+					bEventMsgHandler, NULL);
+	EventMsg_Claim(message_MODECHANGE, window_ANY,
+					Handler_ModeChange, NULL);
+} /* end of vInitialise */
+
+int
+main(int argc, char **argv)
+{
+	int	iFirst, iFiletype;
+
+	TRACE_MSG("main");
+
+	vInitialise();
+	iFirst = iReadOptions(argc, argv);
+	if (iFirst != 1) {
+		return EXIT_FAILURE;
+	}
+
+	if (argc > 1) {
+		iFiletype = iGetFiletype(argv[1]);
+		if (iFiletype < 0) {
+			return EXIT_FAILURE;
+		}
+		vProcessFile(argv[1], iFiletype);
+		TRACE_MSG("main after vProcessFile");
+	}
+
+	for (;;) {
+		Event_Poll();
+	}
+} /* end of main */
diff --git a/main_u.c b/main_u.c
new file mode 100644
index 0000000..4eaaea3
--- /dev/null
+++ b/main_u.c
@@ -0,0 +1,321 @@
+/*
+ * main_u.c
+ *
+ * Released under GPL
+ *
+ * Copyright (C) 1998-2004 A.J. van Os
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * Description:
+ * The main program of 'antiword' (Unix version)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#if defined(__dos)
+#include <fcntl.h>
+#include <io.h>
+#endif /* __dos */
+#if defined(__CYGWIN__) || defined(__CYGMING__)
+#  ifdef X_LOCALE
+#    include <X11/Xlocale.h>
+#  else
+#    include <locale.h>
+#  endif
+#else
+#include <locale.h>
+#endif /* __CYGWIN__ || __CYGMING__ */
+#if defined(N_PLAT_NLM)
+#if !defined(_VA_LIST)
+#include "NW-only/nw_os.h"
+#endif /* !_VA_LIST */
+#include "getopt.h"
+#endif /* N_PLAT_NLM */
+#include "version.h"
+#include "antiword.h"
+
+/* The name of this program */
+static const char	*szTask = NULL;
+
+
+static void
+vUsage(void)
+{
+	fprintf(stderr, "\tName: %s\n", szTask);
+	fprintf(stderr, "\tPurpose: "PURPOSESTRING"\n");
+	fprintf(stderr, "\tAuthor: "AUTHORSTRING"\n");
+	fprintf(stderr, "\tVersion: "VERSIONSTRING);
+#if defined(__dos)
+	fprintf(stderr, VERSIONSTRING2);
+#endif /* __dos */
+	fprintf(stderr, "\n");
+	fprintf(stderr, "\tStatus: "STATUSSTRING"\n");
+	fprintf(stderr,
+		"\tUsage: %s [switches] wordfile1 [wordfile2 ...]\n", szTask);
+	fprintf(stderr,
+		"\tSwitches: [-f|-t|-a papersize|-p papersize|-x dtd]"
+		"[-m mapping][-w #][-i #][-Ls]\n");
+	fprintf(stderr, "\t\t-f formatted text output\n");
+	fprintf(stderr, "\t\t-t text output (default)\n");
+	fprintf(stderr, "\t\t-a <paper size name> Adobe PDF output\n");
+	fprintf(stderr, "\t\t-p <paper size name> PostScript output\n");
+	fprintf(stderr, "\t\t   paper size like: a4, letter or legal\n");
+	fprintf(stderr, "\t\t-x <dtd> XML output\n");
+	fprintf(stderr, "\t\t   like: db (DocBook)\n");
+	fprintf(stderr, "\t\t-m <mapping> character mapping file\n");
+	fprintf(stderr, "\t\t-w <width> in characters of text output\n");
+	fprintf(stderr, "\t\t-i <level> image level (PostScript only)\n");
+	fprintf(stderr, "\t\t-L use landscape mode (PostScript only)\n");
+	fprintf(stderr, "\t\t-r Show removed text\n");
+	fprintf(stderr, "\t\t-s Show hidden (by Word) text\n");
+} /* end of vUsage */
+
+/*
+ * pStdin2TmpFile - save stdin in a temporary file
+ *
+ * returns: the pointer to the temporary file or NULL
+ */
+static FILE *
+pStdin2TmpFile(long *lFilesize)
+{
+	FILE	*pTmpFile;
+	size_t	tSize;
+	BOOL	bFailure;
+	UCHAR	aucBytes[BUFSIZ];
+
+	DBG_MSG("pStdin2TmpFile");
+
+	fail(lFilesize == NULL);
+
+	/* Open the temporary file */
+	pTmpFile = tmpfile();
+	if (pTmpFile == NULL) {
+		return NULL;
+	}
+
+#if defined(__dos)
+	/* Stdin must be read as a binary stream */
+	setmode(fileno(stdin), O_BINARY);
+#endif /* __dos */
+
+	/* Copy stdin to the temporary file */
+	*lFilesize = 0;
+	bFailure = TRUE;
+	for (;;) {
+		tSize = fread(aucBytes, 1, sizeof(aucBytes), stdin);
+		if (tSize == 0) {
+			bFailure = feof(stdin) == 0;
+			break;
+		}
+		if (fwrite(aucBytes, 1, tSize, pTmpFile) != tSize) {
+			bFailure = TRUE;
+			break;
+		}
+		*lFilesize += (long)tSize;
+	}
+
+#if defined(__dos)
+	/* Switch stdin back to a text stream */
+	setmode(fileno(stdin), O_TEXT);
+#endif /* __dos */
+
+	/* Deal with the result of the copy action */
+	if (bFailure) {
+		*lFilesize = 0;
+		(void)fclose(pTmpFile);
+		return NULL;
+	}
+	rewind(pTmpFile);
+	return pTmpFile;
+} /* end of pStdin2TmpFile */
+
+/*
+ * bProcessFile - process a single file
+ *
+ * returns: TRUE when the given file is a supported Word file, otherwise FALSE
+ */
+static BOOL
+bProcessFile(const char *szFilename)
+{
+	FILE		*pFile;
+	diagram_type	*pDiag;
+	long		lFilesize;
+	int		iWordVersion;
+	BOOL		bResult;
+
+	fail(szFilename == NULL || szFilename[0] == '\0');
+
+	DBG_MSG(szFilename);
+
+	if (szFilename[0] == '-' && szFilename[1] == '\0') {
+		pFile = pStdin2TmpFile(&lFilesize);
+		if (pFile == NULL) {
+			werr(0, "I can't save the standard input to a file");
+			return FALSE;
+		}
+	} else {
+		pFile = fopen(szFilename, "rb");
+		if (pFile == NULL) {
+			werr(0, "I can't open '%s' for reading", szFilename);
+			return FALSE;
+		}
+
+		lFilesize = lGetFilesize(szFilename);
+		if (lFilesize < 0) {
+			(void)fclose(pFile);
+			werr(0, "I can't get the size of '%s'", szFilename);
+			return FALSE;
+		}
+	}
+
+	iWordVersion = iGuessVersionNumber(pFile, lFilesize);
+	if (iWordVersion < 0 || iWordVersion == 3) {
+		if (bIsRtfFile(pFile)) {
+			werr(0, "%s is not a Word Document."
+				" It is probably a Rich Text Format file",
+				szFilename);
+		} if (bIsWordPerfectFile(pFile)) {
+			werr(0, "%s is not a Word Document."
+				" It is probably a Word Perfect file",
+				szFilename);
+		} else {
+#if defined(__dos)
+			werr(0, "%s is not a Word Document or the filename"
+				" is not in the 8+3 format.", szFilename);
+#else
+			werr(0, "%s is not a Word Document.", szFilename);
+#endif /* __dos */
+		}
+		(void)fclose(pFile);
+		return FALSE;
+	}
+	/* Reset any reading done during file testing */
+	rewind(pFile);
+
+	pDiag = pCreateDiagram(szTask, szFilename);
+	if (pDiag == NULL) {
+		(void)fclose(pFile);
+		return FALSE;
+	}
+
+	bResult = bWordDecryptor(pFile, lFilesize, pDiag);
+	vDestroyDiagram(pDiag);
+
+	(void)fclose(pFile);
+	return bResult;
+} /* end of bProcessFile */
+
+int
+main(int argc, char **argv)
+{
+	options_type	tOptions;
+	const char	*szWordfile;
+	int	iFirst, iIndex, iGoodCount;
+	BOOL	bUsage, bMultiple, bUseTXT, bUseXML;
+
+	if (argc <= 0) {
+		return EXIT_FAILURE;
+	}
+
+	szTask = szBasename(argv[0]);
+
+	if (argc <= 1) {
+		iFirst = 1;
+		bUsage = TRUE;
+	} else {
+		iFirst = iReadOptions(argc, argv);
+		bUsage = iFirst <= 0;
+	}
+	if (bUsage) {
+		vUsage();
+		return iFirst < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+	}
+
+#if defined(N_PLAT_NLM) && !defined(_VA_LIST)
+	nwinit();
+#endif /* N_PLAT_NLM && !_VA_LIST */
+
+	vGetOptions(&tOptions);
+
+#if !defined(__dos)
+	if (is_locale_utf8()) {
+#if defined(__STDC_ISO_10646__)
+		/*
+		 * If the user wants UTF-8 and the envirionment variables
+		 * support UTF-8, than set the locale accordingly
+		 */
+		if (tOptions.eEncoding == encoding_utf_8) {
+			if (setlocale(LC_CTYPE, "") == NULL) {
+				werr(1, "Can't set the UTF-8 locale! "
+					"Check LANG, LC_CTYPE, LC_ALL.");
+			}
+			DBG_MSG("The UTF-8 locale has been set");
+		} else {
+			(void)setlocale(LC_CTYPE, "C");
+		}
+#endif /* __STDC_ISO_10646__ */
+	} else {
+		if (setlocale(LC_CTYPE, "") == NULL) {
+			werr(0, "Can't set the locale! Will use defaults");
+			(void)setlocale(LC_CTYPE, "C");
+		}
+		DBG_MSG("The locale has been set");
+	}
+#endif /* !__dos */
+
+	bMultiple = argc - iFirst > 1;
+	bUseTXT = tOptions.eConversionType == conversion_text ||
+		tOptions.eConversionType == conversion_fmt_text;
+	bUseXML = tOptions.eConversionType == conversion_xml;
+	iGoodCount = 0;
+
+#if defined(__dos)
+	if (tOptions.eConversionType == conversion_pdf) {
+		/* PDF must be written as a binary stream */
+		setmode(fileno(stdout), O_BINARY);
+	}
+#endif /* __dos */
+
+	if (bUseXML) {
+		fprintf(stdout,
+	"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+	"<!DOCTYPE %s PUBLIC \"-//OASIS//DTD DocBook XML V4.1.2//EN\"\n"
+	"\t\"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd\">\n",
+		bMultiple ? "set" : "book");
+		if (bMultiple) {
+			fprintf(stdout, "<set>\n");
+		}
+	}
+
+	for (iIndex = iFirst; iIndex < argc; iIndex++) {
+		if (bMultiple && bUseTXT) {
+			szWordfile = szBasename(argv[iIndex]);
+			fprintf(stdout, "::::::::::::::\n");
+			fprintf(stdout, "%s\n", szWordfile);
+			fprintf(stdout, "::::::::::::::\n");
+		}
+		if (bProcessFile(argv[iIndex])) {
+			iGoodCount++;
+		}
+	}
+
+	if (bMultiple && bUseXML) {
+		fprintf(stdout, "</set>\n");
+	}
+
+	DBG_DEC(iGoodCount);
+	return iGoodCount <= 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+} /* end of main */
diff --git a/misc.c b/misc.c
new file mode 100644
index 0000000..609a2f0
--- /dev/null
+++ b/misc.c
@@ -0,0 +1,894 @@
+/*
+ * misc.c
+ * Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Miscellaneous functions
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+#if defined(__riscos)
+#include "DeskLib:SWI.h"
+#else
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif /* __riscos */
+#if !defined(S_ISREG)
+#define S_ISREG(x)	(((x) & S_IFMT) == S_IFREG)
+#endif /* !S_ISREG */
+#include "antiword.h"
+#if defined(__vms)
+#include <unixlib.h>
+#endif
+
+#if !defined(__riscos)
+/*
+ * szGetHomeDirectory - get the name of the home directory
+ */
+const char *
+szGetHomeDirectory(void)
+{
+	const char	*szHome;
+
+#if defined(__vms)
+	szHome = decc$translate_vms(getenv("HOME"));
+#elif defined(__Plan9__)
+	szHome = getenv("home");
+#else
+	szHome = getenv("HOME");
+#endif /* __vms */
+
+	if (szHome == NULL || szHome[0] == '\0') {
+#if defined(N_PLAT_NLM)
+		szHome = "SYS:";
+#elif defined(__dos)
+		szHome = "C:";
+#else
+		werr(0, "I can't find the name of your HOME directory");
+		szHome = "";
+#endif /* __dos */
+	}
+	return szHome;
+} /* end of szGetHomeDirectory */
+
+/*
+ * szGetAntiwordDirectory - get the name of the Antiword directory
+ */
+const char *
+szGetAntiwordDirectory(void)
+{
+#if defined(__vms)
+	return decc$translate_vms(getenv("ANTIWORDHOME"));
+#else
+	return getenv("ANTIWORDHOME");
+#endif /* __vms */
+} /* end of szGetAntiwordDirectory */
+#endif /* !__riscos */
+
+/*
+ * Get the size of the specified file.
+ * Returns -1 if the file does not exist or is not a proper file.
+ */
+long
+lGetFilesize(const char *szFilename)
+{
+#if defined(__riscos)
+	os_error	*e;
+	int	iType, iSize;
+
+	e = SWI(2, 5, SWI_OS_File | XOS_Bit,
+		17, szFilename,
+		&iType, NULL, NULL, NULL, &iSize);
+	if (e != NULL) {
+		werr(0, "Get Filesize error %d: %s",
+			e->errnum, e->errmess);
+		return -1;
+	}
+	if (iType != 1) {
+		/* It's not a proper file or the file does not exist */
+		return -1;
+	}
+	return (long)iSize;
+#else
+	struct stat	tBuffer;
+
+	errno = 0;
+	if (stat(szFilename, &tBuffer) != 0) {
+		werr(0, "Get Filesize error %d", errno);
+		return -1;
+	}
+	if (!S_ISREG(tBuffer.st_mode)) {
+		/* It's not a regular file */
+		return -1;
+	}
+	return (long)tBuffer.st_size;
+#endif /* __riscos */
+} /* end of lGetFilesize */
+
+#if defined(DEBUG)
+void
+vPrintBlock(const char	*szFile, int iLine,
+		const UCHAR *aucBlock, size_t tLength)
+{
+	int i, j;
+
+	fail(szFile == NULL || iLine < 0 || aucBlock == NULL);
+
+	fprintf(stderr, "%s[%3d]:\n", szFile, iLine);
+	for (i = 0; i < 32; i++) {
+		if (16 * i >= (int)tLength) {
+			return;
+		}
+		fprintf(stderr, "%03x: ", (unsigned int)(16 * i));
+		for (j = 0; j < 16; j++) {
+			if (16 * i + j < (int)tLength) {
+				fprintf(stderr, "%02x ",
+					(unsigned int)aucBlock[16 * i + j]);
+			}
+		}
+		fprintf(stderr, "\n");
+	}
+} /* end of vPrintBlock */
+
+void
+vPrintUnicode(const char *szFile, int iLine, const UCHAR *aucUni, size_t tLen)
+{
+	char	*szASCII;
+
+	fail(tLen % 2 != 0);
+
+	tLen /= 2;	/* Length in bytes to length in characters */
+	szASCII = xmalloc(tLen + 1);
+	(void)unincpy(szASCII, aucUni, tLen);
+	szASCII[tLen] = '\0';
+	(void)fprintf(stderr, "%s[%3d]: %.*s\n",
+				szFile, iLine, (int)tLen, szASCII);
+	szASCII = xfree(szASCII);
+} /* end of vPrintUnicode */
+
+BOOL
+bCheckDoubleLinkedList(output_type *pAnchor)
+{
+	output_type	*pCurr, *pLast;
+	int		iInList;
+
+	pLast = pAnchor;
+	iInList = 0;
+	for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
+		pLast = pCurr;
+		iInList++;
+	}
+	NO_DBG_DEC(iInList);
+	for (pCurr = pLast; pCurr != NULL; pCurr = pCurr->pPrev) {
+		pLast = pCurr;
+		iInList--;
+	}
+	DBG_DEC_C(iInList != 0, iInList);
+	return pAnchor == pLast && iInList == 0;
+} /* end of bCheckDoubleLinkedList */
+#endif /* DEBUG */
+
+/*
+ * bReadBytes
+ * This function reads the specified number of bytes from the specified file,
+ * starting from the specified offset.
+ * Returns TRUE when successfull, otherwise FALSE
+ */
+BOOL
+bReadBytes(UCHAR *aucBytes, size_t tMemb, ULONG ulOffset, FILE *pFile)
+{
+	fail(aucBytes == NULL || pFile == NULL || ulOffset > (ULONG)LONG_MAX);
+
+	if (ulOffset > (ULONG)LONG_MAX) {
+		return FALSE;
+	}
+	if (fseek(pFile, (long)ulOffset, SEEK_SET) != 0) {
+		return FALSE;
+	}
+	if (fread(aucBytes, sizeof(UCHAR), tMemb, pFile) != tMemb) {
+		return FALSE;
+	}
+	return TRUE;
+} /* end of bReadBytes */
+
+/*
+ * bReadBuffer
+ * This function fills the specified buffer with the specified number of bytes,
+ * starting at the specified offset within the Big/Small Block Depot.
+ *
+ * Returns TRUE when successful, otherwise FALSE
+ */
+BOOL
+bReadBuffer(FILE *pFile, ULONG ulStartBlock,
+	const ULONG *aulBlockDepot, size_t tBlockDepotLen, size_t tBlockSize,
+	UCHAR *aucBuffer, ULONG ulOffset, size_t tToRead)
+{
+	ULONG	ulBegin, ulIndex;
+	size_t	tLen;
+
+	fail(pFile == NULL);
+	fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
+	fail(aulBlockDepot == NULL);
+	fail(tBlockSize != BIG_BLOCK_SIZE && tBlockSize != SMALL_BLOCK_SIZE);
+	fail(aucBuffer == NULL);
+	fail(tToRead == 0);
+
+	for (ulIndex = ulStartBlock;
+	     ulIndex != END_OF_CHAIN && tToRead != 0;
+	     ulIndex = aulBlockDepot[ulIndex]) {
+		if (ulIndex >= (ULONG)tBlockDepotLen) {
+			DBG_DEC(ulIndex);
+			DBG_DEC(tBlockDepotLen);
+			if (tBlockSize >= BIG_BLOCK_SIZE) {
+				werr(1, "The Big Block Depot is damaged");
+			} else {
+				werr(1, "The Small Block Depot is damaged");
+			}
+		}
+		if (ulOffset >= (ULONG)tBlockSize) {
+			ulOffset -= tBlockSize;
+			continue;
+		}
+		ulBegin = ulDepotOffset(ulIndex, tBlockSize) + ulOffset;
+		tLen = min(tBlockSize - (size_t)ulOffset, tToRead);
+		ulOffset = 0;
+		if (!bReadBytes(aucBuffer, tLen, ulBegin, pFile)) {
+			werr(0, "Read big block 0x%lx not possible", ulBegin);
+			return FALSE;
+		}
+		aucBuffer += tLen;
+		tToRead -= tLen;
+	}
+	DBG_DEC_C(tToRead != 0, tToRead);
+	return tToRead == 0;
+} /* end of bReadBuffer */
+
+/*
+ * Convert a Word colornumber into a true color for use in a drawfile
+ *
+ * Returns the true color
+ */
+ULONG
+ulColor2Color(UCHAR ucFontColor)
+{
+	static const ULONG	aulColorTable[] = {
+		/*  0 */	0x00000000UL,	/* Automatic */
+		/*  1 */	0x00000000UL,	/* Black */
+		/*  2 */	0xff000000UL,	/* Blue */
+		/*  3 */	0xffff0000UL,	/* Turquoise */
+		/*  4 */	0x00ff0000UL,	/* Bright Green */
+		/*  5 */	0xff00ff00UL,	/* Pink */
+		/*  6 */	0x0000ff00UL,	/* Red */
+		/*  7 */	0x00ffff00UL,	/* Yellow */
+		/*  8 */	0xffffff00UL,	/* White */
+		/*  9 */	0x80000000UL,	/* Dark Blue */
+		/* 10 */	0x80800000UL,	/* Teal */
+		/* 11 */	0x00800000UL,	/* Green */
+		/* 12 */	0x80008000UL,	/* Violet */
+		/* 13 */	0x00008000UL,	/* Dark Red */
+		/* 14 */	0x00808000UL,	/* Dark Yellow */
+		/* 15 */	0x80808000UL,	/* Gray 50% */
+		/* 16 */	0xc0c0c000UL,	/* Gray 25% */
+	};
+	if ((size_t)ucFontColor >= elementsof(aulColorTable)) {
+		return aulColorTable[0];
+	}
+	return aulColorTable[(int)ucFontColor];
+} /* end of ulColor2Color */
+
+/*
+ * iFindSplit - find a place to split the string
+ *
+ * returns the index of the split character or -1 if no split found.
+ */
+static int
+iFindSplit(const char *szString, size_t tStringLen)
+{
+	size_t	tSplit;
+
+	if (tStringLen == 0) {
+		return -1;
+	}
+	tSplit = tStringLen - 1;
+	while (tSplit >= 1) {
+		if (szString[tSplit] == ' ' ||
+		    (szString[tSplit] == '-' && szString[tSplit - 1] != ' ')) {
+			return (int)tSplit;
+		}
+		tSplit--;
+	}
+	return -1;
+} /* end of iFindSplit */
+
+/*
+ * pSplitList - split the specified list in a printable part and a leftover part
+ *
+ * returns the pointer to the leftover part
+ */
+output_type *
+pSplitList(output_type *pAnchor)
+{
+	output_type	*pCurr, *pLeftOver;
+	int		iIndex;
+
+ 	fail(pAnchor == NULL);
+
+	for (pCurr = pAnchor; pCurr->pNext != NULL; pCurr = pCurr->pNext)
+		;	/* EMPTY */
+	iIndex = -1;
+	for (; pCurr != NULL; pCurr = pCurr->pPrev) {
+		iIndex = iFindSplit(pCurr->szStorage, pCurr->tNextFree);
+		if (iIndex >= 0) {
+			break;
+		}
+	}
+
+	if (pCurr == NULL || iIndex < 0) {
+		/* No split, no leftover */
+		return NULL;
+	}
+	/* Split over the iIndex-th character */
+	NO_DBG_MSG("pLeftOver");
+	pLeftOver = xmalloc(sizeof(*pLeftOver));
+	fail(pCurr->tNextFree < (size_t)iIndex);
+	pLeftOver->tStorageSize = pCurr->tNextFree - (size_t)iIndex;
+	pLeftOver->szStorage = xmalloc(pLeftOver->tStorageSize);
+	pLeftOver->tNextFree = pCurr->tNextFree - (size_t)iIndex - 1;
+	(void)strncpy(pLeftOver->szStorage,
+		pCurr->szStorage + iIndex + 1, pLeftOver->tNextFree);
+	pLeftOver->szStorage[pLeftOver->tNextFree] = '\0';
+	NO_DBG_MSG(pLeftOver->szStorage);
+	pLeftOver->ucFontColor = pCurr->ucFontColor;
+	pLeftOver->usFontStyle = pCurr->usFontStyle;
+	pLeftOver->tFontRef = pCurr->tFontRef;
+	pLeftOver->usFontSize = pCurr->usFontSize;
+	pLeftOver->lStringWidth = lComputeStringWidth(
+					pLeftOver->szStorage,
+					pLeftOver->tNextFree,
+					pLeftOver->tFontRef,
+					pLeftOver->usFontSize);
+	pLeftOver->pPrev = NULL;
+	pLeftOver->pNext = pCurr->pNext;
+	if (pLeftOver->pNext != NULL) {
+		pLeftOver->pNext->pPrev = pLeftOver;
+	}
+	fail(!bCheckDoubleLinkedList(pLeftOver));
+
+	NO_DBG_MSG("pAnchor");
+	NO_DBG_HEX(pCurr->szStorage[iIndex]);
+	while (iIndex >= 0 && isspace((int)(UCHAR)pCurr->szStorage[iIndex])) {
+		iIndex--;
+	}
+	pCurr->tNextFree = (size_t)iIndex + 1;
+	pCurr->szStorage[pCurr->tNextFree] = '\0';
+	NO_DBG_MSG(pCurr->szStorage);
+	pCurr->lStringWidth = lComputeStringWidth(
+					pCurr->szStorage,
+					pCurr->tNextFree,
+					pCurr->tFontRef,
+					pCurr->usFontSize);
+	pCurr->pNext = NULL;
+	fail(!bCheckDoubleLinkedList(pAnchor));
+
+	return pLeftOver;
+} /* end of pSplitList */
+
+/*
+ * tNumber2Roman - convert a number to Roman Numerals
+ *
+ * returns the number of characters written
+ */
+size_t
+tNumber2Roman(UINT uiNumber, BOOL bUpperCase, char *szOutput)
+{
+	char	*outp, *p, *q;
+	UINT	uiNextVal, uiValue;
+
+	fail(szOutput == NULL);
+
+	uiNumber %= 4000;	/* Very high numbers can't be represented */
+	if (uiNumber == 0) {
+		szOutput[0] = '\0';
+		return 0;
+	}
+
+	outp = szOutput;
+	p = bUpperCase ? "M\2D\5C\2L\5X\2V\5I" : "m\2d\5c\2l\5x\2v\5i";
+	uiValue = 1000;
+	for (;;) {
+		while (uiNumber >= uiValue) {
+			*outp++ = *p;
+			uiNumber -= uiValue;
+		}
+		if (uiNumber == 0) {
+			*outp = '\0';
+			fail(outp < szOutput);
+			return (size_t)(outp - szOutput);
+		}
+		q = p + 1;
+		uiNextVal = uiValue / (UINT)(UCHAR)*q;
+		if ((int)*q == 2) {		/* magic */
+			uiNextVal /= (UINT)(UCHAR)*(q += 2);
+		}
+		if (uiNumber + uiNextVal >= uiValue) {
+			*outp++ = *++q;
+			uiNumber += uiNextVal;
+		} else {
+			p++;
+			uiValue /= (UINT)(UCHAR)(*p++);
+		}
+	}
+} /* end of tNumber2Roman */
+
+/*
+ * iNumber2Alpha - convert a number to alphabetic "numbers"
+ *
+ * returns the number of characters written
+ */
+size_t
+tNumber2Alpha(UINT uiNumber, BOOL bUpperCase, char *szOutput)
+{
+	char	*outp;
+	UINT	uiTmp;
+
+	fail(szOutput == NULL);
+
+	if (uiNumber == 0) {
+		szOutput[0] = '\0';
+		return 0;
+	}
+
+	outp = szOutput;
+	uiTmp = (UINT)(bUpperCase ? 'A': 'a');
+	if (uiNumber <= 26) {
+		uiNumber -= 1;
+		*outp++ = (char)(uiTmp + uiNumber);
+	} else if (uiNumber <= 26U + 26U*26U) {
+		uiNumber -= 26 + 1;
+		*outp++ = (char)(uiTmp + uiNumber / 26);
+		*outp++ = (char)(uiTmp + uiNumber % 26);
+	} else if (uiNumber <= 26U + 26U*26U + 26U*26U*26U) {
+		uiNumber -= 26 + 26*26 + 1;
+		*outp++ = (char)(uiTmp + uiNumber / (26*26));
+		*outp++ = (char)(uiTmp + uiNumber / 26 % 26);
+		*outp++ = (char)(uiTmp + uiNumber % 26);
+	}
+	*outp = '\0';
+	fail(outp < szOutput);
+	return (size_t)(outp - szOutput);
+} /* end of tNumber2Alpha */
+
+/*
+ * unincpy - copy a counted Unicode string to an single-byte string
+ */
+char *
+unincpy(char *s1, const UCHAR *s2, size_t n)
+{
+	char	*pcDest;
+	ULONG	ulChar;
+	size_t	tLen;
+	USHORT	usUni;
+
+	for (pcDest = s1, tLen = 0; tLen < n; pcDest++, tLen++) {
+		usUni = usGetWord(tLen * 2, s2);
+		if (usUni == 0) {
+			break;
+		}
+		ulChar = ulTranslateCharacters(usUni, 0, 8,
+				conversion_unknown, encoding_neutral, FALSE);
+		if (ulChar == IGNORE_CHARACTER) {
+			ulChar = (ULONG)'?';
+		}
+		*pcDest = (char)ulChar;
+	}
+	for (; tLen < n; tLen++) {
+		*pcDest++ = '\0';
+	}
+	return s1;
+} /* end of unincpy */
+
+/*
+ * unilen - calculate the length of a Unicode string
+ *
+ * returns the length in bytes
+ */
+size_t
+unilen(const UCHAR *s)
+{
+	size_t	tLen;
+	USHORT	usUni;
+
+	tLen = 0;
+	for (;;) {
+		usUni = usGetWord(tLen, s);
+		if (usUni == 0) {
+			return tLen;
+		}
+		tLen += 2;
+	}
+} /* end of unilen */
+
+/*
+ * szBaseName - get the basename of the specified filename
+ */
+const char *
+szBasename(const char *szFilename)
+{
+	const char	*szTmp;
+
+	fail(szFilename == NULL);
+
+	if (szFilename == NULL || szFilename[0] == '\0') {
+		return "null";
+	}
+
+	szTmp = strrchr(szFilename, FILE_SEPARATOR[0]);
+	if (szTmp == NULL) {
+		return szFilename;
+	}
+	return ++szTmp;
+} /* end of szBasename */
+
+/*
+ * lComputeLeading - compute the leading
+ *
+ * NOTE: the fontsize is specified in half points
+ *
+ * Returns the leading in drawunits
+ */
+long
+lComputeLeading(USHORT usFontSize)
+{
+	long	lLeading;
+
+	lLeading = (long)usFontSize * 500L;
+	if (usFontSize < 18) {		/* Small text: 112% */
+		lLeading *= 112;
+	} else if (usFontSize < 28) {	/* Normal text: 124% */
+		lLeading *= 124;
+	} else if (usFontSize < 48) {	/* Small headlines: 104% */
+		lLeading *= 104;
+	} else {			/* Large headlines: 100% */
+		lLeading *= 100;
+	}
+	lLeading = lMilliPoints2DrawUnits(lLeading);
+	lLeading += 50;
+	lLeading /= 100;
+	return lLeading;
+} /* end of lComputeLeading */
+
+/*
+ * Convert a UCS character to an UTF-8 string
+ *
+ * Returns the string length of the result
+ */
+size_t
+tUcs2Utf8(ULONG ulChar, char *szResult, size_t tMaxResultLen)
+{
+	if (szResult == NULL || tMaxResultLen == 0) {
+		return 0;
+	}
+
+	if (ulChar < 0x80 && tMaxResultLen >= 2) {
+		szResult[0] = (char)ulChar;
+		szResult[1] = '\0';
+		return 1;
+	}
+	if (ulChar < 0x800 && tMaxResultLen >= 3) {
+		szResult[0] = (char)(0xc0 | ulChar >> 6);
+		szResult[1] = (char)(0x80 | (ulChar & 0x3f));
+		szResult[2] = '\0';
+		return 2;
+	}
+	if (ulChar < 0x10000 && tMaxResultLen >= 4) {
+		szResult[0] = (char)(0xe0 | ulChar >> 12);
+		szResult[1] = (char)(0x80 | (ulChar >> 6 & 0x3f));
+		szResult[2] = (char)(0x80 | (ulChar & 0x3f));
+		szResult[3] = '\0';
+		return 3;
+	}
+	if (ulChar < 0x200000 && tMaxResultLen >= 5) {
+		szResult[0] = (char)(0xf0 | ulChar >> 18);
+		szResult[1] = (char)(0x80 | (ulChar >> 12 & 0x3f));
+		szResult[2] = (char)(0x80 | (ulChar >> 6 & 0x3f));
+		szResult[3] = (char)(0x80 | (ulChar & 0x3f));
+		szResult[4] = '\0';
+		return 4;
+	}
+	szResult[0] = '\0';
+	return 0;
+} /* end of tUcs2Utf8 */
+
+/*
+ * vGetBulletValue - get the bullet value for the conversing type and encoding
+ */
+void
+vGetBulletValue(conversion_type eConversionType, encoding_type eEncoding,
+	char *szResult, size_t tMaxResultLen)
+{
+	fail(szResult == NULL);
+	fail(tMaxResultLen < 2);
+
+	if (eEncoding == encoding_utf_8) {
+		(void)tUcs2Utf8(UNICODE_BULLET, szResult, tMaxResultLen);
+	} else {
+		szResult[0] = (char)ucGetBulletCharacter(eConversionType,
+							eEncoding);
+		szResult[1] = '\0';
+	}
+} /* end of vGetBulletValue */
+
+/*
+ * bAllZero - are all bytes zero?
+ */
+BOOL
+bAllZero(const UCHAR *aucBytes, size_t tLength)
+{
+	size_t	tIndex;
+
+	if (aucBytes == NULL || tLength == 0) {
+		return TRUE;
+	}
+
+	for (tIndex = 0; tIndex < tLength; tIndex++) {
+		if (aucBytes[tIndex] != 0) {
+			return FALSE;
+		}
+	}
+	return TRUE;
+} /* end of bAllZero */
+
+#if !defined(__riscos)
+/*
+ * GetCodesetFromLocale - get the codeset from the current locale
+ *
+ * Original version: Copyright (C) 1999  Bruno Haible
+ * Syntax:
+ * language[_territory][.codeset][@modifier][+special][,[sponsor][_revision]]
+ *
+ * Returns TRUE when sucessful, otherwise FALSE
+ */
+static BOOL
+bGetCodesetFromLocale(char *szCodeset, size_t tMaxCodesetLength, BOOL *pbEuro)
+{
+#if !defined(__dos)
+	const char	*szLocale;
+	const char	*pcTmp;
+	size_t		tIndex;
+	char		szModifier[6];
+#endif /* __dos */
+
+	if (pbEuro != NULL) {
+		*pbEuro = FALSE;	/* Until proven otherwise */
+	}
+	if (szCodeset == NULL || tMaxCodesetLength == 0) {
+		return FALSE;
+	}
+
+#if defined(__dos)
+	if (tMaxCodesetLength < 2 + sizeof(int) * 3 + 1) {
+		DBG_DEC(tMaxCodesetLength);
+		DBG_DEC(2 + sizeof(int) * 3 + 1);
+		return FALSE;
+	}
+	/* Get the active codepage from DOS */
+	sprintf(szCodeset, "cp%d", iGetCodepage());
+	DBG_MSG(szCodeset);
+#else
+	/* Get the locale from the environment */
+	szLocale = getenv("LC_ALL");
+	if (szLocale == NULL || szLocale[0] == '\0') {
+		szLocale = getenv("LC_CTYPE");
+		if (szLocale == NULL || szLocale[0] == '\0') {
+			szLocale = getenv("LANG");
+		}
+	}
+	if (szLocale == NULL || szLocale[0] == '\0') {
+		/* No locale, so no codeset name and no modifier */
+		return FALSE;
+	}
+	DBG_MSG(szLocale);
+	pcTmp = strchr(szLocale, '.');
+	if (pcTmp == NULL) {
+		/* No codeset name */
+		szCodeset[0] = '\0';
+	} else {
+		/* Copy the codeset name */
+		pcTmp++;
+		for (tIndex = 0; tIndex < tMaxCodesetLength; tIndex++) {
+			if (*pcTmp == '@' || *pcTmp == '+' ||
+			    *pcTmp == ',' || *pcTmp == '_' ||
+			    *pcTmp == '\0') {
+				szCodeset[tIndex] = '\0';
+				break;
+			}
+			szCodeset[tIndex] = *pcTmp;
+			pcTmp++;
+		}
+		szCodeset[tMaxCodesetLength - 1] = '\0';
+	}
+	if (pbEuro == NULL) {
+		/* No need to get the modifier */
+		return TRUE;
+	}
+	pcTmp = strchr(szLocale, '@');
+	if (pcTmp != NULL) {
+		/* Copy the modifier */
+		pcTmp++;
+		for (tIndex = 0; tIndex < sizeof(szModifier); tIndex++) {
+			if (*pcTmp == '+' || *pcTmp == ',' ||
+			    *pcTmp == '_' || *pcTmp == '\0') {
+				szModifier[tIndex] = '\0';
+				break;
+			}
+			szModifier[tIndex] = *pcTmp;
+			pcTmp++;
+		}
+		szModifier[sizeof(szModifier) - 1] = '\0';
+		*pbEuro = STRCEQ(szModifier, "Euro");
+	}
+#endif /* __dos */
+	return TRUE;
+} /* end of bGetCodesetFromLocale */
+
+/*
+ * GetNormalizedCodeset - get the normalized codeset from the current locale
+ *
+ * Returns TRUE when sucessful, otherwise FALSE
+ */
+BOOL
+bGetNormalizedCodeset(char *szCodeset, size_t tMaxCodesetLength, BOOL *pbEuro)
+{
+	BOOL	bOnlyDigits;
+	const char	*pcSrc;
+	char	*pcDest;
+	char	*szTmp, *szCodesetNorm;
+
+	if (pbEuro != NULL) {
+		*pbEuro = FALSE;	/* Until proven otherwise */
+	}
+	if (szCodeset == NULL || tMaxCodesetLength < 4) {
+		return FALSE;
+	}
+
+	/* Get the codeset name */
+	szTmp = xmalloc(tMaxCodesetLength - 3);
+	if (!bGetCodesetFromLocale(szTmp, tMaxCodesetLength - 3, pbEuro)) {
+		szTmp = xfree(szTmp);
+		return FALSE;
+	}
+	/* Normalize the codeset name */
+	szCodesetNorm = xmalloc(tMaxCodesetLength - 3);
+	bOnlyDigits = TRUE;
+	pcDest = szCodesetNorm;
+	for (pcSrc = szTmp; *pcSrc != '\0'; pcSrc++) {
+		if (isalnum(*pcSrc)) {
+			*pcDest = tolower(*pcSrc);
+			if (!isdigit(*pcDest)) {
+				bOnlyDigits = FALSE;
+			}
+			pcDest++;
+		}
+	}
+	*pcDest = '\0';
+	DBG_MSG(szCodesetNorm);
+	/* Add "iso" when szCodesetNorm contains all digits */
+	if (bOnlyDigits && szCodesetNorm[0] != '\0') {
+		fail(strlen(szCodesetNorm) + 3 >= tMaxCodesetLength);
+		sprintf(szCodeset, "iso%s", szCodesetNorm);
+	} else {
+		fail(strlen(szCodesetNorm) >= tMaxCodesetLength);
+		strncpy(szCodeset, szCodesetNorm, pcDest - szCodesetNorm + 1);
+		szCodeset[tMaxCodesetLength - 1] = '\0';
+	}
+	DBG_MSG(szCodeset);
+	/* Clean up and leave */
+	szCodesetNorm = xfree(szCodesetNorm);
+	szTmp = xfree(szTmp);
+	return TRUE;
+} /* end of bGetNormalizedCodeset */
+
+/*
+ * szGetDefaultMappingFile - get the default mapping file
+ *
+ * Returns the basename of the default mapping file
+ */
+const char *
+szGetDefaultMappingFile(void)
+{
+	static const struct {
+		const char	*szCodeset;
+		const char	*szMappingFile;
+	} atMappingFile[] = {
+		{ "iso88591",	MAPPING_FILE_8859_1 },
+		{ "iso88592",	MAPPING_FILE_8859_2 },
+		{ "iso88593",	"8859-3.txt" },
+		{ "iso88594",	"8859-4.txt" },
+		{ "iso88595",	"8859-5.txt" },
+		{ "iso88596",	MAPPING_FILE_8859_5 },
+		{ "iso88597",	"8859-7.txt" },
+		{ "iso88598",	"8859-8.txt" },
+		{ "iso88599",	"8859-9.txt" },
+		{ "iso885910",	"8859-10.txt" },
+		{ "iso885913",	"8859-13.txt" },
+		{ "iso885914",	"8859-14.txt" },
+		{ "iso885915",	MAPPING_FILE_8859_15 },
+		{ "iso885916",	"8859-16.txt" },
+		{ "koi8r",	MAPPING_FILE_KOI8_R },
+		{ "koi8u",	MAPPING_FILE_KOI8_U },
+		{ "utf8",	MAPPING_FILE_UTF_8 },
+		{ "cp437",	MAPPING_FILE_CP437 },
+		{ "cp850",	"cp850.txt" },
+		{ "cp852",	MAPPING_FILE_CP852 },
+		{ "cp862",	"cp862.txt" },
+		{ "cp864",	"cp864.txt" },
+		{ "cp866",	MAPPING_FILE_CP866 },
+		{ "cp1250",	MAPPING_FILE_CP1250 },
+		{ "cp1251",	MAPPING_FILE_CP1251 },
+		{ "cp1252",	"cp1252.txt" },
+	};
+	size_t	tIndex;
+	BOOL	bEuro;
+	char	szCodeset[20];
+
+	szCodeset[0] = '\0';
+	bEuro = FALSE;
+	/* Get the normalized codeset name */
+	if (!bGetNormalizedCodeset(szCodeset, sizeof(szCodeset), &bEuro)) {
+		return MAPPING_FILE_8859_1;
+	}
+	if (szCodeset[0] == '\0') {
+		if (bEuro) {
+			/* Default mapping file (with Euro sign) */
+			return MAPPING_FILE_8859_15;
+		} else {
+			/* Default mapping file (without Euro sign) */
+			return MAPPING_FILE_8859_1;
+		}
+	}
+	/* Find the name in the table */
+	for (tIndex = 0; tIndex < elementsof(atMappingFile); tIndex++) {
+		if (STREQ(atMappingFile[tIndex].szCodeset, szCodeset)) {
+			return atMappingFile[tIndex].szMappingFile;
+		}
+	}
+	/* Default default mapping file */
+#if defined(__dos)
+	return MAPPING_FILE_CP437;
+#else
+	return MAPPING_FILE_8859_1;
+#endif /* __dos */
+} /* end of szGetDefaultMappingFile */
+#endif /* !__riscos */
+
+/*
+ * tConvertDTTM - convert Windows Date and Time format
+ *
+ * returns Unix time_t or -1
+ */
+time_t
+tConvertDTTM(ULONG ulDTTM)
+{
+	struct tm	tTime;
+	time_t		tResult;
+
+	if (ulDTTM == 0) {
+		return (time_t)-1;
+	}
+	memset(&tTime, 0, sizeof(tTime));
+	tTime.tm_min = (int)(ulDTTM & 0x0000003f);
+	tTime.tm_hour = (int)((ulDTTM & 0x000007c0) >> 6);
+	tTime.tm_mday = (int)((ulDTTM & 0x0000f800) >> 11);
+	tTime.tm_mon = (int)((ulDTTM & 0x000f0000) >> 16);
+	tTime.tm_year = (int)((ulDTTM & 0x1ff00000) >> 20);
+	tTime.tm_isdst = -1;
+	tTime.tm_mon--;         /* From 01-12 to 00-11 */
+	tResult = mktime(&tTime);
+	NO_DBG_MSG(ctime(&tResult));
+	return tResult;
+} /* end of tConvertDTTM */
diff --git a/mkfile b/mkfile
new file mode 100644
index 0000000..d609c25
--- /dev/null
+++ b/mkfile
@@ -0,0 +1,30 @@
+</$objtype/mkfile
+
+TARG=antiword
+
+CFLAGS=-Bp -I/sys/include/ape -I/$objtype/include/ape -DNDEBUG -D_POSIX_SOURCE -D__Plan9__
+
+TARG=antiword
+OFILES= main_u.$O asc85enc.$O blocklist.$O chartrans.$O datalist.$O depot.$O\
+	dib2eps.$O fail.$O finddata.$O findtext.$O fmt_text.$O fontlist.$O\
+	fonts.$O fonts_u.$O imgexam.$O imgtrans.$O jpeg2eps.$O listlist.$O\
+	misc.$O notes.$O options.$O out2window.$O output.$O pdf.$O pictlist.$O\
+	png2eps.$O postscript.$O prop0.$O prop2.$O prop6.$O prop8.$O\
+	properties.$O propmod.$O rowlist.$O sectlist.$O stylelist.$O\
+	stylesheet.$O summary.$O tabstop.$O text.$O unix.$O utf8.$O\
+	word2text.$O worddos.$O wordlib.$O wordmac.$O wordole.$O wordwin.$O\
+	xmalloc.$O xml.$O
+
+HFILES=antiword.h debug.h draw.h fail.h fontinfo.h version.h wordconst.h wordtypes.h
+
+BIN=/$objtype/bin/aux
+
+</sys/src/cmd/mkone
+
+main_u.$O: version.h
+postscript.$O: version.h
+pdf.$O: version.h
+fonts_u.$O: fontinfo.h
+
+# fontinfo.h: Unix-fontinfo.pl
+# 	fontinfo.pl > fontinfo.h
diff --git a/notes.c b/notes.c
new file mode 100644
index 0000000..ffc7526
--- /dev/null
+++ b/notes.c
@@ -0,0 +1,876 @@
+/*
+ * notes.c
+ * Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Functions to tell the difference between footnotes and endnotes
+ */
+
+#include "antiword.h"
+
+/*
+ * Private structures to hide the way the information
+ * is stored from the rest of the program
+ */
+typedef struct footnote_local_tag {
+        footnote_block_type	tInfo;
+        ULONG			ulCharPosStart;
+        ULONG			ulCharPosNext;
+        BOOL			bUseful;
+} footnote_local_type;
+
+/* Variables needed to write the Footnote and Endnote information */
+static ULONG	*aulFootnoteList = NULL;
+static size_t	tFootnoteListLength = 0;
+static ULONG	*aulEndnoteList = NULL;
+static size_t	tEndnoteListLength = 0;
+/* Variables needed to write the Footnote Text */
+static footnote_local_type	*pFootnoteText = NULL;
+static size_t			tFootnoteTextLength = 0;
+
+
+/*
+ * Destroy the lists with footnote and endnote information
+ */
+void
+vDestroyNotesInfoLists(void)
+{
+	footnote_local_type	*pRecord;
+	size_t			tFootnote;
+
+	TRACE_MSG("vDestroyNotesInfoLists");
+
+	/* Free the lists and reset all control variables */
+	aulEndnoteList = xfree(aulEndnoteList);
+	aulFootnoteList = xfree(aulFootnoteList);
+	tEndnoteListLength = 0;
+	tFootnoteListLength = 0;
+	for (tFootnote = 0; tFootnote < tFootnoteTextLength; tFootnote++) {
+		pRecord = pFootnoteText + tFootnote;
+		pRecord->tInfo.szText = xfree(pRecord->tInfo.szText);
+	}
+	pFootnoteText = xfree(pFootnoteText);
+	tFootnoteTextLength = 0;
+} /* end of vDestroyNotesInfoLists */
+
+/*
+ * Build the list with footnote information for Word for DOS files
+ */
+static void
+vGet0FootnotesInfoAndText(FILE *pFile, const UCHAR *aucHeader)
+{
+	footnote_local_type	*pCurr;
+	UCHAR	*aucBuffer;
+	ULONG	ulFileOffset, ulBeginOfText, ulOffset, ulBeginFootnoteInfo;
+	ULONG	ulCharPos, ulBeginNextBlock;
+	size_t	tFootnotes, tFootnoteInfoLen;
+	size_t	tIndex;
+	UCHAR   aucTmp[2];
+
+	TRACE_MSG("vGet0FootnotesInfoAndText");
+
+	fail(pFile == NULL || aucHeader == NULL);
+
+	ulBeginOfText = 128;
+	NO_DBG_HEX(ulBeginOfText);
+	ulBeginFootnoteInfo =  128 * (ULONG)usGetWord(0x14, aucHeader);
+	DBG_HEX(ulBeginFootnoteInfo);
+	ulBeginNextBlock = 128 * (ULONG)usGetWord(0x16, aucHeader);
+	DBG_HEX(ulBeginNextBlock);
+
+	if (ulBeginFootnoteInfo == ulBeginNextBlock) {
+		DBG_MSG("No Footnotes in this document");
+		return;
+	}
+
+	/* Read the the number of footnotes + 1 */
+	if (!bReadBytes(aucTmp, 2, ulBeginFootnoteInfo, pFile)) {
+		return;
+	}
+	tFootnotes = (size_t)usGetWord(0, aucTmp);
+	if (tFootnotes < 2) {
+		DBG_MSG("No Footnotes in this document (2)");
+	}
+	DBG_DEC(tFootnotes);
+	tFootnoteInfoLen =  8 * tFootnotes;
+
+	aucBuffer = xmalloc(tFootnoteInfoLen);
+	if (!bReadBytes(aucBuffer,
+			tFootnoteInfoLen, ulBeginFootnoteInfo + 4, pFile)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+	DBG_PRINT_BLOCK(aucBuffer, tFootnoteInfoLen);
+
+	/* Get footnote information */
+	fail(tFootnoteListLength != 0);
+	tFootnoteListLength = tFootnotes - 1;
+	fail(tFootnoteListLength == 0);
+
+	fail(aulFootnoteList != NULL);
+	aulFootnoteList = xcalloc(tFootnoteListLength, sizeof(ULONG));
+
+	for (tIndex = 0; tIndex < tFootnoteListLength; tIndex++) {
+		ulOffset = ulGetLong(tIndex * 8, aucBuffer);
+		DBG_HEX(ulOffset);
+		ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
+		DBG_HEX(ulFileOffset);
+		aulFootnoteList[tIndex] = ulFileOffset;
+	}
+
+	/* Get footnote text */
+	fail(tFootnoteTextLength != 0);
+	tFootnoteTextLength = tFootnotes - 1;
+	fail(tFootnoteTextLength == 0);
+
+	fail(pFootnoteText != NULL);
+	pFootnoteText = xcalloc(tFootnoteTextLength,
+				sizeof(footnote_local_type));
+
+	for (tIndex = 0; tIndex < tFootnoteTextLength; tIndex++) {
+		pCurr = pFootnoteText + tIndex;
+		pCurr->tInfo.szText = NULL;
+		ulOffset = ulGetLong(tIndex * 8 + 4, aucBuffer);
+		DBG_HEX(ulOffset);
+		ulCharPos = ulBeginOfText + ulOffset;
+		DBG_HEX(ulCharPos);
+		DBG_HEX(ulCharPos2FileOffset(ulCharPos));
+		pCurr->ulCharPosStart = ulCharPos;
+		ulOffset = ulGetLong((tIndex + 1) * 8 + 4, aucBuffer);
+		DBG_HEX(ulOffset);
+		ulCharPos = ulBeginOfText + ulOffset;
+		DBG_HEX(ulCharPos);
+		DBG_HEX(ulCharPos2FileOffset(ulCharPos));
+		pCurr->ulCharPosNext = ulCharPos;
+		pCurr->bUseful = pCurr->ulCharPosStart != pCurr->ulCharPosNext;
+	}
+	aucBuffer = xfree(aucBuffer);
+} /* end of vGet0FootnotesInfoAndText */
+
+/*
+ * Build the lists note information for Word for DOS files
+ */
+static void
+vGet0NotesInfo(FILE *pFile, const UCHAR *aucHeader)
+{
+	TRACE_MSG("vGet0NotesInfo");
+
+	vGet0FootnotesInfoAndText(pFile, aucHeader);
+	/* There are no endnotes in a Word for DOS file */
+} /* end of vGet0NotesInfo */
+
+/*
+ * Build the list with footnote information for WinWord 1/2 files
+ */
+static void
+vGet2FootnotesInfo(FILE *pFile, const UCHAR *aucHeader)
+{
+	UCHAR	*aucBuffer;
+	ULONG	ulFileOffset, ulBeginOfText, ulOffset, ulBeginFootnoteInfo;
+	size_t	tFootnoteInfoLen;
+	size_t	tIndex;
+
+	TRACE_MSG("vGet2FootnotesInfo");
+
+	fail(pFile == NULL || aucHeader == NULL);
+
+	ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
+	NO_DBG_HEX(ulBeginOfText);
+	ulBeginFootnoteInfo = ulGetLong(0x64, aucHeader); /* fcPlcffndRef */
+	NO_DBG_HEX(ulBeginFootnoteInfo);
+	tFootnoteInfoLen = (size_t)usGetWord(0x68, aucHeader); /* cbPlcffndRef */
+	NO_DBG_DEC(tFootnoteInfoLen);
+
+	if (tFootnoteInfoLen < 10) {
+		DBG_MSG("No Footnotes in this document");
+		return;
+	}
+
+	aucBuffer = xmalloc(tFootnoteInfoLen);
+	if (!bReadBytes(aucBuffer,
+			tFootnoteInfoLen, ulBeginFootnoteInfo, pFile)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteInfoLen);
+
+	fail(tFootnoteListLength != 0);
+	tFootnoteListLength = (tFootnoteInfoLen - 4) / 6;
+	fail(tFootnoteListLength == 0);
+
+	fail(aulFootnoteList != NULL);
+	aulFootnoteList = xcalloc(tFootnoteListLength, sizeof(ULONG));
+
+	for (tIndex = 0; tIndex < tFootnoteListLength; tIndex++) {
+		ulOffset = ulGetLong(tIndex * 4, aucBuffer);
+		NO_DBG_HEX(ulOffset);
+		ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
+		NO_DBG_HEX(ulFileOffset);
+		aulFootnoteList[tIndex] = ulFileOffset;
+	}
+	aucBuffer = xfree(aucBuffer);
+} /* end of vGet2FootnotesInfo */
+
+/*
+ * Build the list with footnote text information for WinWord 1/2 files
+ */
+static void
+vGet2FootnotesText(FILE *pFile, const UCHAR *aucHeader)
+{
+	footnote_local_type	*pCurr;
+	UCHAR	*aucBuffer;
+	ULONG	ulCharPos, ulBeginOfFootnotes, ulOffset, ulBeginFootnoteText;
+	size_t	tFootnoteTextLen;
+	size_t	tIndex;
+
+	TRACE_MSG("vGet2FootnotesText");
+
+	fail(pFile == NULL || aucHeader == NULL);
+
+	ulBeginOfFootnotes = ulGetLong(0x18, aucHeader); /* fcMin */
+	ulBeginOfFootnotes += ulGetLong(0x34, aucHeader); /* ccpText */
+	NO_DBG_HEX(ulBeginOfFootnotes);
+
+	ulBeginFootnoteText = ulGetLong(0x6a, aucHeader); /* fcPlcffndTxt */
+	NO_DBG_HEX(ulBeginFootnoteText);
+	tFootnoteTextLen =
+		(size_t)usGetWord(0x6e, aucHeader); /* cbPlcffndTxt */
+	NO_DBG_DEC(tFootnoteTextLen);
+
+	if (tFootnoteTextLen < 12) {
+		DBG_MSG("No Footnote text in this document");
+		return;
+	}
+
+	aucBuffer = xmalloc(tFootnoteTextLen);
+	if (!bReadBytes(aucBuffer,
+			tFootnoteTextLen, ulBeginFootnoteText, pFile)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteTextLen);
+
+	fail(tFootnoteTextLength != 0);
+	tFootnoteTextLength = tFootnoteTextLen / 4 - 2;
+	fail(tFootnoteTextLength == 0);
+
+	fail(pFootnoteText != NULL);
+	pFootnoteText = xcalloc(tFootnoteTextLength,
+				sizeof(footnote_local_type));
+
+	for (tIndex = 0; tIndex < tFootnoteTextLength; tIndex++) {
+		pCurr = pFootnoteText + tIndex;
+		pCurr->tInfo.szText = NULL;
+		ulOffset = ulGetLong(tIndex * 4, aucBuffer);
+		NO_DBG_HEX(ulOffset);
+		ulCharPos = ulBeginOfFootnotes + ulOffset;
+		NO_DBG_HEX(ulCharPos);
+		NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
+		pCurr->ulCharPosStart = ulCharPos;
+		ulOffset = ulGetLong(tIndex * 4 + 4, aucBuffer);
+		NO_DBG_HEX(ulOffset);
+		ulCharPos = ulBeginOfFootnotes + ulOffset;
+		NO_DBG_HEX(ulCharPos);
+		NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
+		pCurr->ulCharPosNext = ulCharPos;
+		pCurr->bUseful = pCurr->ulCharPosStart != pCurr->ulCharPosNext;
+	}
+	aucBuffer = xfree(aucBuffer);
+} /* end of vGet2FootnotesText */
+
+/*
+ * Build the lists note information for WinWord 1/2 files
+ */
+static void
+vGet2NotesInfo(FILE *pFile, const UCHAR *aucHeader)
+{
+	TRACE_MSG("vGet2NotesInfo");
+
+	vGet2FootnotesInfo(pFile, aucHeader);
+	vGet2FootnotesText(pFile, aucHeader);
+	/* There are no endnotes in a WinWord 1/2 file */
+} /* end of vGet2NotesInfo */
+
+/*
+ * Build the list with footnote information for Word 6/7 files
+ */
+static void
+vGet6FootnotesInfo(FILE *pFile, ULONG ulStartBlock,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const UCHAR *aucHeader)
+{
+	UCHAR	*aucBuffer;
+	ULONG	ulFileOffset, ulBeginOfText, ulOffset, ulBeginFootnoteInfo;
+	size_t	tFootnoteInfoLen;
+	size_t	tIndex;
+
+	TRACE_MSG("vGet6FootnotesInfo");
+
+	fail(pFile == NULL || aucHeader == NULL);
+	fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
+	fail(aulBBD == NULL);
+
+	ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
+	NO_DBG_HEX(ulBeginOfText);
+	ulBeginFootnoteInfo = ulGetLong(0x68, aucHeader); /* fcPlcffndRef */
+	NO_DBG_HEX(ulBeginFootnoteInfo);
+	tFootnoteInfoLen =
+		(size_t)ulGetLong(0x6c, aucHeader); /* lcbPlcffndRef */
+	NO_DBG_DEC(tFootnoteInfoLen);
+
+	if (tFootnoteInfoLen < 10) {
+		DBG_MSG("No Footnotes in this document");
+		return;
+	}
+
+	aucBuffer = xmalloc(tFootnoteInfoLen);
+	if (!bReadBuffer(pFile, ulStartBlock,
+			aulBBD, tBBDLen, BIG_BLOCK_SIZE,
+			aucBuffer, ulBeginFootnoteInfo, tFootnoteInfoLen)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteInfoLen);
+
+	fail(tFootnoteListLength != 0);
+	tFootnoteListLength = (tFootnoteInfoLen - 4) / 6;
+	fail(tFootnoteListLength == 0);
+
+	fail(aulFootnoteList != NULL);
+	aulFootnoteList = xcalloc(tFootnoteListLength, sizeof(ULONG));
+
+	for (tIndex = 0; tIndex < tFootnoteListLength; tIndex++) {
+		ulOffset = ulGetLong(tIndex * 4, aucBuffer);
+		NO_DBG_HEX(ulOffset);
+		ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
+		NO_DBG_HEX(ulFileOffset);
+		aulFootnoteList[tIndex] = ulFileOffset;
+	}
+	aucBuffer = xfree(aucBuffer);
+} /* end of vGet6FootnotesInfo */
+
+/*
+ * Build the list with footnote text information for Word 6/7 files
+ */
+static void
+vGet6FootnotesText(FILE *pFile, ULONG ulStartBlock,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const UCHAR *aucHeader)
+{
+	footnote_local_type	*pCurr;
+	UCHAR	*aucBuffer;
+	ULONG	ulCharPos, ulBeginOfFootnotes, ulOffset, ulBeginFootnoteText;
+	size_t	tFootnoteTextLen;
+	size_t	tIndex;
+
+	TRACE_MSG("vGet6FootnotesText");
+
+	fail(pFile == NULL || aucHeader == NULL);
+	fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
+	fail(aulBBD == NULL);
+
+	ulBeginOfFootnotes = ulGetLong(0x18, aucHeader); /* fcMin */
+	ulBeginOfFootnotes += ulGetLong(0x34, aucHeader); /* ccpText */
+	NO_DBG_HEX(ulBeginOfFootnotes);
+
+	ulBeginFootnoteText = ulGetLong(0x70, aucHeader); /* fcPlcffndTxt */
+	NO_DBG_HEX(ulBeginFootnoteText);
+	tFootnoteTextLen =
+		(size_t)ulGetLong(0x74, aucHeader); /* lcbPlcffndTxt */
+	NO_DBG_DEC(tFootnoteTextLen);
+
+	if (tFootnoteTextLen < 12) {
+		DBG_MSG("No Footnote text in this document");
+		return;
+	}
+
+	aucBuffer = xmalloc(tFootnoteTextLen);
+	if (!bReadBuffer(pFile, ulStartBlock,
+			aulBBD, tBBDLen, BIG_BLOCK_SIZE,
+			aucBuffer, ulBeginFootnoteText, tFootnoteTextLen)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteTextLen);
+
+	fail(tFootnoteTextLength != 0);
+	tFootnoteTextLength = tFootnoteTextLen / 4 - 2;
+	fail(tFootnoteTextLength == 0);
+
+	fail(pFootnoteText != NULL);
+	pFootnoteText = xcalloc(tFootnoteTextLength,
+				sizeof(footnote_local_type));
+
+	for (tIndex = 0; tIndex < tFootnoteTextLength; tIndex++) {
+		pCurr = pFootnoteText + tIndex;
+		pCurr->tInfo.szText = NULL;
+		ulOffset = ulGetLong(tIndex * 4, aucBuffer);
+		NO_DBG_HEX(ulOffset);
+		ulCharPos = ulBeginOfFootnotes + ulOffset;
+		NO_DBG_HEX(ulCharPos);
+		NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
+		pCurr->ulCharPosStart = ulCharPos;
+		ulOffset = ulGetLong(tIndex * 4 + 4, aucBuffer);
+		NO_DBG_HEX(ulOffset);
+		ulCharPos = ulBeginOfFootnotes + ulOffset;
+		NO_DBG_HEX(ulCharPos);
+		NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
+		pCurr->ulCharPosNext = ulCharPos;
+		pCurr->bUseful = pCurr->ulCharPosStart != pCurr->ulCharPosNext;
+	}
+	aucBuffer = xfree(aucBuffer);
+} /* end of vGet6FootnotesText */
+
+/*
+ * Build the list with endnote information for Word 6/7 files
+ */
+static void
+vGet6EndnotesInfo(FILE *pFile, ULONG ulStartBlock,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const UCHAR *aucHeader)
+{
+	UCHAR	*aucBuffer;
+	ULONG	ulFileOffset, ulBeginOfText, ulOffset, ulBeginEndnoteInfo;
+	size_t	tEndnoteInfoLen;
+	size_t	tIndex;
+
+	TRACE_MSG("vGet6EndnotesInfo");
+
+	fail(pFile == NULL || aucHeader == NULL);
+	fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
+	fail(aulBBD == NULL);
+
+	ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
+	NO_DBG_HEX(ulBeginOfText);
+	ulBeginEndnoteInfo = ulGetLong(0x1d2, aucHeader); /* fcPlcfendRef */
+	NO_DBG_HEX(ulBeginEndnoteInfo);
+	tEndnoteInfoLen =
+		(size_t)ulGetLong(0x1d6, aucHeader); /* lcbPlcfendRef */
+	NO_DBG_DEC(tEndnoteInfoLen);
+
+	if (tEndnoteInfoLen < 10) {
+		DBG_MSG("No Endnotes in this document");
+		return;
+	}
+
+	aucBuffer = xmalloc(tEndnoteInfoLen);
+	if (!bReadBuffer(pFile, ulStartBlock,
+			aulBBD, tBBDLen, BIG_BLOCK_SIZE,
+			aucBuffer, ulBeginEndnoteInfo, tEndnoteInfoLen)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tEndnoteInfoLen);
+
+	fail(tEndnoteListLength != 0);
+	tEndnoteListLength = (tEndnoteInfoLen - 4) / 6;
+	fail(tEndnoteListLength == 0);
+
+	fail(aulEndnoteList != NULL);
+	aulEndnoteList = xcalloc(tEndnoteListLength, sizeof(ULONG));
+
+	for (tIndex = 0; tIndex < tEndnoteListLength; tIndex++) {
+		ulOffset = ulGetLong(tIndex * 4, aucBuffer);
+		NO_DBG_HEX(ulOffset);
+		ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
+		NO_DBG_HEX(ulFileOffset);
+		aulEndnoteList[tIndex] = ulFileOffset;
+	}
+	aucBuffer = xfree(aucBuffer);
+} /* end of vGet6EndnotesInfo */
+
+/*
+ * Build the lists note information for Word 6/7 files
+ */
+static void
+vGet6NotesInfo(FILE *pFile, ULONG ulStartBlock,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const UCHAR *aucHeader)
+{
+	TRACE_MSG("vGet6NotesInfo");
+
+	vGet6FootnotesInfo(pFile, ulStartBlock,
+			aulBBD, tBBDLen, aucHeader);
+	vGet6FootnotesText(pFile, ulStartBlock,
+			aulBBD, tBBDLen, aucHeader);
+	vGet6EndnotesInfo(pFile, ulStartBlock,
+			aulBBD, tBBDLen, aucHeader);
+} /* end of vGet6NotesInfo */
+
+/*
+ * Build the list with footnote information for Word 8/9/10 files
+ */
+static void
+vGet8FootnotesInfo(FILE *pFile, const pps_info_type *pPPS,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const ULONG *aulSBD, size_t tSBDLen,
+	const UCHAR *aucHeader)
+{
+	const ULONG	*aulBlockDepot;
+	UCHAR	*aucBuffer;
+	ULONG	ulFileOffset, ulBeginOfText, ulOffset, ulBeginFootnoteInfo;
+	size_t	tFootnoteInfoLen, tBlockDepotLen, tBlockSize;
+	size_t	tIndex;
+
+	TRACE_MSG("vGet8FootnotesInfo");
+
+	ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
+	NO_DBG_HEX(ulBeginOfText);
+	ulBeginFootnoteInfo = ulGetLong(0xaa, aucHeader); /* fcPlcffndRef */
+	NO_DBG_HEX(ulBeginFootnoteInfo);
+	tFootnoteInfoLen =
+		(size_t)ulGetLong(0xae, aucHeader); /* lcbPlcffndRef */
+	NO_DBG_DEC(tFootnoteInfoLen);
+
+	if (tFootnoteInfoLen < 10) {
+		DBG_MSG("No Footnotes in this document");
+		return;
+	}
+
+	NO_DBG_DEC(pPPS->tTable.ulSB);
+	NO_DBG_HEX(pPPS->tTable.ulSize);
+	if (pPPS->tTable.ulSize == 0) {
+		DBG_MSG("No footnotes information");
+		return;
+	}
+
+	if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
+	  	/* Use the Small Block Depot */
+		aulBlockDepot = aulSBD;
+		tBlockDepotLen = tSBDLen;
+		tBlockSize = SMALL_BLOCK_SIZE;
+	} else {
+	  	/* Use the Big Block Depot */
+		aulBlockDepot = aulBBD;
+		tBlockDepotLen = tBBDLen;
+		tBlockSize = BIG_BLOCK_SIZE;
+	}
+	aucBuffer = xmalloc(tFootnoteInfoLen);
+	if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
+			aulBlockDepot, tBlockDepotLen, tBlockSize,
+			aucBuffer, ulBeginFootnoteInfo, tFootnoteInfoLen)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteInfoLen);
+
+	fail(tFootnoteListLength != 0);
+	tFootnoteListLength = (tFootnoteInfoLen - 4) / 6;
+	fail(tFootnoteListLength == 0);
+
+	fail(aulFootnoteList != NULL);
+	aulFootnoteList = xcalloc(tFootnoteListLength, sizeof(ULONG));
+
+	for (tIndex = 0; tIndex < tFootnoteListLength; tIndex++) {
+		ulOffset = ulGetLong(tIndex * 4, aucBuffer);
+		NO_DBG_HEX(ulOffset);
+		ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
+		NO_DBG_HEX(ulFileOffset);
+		aulFootnoteList[tIndex] = ulFileOffset;
+	}
+	aucBuffer = xfree(aucBuffer);
+} /* end of vGet8FootnotesInfo */
+
+/*
+ * Build the list with footnote text information for Word 8/9/10 files
+ */
+static void
+vGet8FootnotesText(FILE *pFile, const pps_info_type *pPPS,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const ULONG *aulSBD, size_t tSBDLen,
+	const UCHAR *aucHeader)
+{
+	footnote_local_type	*pCurr;
+	const ULONG	*aulBlockDepot;
+	UCHAR	*aucBuffer;
+	ULONG	ulCharPos, ulBeginOfFootnotes, ulOffset, ulBeginFootnoteText;
+	size_t	tFootnoteTextLen, tBlockDepotLen, tBlockSize;
+	size_t	tIndex;
+
+	TRACE_MSG("vGet8FootnotesText");
+
+	ulBeginOfFootnotes = ulGetLong(0x18, aucHeader); /* fcMin */
+	ulBeginOfFootnotes += ulGetLong(0x4c, aucHeader); /* ccpText */
+	NO_DBG_HEX(ulBeginOfFootnotes);
+
+	ulBeginFootnoteText = ulGetLong(0xb2, aucHeader); /* fcPlcffndTxt */
+	NO_DBG_HEX(ulBeginFootnoteText);
+	tFootnoteTextLen =
+		(size_t)ulGetLong(0xb6, aucHeader); /* lcbPlcffndTxt */
+	NO_DBG_DEC(tFootnoteTextLen);
+
+	if (tFootnoteTextLen < 12) {
+		DBG_MSG("No Footnote text in this document");
+		return;
+	}
+
+	NO_DBG_DEC(pPPS->tTable.ulSB);
+	NO_DBG_HEX(pPPS->tTable.ulSize);
+	if (pPPS->tTable.ulSize == 0) {
+		DBG_MSG("No footnote text information");
+		return;
+	}
+
+	if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
+	  	/* Use the Small Block Depot */
+		aulBlockDepot = aulSBD;
+		tBlockDepotLen = tSBDLen;
+		tBlockSize = SMALL_BLOCK_SIZE;
+	} else {
+	  	/* Use the Big Block Depot */
+		aulBlockDepot = aulBBD;
+		tBlockDepotLen = tBBDLen;
+		tBlockSize = BIG_BLOCK_SIZE;
+	}
+	aucBuffer = xmalloc(tFootnoteTextLen);
+	if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
+			aulBlockDepot, tBlockDepotLen, tBlockSize,
+			aucBuffer, ulBeginFootnoteText, tFootnoteTextLen)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteTextLen);
+
+	fail(tFootnoteTextLength != 0);
+	tFootnoteTextLength = tFootnoteTextLen / 4 - 2;
+	fail(tFootnoteTextLength == 0);
+
+	fail(pFootnoteText != NULL);
+	pFootnoteText = xcalloc(tFootnoteTextLength,
+				sizeof(footnote_local_type));
+
+	for (tIndex = 0; tIndex < tFootnoteTextLength; tIndex++) {
+		pCurr = pFootnoteText + tIndex;
+		pCurr->tInfo.szText = NULL;
+		ulOffset = ulGetLong(tIndex * 4, aucBuffer);
+		NO_DBG_HEX(ulOffset);
+		ulCharPos = ulBeginOfFootnotes + ulOffset;
+		NO_DBG_HEX(ulCharPos);
+		NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
+		pCurr->ulCharPosStart = ulCharPos;
+		ulOffset = ulGetLong(tIndex * 4 + 4, aucBuffer);
+		NO_DBG_HEX(ulOffset);
+		ulCharPos = ulBeginOfFootnotes + ulOffset;
+		NO_DBG_HEX(ulCharPos);
+		NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
+		pCurr->ulCharPosNext = ulCharPos;
+		pCurr->bUseful = pCurr->ulCharPosStart != pCurr->ulCharPosNext;
+	}
+	aucBuffer = xfree(aucBuffer);
+} /* end of vGet8FootnotesText */
+
+/*
+ * Build the list with endnote information for Word 8/9/10 files
+ */
+static void
+vGet8EndnotesInfo(FILE *pFile, const pps_info_type *pPPS,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const ULONG *aulSBD, size_t tSBDLen,
+	const UCHAR *aucHeader)
+{
+	const ULONG	*aulBlockDepot;
+	UCHAR	*aucBuffer;
+	ULONG	ulFileOffset, ulBeginOfText, ulOffset, ulBeginEndnoteInfo;
+	size_t	tEndnoteInfoLen, tBlockDepotLen, tBlockSize;
+	size_t	tIndex;
+
+	TRACE_MSG("vGet8EndnotesInfo");
+
+	ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
+	NO_DBG_HEX(ulBeginOfText);
+	ulBeginEndnoteInfo = ulGetLong(0x20a, aucHeader); /* fcPlcfendRef */
+	NO_DBG_HEX(ulBeginEndnoteInfo);
+	tEndnoteInfoLen = (size_t)ulGetLong(0x20e, aucHeader); /* lcbPlcfendRef */
+	NO_DBG_DEC(tEndnoteInfoLen);
+
+	if (tEndnoteInfoLen < 10) {
+		DBG_MSG("No endnotes in this document");
+		return;
+	}
+
+	NO_DBG_DEC(pPPS->tTable.ulSB);
+	NO_DBG_HEX(pPPS->tTable.ulSize);
+	if (pPPS->tTable.ulSize == 0) {
+		DBG_MSG("No endnotes information");
+		return;
+	}
+
+	if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
+	  	/* Use the Small Block Depot */
+		aulBlockDepot = aulSBD;
+		tBlockDepotLen = tSBDLen;
+		tBlockSize = SMALL_BLOCK_SIZE;
+	} else {
+	  	/* Use the Big Block Depot */
+		aulBlockDepot = aulBBD;
+		tBlockDepotLen = tBBDLen;
+		tBlockSize = BIG_BLOCK_SIZE;
+	}
+	aucBuffer = xmalloc(tEndnoteInfoLen);
+	if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
+			aulBlockDepot, tBlockDepotLen, tBlockSize,
+			aucBuffer, ulBeginEndnoteInfo, tEndnoteInfoLen)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tEndnoteInfoLen);
+
+	fail(tEndnoteListLength != 0);
+	tEndnoteListLength = (tEndnoteInfoLen - 4) / 6;
+	fail(tEndnoteListLength == 0);
+
+	fail(aulEndnoteList != NULL);
+	aulEndnoteList = xcalloc(tEndnoteListLength, sizeof(ULONG));
+
+	for (tIndex = 0; tIndex < tEndnoteListLength; tIndex++) {
+		ulOffset = ulGetLong(tIndex * 4, aucBuffer);
+		NO_DBG_HEX(ulOffset);
+		ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
+		NO_DBG_HEX(ulFileOffset);
+		aulEndnoteList[tIndex] = ulFileOffset;
+	}
+	aucBuffer = xfree(aucBuffer);
+} /* end of vGet8EndnotesInfo */
+
+/*
+ * Build the lists with footnote and endnote information for Word 8/9/10 files
+ */
+static void
+vGet8NotesInfo(FILE *pFile, const pps_info_type *pPPS,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const ULONG *aulSBD, size_t tSBDLen,
+	const UCHAR *aucHeader)
+{
+	TRACE_MSG("vGet8NotesInfo");
+
+	vGet8FootnotesInfo(pFile, pPPS,
+			aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
+	vGet8FootnotesText(pFile, pPPS,
+			aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
+	vGet8EndnotesInfo(pFile, pPPS,
+			aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
+} /* end of vGet8NotesInfo */
+
+/*
+ * Build the lists with footnote and endnote information
+ */
+void
+vGetNotesInfo(FILE *pFile, const pps_info_type *pPPS,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const ULONG *aulSBD, size_t tSBDLen,
+	const UCHAR *aucHeader, int iWordVersion)
+{
+	TRACE_MSG("vGetNotesInfo");
+
+	fail(pFile == NULL);
+	fail(pPPS == NULL && iWordVersion >= 6);
+	fail(aulBBD == NULL && tBBDLen != 0);
+	fail(aulSBD == NULL && tSBDLen != 0);
+	fail(aucHeader == NULL);
+
+	switch (iWordVersion) {
+	case 0:
+		vGet0NotesInfo(pFile, aucHeader);
+		break;
+	case 1:
+	case 2:
+		vGet2NotesInfo(pFile, aucHeader);
+		break;
+	case 4:
+	case 5:
+		break;
+	case 6:
+	case 7:
+		vGet6NotesInfo(pFile, pPPS->tWordDocument.ulSB,
+			aulBBD, tBBDLen, aucHeader);
+		break;
+	case 8:
+		vGet8NotesInfo(pFile, pPPS,
+			aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
+		break;
+	default:
+		werr(0, "Sorry, no notes information");
+		break;
+	}
+} /* end of vGetNotesInfo */
+
+/*
+ *  vPrepareFootnoteText - prepare the footnote text
+ */
+void
+vPrepareFootnoteText(FILE *pFile)
+{ 
+	footnote_local_type	*pCurr;
+	size_t		tFootnote;
+
+	fail(pFile == NULL);
+	fail(pFootnoteText == NULL && tFootnoteTextLength != 0);
+
+	if (pFootnoteText == NULL || tFootnoteTextLength == 0) {
+		/* No information */
+		return;
+	}
+
+	/* Fill text and useful-ness */
+	for (tFootnote = 0; tFootnote < tFootnoteTextLength; tFootnote++) {
+		pCurr = pFootnoteText + tFootnote;
+		pCurr->bUseful = pCurr->ulCharPosStart != pCurr->ulCharPosNext;
+		if (pCurr->bUseful) {
+			pCurr->tInfo.szText = szFootnoteDecryptor(pFile,
+							pCurr->ulCharPosStart,
+							pCurr->ulCharPosNext);
+		} else {
+			pCurr->tInfo.szText = NULL;
+		}
+	}
+} /* end of vPrepareFootnoteText */
+
+/*
+ * szGetFootnootText - get the text of the spefified footnote
+ */
+const char *
+szGetFootnootText(UINT uiFootnoteIndex)
+{
+	if ((size_t)uiFootnoteIndex >= tFootnoteTextLength) {
+		return NULL;
+	}
+	return pFootnoteText[uiFootnoteIndex].tInfo.szText;
+} /* end of szGetFootnootText */
+
+/*
+ * Get the notetype of the note at the given fileoffset
+ */
+notetype_enum
+eGetNotetype(ULONG ulFileOffset)
+{
+	size_t	tIndex;
+
+	TRACE_MSG("eGetNotetype");
+
+	fail(aulFootnoteList == NULL && tFootnoteListLength != 0);
+	fail(aulEndnoteList == NULL && tEndnoteListLength != 0);
+
+	/* Go for the easy answers first */
+	if (tFootnoteListLength == 0 && tEndnoteListLength == 0) {
+		return notetype_is_unknown;
+	}
+	if (tEndnoteListLength == 0) {
+		return notetype_is_footnote;
+	}
+	if (tFootnoteListLength == 0) {
+		return notetype_is_endnote;
+	}
+	/* No easy answer, so we search */
+	for (tIndex = 0; tIndex < tFootnoteListLength; tIndex++) {
+		if (aulFootnoteList[tIndex] == ulFileOffset) {
+			return notetype_is_footnote;
+		}
+	}
+	for (tIndex = 0; tIndex < tEndnoteListLength; tIndex++) {
+		if (aulEndnoteList[tIndex] == ulFileOffset) {
+			return notetype_is_endnote;
+		}
+	}
+	/* Not found */
+	return notetype_is_unknown;
+} /* end of eGetNotetype */
diff --git a/options.c b/options.c
new file mode 100644
index 0000000..8379fef
--- /dev/null
+++ b/options.c
@@ -0,0 +1,950 @@
+/*
+ * options.c
+ * Copyright (C) 1998-2004 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Read and write the options
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if defined(__riscos)
+#include "DeskLib:Error.h"
+#include "DeskLib:Wimp.h"
+#else
+#include <stdlib.h>
+#if defined(__dos) || defined(N_PLAT_NLM)
+extern int getopt(int, char **, const char *);
+#else
+#include <unistd.h>
+#endif /* __dos */
+#endif /* __riscos */
+#include "antiword.h"
+
+#if defined(__riscos)
+#define PARAGRAPH_BREAK		"set paragraph_break=%d"
+#define AUTOFILETYPE		"set autofiletype_allowed=%d"
+#define USE_OUTLINEFONTS	"set use_outlinefonts=%d"
+#define SHOW_IMAGES		"set show_images=%d"
+#define HIDE_HIDDEN_TEXT	"set hide_hidden_text=%d"
+#define SCALE_FACTOR_START	"set scale_factor_start=%d"
+#else
+#define LEAFNAME_SIZE		(32+1)
+#endif /* __riscos */
+
+/* Current values for options */
+static options_type	tOptionsCurr;
+#if defined(__riscos)
+/* Temporary values for options */
+static options_type	tOptionsTemp;
+#else
+typedef struct papersize_tag {
+	char	szName[16];	/* Papersize name */
+	USHORT	usWidth;	/* In points */
+	USHORT	usHeight;	/* In points */
+} papersize_type;
+
+static const papersize_type atPaperSizes[] = {
+	{	"10x14",	 720,	1008	},
+	{	"a3",		 842,	1191	},
+	{	"a4",		 595,	 842	},
+	{	"a5",		 420,	 595	},
+	{	"b4",		 729,	1032	},
+	{	"b5",		 516,	 729	},
+	{	"executive",	 540,	 720	},
+	{	"folio",	 612,	 936	},
+	{	"legal",	 612,	1008	},
+	{	"letter",	 612,	 792	},
+	{	"note",		 540,	 720	},
+	{	"quarto",	 610,	 780	},
+	{	"statement",	 396,	 612	},
+	{	"tabloid",	 792,	1224	},
+	{	"",		   0,	   0	},
+};
+#endif /* __riscos */
+/* Default values for options */
+static const options_type	tOptionsDefault = {
+	DEFAULT_SCREEN_WIDTH,
+#if defined(__riscos)
+	conversion_draw,
+#else
+	conversion_text,
+#endif /* __riscos */
+	TRUE,
+	TRUE,
+	FALSE,
+	encoding_latin_1,
+	INT_MAX,
+	INT_MAX,
+	level_default,
+#if defined(__riscos)
+	TRUE,
+	DEFAULT_SCALE_FACTOR,
+#endif /* __riscos */
+};
+
+
+#if !defined(__riscos)
+/*
+ * bCorrectPapersize - see if the papersize is correct
+ *
+ * TRUE if the papersize is correct, otherwise FALSE
+ */
+static BOOL
+bCorrectPapersize(const char *szName, conversion_type eConversionType)
+{
+	const papersize_type	*pPaperSize;
+
+	for (pPaperSize = atPaperSizes;
+	     pPaperSize->szName[0] != '\0';
+	     pPaperSize++) {
+		if (!STRCEQ(pPaperSize->szName,  szName)) {
+			continue;
+		}
+		DBG_DEC(pPaperSize->usWidth);
+		DBG_DEC(pPaperSize->usHeight);
+		tOptionsCurr.eConversionType = eConversionType;
+		tOptionsCurr.iPageHeight = (int)pPaperSize->usHeight;
+		tOptionsCurr.iPageWidth = (int)pPaperSize->usWidth;
+		return TRUE;
+	}
+	return FALSE;
+} /* end of bCorrectPapersize */
+
+/*
+ * szCreateSuffix - create a suffix for the file
+ *
+ * Returns the suffix
+ */
+static const char *
+szCreateSuffix(const char *szLeafname)
+{
+	const char	*pcDot;
+
+	pcDot = strrchr(szLeafname, '.');
+	if (pcDot != NULL && STRCEQ(pcDot, ".txt")) {
+		/* There is already a .txt suffix, no need for another one */
+		return "";
+	}
+	return ".txt";
+} /* end of szCreateSuffix */
+
+/*
+ * eMappingFile2Encoding - convert the mapping file to an encoding
+ */
+static encoding_type
+eMappingFile2Encoding(const char *szLeafname)
+{
+	char	szMappingFile[LEAFNAME_SIZE+4];
+
+	fail(szLeafname == NULL);
+
+	if (strlen(szLeafname) + 4 >= sizeof(szMappingFile)) {
+		DBG_MSG(szLeafname);
+		return encoding_latin_1;
+	}
+
+	sprintf(szMappingFile, "%s%s", szLeafname, szCreateSuffix(szLeafname));
+
+	DBG_MSG(szMappingFile);
+
+	if (STRCEQ(szMappingFile, MAPPING_FILE_UTF_8)) {
+		return encoding_utf_8;
+	}
+	if (STRCEQ(szMappingFile, MAPPING_FILE_CP852) ||
+	    STRCEQ(szMappingFile, MAPPING_FILE_CP1250) ||
+	    STRCEQ(szMappingFile, MAPPING_FILE_8859_2)) {
+		return encoding_latin_2;
+	}
+	if (STRCEQ(szMappingFile, MAPPING_FILE_KOI8_R) ||
+	    STRCEQ(szMappingFile, MAPPING_FILE_KOI8_U) ||
+	    STRCEQ(szMappingFile, MAPPING_FILE_CP866) ||
+	    STRCEQ(szMappingFile, MAPPING_FILE_CP1251) ||
+	    STRCEQ(szMappingFile, MAPPING_FILE_8859_5)) {
+		return encoding_cyrillic;
+	}
+	return encoding_latin_1;
+} /* end of eMappingFile2Encoding */
+#endif /* !__riscos */
+
+/*
+ * pOpenCharacterMappingFile - open the mapping file
+ *
+ * Returns the file pointer or NULL
+ */
+static FILE *
+pOpenCharacterMappingFile(const char *szLeafname)
+{
+#if !defined(__riscos)
+	FILE	*pFile;
+	const char	*szHome, *szAntiword, *szSuffix;
+	size_t	tFilenameLen;
+	char	szMappingFile[PATH_MAX+1];
+#endif /* !__riscos */
+
+	if (szLeafname == NULL || szLeafname[0] == '\0') {
+		return NULL;
+	}
+
+	DBG_MSG(szLeafname);
+
+#if defined(__riscos)
+	return fopen(szLeafname, "r");
+#else
+	/* Set the suffix */
+	szSuffix = szCreateSuffix(szLeafname);
+
+	/* Set length */
+	tFilenameLen = strlen(szLeafname) + strlen(szSuffix);
+
+	/* Try the environment version of the mapping file */
+	szAntiword = szGetAntiwordDirectory();
+	if (szAntiword != NULL && szAntiword[0] != '\0') {
+	    if (strlen(szAntiword) + tFilenameLen <
+		sizeof(szMappingFile) -
+		sizeof(FILE_SEPARATOR)) {
+			sprintf(szMappingFile,
+				"%s" FILE_SEPARATOR "%s%s",
+				szAntiword, szLeafname, szSuffix);
+			DBG_MSG(szMappingFile);
+			pFile = fopen(szMappingFile, "r");
+			if (pFile != NULL) {
+				return pFile;
+			}
+		} else {
+			werr(0, "Environment mappingfilename ignored");
+		}
+	}
+
+	/* Try the local version of the mapping file */
+	szHome = szGetHomeDirectory();
+	if (strlen(szHome) + tFilenameLen <
+	    sizeof(szMappingFile) -
+	    sizeof(ANTIWORD_DIR) -
+	    2 * sizeof(FILE_SEPARATOR)) {
+		sprintf(szMappingFile,
+			"%s" FILE_SEPARATOR ANTIWORD_DIR FILE_SEPARATOR "%s%s",
+			szHome, szLeafname, szSuffix);
+		DBG_MSG(szMappingFile);
+		pFile = fopen(szMappingFile, "r");
+		if (pFile != NULL) {
+			return pFile;
+		}
+	} else {
+		werr(0, "Local mappingfilename too long, ignored");
+	}
+
+	/* Try the global version of the mapping file */
+	if (tFilenameLen <
+	    sizeof(szMappingFile) -
+	    sizeof(GLOBAL_ANTIWORD_DIR) -
+	    sizeof(FILE_SEPARATOR)) {
+		sprintf(szMappingFile,
+			GLOBAL_ANTIWORD_DIR FILE_SEPARATOR "%s%s",
+			szLeafname, szSuffix);
+		DBG_MSG(szMappingFile);
+		pFile = fopen(szMappingFile, "r");
+		if (pFile != NULL) {
+			return pFile;
+		}
+	} else {
+		werr(0, "Global mappingfilename too long, ignored");
+	}
+	werr(0, "I can't open your mapping file (%s%s)\n"
+		"It is not in '%s" FILE_SEPARATOR ANTIWORD_DIR "' nor in '"
+		GLOBAL_ANTIWORD_DIR "'.", szLeafname, szSuffix, szHome);
+	return NULL;
+#endif /* __riscos */
+} /* end of pOpenCharacterMappingFile */
+
+/*
+ * vCloseCharacterMappingFile - close the mapping file
+ */
+static void
+vCloseCharacterMappingFile(FILE *pFile)
+{
+	(void)fclose(pFile);
+} /* end of pCloseCharacterMappingFile */
+
+
+/*
+ * iReadOptions - read options
+ *
+ * returns:	-1: error
+ *		 0: help
+ *		>0: index first file argument
+ */
+int
+iReadOptions(int argc, char **argv)
+{
+#if defined(__riscos)
+	FILE	*pFile;
+	const char	*szAlphabet;
+	int	iAlphabet;
+	char	szLine[81];
+#else
+	extern	char	*optarg;
+	extern int	optind;
+	char	*pcChar, *szTmp;
+	int	iChar;
+	char	szLeafname[LEAFNAME_SIZE];
+#endif /* __riscos */
+	FILE	*pCharacterMappingFile;
+	int	iTmp;
+	BOOL	bSuccess;
+
+	DBG_MSG("iReadOptions");
+
+/* Defaults */
+	tOptionsCurr = tOptionsDefault;
+
+#if defined(__riscos)
+/* Choices file */
+	pFile = fopen("<AntiWord$ChoicesFile>", "r");
+	DBG_MSG_C(pFile == NULL, "Choices file not found");
+	DBG_HEX_C(pFile != NULL, pFile);
+	if (pFile != NULL) {
+		while (fgets(szLine, (int)sizeof(szLine), pFile) != NULL) {
+			DBG_MSG(szLine);
+			if (szLine[0] == '#' ||
+			    szLine[0] == '\r' ||
+			    szLine[0] == '\n') {
+				continue;
+			}
+			if (sscanf(szLine, PARAGRAPH_BREAK, &iTmp) == 1 &&
+			    (iTmp == 0 ||
+			    (iTmp >= MIN_SCREEN_WIDTH &&
+			     iTmp <= MAX_SCREEN_WIDTH))) {
+				tOptionsCurr.iParagraphBreak = iTmp;
+				DBG_DEC(tOptionsCurr.iParagraphBreak);
+			} else if (sscanf(szLine, AUTOFILETYPE, &iTmp)
+								== 1) {
+				tOptionsCurr.bAutofiletypeAllowed =
+								iTmp != 0;
+				DBG_DEC(tOptionsCurr.bAutofiletypeAllowed);
+			} else if (sscanf(szLine, USE_OUTLINEFONTS, &iTmp)
+								== 1) {
+				tOptionsCurr.eConversionType =
+					iTmp == 0 ?
+					conversion_text : conversion_draw;
+				DBG_DEC(tOptionsCurr.eConversionType);
+			} else if (sscanf(szLine, SHOW_IMAGES, &iTmp)
+								== 1) {
+				tOptionsCurr.eImageLevel = iTmp != 0 ?
+					level_default : level_no_images;
+			} else if (sscanf(szLine, HIDE_HIDDEN_TEXT, &iTmp)
+								== 1) {
+				tOptionsCurr.bHideHiddenText = iTmp != 0;
+				DBG_DEC(tOptionsCurr.bHideHiddenText);
+			} else if (sscanf(szLine, SCALE_FACTOR_START, &iTmp)
+								== 1) {
+				if (iTmp >= MIN_SCALE_FACTOR &&
+				    iTmp <= MAX_SCALE_FACTOR) {
+					tOptionsCurr.iScaleFactor = iTmp;
+					DBG_DEC(tOptionsCurr.iScaleFactor);
+				}
+			}
+		}
+		(void)fclose(pFile);
+	}
+	iAlphabet = iReadCurrentAlphabetNumber();
+	switch (iAlphabet) {
+	case 101:	/* ISO-8859-1 aka Latin1 */
+		szAlphabet = "<AntiWord$Latin1>";
+		break;
+	case 112:	/* ISO-8859-15 aka Latin9 */
+		szAlphabet = "<AntiWord$Latin9>";
+		break;
+	default:
+		werr(0, "Alphabet '%d' is not supported", iAlphabet);
+		return -1;
+	}
+	pCharacterMappingFile = pOpenCharacterMappingFile(szAlphabet);
+	if (pCharacterMappingFile != NULL) {
+		bSuccess = bReadCharacterMappingTable(pCharacterMappingFile);
+		vCloseCharacterMappingFile(pCharacterMappingFile);
+	} else {
+		bSuccess = FALSE;
+	}
+	return bSuccess ? 1 : -1;
+#else
+/* Environment */
+	szTmp = getenv("COLUMNS");
+	if (szTmp != NULL) {
+		DBG_MSG(szTmp);
+		iTmp = (int)strtol(szTmp, &pcChar, 10);
+		if (*pcChar == '\0') {
+			iTmp -= 4;	/* This is for the edge */
+			if (iTmp < MIN_SCREEN_WIDTH) {
+				iTmp = MIN_SCREEN_WIDTH;
+			} else if (iTmp > MAX_SCREEN_WIDTH) {
+				iTmp = MAX_SCREEN_WIDTH;
+			}
+			tOptionsCurr.iParagraphBreak = iTmp;
+			DBG_DEC(tOptionsCurr.iParagraphBreak);
+		}
+	}
+	strncpy(szLeafname, szGetDefaultMappingFile(), sizeof(szLeafname) - 1);
+	szLeafname[sizeof(szLeafname) - 1] = '\0';
+/* Command line */
+	while ((iChar = getopt(argc, argv, "La:fhi:m:p:rstw:x:")) != -1) {
+		switch (iChar) {
+		case 'L':
+			tOptionsCurr.bUseLandscape = TRUE;
+			break;
+		case 'a':
+			if (!bCorrectPapersize(optarg, conversion_pdf)) {
+				werr(0, "-a without a valid papersize");
+				return -1;
+			}
+			break;
+		case 'f':
+			tOptionsCurr.eConversionType = conversion_fmt_text;
+			break;
+		case 'h':
+			return 0;
+		case 'i':
+			iTmp = (int)strtol(optarg, &pcChar, 10);
+			if (*pcChar != '\0') {
+				break;
+			}
+			switch (iTmp) {
+			case 0:
+				tOptionsCurr.eImageLevel = level_gs_special;
+				break;
+			case 1:
+				tOptionsCurr.eImageLevel = level_no_images;
+				break;
+			case 2:
+				tOptionsCurr.eImageLevel = level_ps_2;
+				break;
+			case 3:
+				tOptionsCurr.eImageLevel = level_ps_3;
+				break;
+			default:
+				tOptionsCurr.eImageLevel = level_default;
+				break;
+			}
+			DBG_DEC(tOptionsCurr.eImageLevel);
+			break;
+		case 'm':
+			if (tOptionsCurr.eConversionType == conversion_xml) {
+				werr(0, "XML doesn't need a mapping file");
+				break;
+			}
+			strncpy(szLeafname, optarg, sizeof(szLeafname) - 1);
+			szLeafname[sizeof(szLeafname) - 1] = '\0';
+			DBG_MSG(szLeafname);
+			break;
+		case 'p':
+			if (!bCorrectPapersize(optarg, conversion_ps)) {
+				werr(0, "-p without a valid papersize");
+				return -1;
+			}
+			break;
+		case 'r':
+			tOptionsCurr.bRemoveRemovedText = FALSE;
+			break;
+		case 's':
+			tOptionsCurr.bHideHiddenText = FALSE;
+			break;
+		case 't':
+			tOptionsCurr.eConversionType = conversion_text;
+			break;
+		case 'w':
+			iTmp = (int)strtol(optarg, &pcChar, 10);
+			if (*pcChar == '\0') {
+				if (iTmp != 0 && iTmp < MIN_SCREEN_WIDTH) {
+					iTmp = MIN_SCREEN_WIDTH;
+				} else if (iTmp > MAX_SCREEN_WIDTH) {
+					iTmp = MAX_SCREEN_WIDTH;
+				}
+				tOptionsCurr.iParagraphBreak = iTmp;
+				DBG_DEC(tOptionsCurr.iParagraphBreak);
+			}
+			break;
+		case 'x':
+			if (STREQ(optarg, "db")) {
+				tOptionsCurr.iParagraphBreak = 0;
+				tOptionsCurr.eConversionType = conversion_xml;
+				strcpy(szLeafname, MAPPING_FILE_UTF_8);
+			} else {
+				werr(0, "-x %s is not supported", optarg);
+				return -1;
+			}
+			break;
+		default:
+			return -1;
+		}
+	}
+
+	tOptionsCurr.eEncoding = eMappingFile2Encoding(szLeafname);
+	DBG_DEC(tOptionsCurr.eEncoding);
+
+	if (tOptionsCurr.eConversionType == conversion_ps &&
+	    tOptionsCurr.eEncoding == encoding_utf_8) {
+		werr(0,
+		"The combination PostScript and UTF-8 is not supported");
+		return -1;
+	}
+
+	if (tOptionsCurr.eConversionType == conversion_pdf &&
+	    tOptionsCurr.eEncoding == encoding_utf_8) {
+		werr(0,
+		"The combination PDF and UTF-8 is not supported");
+		return -1;
+	}
+
+	if (tOptionsCurr.eConversionType == conversion_pdf &&
+	    tOptionsCurr.eEncoding == encoding_cyrillic) {
+		werr(0,
+		"The combination PDF and Cyrillic is not supported");
+		return -1;
+	}
+
+	if (tOptionsCurr.eConversionType == conversion_ps ||
+	    tOptionsCurr.eConversionType == conversion_pdf) {
+		/* PostScript or PDF mode */
+		if (tOptionsCurr.bUseLandscape) {
+			/* Swap the page height and width */
+			iTmp = tOptionsCurr.iPageHeight;
+			tOptionsCurr.iPageHeight = tOptionsCurr.iPageWidth;
+			tOptionsCurr.iPageWidth = iTmp;
+		}
+		/* The paragraph break depends on the width of the paper */
+		tOptionsCurr.iParagraphBreak = iMilliPoints2Char(
+			(long)tOptionsCurr.iPageWidth * 1000 -
+			lDrawUnits2MilliPoints(
+				PS_LEFT_MARGIN + PS_RIGHT_MARGIN));
+		DBG_DEC(tOptionsCurr.iParagraphBreak);
+	}
+
+	pCharacterMappingFile = pOpenCharacterMappingFile(szLeafname);
+	if (pCharacterMappingFile != NULL) {
+		bSuccess = bReadCharacterMappingTable(pCharacterMappingFile);
+		vCloseCharacterMappingFile(pCharacterMappingFile);
+	} else {
+		bSuccess = FALSE;
+	}
+	return bSuccess ? optind : -1;
+#endif /* __riscos */
+} /* end of iReadOptions */
+
+/*
+ * vGetOptions - get a copy of the current option values
+ */
+void
+vGetOptions(options_type *pOptions)
+{
+	fail(pOptions == NULL);
+
+	*pOptions = tOptionsCurr;
+} /* end of vGetOptions */
+
+#if defined(__riscos)
+/*
+ * vWriteOptions - write the current options to the Options file
+ */
+static void
+vWriteOptions(void)
+{
+	FILE	*pFile;
+	char	*szOptionsFile;
+
+	TRACE_MSG("vWriteOptions");
+
+	szOptionsFile = getenv("AntiWord$ChoicesSave");
+	if (szOptionsFile == NULL) {
+		werr(0, "Warning: Name of the Choices file not found");
+		return;
+	}
+	if (!bMakeDirectory(szOptionsFile)) {
+		werr(0,
+		"Warning: I can't make a directory for the Choices file");
+		return;
+	}
+	pFile = fopen(szOptionsFile, "w");
+	if (pFile == NULL) {
+		werr(0, "Warning: I can't write the Choices file");
+		return;
+	}
+	(void)fprintf(pFile, PARAGRAPH_BREAK"\n",
+		tOptionsCurr.iParagraphBreak);
+	(void)fprintf(pFile, AUTOFILETYPE"\n",
+		tOptionsCurr.bAutofiletypeAllowed);
+	(void)fprintf(pFile, USE_OUTLINEFONTS"\n",
+		tOptionsCurr.eConversionType == conversion_text ? 0 : 1);
+	(void)fprintf(pFile, SHOW_IMAGES"\n",
+		tOptionsCurr.eImageLevel == level_no_images ? 0 : 1);
+	(void)fprintf(pFile, HIDE_HIDDEN_TEXT"\n",
+		tOptionsCurr.bHideHiddenText);
+	(void)fprintf(pFile, SCALE_FACTOR_START"\n",
+		tOptionsCurr.iScaleFactor);
+	(void)fclose(pFile);
+} /* end of vWriteOptions */
+
+/*
+ * vChoicesOpenAction - action to be taken when the Choices window opens
+ */
+void
+vChoicesOpenAction(window_handle tWindow)
+{
+	TRACE_MSG("vChoicesOpenAction");
+
+	tOptionsTemp = tOptionsCurr;
+	if (tOptionsTemp.iParagraphBreak == 0) {
+		vUpdateRadioButton(tWindow, CHOICES_BREAK_BUTTON, FALSE);
+		vUpdateRadioButton(tWindow, CHOICES_NO_BREAK_BUTTON, TRUE);
+		vUpdateWriteableNumber(tWindow, CHOICES_BREAK_WRITEABLE,
+					DEFAULT_SCREEN_WIDTH);
+	} else {
+		vUpdateRadioButton(tWindow, CHOICES_BREAK_BUTTON, TRUE);
+		vUpdateRadioButton(tWindow, CHOICES_NO_BREAK_BUTTON, FALSE);
+		vUpdateWriteableNumber(tWindow,
+			CHOICES_BREAK_WRITEABLE,
+			tOptionsTemp.iParagraphBreak);
+	}
+	vUpdateRadioButton(tWindow, CHOICES_AUTOFILETYPE_BUTTON,
+					tOptionsTemp.bAutofiletypeAllowed);
+	vUpdateRadioButton(tWindow, CHOICES_HIDDEN_TEXT_BUTTON,
+					tOptionsTemp.bHideHiddenText);
+	if (tOptionsTemp.eConversionType == conversion_draw) {
+		vUpdateRadioButton(tWindow,
+			CHOICES_WITH_IMAGES_BUTTON,
+			tOptionsTemp.eImageLevel != level_no_images);
+		vUpdateRadioButton(tWindow,
+			CHOICES_NO_IMAGES_BUTTON,
+			tOptionsTemp.eImageLevel == level_no_images);
+		vUpdateRadioButton(tWindow,
+			CHOICES_TEXTONLY_BUTTON, FALSE);
+	} else {
+		vUpdateRadioButton(tWindow,
+			CHOICES_WITH_IMAGES_BUTTON, FALSE);
+		vUpdateRadioButton(tWindow,
+			CHOICES_NO_IMAGES_BUTTON, FALSE);
+		vUpdateRadioButton(tWindow,
+			CHOICES_TEXTONLY_BUTTON, TRUE);
+	}
+	vUpdateWriteableNumber(tWindow,
+		CHOICES_SCALE_WRITEABLE, tOptionsTemp.iScaleFactor);
+	TRACE_MSG("end of vChoicesOpenAction");
+} /* end of vChoicesOpenAction */
+
+/*
+ * vDefaultButtonAction - action when the default button is clicked
+ */
+static void
+vDefaultButtonAction(window_handle tWindow)
+{
+	TRACE_MSG("vDefaultButtonAction");
+
+	tOptionsTemp = tOptionsDefault;
+	vUpdateRadioButton(tWindow, CHOICES_BREAK_BUTTON, TRUE);
+	vUpdateRadioButton(tWindow, CHOICES_NO_BREAK_BUTTON, FALSE);
+	vUpdateWriteableNumber(tWindow, CHOICES_BREAK_WRITEABLE,
+			tOptionsTemp.iParagraphBreak);
+	vUpdateRadioButton(tWindow, CHOICES_AUTOFILETYPE_BUTTON,
+			tOptionsTemp.bAutofiletypeAllowed);
+	vUpdateRadioButton(tWindow, CHOICES_HIDDEN_TEXT_BUTTON,
+			tOptionsTemp.bHideHiddenText);
+	vUpdateRadioButton(tWindow, CHOICES_WITH_IMAGES_BUTTON,
+			tOptionsTemp.eConversionType == conversion_draw &&
+			tOptionsTemp.eImageLevel != level_no_images);
+	vUpdateRadioButton(tWindow, CHOICES_NO_IMAGES_BUTTON,
+			tOptionsTemp.eConversionType == conversion_draw &&
+			tOptionsTemp.eImageLevel == level_no_images);
+	vUpdateRadioButton(tWindow, CHOICES_TEXTONLY_BUTTON,
+			tOptionsTemp.eConversionType == conversion_text);
+	vUpdateWriteableNumber(tWindow, CHOICES_SCALE_WRITEABLE,
+			tOptionsTemp.iScaleFactor);
+} /* end of vDefaultButtonAction */
+
+/*
+ * vApplyButtonAction - action to be taken when the OK button is clicked
+ */
+static void
+vApplyButtonAction(void)
+{
+	TRACE_MSG("vApplyButtonAction");
+
+	tOptionsCurr = tOptionsTemp;
+} /* end of vApplyButtonAction */
+
+/*
+ * vSaveButtonAction - action to be taken when the save button is clicked
+ */
+static void
+vSaveButtonAction(void)
+{
+	TRACE_MSG("vSaveButtonAction");
+
+	vApplyButtonAction();
+	vWriteOptions();
+} /* end of vSaveButtonAction */
+
+/*
+ * vSetParagraphBreak - set the paragraph break to the given number
+ */
+static void
+vSetParagraphBreak(window_handle tWindow, int iNumber)
+{
+	tOptionsTemp.iParagraphBreak = iNumber;
+	if (tOptionsTemp.iParagraphBreak == 0) {
+		return;
+	}
+	vUpdateWriteableNumber(tWindow,
+			CHOICES_BREAK_WRITEABLE,
+			tOptionsTemp.iParagraphBreak);
+} /* end of vSetParagraphBreak */
+
+/*
+ * vChangeParagraphBreak - change the paragraph break with the given number
+ */
+static void
+vChangeParagraphBreak(window_handle tWindow, int iNumber)
+{
+	int	iTmp;
+
+	iTmp = tOptionsTemp.iParagraphBreak + iNumber;
+	if (iTmp < MIN_SCREEN_WIDTH || iTmp > MAX_SCREEN_WIDTH) {
+	  	/* Ignore */
+		return;
+	}
+	tOptionsTemp.iParagraphBreak = iTmp;
+	vUpdateWriteableNumber(tWindow,
+			CHOICES_BREAK_WRITEABLE,
+			tOptionsTemp.iParagraphBreak);
+} /* end of vChangeParagraphBreak */
+
+/*
+ * vChangeAutofiletype - invert the permission to autofiletype
+ */
+static void
+vChangeAutofiletype(window_handle tWindow)
+{
+	tOptionsTemp.bAutofiletypeAllowed =
+				!tOptionsTemp.bAutofiletypeAllowed;
+	vUpdateRadioButton(tWindow,
+			CHOICES_AUTOFILETYPE_BUTTON,
+			tOptionsTemp.bAutofiletypeAllowed);
+} /* end of vChangeAutofiletype */
+
+/*
+ * vChangeHiddenText - invert the hide/show hidden text
+ */
+static void
+vChangeHiddenText(window_handle tWindow)
+{
+	tOptionsTemp.bHideHiddenText = !tOptionsTemp.bHideHiddenText;
+	vUpdateRadioButton(tWindow,
+			CHOICES_HIDDEN_TEXT_BUTTON,
+			tOptionsTemp.bHideHiddenText);
+} /* end of vChangeHiddenText */
+
+/*
+ * vUseFontsImages - use outline fonts, show images
+ */
+static void
+vUseFontsImages(BOOL bUseOutlineFonts, BOOL bShowImages)
+{
+	tOptionsTemp.eConversionType =
+		bUseOutlineFonts ? conversion_draw : conversion_text;
+	tOptionsTemp.eImageLevel =
+		bUseOutlineFonts && bShowImages ?
+		level_default : level_no_images;
+} /* end of vUseFontsImages */
+
+/*
+ * vSetScaleFactor - set the scale factor to the given number
+ */
+static void
+vSetScaleFactor(window_handle tWindow, int iNumber)
+{
+  	tOptionsTemp.iScaleFactor = iNumber;
+	vUpdateWriteableNumber(tWindow,
+			CHOICES_SCALE_WRITEABLE,
+			tOptionsTemp.iScaleFactor);
+} /* end of vSetScaleFactor */
+
+/*
+ * vChangeScaleFactor - change the scale factor with the given number
+ */
+static void
+vChangeScaleFactor(window_handle tWindow, int iNumber)
+{
+	int	iTmp;
+
+	iTmp = tOptionsTemp.iScaleFactor + iNumber;
+	if (iTmp < MIN_SCALE_FACTOR || iTmp > MAX_SCALE_FACTOR) {
+	  	/* Ignore */
+		return;
+	}
+	tOptionsTemp.iScaleFactor = iTmp;
+	vUpdateWriteableNumber(tWindow,
+			CHOICES_SCALE_WRITEABLE,
+			tOptionsTemp.iScaleFactor);
+} /* end of vChangeScaleFactor */
+
+/*
+ * bChoicesMouseClick - handle a mouse click in the Choices window
+ */
+BOOL
+bChoicesMouseClick(event_pollblock *pEvent, void *pvReference)
+{
+	icon_handle	tAction;
+	mouse_block	*pMouse;
+	BOOL		bCloseWindow;
+
+	TRACE_MSG("bChoicesMouseClick");
+
+	fail(pEvent == NULL);
+	fail(pEvent->type != event_CLICK);
+
+	pMouse = &pEvent->data.mouse;
+	if (!pMouse->button.data.select && !pMouse->button.data.adjust) {
+		/* Not handled here */
+		DBG_HEX(pMouse->button.value);
+		return FALSE;
+	}
+
+	/* Which action should be taken */
+	tAction = pMouse->icon;
+	if (pMouse->button.data.adjust) {
+	  	/* The adjust button reverses the direction */
+		switch (pMouse->icon) {
+		case CHOICES_BREAK_UP_BUTTON:
+			tAction = CHOICES_BREAK_DOWN_BUTTON;
+			break;
+		case CHOICES_BREAK_DOWN_BUTTON:
+			tAction = CHOICES_BREAK_UP_BUTTON;
+			break;
+		case CHOICES_SCALE_UP_BUTTON:
+			tAction = CHOICES_SCALE_DOWN_BUTTON;
+			break;
+		case CHOICES_SCALE_DOWN_BUTTON:
+			tAction = CHOICES_SCALE_UP_BUTTON;
+			break;
+		default:
+			break;
+		}
+	}
+
+	/* Actions */
+	bCloseWindow = FALSE;
+	switch (tAction) {
+	case CHOICES_DEFAULT_BUTTON:
+		vDefaultButtonAction(pMouse->window);
+		break;
+	case CHOICES_SAVE_BUTTON:
+		vSaveButtonAction();
+		break;
+	case CHOICES_CANCEL_BUTTON:
+		bCloseWindow = TRUE;
+		break;
+	case CHOICES_APPLY_BUTTON:
+		vApplyButtonAction();
+		bCloseWindow = TRUE;
+		break;
+	case CHOICES_BREAK_BUTTON:
+		vSetParagraphBreak(pMouse->window, DEFAULT_SCREEN_WIDTH);
+		break;
+	case CHOICES_BREAK_UP_BUTTON:
+		vChangeParagraphBreak(pMouse->window, 1);
+		break;
+	case CHOICES_BREAK_DOWN_BUTTON:
+		vChangeParagraphBreak(pMouse->window, -1);
+		break;
+	case CHOICES_NO_BREAK_BUTTON:
+		vSetParagraphBreak(pMouse->window, 0);
+		break;
+	case CHOICES_AUTOFILETYPE_BUTTON:
+		vChangeAutofiletype(pMouse->window);
+		break;
+	case CHOICES_HIDDEN_TEXT_BUTTON:
+		vChangeHiddenText(pMouse->window);
+		break;
+	case CHOICES_WITH_IMAGES_BUTTON:
+		vUseFontsImages(TRUE, TRUE);
+		break;
+	case CHOICES_NO_IMAGES_BUTTON:
+		vUseFontsImages(TRUE, FALSE);
+		break;
+	case CHOICES_TEXTONLY_BUTTON:
+		vUseFontsImages(FALSE, FALSE);
+		break;
+	case CHOICES_SCALE_UP_BUTTON:
+		vChangeScaleFactor(pMouse->window, 5);
+		break;
+	case CHOICES_SCALE_DOWN_BUTTON:
+		vChangeScaleFactor(pMouse->window, -5);
+		break;
+	default:
+		DBG_DEC(pMouse->icon);
+		break;
+	}
+	if (bCloseWindow) {
+		Error_CheckFatal(Wimp_CloseWindow(pMouse->window));
+	}
+	return TRUE;
+} /* end of bChoicesMouseClick */
+
+/*
+ * bChoicesKeyPressed - handle a key in the Choices window
+ */
+BOOL
+bChoicesKeyPressed(event_pollblock *pEvent, void *pvReference)
+{
+	icon_block	tIcon;
+	caret_block	*pCaret;
+	char		*pcChar;
+	int		iNumber;
+
+	DBG_MSG("bChoicesKeyPressed");
+
+	fail(pEvent == NULL);
+	fail(pEvent->type != event_KEY);
+
+	if (pEvent->data.key.code != '\r') {
+		Error_CheckFatal(Wimp_ProcessKey(pEvent->data.key.code));
+		return TRUE;
+	}
+
+	pCaret = &pEvent->data.key.caret;
+
+	Error_CheckFatal(Wimp_GetIconState(pCaret->window, pCaret->icon, &tIcon));
+	if (!tIcon.flags.data.text || !tIcon.flags.data.indirected) {
+		werr(1, "Icon %d must be indirected text", (int)pCaret->icon);
+	}
+	iNumber = (int)strtol(tIcon.data.indirecttext.buffer, &pcChar, 10);
+
+	switch(pCaret->icon) {
+	case CHOICES_BREAK_WRITEABLE:
+		if (*pcChar != '\0' && *pcChar != '\r') {
+			DBG_DEC(*pcChar);
+			iNumber = DEFAULT_SCREEN_WIDTH;
+		} else if (iNumber < MIN_SCREEN_WIDTH) {
+			iNumber = MIN_SCREEN_WIDTH;
+		} else if (iNumber > MAX_SCREEN_WIDTH) {
+			iNumber = MAX_SCREEN_WIDTH;
+		}
+		vSetParagraphBreak(pCaret->window, iNumber);
+		break;
+	case CHOICES_SCALE_WRITEABLE:
+		if (*pcChar != '\0' && *pcChar != '\r') {
+			DBG_DEC(*pcChar);
+			iNumber = DEFAULT_SCALE_FACTOR;
+		} else if (iNumber < MIN_SCALE_FACTOR) {
+			iNumber = MIN_SCALE_FACTOR;
+		} else if (iNumber > MAX_SCALE_FACTOR) {
+			iNumber = MAX_SCALE_FACTOR;
+		}
+		vSetScaleFactor(pCaret->window, iNumber);
+		break;
+	default:
+		DBG_DEC(pCaret->icon);
+		break;
+	}
+	return TRUE;
+} /* end of bChoicesKeyPressed */
+#endif /* __riscos */
diff --git a/out2window.c b/out2window.c
new file mode 100644
index 0000000..9bdacc3
--- /dev/null
+++ b/out2window.c
@@ -0,0 +1,768 @@
+/*
+ * out2window.c
+ * Copyright (C) 1998-2005 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Output to a text window
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "antiword.h"
+
+/* Used for numbering the chapters */
+static unsigned int	auiHdrCounter[9];
+
+
+/*
+ * vString2Diagram - put a string into a diagram
+ */
+static void
+vString2Diagram(diagram_type *pDiag, output_type *pAnchor)
+{
+	output_type	*pOutput;
+	long		lWidth;
+	USHORT		usMaxFontSize;
+
+	TRACE_MSG("vString2Diagram");
+
+	fail(pDiag == NULL);
+	fail(pAnchor == NULL);
+
+	/* Compute the maximum fontsize in this string */
+	usMaxFontSize = MIN_FONT_SIZE;
+	for (pOutput = pAnchor; pOutput != NULL; pOutput = pOutput->pNext) {
+		if (pOutput->usFontSize > usMaxFontSize) {
+			usMaxFontSize = pOutput->usFontSize;
+		}
+	}
+
+	/* Goto the next line */
+	vMove2NextLine(pDiag, pAnchor->tFontRef, usMaxFontSize);
+
+	/* Output all substrings */
+	for (pOutput = pAnchor; pOutput != NULL; pOutput = pOutput->pNext) {
+		lWidth = lMilliPoints2DrawUnits(pOutput->lStringWidth);
+		vSubstring2Diagram(pDiag, pOutput->szStorage,
+			pOutput->tNextFree, lWidth, pOutput->ucFontColor,
+			pOutput->usFontStyle, pOutput->tFontRef,
+			pOutput->usFontSize, usMaxFontSize);
+	}
+
+	/* Goto the start of the line */
+	pDiag->lXleft = 0;
+	TRACE_MSG("leaving vString2Diagram");
+} /* end of vString2Diagram */
+
+/*
+ * vSetLeftIndentation - set the left indentation of the specified diagram
+ */
+void
+vSetLeftIndentation(diagram_type *pDiag, long lLeftIndentation)
+{
+	long	lX;
+
+	TRACE_MSG("vSetLeftIndentation");
+
+	fail(pDiag == NULL);
+	fail(lLeftIndentation < 0);
+
+	lX = lMilliPoints2DrawUnits(lLeftIndentation);
+	if (lX > 0) {
+		pDiag->lXleft = lX;
+	} else {
+		pDiag->lXleft = 0;
+	}
+} /* end of vSetLeftIndentation */
+
+/*
+ * lComputeNetWidth - compute the net string width
+ */
+static long
+lComputeNetWidth(output_type *pAnchor)
+{
+	output_type	*pTmp;
+	long		lNetWidth;
+
+	TRACE_MSG("lComputeNetWidth");
+
+	fail(pAnchor == NULL);
+
+	/* Step 1: Count all but the last sub-string */
+	lNetWidth = 0;
+	for (pTmp = pAnchor; pTmp->pNext != NULL; pTmp = pTmp->pNext) {
+		fail(pTmp->lStringWidth < 0);
+		lNetWidth += pTmp->lStringWidth;
+	}
+	fail(pTmp == NULL);
+	fail(pTmp->pNext != NULL);
+
+	/* Step 2: remove the white-space from the end of the string */
+	while (pTmp->tNextFree != 0 &&
+	       isspace((int)(UCHAR)pTmp->szStorage[pTmp->tNextFree - 1])) {
+		pTmp->szStorage[pTmp->tNextFree - 1] = '\0';
+		pTmp->tNextFree--;
+		NO_DBG_DEC(pTmp->lStringWidth);
+		pTmp->lStringWidth = lComputeStringWidth(
+						pTmp->szStorage,
+						pTmp->tNextFree,
+						pTmp->tFontRef,
+						pTmp->usFontSize);
+		NO_DBG_DEC(pTmp->lStringWidth);
+	}
+
+	/* Step 3: Count the last sub-string */
+	lNetWidth += pTmp->lStringWidth;
+	return lNetWidth;
+} /* end of lComputeNetWidth */
+
+/*
+ * iComputeHoles - compute number of holes
+ * (A hole is a number of whitespace characters followed by a
+ *  non-whitespace character)
+ */
+static int
+iComputeHoles(output_type *pAnchor)
+{
+	output_type	*pTmp;
+	size_t	tIndex;
+	int	iCounter;
+	BOOL	bWasSpace, bIsSpace;
+
+	TRACE_MSG("iComputeHoles");
+
+	fail(pAnchor == NULL);
+
+	iCounter = 0;
+	bIsSpace = FALSE;
+	/* Count the holes */
+	for (pTmp = pAnchor; pTmp != NULL; pTmp = pTmp->pNext) {
+		fail(pTmp->tNextFree != strlen(pTmp->szStorage));
+		for (tIndex = 0; tIndex <= pTmp->tNextFree; tIndex++) {
+			bWasSpace = bIsSpace;
+			bIsSpace = isspace((int)(UCHAR)pTmp->szStorage[tIndex]);
+			if (bWasSpace && !bIsSpace) {
+				iCounter++;
+			}
+		}
+	}
+	return iCounter;
+} /* end of iComputeHoles */
+
+/*
+ * vAlign2Window - Align a string and insert it into the text
+ */
+void
+vAlign2Window(diagram_type *pDiag, output_type *pAnchor,
+	long lScreenWidth, UCHAR ucAlignment)
+{
+	long	lNetWidth, lLeftIndentation;
+
+	TRACE_MSG("vAlign2Window");
+
+	fail(pDiag == NULL || pAnchor == NULL);
+	fail(lScreenWidth < lChar2MilliPoints(MIN_SCREEN_WIDTH));
+
+	lNetWidth = lComputeNetWidth(pAnchor);
+
+	if (lScreenWidth > lChar2MilliPoints(MAX_SCREEN_WIDTH) ||
+	    lNetWidth <= 0) {
+		/*
+		 * Screenwidth is "infinite", so no alignment is possible
+		 * Don't bother to align an empty line
+		 */
+		vString2Diagram(pDiag, pAnchor);
+		TRACE_MSG("leaving vAlign2Window #1");
+		return;
+	}
+
+	switch (ucAlignment) {
+	case ALIGNMENT_CENTER:
+		lLeftIndentation = (lScreenWidth - lNetWidth) / 2;
+		DBG_DEC_C(lLeftIndentation < 0, lLeftIndentation);
+		if (lLeftIndentation > 0) {
+			vSetLeftIndentation(pDiag, lLeftIndentation);
+		}
+		break;
+	case ALIGNMENT_RIGHT:
+		lLeftIndentation = lScreenWidth - lNetWidth;
+		DBG_DEC_C(lLeftIndentation < 0, lLeftIndentation);
+		if (lLeftIndentation > 0) {
+			vSetLeftIndentation(pDiag, lLeftIndentation);
+		}
+		break;
+	case ALIGNMENT_JUSTIFY:
+	case ALIGNMENT_LEFT:
+	default:
+		break;
+	}
+	vString2Diagram(pDiag, pAnchor);
+	TRACE_MSG("leaving vAlign2Window #2");
+} /* end of vAlign2Window */
+
+/*
+ * vJustify2Window - Justify a string and insert it into the text
+ */
+void
+vJustify2Window(diagram_type *pDiag, output_type *pAnchor,
+	long lScreenWidth, long lRightIndentation, UCHAR ucAlignment)
+{
+	output_type	*pTmp;
+	char	*pcNew, *pcOld, *szStorage;
+	long	lNetWidth, lSpaceWidth, lToAdd;
+	int	iFillerLen, iHoles;
+
+	TRACE_MSG("vJustify2Window");
+
+	fail(pDiag == NULL || pAnchor == NULL);
+	fail(lScreenWidth < MIN_SCREEN_WIDTH);
+	fail(lRightIndentation > 0);
+
+	if (ucAlignment != ALIGNMENT_JUSTIFY) {
+		vAlign2Window(pDiag, pAnchor, lScreenWidth, ucAlignment);
+		return;
+	}
+
+	lNetWidth = lComputeNetWidth(pAnchor);
+
+	if (lScreenWidth > lChar2MilliPoints(MAX_SCREEN_WIDTH) ||
+	    lNetWidth <= 0) {
+		/*
+		 * Screenwidth is "infinite", so justify is not possible
+		 * Don't bother to justify an empty line
+		 */
+		vString2Diagram(pDiag, pAnchor);
+		TRACE_MSG("leaving vJustify2Window #1");
+		return;
+	}
+
+	/* Justify */
+	fail(ucAlignment != ALIGNMENT_JUSTIFY);
+	lSpaceWidth = lComputeStringWidth(" ", 1,
+				pAnchor->tFontRef, pAnchor->usFontSize);
+	lToAdd = lScreenWidth -
+			lNetWidth -
+			lDrawUnits2MilliPoints(pDiag->lXleft) +
+			lRightIndentation;
+#if defined(DEBUG)
+	if (lToAdd / lSpaceWidth < -1) {
+		DBG_DEC(lSpaceWidth);
+		DBG_DEC(lToAdd);
+		DBG_DEC(lScreenWidth);
+		DBG_DEC(lNetWidth);
+		DBG_DEC(lDrawUnits2MilliPoints(pDiag->lXleft));
+		DBG_DEC(pDiag->lXleft);
+		DBG_DEC(lRightIndentation);
+	}
+#endif /* DEBUG */
+	lToAdd /= lSpaceWidth;
+	DBG_DEC_C(lToAdd < 0, lToAdd);
+	if (lToAdd <= 0) {
+		vString2Diagram(pDiag, pAnchor);
+		TRACE_MSG("leaving vJustify2Window #2");
+		return;
+	}
+
+	/* Justify by adding spaces */
+	iHoles = iComputeHoles(pAnchor);
+	for (pTmp = pAnchor; pTmp != NULL; pTmp = pTmp->pNext) {
+		fail(pTmp->tNextFree != strlen(pTmp->szStorage));
+		fail(lToAdd < 0);
+		szStorage = xmalloc(pTmp->tNextFree + (size_t)lToAdd + 1);
+		pcNew = szStorage;
+		for (pcOld = pTmp->szStorage; *pcOld != '\0'; pcOld++) {
+			*pcNew++ = *pcOld;
+			if (*pcOld == ' ' &&
+			    *(pcOld + 1) != ' ' &&
+			    iHoles > 0) {
+				iFillerLen = (int)(lToAdd / iHoles);
+				lToAdd -= iFillerLen;
+				iHoles--;
+				for (; iFillerLen > 0; iFillerLen--) {
+					*pcNew++ = ' ';
+				}
+			}
+		}
+		*pcNew = '\0';
+		pTmp->szStorage = xfree(pTmp->szStorage);
+		pTmp->szStorage = szStorage;
+		pTmp->tStorageSize = pTmp->tNextFree + (size_t)lToAdd + 1;
+		pTmp->lStringWidth +=
+			(pcNew - szStorage - (long)pTmp->tNextFree) *
+			lSpaceWidth;
+		fail(pcNew < szStorage);
+		pTmp->tNextFree = (size_t)(pcNew - szStorage);
+		fail(pTmp->tNextFree != strlen(pTmp->szStorage));
+	}
+	DBG_DEC_C(lToAdd != 0, lToAdd);
+	vString2Diagram(pDiag, pAnchor);
+	TRACE_MSG("leaving vJustify2Window #3");
+} /* end of vJustify2Window */
+
+/*
+ * vResetStyles - reset the style information variables
+ */
+void
+vResetStyles(void)
+{
+	TRACE_MSG("vResetStyles");
+
+	(void)memset(auiHdrCounter, 0, sizeof(auiHdrCounter));
+} /* end of vResetStyles */
+
+/*
+ * tStyle2Window - Add the style characters to the line
+ *
+ * Returns the length of the resulting string
+ */
+size_t
+tStyle2Window(char *szLine, size_t tLineSize, const style_block_type *pStyle,
+	const section_block_type *pSection)
+{
+	char	*pcTxt;
+	size_t	tIndex, tStyleIndex;
+	BOOL	bNeedPrevLvl;
+	level_type_enum	eNumType;
+	UCHAR	ucNFC;
+
+	TRACE_MSG("tStyle2Window");
+
+	fail(szLine == NULL || pStyle == NULL || pSection == NULL);
+
+	if (pStyle->usIstd == 0 || pStyle->usIstd > 9) {
+		szLine[0] = '\0';
+		return 0;
+	}
+
+	/* Set the numbers */
+	tStyleIndex = (size_t)pStyle->usIstd - 1;
+	for (tIndex = 0; tIndex < 9; tIndex++) {
+		if (tIndex == tStyleIndex) {
+			auiHdrCounter[tIndex]++;
+		} else if (tIndex > tStyleIndex) {
+			auiHdrCounter[tIndex] = 0;
+		} else if (auiHdrCounter[tIndex] == 0) {
+			auiHdrCounter[tIndex] = 1;
+		}
+	}
+
+	eNumType = eGetNumType(pStyle->ucNumLevel);
+	if (eNumType != level_type_outline) {
+		szLine[0] = '\0';
+		return 0;
+	}
+
+	/* Print the numbers */
+	pcTxt = szLine;
+	bNeedPrevLvl = (pSection->usNeedPrevLvl & BIT(tStyleIndex)) != 0;
+	for (tIndex = 0; tIndex <= tStyleIndex; tIndex++) {
+		if (tIndex == tStyleIndex ||
+		    (bNeedPrevLvl && tIndex < tStyleIndex)) {
+			if (pcTxt - szLine >= tLineSize - 25) {
+				/* Prevent a possible buffer overflow */
+				DBG_DEC(pcTxt - szLine);
+				DBG_DEC(tLineSize - 25);
+				DBG_FIXME();
+				szLine[0] = '\0';
+				return 0;
+			}
+			ucNFC = pSection->aucNFC[tIndex];
+			switch(ucNFC) {
+			case LIST_ARABIC_NUM:
+			case LIST_NUMBER_TXT:
+			case LIST_ORDINAL_TXT:
+				pcTxt += sprintf(pcTxt, "%u",
+					auiHdrCounter[tIndex]);
+				break;
+			case LIST_UPPER_ROMAN:
+			case LIST_LOWER_ROMAN:
+				pcTxt += tNumber2Roman(
+					auiHdrCounter[tIndex],
+					ucNFC == LIST_UPPER_ROMAN,
+					pcTxt);
+				break;
+			case LIST_UPPER_ALPHA:
+			case LIST_LOWER_ALPHA:
+				pcTxt += tNumber2Alpha(
+					auiHdrCounter[tIndex],
+					ucNFC == LIST_UPPER_ALPHA,
+					pcTxt);
+				break;
+			case LIST_OUTLINE_NUM:
+				pcTxt += sprintf(pcTxt, "%02u",
+					auiHdrCounter[tIndex]);
+				break;
+			default:
+				DBG_DEC(ucNFC);
+				DBG_FIXME();
+				pcTxt += sprintf(pcTxt, "%u",
+					auiHdrCounter[tIndex]);
+				break;
+			}
+			if (tIndex < tStyleIndex) {
+				*pcTxt++ = '.';
+			} else if (tIndex == tStyleIndex) {
+				*pcTxt++ = ' ';
+			}
+		}
+	}
+	*pcTxt = '\0';
+	NO_DBG_MSG_C((int)pStyle->usIstd >= 1 &&
+		(int)pStyle->usIstd <= 9 &&
+		eNumType != level_type_none &&
+		eNumType != level_type_outline, szLine);
+	NO_DBG_MSG_C(szLine[0] != '\0', szLine);
+	fail(pcTxt < szLine);
+	return (size_t)(pcTxt - szLine);
+} /* end of tStyle2Window */
+
+/*
+ * vRemoveRowEnd - remove the end of table row indicator
+ *
+ * Remove the double TABLE_SEPARATOR characters from the end of the string.
+ * Special: remove the TABLE_SEPARATOR, 0x0a sequence
+ */
+static void
+vRemoveRowEnd(char *szRowTxt)
+{
+	int	iLastIndex;
+
+	TRACE_MSG("vRemoveRowEnd");
+
+	fail(szRowTxt == NULL || szRowTxt[0] == '\0');
+
+	iLastIndex = (int)strlen(szRowTxt) - 1;
+
+	if (szRowTxt[iLastIndex] == TABLE_SEPARATOR ||
+	    szRowTxt[iLastIndex] == (char)0x0a) {
+		szRowTxt[iLastIndex] = '\0';
+		iLastIndex--;
+	} else {
+		DBG_HEX(szRowTxt[iLastIndex]);
+	}
+
+	if (iLastIndex >= 0 && szRowTxt[iLastIndex] == (char)0x0a) {
+		szRowTxt[iLastIndex] = '\0';
+		iLastIndex--;
+	}
+
+	if (iLastIndex >= 0 && szRowTxt[iLastIndex] == TABLE_SEPARATOR) {
+		szRowTxt[iLastIndex] = '\0';
+		return;
+	}
+
+	DBG_DEC(iLastIndex);
+	DBG_HEX(szRowTxt[iLastIndex]);
+	DBG_MSG(szRowTxt);
+} /* end of vRemoveRowEnd */
+
+/*
+ * tComputeStringLengthMax - max string length in relation to max column width
+ *
+ * Return the maximum string length
+ */
+static size_t
+tComputeStringLengthMax(const char *szString, size_t tColumnWidthMax)
+{
+	const char	*pcTmp;
+	size_t	tLengthMax, tLenPrev, tLen, tWidth;
+
+	TRACE_MSG("tComputeStringLengthMax");
+
+	fail(szString == NULL);
+	fail(tColumnWidthMax == 0);
+
+	pcTmp = strchr(szString, '\n');
+	if (pcTmp != NULL) {
+		tLengthMax = (size_t)(pcTmp - szString + 1);
+	} else {
+		tLengthMax = strlen(szString);
+	}
+	if (tLengthMax == 0) {
+		return 0;
+	}
+
+	tLen = 0;
+	tWidth = 0;
+	for (;;) {
+		tLenPrev = tLen;
+		tLen += tGetCharacterLength(szString + tLen);
+		DBG_DEC_C(tLen > tLengthMax, tLen);
+		DBG_DEC_C(tLen > tLengthMax, tLengthMax);
+		fail(tLen > tLengthMax);
+		tWidth = tCountColumns(szString, tLen);
+		if (tWidth > tColumnWidthMax) {
+			return tLenPrev;
+		}
+		if (tLen >= tLengthMax) {
+			return tLengthMax;
+		}
+	}
+} /* end of tComputeStringLengthMax */
+
+/*
+ * tGetBreakingPoint - get the number of bytes that fit the column
+ *
+ * Returns the number of bytes that fit the column
+ */
+static size_t
+tGetBreakingPoint(const char *szString,
+	size_t tLen, size_t tWidth, size_t tColumnWidthMax)
+{
+	int	iIndex;
+
+	TRACE_MSG("tGetBreakingPoint");
+
+	fail(szString == NULL);
+	fail(tLen > strlen(szString));
+	fail(tWidth > tColumnWidthMax);
+
+	if (tWidth < tColumnWidthMax ||
+	    (tWidth == tColumnWidthMax &&
+	     (szString[tLen] == ' ' ||
+	      szString[tLen] == '\n' ||
+	      szString[tLen] == '\0'))) {
+		/* The string already fits, do nothing */
+		return tLen;
+	}
+	/* Search for a breaking point */
+	for (iIndex = (int)tLen - 1; iIndex >= 0; iIndex--) {
+		if (szString[iIndex] == ' ') {
+			return (size_t)iIndex;
+		}
+	}
+	/* No breaking point found, just fill the column */
+	return tLen;
+} /* end of tGetBreakingPoint */
+
+/*
+ * tComputeColumnWidthMax - compute the maximum column width
+ */
+static size_t
+tComputeColumnWidthMax(short sWidth, long lCharWidth, double dFactor)
+{
+	size_t	tColumnWidthMax;
+
+	TRACE_MSG("tComputeColumnWidthMax");
+
+	fail(sWidth < 0);
+	fail(lCharWidth <= 0);
+	fail(dFactor <= 0.0);
+
+	tColumnWidthMax = (size_t)(
+		(lTwips2MilliPoints(sWidth) * dFactor + lCharWidth / 2.0) /
+		 lCharWidth);
+	if (tColumnWidthMax == 0) {
+		/* Minimum column width */
+		return 1;
+	}
+	if (tColumnWidthMax > 1) {
+		/* Make room for the TABLE_SEPARATOR_CHAR */
+		tColumnWidthMax--;
+	}
+	NO_DBG_DEC(tColumnWidthMax);
+	return tColumnWidthMax;
+} /* end of tComputeColumnWidthMax */
+
+/*
+ * vTableRow2Window - put a table row into a diagram
+ */
+void
+vTableRow2Window(diagram_type *pDiag, output_type *pOutput,
+	const row_block_type *pRowInfo,
+	conversion_type eConversionType, int iParagraphBreak)
+{
+	output_type	tRow;
+	char	*aszColTxt[TABLE_COLUMN_MAX];
+	char	*szLine, *pcTxt;
+	double	dMagnify;
+	long	lCharWidthLarge, lCharWidthSmall;
+	size_t	tColumnWidthTotal, atColumnWidthMax[TABLE_COLUMN_MAX];
+	size_t	tSize, tColumnWidthMax, tWidth, tLen;
+	int	iIndex, iNbrOfColumns, iTmp;
+	BOOL	bNotReady;
+
+	TRACE_MSG("vTableRow2Window");
+
+	fail(pDiag == NULL || pOutput == NULL || pRowInfo == NULL);
+	fail(pOutput->szStorage == NULL);
+	fail(pOutput->pNext != NULL);
+	fail(iParagraphBreak < 0);
+
+	/* Character sizes */
+	lCharWidthLarge = lComputeStringWidth("W", 1,
+				pOutput->tFontRef, pOutput->usFontSize);
+	NO_DBG_DEC(lCharWidthLarge);
+	lCharWidthSmall = lComputeStringWidth("i", 1,
+				pOutput->tFontRef, pOutput->usFontSize);
+	NO_DBG_DEC(lCharWidthSmall);
+	/* For the time being: use a fixed width font */
+	fail(lCharWidthLarge != lCharWidthSmall);
+
+	vRemoveRowEnd(pOutput->szStorage);
+
+	/* Split the row text into a set of column texts */
+	aszColTxt[0] = pOutput->szStorage;
+	for (iNbrOfColumns = 1;
+	     iNbrOfColumns < TABLE_COLUMN_MAX;
+	     iNbrOfColumns++) {
+		aszColTxt[iNbrOfColumns] =
+				strchr(aszColTxt[iNbrOfColumns - 1],
+					TABLE_SEPARATOR);
+		if (aszColTxt[iNbrOfColumns] == NULL) {
+			break;
+		}
+		*aszColTxt[iNbrOfColumns] = '\0';
+		aszColTxt[iNbrOfColumns]++;
+		NO_DBG_DEC(iNbrOfColumns);
+		NO_DBG_MSG(aszColTxt[iNbrOfColumns]);
+	}
+
+	/* Work around a bug in Word */
+	while (iNbrOfColumns > (int)pRowInfo->ucNumberOfColumns &&
+	       pRowInfo->asColumnWidth[iNbrOfColumns] == 0) {
+		iNbrOfColumns--;
+	}
+
+	DBG_DEC_C(iNbrOfColumns != (int)pRowInfo->ucNumberOfColumns,
+		iNbrOfColumns);
+	DBG_DEC_C(iNbrOfColumns != (int)pRowInfo->ucNumberOfColumns,
+		pRowInfo->ucNumberOfColumns);
+	if (iNbrOfColumns != (int)pRowInfo->ucNumberOfColumns) {
+		werr(0, "Skipping an unmatched table row");
+		return;
+	}
+
+#if defined(__FULL_TEXT_SEARCH)
+	/* No table formatting: use for full-text search (untested) */
+	for (iIndex = 0; iIndex < iNbrOfColumns; iIndex++) {
+		fprintf(pDiag->pOutFile, "%s\n" , aszColTxt[iIndex]);
+	}
+#else
+	if (bAddTableRow(pDiag, aszColTxt, iNbrOfColumns,
+			pRowInfo->asColumnWidth, pRowInfo->ucBorderInfo)) {
+		/* All work has been done */
+		return;
+	}
+
+	/* Fill the table with maximum column widths */
+	if (eConversionType == conversion_text ||
+	    eConversionType == conversion_fmt_text) {
+		if (iParagraphBreak == 0 ||
+		    iParagraphBreak >= MAX_SCREEN_WIDTH) {
+			dMagnify = (double)MAX_SCREEN_WIDTH;
+		} else if (iParagraphBreak <= MIN_SCREEN_WIDTH) {
+			dMagnify = (double)MIN_SCREEN_WIDTH;
+		} else {
+			dMagnify = (double)iParagraphBreak;
+		}
+		dMagnify /= (double)DEFAULT_SCREEN_WIDTH;
+		DBG_FLT_C(dMagnify < 0.99 || dMagnify > 1.01, dMagnify);
+	} else {
+		dMagnify = 1.0;
+	}
+	tColumnWidthTotal = 0;
+	for (iIndex = 0; iIndex < iNbrOfColumns; iIndex++) {
+		atColumnWidthMax[iIndex] = tComputeColumnWidthMax(
+					pRowInfo->asColumnWidth[iIndex],
+					lCharWidthLarge,
+					dMagnify);
+		tColumnWidthTotal += atColumnWidthMax[iIndex];
+	}
+
+	/*
+	 * Get enough space for the row.
+	 * Worst case: three bytes per UTF-8 character
+	 */
+	tSize = 3 * (1 + tColumnWidthTotal + (size_t)iNbrOfColumns + 3);
+	szLine = xmalloc(tSize);
+
+	do {
+		/* Print one line of a table row */
+		bNotReady = FALSE;
+		pcTxt = szLine;
+		*pcTxt++ = TABLE_SEPARATOR_CHAR;
+		for (iIndex = 0; iIndex < iNbrOfColumns; iIndex++) {
+			tColumnWidthMax = atColumnWidthMax[iIndex];
+			if (aszColTxt[iIndex] == NULL) {
+				/* Add an empty column */
+				for (iTmp = 0;
+				     iTmp < (int)tColumnWidthMax;
+				     iTmp++) {
+					*pcTxt++ = (char)FILLER_CHAR;
+				}
+				*pcTxt++ = TABLE_SEPARATOR_CHAR;
+				*pcTxt = '\0';
+				continue;
+			}
+			/* Compute the length and width of the column text */
+			tLen = tComputeStringLengthMax(
+					aszColTxt[iIndex], tColumnWidthMax);
+			NO_DBG_DEC(tLen);
+			while (tLen != 0 &&
+					(aszColTxt[iIndex][tLen - 1] == '\n' ||
+					 aszColTxt[iIndex][tLen - 1] == ' ')) {
+				aszColTxt[iIndex][tLen - 1] = ' ';
+				tLen--;
+			}
+			tWidth = tCountColumns(aszColTxt[iIndex], tLen);
+			fail(tWidth > tColumnWidthMax);
+			tLen = tGetBreakingPoint(aszColTxt[iIndex],
+					tLen, tWidth, tColumnWidthMax);
+			tWidth = tCountColumns(aszColTxt[iIndex], tLen);
+			if (tLen == 0 && *aszColTxt[iIndex] == '\0') {
+				/* No text at all */
+				aszColTxt[iIndex] = NULL;
+			} else {
+				/* Add the text */
+				pcTxt += sprintf(pcTxt,
+					"%.*s", (int)tLen, aszColTxt[iIndex]);
+				if (tLen == 0 && *aszColTxt[iIndex] != ' ') {
+					tLen = tGetCharacterLength(
+							aszColTxt[iIndex]);
+					DBG_CHR(*aszColTxt[iIndex]);
+					DBG_FIXME();
+					fail(tLen == 0);
+				}
+				aszColTxt[iIndex] += tLen;
+				while (*aszColTxt[iIndex] == ' ') {
+					aszColTxt[iIndex]++;
+				}
+				if (*aszColTxt[iIndex] == '\0') {
+					/* This row is now complete */
+					aszColTxt[iIndex] = NULL;
+				} else {
+					/* This row needs more lines */
+					bNotReady = TRUE;
+				}
+			}
+			/* Fill up the rest */
+			for (iTmp = 0;
+			     iTmp < (int)tColumnWidthMax - (int)tWidth;
+			     iTmp++) {
+				*pcTxt++ = (char)FILLER_CHAR;
+			}
+			/* End of column */
+			*pcTxt++ = TABLE_SEPARATOR_CHAR;
+			*pcTxt = '\0';
+		}
+		/* Output the table row line */
+		*pcTxt = '\0';
+		tRow = *pOutput;
+		tRow.szStorage = szLine;
+		fail(pcTxt < szLine);
+		tRow.tNextFree = (size_t)(pcTxt - szLine);
+		tRow.lStringWidth = lComputeStringWidth(
+					tRow.szStorage,
+					tRow.tNextFree,
+					tRow.tFontRef,
+					tRow.usFontSize);
+		vString2Diagram(pDiag, &tRow);
+		TRACE_MSG("after vString2Diagram in vTableRow2Window");
+	} while (bNotReady);
+	/* Clean up before you leave */
+	szLine = xfree(szLine);
+	TRACE_MSG("leaving vTableRow2Window");
+#endif /* __FULL_TEXT_SEARCH */
+} /* end of vTableRow2Window */
diff --git a/output.c b/output.c
new file mode 100644
index 0000000..b2757ab
--- /dev/null
+++ b/output.c
@@ -0,0 +1,538 @@
+/*
+ * output.c
+ * Copyright (C) 2002-2004 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Generic output generating functions
+ */
+
+#include "antiword.h"
+
+static conversion_type	eConversionType = conversion_unknown;
+static encoding_type	eEncoding = encoding_neutral;
+
+
+/*
+ * vPrologue1 - get options and call a specific initialization
+ */
+static void
+vPrologue1(diagram_type *pDiag, const char *szTask, const char *szFilename)
+{
+	options_type	tOptions;
+
+	fail(pDiag == NULL);
+	fail(szTask == NULL || szTask[0] == '\0');
+
+	vGetOptions(&tOptions);
+	eConversionType = tOptions.eConversionType;
+	eEncoding = tOptions.eEncoding;
+
+	switch (eConversionType) {
+	case conversion_text:
+		vPrologueTXT(pDiag, &tOptions);
+		break;
+	case conversion_fmt_text:
+		vPrologueFMT(pDiag, &tOptions);
+		break;
+	case conversion_ps:
+		vProloguePS(pDiag, szTask, szFilename, &tOptions);
+		break;
+	case conversion_xml:
+		vPrologueXML(pDiag, &tOptions);
+		break;
+	case conversion_pdf:
+		vProloguePDF(pDiag, szTask, &tOptions);
+		break;
+	default:
+		DBG_DEC(eConversionType);
+		break;
+	}
+} /* end of vPrologue1 */
+
+/*
+ * vEpilogue - clean up after everything is done
+ */
+static void
+vEpilogue(diagram_type *pDiag)
+{
+	switch (eConversionType) {
+	case conversion_text:
+	case conversion_fmt_text:
+		vEpilogueTXT(pDiag->pOutFile);
+		break;
+	case conversion_ps:
+		vEpiloguePS(pDiag);
+		break;
+	case conversion_xml:
+		vEpilogueXML(pDiag);
+		break;
+	case conversion_pdf:
+		vEpiloguePDF(pDiag);
+		break;
+	default:
+		DBG_DEC(eConversionType);
+		break;
+	}
+} /* end of vEpilogue */
+
+/*
+ * vImagePrologue - perform image initialization
+ */
+void
+vImagePrologue(diagram_type *pDiag, const imagedata_type *pImg)
+{
+	switch (eConversionType) {
+	case conversion_text:
+	case conversion_fmt_text:
+		break;
+	case conversion_ps:
+		vImageProloguePS(pDiag, pImg);
+		break;
+	case conversion_xml:
+		break;
+	case conversion_pdf:
+		vImageProloguePDF(pDiag, pImg);
+		break;
+	default:
+		DBG_DEC(eConversionType);
+		break;
+	}
+} /* end of vImagePrologue */
+
+/*
+ * vImageEpilogue - clean up an image
+ */
+void
+vImageEpilogue(diagram_type *pDiag)
+{
+	switch (eConversionType) {
+	case conversion_text:
+	case conversion_fmt_text:
+		break;
+	case conversion_ps:
+		vImageEpiloguePS(pDiag);
+		break;
+	case conversion_xml:
+		break;
+	case conversion_pdf:
+		vImageEpiloguePDF(pDiag);
+		break;
+	default:
+		DBG_DEC(eConversionType);
+		break;
+	}
+} /* end of vImageEpilogue */
+
+/*
+ * bAddDummyImage - add a dummy image
+ *
+ * return TRUE when successful, otherwise FALSE
+ */
+BOOL
+bAddDummyImage(diagram_type *pDiag, const imagedata_type *pImg)
+{
+	switch (eConversionType) {
+	case conversion_text:
+	case conversion_fmt_text:
+		return FALSE;
+	case conversion_ps:
+		return bAddDummyImagePS(pDiag, pImg);
+	case conversion_xml:
+		return FALSE;
+	case conversion_pdf:
+		return bAddDummyImagePDF(pDiag, pImg);
+	default:
+		DBG_DEC(eConversionType);
+		return FALSE;
+	}
+} /* end of bAddDummyImage */
+
+/*
+ * pCreateDiagram - create and initialize a diagram
+ *
+ * remark: does not return if the diagram can't be created
+ */
+diagram_type *
+pCreateDiagram(const char *szTask, const char *szFilename)
+{
+	diagram_type	*pDiag;
+
+	fail(szTask == NULL || szTask[0] == '\0');
+	DBG_MSG("pCreateDiagram");
+
+	/* Get the necessary memory */
+	pDiag = xmalloc(sizeof(diagram_type));
+	/* Initialization */
+	pDiag->pOutFile = stdout;
+	vPrologue1(pDiag, szTask, szFilename);
+	/* Return success */
+	return pDiag;
+} /* end of pCreateDiagram */
+
+/*
+ * vDestroyDiagram - remove a diagram by freeing the memory it uses
+ */
+void
+vDestroyDiagram(diagram_type *pDiag)
+{
+	DBG_MSG("vDestroyDiagram");
+
+	fail(pDiag == NULL);
+
+	if (pDiag == NULL) {
+		return;
+	}
+	vEpilogue(pDiag);
+	pDiag = xfree(pDiag);
+} /* end of vDestroyDiagram */
+
+/*
+ * vPrologue2 - call a specific initialization
+ */
+void
+vPrologue2(diagram_type *pDiag, int iWordVersion)
+{
+	switch (eConversionType) {
+	case conversion_text:
+	case conversion_fmt_text:
+		break;
+	case conversion_ps:
+		vAddFontsPS(pDiag);
+		break;
+	case conversion_xml:
+		vCreateBookIntro(pDiag, iWordVersion);
+		break;
+	case conversion_pdf:
+		vCreateInfoDictionary(pDiag, iWordVersion);
+		vAddFontsPDF(pDiag);
+		break;
+	default:
+		DBG_DEC(eConversionType);
+		break;
+	}
+} /* end of vPrologue2 */
+
+/*
+ * vMove2NextLine - move to the next line
+ */
+void
+vMove2NextLine(diagram_type *pDiag, drawfile_fontref tFontRef,
+	USHORT usFontSize)
+{
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+	fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
+
+	switch (eConversionType) {
+	case conversion_text:
+	case conversion_fmt_text:
+		vMove2NextLineTXT(pDiag);
+		break;
+	case conversion_ps:
+		vMove2NextLinePS(pDiag, usFontSize);
+		break;
+	case conversion_xml:
+		vMove2NextLineXML(pDiag);
+		break;
+	case conversion_pdf:
+		vMove2NextLinePDF(pDiag, usFontSize);
+		break;
+	default:
+		DBG_DEC(eConversionType);
+		break;
+	}
+} /* end of vMove2NextLine */
+
+/*
+ * vSubstring2Diagram - put a sub string into a diagram
+ */
+void
+vSubstring2Diagram(diagram_type *pDiag,
+	char *szString, size_t tStringLength, long lStringWidth,
+	UCHAR ucFontColor, USHORT usFontstyle, drawfile_fontref tFontRef,
+	USHORT usFontSize, USHORT usMaxFontSize)
+{
+	switch (eConversionType) {
+	case conversion_text:
+		vSubstringTXT(pDiag, szString, tStringLength, lStringWidth);
+		break;
+	case conversion_fmt_text:
+		vSubstringFMT(pDiag, szString, tStringLength, lStringWidth,
+				usFontstyle);
+		break;
+	case conversion_ps:
+		vSubstringPS(pDiag, szString, tStringLength, lStringWidth,
+				ucFontColor, usFontstyle, tFontRef,
+				usFontSize, usMaxFontSize);
+		break;
+	case conversion_xml:
+		vSubstringXML(pDiag, szString, tStringLength, lStringWidth,
+				usFontstyle);
+		break;
+	case conversion_pdf:
+		vSubstringPDF(pDiag, szString, tStringLength, lStringWidth,
+				ucFontColor, usFontstyle, tFontRef,
+				usFontSize, usMaxFontSize);
+		break;
+	default:
+		DBG_DEC(eConversionType);
+		break;
+	}
+	pDiag->lXleft += lStringWidth;
+} /* end of vSubstring2Diagram */
+
+/*
+ * Create a start of paragraph (phase 1)
+ * Before indentation, list numbering, bullets etc.
+ */
+void
+vStartOfParagraph1(diagram_type *pDiag, long lBeforeIndentation)
+{
+	fail(pDiag == NULL);
+
+	switch (eConversionType) {
+	case conversion_text:
+	case conversion_fmt_text:
+		vStartOfParagraphTXT(pDiag, lBeforeIndentation);
+		break;
+	case conversion_ps:
+		vStartOfParagraphPS(pDiag, lBeforeIndentation);
+		break;
+	case conversion_xml:
+		break;
+	case conversion_pdf:
+		vStartOfParagraphPDF(pDiag, lBeforeIndentation);
+		break;
+	default:
+		DBG_DEC(eConversionType);
+		break;
+	}
+} /* end of vStartOfParagraph1 */
+
+/*
+ * Create a start of paragraph (phase 2)
+ * After indentation, list numbering, bullets etc.
+ */
+void
+vStartOfParagraph2(diagram_type *pDiag)
+{
+	fail(pDiag == NULL);
+
+	switch (eConversionType) {
+	case conversion_text:
+	case conversion_fmt_text:
+		break;
+	case conversion_ps:
+		break;
+	case conversion_xml:
+		vStartOfParagraphXML(pDiag, 1);
+		break;
+	case conversion_pdf:
+		break;
+	default:
+		DBG_DEC(eConversionType);
+		break;
+	}
+} /* end of vStartOfParagraph2 */
+
+/*
+ * Create an end of paragraph
+ */
+void
+vEndOfParagraph(diagram_type *pDiag,
+	drawfile_fontref tFontRef, USHORT usFontSize, long lAfterIndentation)
+{
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+	fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
+	fail(lAfterIndentation < 0);
+
+	switch (eConversionType) {
+	case conversion_text:
+	case conversion_fmt_text:
+		vEndOfParagraphTXT(pDiag, lAfterIndentation);
+		break;
+	case conversion_ps:
+		vEndOfParagraphPS(pDiag, usFontSize, lAfterIndentation);
+		break;
+	case conversion_xml:
+		vEndOfParagraphXML(pDiag, 1);
+		break;
+	case conversion_pdf:
+		vEndOfParagraphPDF(pDiag, usFontSize, lAfterIndentation);
+		break;
+	default:
+		DBG_DEC(eConversionType);
+		break;
+	}
+} /* end of vEndOfParagraph */
+
+/*
+ * Create an end of page
+ */
+void
+vEndOfPage(diagram_type *pDiag, long lAfterIndentation, BOOL bNewSection)
+{
+	switch (eConversionType) {
+	case conversion_text:
+	case conversion_fmt_text:
+		vEndOfPageTXT(pDiag, lAfterIndentation);
+		break;
+	case conversion_ps:
+		vEndOfPagePS(pDiag, bNewSection);
+		break;
+	case conversion_xml:
+		vEndOfPageXML(pDiag);
+		break;
+	case conversion_pdf:
+		vEndOfPagePDF(pDiag, bNewSection);
+		break;
+	default:
+		DBG_DEC(eConversionType);
+		break;
+	}
+} /* end of vEndOfPage */
+
+/*
+ * vSetHeaders - set the headers
+ */
+void
+vSetHeaders(diagram_type *pDiag, USHORT usIstd)
+{
+	switch (eConversionType) {
+	case conversion_text:
+	case conversion_fmt_text:
+		break;
+	case conversion_ps:
+		break;
+	case conversion_xml:
+		vSetHeadersXML(pDiag, usIstd);
+		break;
+	case conversion_pdf:
+		break;
+	default:
+		DBG_DEC(eConversionType);
+		break;
+	}
+} /* end of vSetHeaders */
+
+/*
+ * Create a start of list
+ */
+void
+vStartOfList(diagram_type *pDiag, UCHAR ucNFC, BOOL bIsEndOfTable)
+{
+	switch (eConversionType) {
+	case conversion_text:
+	case conversion_fmt_text:
+		break;
+	case conversion_ps:
+		break;
+	case conversion_xml:
+		vStartOfListXML(pDiag, ucNFC, bIsEndOfTable);
+		break;
+	case conversion_pdf:
+		break;
+	default:
+		DBG_DEC(eConversionType);
+		break;
+	}
+} /* end of vStartOfList */
+
+/*
+ * Create an end of list
+ */
+void
+vEndOfList(diagram_type *pDiag)
+{
+	switch (eConversionType) {
+	case conversion_text:
+	case conversion_fmt_text:
+		break;
+	case conversion_ps:
+		break;
+	case conversion_xml:
+		vEndOfListXML(pDiag);
+		break;
+	case conversion_pdf:
+		break;
+	default:
+		DBG_DEC(eConversionType);
+		break;
+	}
+} /* end of vEndOfList */
+
+/*
+ * Create a start of a list item
+ */
+void
+vStartOfListItem(diagram_type *pDiag, BOOL bNoMarks)
+{
+	switch (eConversionType) {
+	case conversion_text:
+	case conversion_fmt_text:
+		break;
+	case conversion_ps:
+		break;
+	case conversion_xml:
+		vStartOfListItemXML(pDiag, bNoMarks);
+		break;
+	case conversion_pdf:
+		break;
+	default:
+		DBG_DEC(eConversionType);
+		break;
+	}
+} /* end of vStartOfListItem */
+
+/*
+ * Create an end of a table
+ */
+void
+vEndOfTable(diagram_type *pDiag)
+{
+	switch (eConversionType) {
+	case conversion_text:
+	case conversion_fmt_text:
+		break;
+	case conversion_ps:
+		break;
+	case conversion_xml:
+		vEndOfTableXML(pDiag);
+		break;
+	case conversion_pdf:
+		break;
+	default:
+		DBG_DEC(eConversionType);
+		break;
+	}
+} /* end of vEndOfTable */
+
+/*
+ * Add a table row
+ *
+ * Returns TRUE when conversion type is XML
+ */
+BOOL
+bAddTableRow(diagram_type *pDiag, char **aszColTxt,
+	int iNbrOfColumns, const short *asColumnWidth, UCHAR ucBorderInfo)
+{
+	switch (eConversionType) {
+	case conversion_text:
+	case conversion_fmt_text:
+		break;
+	case conversion_ps:
+		break;
+	case conversion_xml:
+		vAddTableRowXML(pDiag, aszColTxt,
+				iNbrOfColumns, asColumnWidth,
+				ucBorderInfo);
+		return TRUE;
+	case conversion_pdf:
+		break;
+	default:
+		DBG_DEC(eConversionType);
+		break;
+	}
+	return FALSE;
+} /* end of bAddTableRow */
diff --git a/pdf.c b/pdf.c
new file mode 100644
index 0000000..85b7101
--- /dev/null
+++ b/pdf.c
@@ -0,0 +1,1148 @@
+/*
+ * pdf.c
+ * Copyright (C) 2003-2005 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Functions to deal with the Adobe Portable Document Format (pdf)
+ *
+ */
+
+#include <stdarg.h>
+#include <string.h>
+#include "version.h"
+#include "antiword.h"
+
+
+/* Constants for the file positions */
+#define INITIAL_LOCATION_SIZE	20
+#define INITIAL_PAGEOBJECT_SIZE	 5
+#if defined(DEBUG)
+#define EXTENSION_ARRAY_SIZE	10
+#else
+#define EXTENSION_ARRAY_SIZE	30
+#endif /* DEBUG */
+
+/* The character set */
+static encoding_type	eEncoding = encoding_neutral;
+/* Current creator for a PDF header */
+static const char	*szProducer = NULL;
+/* The height and width of a PDF page (in DrawUnits) */
+static long		lPageHeight = LONG_MAX;
+static long		lPageWidth = LONG_MAX;
+/* The height of the footer on the current page (in DrawUnits) */
+static long		lFooterHeight = 0;
+/* Inside a footer (to prevent an infinite loop when the footer is too big) */
+static BOOL		bInFtrSpace = FALSE;
+/* Current font information */
+static drawfile_fontref	tFontRefCurr = (drawfile_fontref)-1;
+static USHORT		usFontSizeCurr = 0;
+static int		iFontColorCurr = -1;
+/* Current vertical position information */
+static long		lYtopCurr = -1;
+/* Image counter */
+static int		iImageCount = 0;
+/* Section index */
+static int		iSectionIndex = 0;
+/* Are we on the first page of the section? */
+static BOOL		bFirstInSection = TRUE;
+/* File positions */
+static long		lFilePosition = 0;
+static long		*alLocation = NULL;
+static size_t		tLocations = 0;
+static int		iMaxLocationNumber = 0;
+/* File position at the start of a page */
+static long		lStreamStart = -1;
+/* Page objects */
+static int		*aiPageObject = NULL;
+static int		iPageCount = 0;
+static size_t		tMaxPageObjects = 0;
+/* Current object number */
+/* 1 = root; 2 = info; 3 = pages; 4 = encoding; 5-16 = fonts; 17 = resources */
+static int		iObjectNumberCurr = 17;
+
+static void		vMoveTo(diagram_type *, long);
+
+static const struct {
+	const char	*szPDFname;
+	const char	*szPSname;
+} atFontname[] = {
+	{ "Courier",			FONT_MONOSPACED_PLAIN },
+	{ "Courier-Bold",		FONT_MONOSPACED_BOLD },
+	{ "Courier-Oblique",		FONT_MONOSPACED_ITALIC },
+	{ "Courier-BoldOblique",	FONT_MONOSPACED_BOLDITALIC },
+	{ "Helvetica",			FONT_SANS_SERIF_PLAIN },
+	{ "Helvetica-Bold",		FONT_SANS_SERIF_BOLD },
+	{ "Helvetica-Oblique",		FONT_SANS_SERIF_ITALIC },
+	{ "Helvetica-BoldOblique",	FONT_SANS_SERIF_BOLDITALIC },
+	{ "Times-Roman",		FONT_SERIF_PLAIN },
+	{ "Times-Bold",			FONT_SERIF_BOLD },
+	{ "Times-Italic",		FONT_SERIF_ITALIC },
+	{ "Times-BoldItalic",		FONT_SERIF_BOLDITALIC },
+};
+
+static const char *iso_8859_1[] = {
+"128 /Euro",
+"140 /ellipsis /trademark /perthousand /bullet",
+"    /quoteleft /quoteright /guilsinglleft /guilsinglright",
+"    /quotedblleft /quotedblright /quotedblbase /endash /emdash",
+"    /minus /OE /oe /dagger /daggerdbl /fi /fl",
+"160 /space /exclamdown /cent /sterling /currency",
+"    /yen /brokenbar /section /dieresis /copyright",
+"    /ordfeminine /guillemotleft /logicalnot /hyphen /registered",
+"    /macron /degree /plusminus /twosuperior /threesuperior",
+"    /acute /mu /paragraph /periodcentered /cedilla",
+"    /onesuperior /ordmasculine /guillemotright /onequarter",
+"    /onehalf /threequarters /questiondown /Agrave /Aacute",
+"    /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla",
+"    /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute",
+"    /Icircumflex /Idieresis /Eth /Ntilde /Ograve /Oacute",
+"    /Ocircumflex /Otilde /Odieresis /multiply /Oslash",
+"    /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn",
+"    /germandbls /agrave /aacute /acircumflex /atilde",
+"    /adieresis /aring /ae /ccedilla /egrave /eacute",
+"    /ecircumflex /edieresis /igrave /iacute /icircumflex",
+"    /idieresis /eth /ntilde /ograve /oacute /ocircumflex",
+"    /otilde /odieresis /divide /oslash /ugrave /uacute",
+"    /ucircumflex /udieresis /yacute /thorn /ydieresis",
+};
+
+static const char *iso_8859_2[] = {
+"160 /space /Aogonek /breve /Lslash /currency /Lcaron",
+"    /Sacute /section /dieresis /Scaron /Scommaaccent",
+"    /Tcaron /Zacute /hyphen /Zcaron /Zdotaccent /degree",
+"    /aogonek /ogonek /lslash /acute /lcaron /sacute",
+"    /caron /cedilla /scaron /scommaaccent /tcaron",
+"    /zacute /hungarumlaut /zcaron /zdotaccent /Racute",
+"    /Aacute /Acircumflex /Abreve /Adieresis /Lacute",
+"    /Cacute /Ccedilla /Ccaron /Eacute /Eogonek",
+"    /Edieresis /Ecaron /Iacute /Icircumflex /Dcaron",
+"    /.notdef /Nacute /Ncaron /Oacute /Ocircumflex",
+"    /Ohungarumlaut /Odieresis /multiply /Rcaron /Uring",
+"    /Uacute /Uhungarumlaut /Udieresis /Yacute /Tcommaaccent",
+"    /germandbls /racute /aacute /acircumflex /abreve",
+"    /adieresis /lacute /cacute /ccedilla /ccaron /eacute",
+"    /eogonek /edieresis /ecaron /iacute /icircumflex",
+"    /dcaron /.notdef /nacute /ncaron /oacute /ocircumflex",
+"    /ohungarumlaut /odieresis /divide /rcaron /uring",
+"    /uacute /uhungarumlaut /udieresis /yacute /tcommaaccent",
+"    /dotaccent",
+};
+
+
+/*
+ * tGetFontIndex - get the font index
+ */
+static size_t
+tGetFontIndex(drawfile_fontref tFontRef)
+{
+	const char	*szFontname;
+	size_t		tIndex;
+
+	/* Get the font name */
+	szFontname = szGetFontname(tFontRef);
+	fail(szFontname == NULL);
+	if (szFontname == NULL) {
+		return 0;
+	}
+
+	/* Find the name in the table */
+	for (tIndex = 0; tIndex < elementsof(atFontname); tIndex++) {
+		if (STRCEQ(atFontname[tIndex].szPSname, szFontname)) {
+			return tIndex;
+		}
+	}
+	/* Not found */
+	DBG_DEC(tFontRef);
+	DBG_MSG(szFontname);
+	return 0;
+} /* end of tGetFontIndex */
+
+/*
+ * vSetLocation - store the location of objects
+ */
+static void
+vSetLocation(int iLocationNumber)
+{
+	fail(iLocationNumber <= 0);
+
+	if ((size_t)iLocationNumber >= tLocations) {
+		/* Extend and set to zero */
+		tLocations += EXTENSION_ARRAY_SIZE;
+		alLocation = xrealloc(alLocation, tLocations * sizeof(long));
+		memset(alLocation + tLocations - EXTENSION_ARRAY_SIZE,
+			0,
+			EXTENSION_ARRAY_SIZE * sizeof(long));
+		DBG_DEC(tLocations);
+	}
+	if (iLocationNumber > iMaxLocationNumber) {
+		iMaxLocationNumber = iLocationNumber;
+	}
+
+	DBG_DEC_C((size_t)iLocationNumber >= tLocations, iLocationNumber);
+	DBG_DEC_C((size_t)iLocationNumber >= tLocations, tLocations);
+	fail((size_t)iLocationNumber >= tLocations);
+
+	alLocation[iLocationNumber] = lFilePosition;
+} /* end of vSetLocation */
+
+/*
+ * vFillNextPageObject - fil the next page object with the current object number
+ */
+static void
+vFillNextPageObject(void)
+{
+	iPageCount++;
+	if ((size_t)iPageCount >= tMaxPageObjects) {
+		/* Extend the array */
+		tMaxPageObjects += EXTENSION_ARRAY_SIZE;
+		aiPageObject = xrealloc(aiPageObject,
+					tMaxPageObjects * sizeof(int));
+		DBG_DEC(tMaxPageObjects);
+	}
+	aiPageObject[iPageCount] = iObjectNumberCurr;
+} /* end of vFillNextPageObject */
+
+/*
+ * vFPprintf - printf and update the fileposition
+ *
+ * called with arguments like fprintf(3)
+ */
+static void
+vFPprintf(FILE *pOutFile, const char *szFormat, ...)
+{
+	va_list	tArg;
+
+	va_start(tArg, szFormat);
+	lFilePosition += vfprintf(pOutFile, szFormat, tArg);
+	va_end(tArg);
+} /* end of vFPprintf */
+
+/*
+ * vCreateInfoDictionary - create the document information dictionary
+ */
+void
+vCreateInfoDictionary(diagram_type *pDiag, int iWordVersion)
+{
+	FILE	*pOutFile;
+	const char	*szTitle, *szAuthor, *szSubject, *szCreator;
+	const char	*szCreationDate, *szModDate;
+
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+	fail(iWordVersion < 0);
+	fail(szProducer == NULL || szProducer[0] == '\0');
+
+	szTitle = szGetTitle();
+	szAuthor = szGetAuthor();
+	szSubject = szGetSubject();
+	szCreationDate = szGetCreationDate();
+	szModDate = szGetModDate();
+
+	switch (iWordVersion) {
+	case 0: szCreator = "Word for DOS"; break;
+	case 1: szCreator = "WinWord 1.x"; break;
+	case 2: szCreator = "WinWord 2.0"; break;
+	case 4: szCreator = "MacWord 4"; break;
+	case 5: szCreator = "MacWord 5"; break;
+	case 6: szCreator = "Word 6"; break;
+	case 7: szCreator = "Word 7/95"; break;
+	case 8: szCreator = "Word 97 or later"; break;
+	default: szCreator = NULL; break;
+	}
+
+	pOutFile = pDiag->pOutFile;
+
+	vSetLocation(2);
+	vFPprintf(pOutFile, "2 0 obj\n");
+	vFPprintf(pOutFile, "<<\n");
+	if (szTitle != NULL && szTitle[0] != '\0') {
+		vFPprintf(pOutFile, "/Title (%s)\n", szTitle);
+	}
+	if (szAuthor != NULL && szAuthor[0] != '\0') {
+		vFPprintf(pOutFile, "/Author (%s)\n", szAuthor);
+	}
+	if (szSubject != NULL && szSubject[0] != '\0') {
+		vFPprintf(pOutFile, "/Subject (%s)\n", szSubject);
+	}
+	if (szCreator != NULL && szCreator[0] != '\0') {
+		vFPprintf(pOutFile, "/Creator (%s)\n", szCreator);
+	}
+	vFPprintf(pOutFile, "/Producer (%s %s)\n", szProducer, VERSIONSTRING);
+	if (szCreationDate != NULL && szCreationDate[0] != '\0') {
+		vFPprintf(pOutFile, "/CreationDate (%s)\n", szCreationDate);
+	}
+	if (szModDate != NULL && szModDate[0] != '\0') {
+		vFPprintf(pOutFile, "/ModDate (%s)\n", szModDate);
+	}
+	vFPprintf(pOutFile, ">>\n");
+	vFPprintf(pOutFile, "endobj\n");
+} /* end of vCreateInfoDictionary */
+
+/*
+ * vAddHdrFtr - add a header or footer
+ */
+static void
+vAddHdrFtr(diagram_type *pDiag, const hdrftr_block_type *pHdrFtrInfo)
+{
+	output_type	*pStart, *pPrev, *pNext;
+
+	fail(pDiag == NULL);
+	fail(pHdrFtrInfo == NULL);
+
+	vStartOfParagraphPDF(pDiag, 0);
+	pStart = pHdrFtrInfo->pText;
+	while (pStart != NULL) {
+		pNext = pStart;
+		while (pNext != NULL &&
+		       (pNext->tNextFree != 1 ||
+		        (pNext->szStorage[0] != PAR_END &&
+		         pNext->szStorage[0] != HARD_RETURN))) {
+			pNext = pNext->pNext;
+		}
+		if (pNext == NULL) {
+			if (bOutputContainsText(pStart)) {
+				vAlign2Window(pDiag, pStart,
+					lChar2MilliPoints(DEFAULT_SCREEN_WIDTH),
+					ALIGNMENT_LEFT);
+			} else {
+				vMove2NextLinePDF(pDiag, pStart->usFontSize);
+			}
+			break;
+		}
+		fail(pNext->tNextFree != 1);
+		fail(pNext->szStorage[0] != PAR_END &&
+			pNext->szStorage[0] != HARD_RETURN);
+
+		if (pStart != pNext) {
+			/* There is something to print */
+			pPrev = pNext->pPrev;
+			fail(pPrev->pNext != pNext);
+			/* Cut the chain */
+			pPrev->pNext = NULL;
+			if (bOutputContainsText(pStart)) {
+				/* Print it */
+				vAlign2Window(pDiag, pStart,
+					lChar2MilliPoints(DEFAULT_SCREEN_WIDTH),
+					ALIGNMENT_LEFT);
+			} else {
+				/* Just an empty line */
+				vMove2NextLinePDF(pDiag, pStart->usFontSize);
+			}
+			/* Repair the chain */
+			pPrev->pNext = pNext;
+		}
+		if (pNext->szStorage[0] == PAR_END) {
+			vEndOfParagraphPDF(pDiag, pNext->usFontSize,
+					(long)pNext->usFontSize * 200);
+		}
+		pStart = pNext->pNext;
+	}
+} /* end of vAddHdrFtr */
+
+/*
+ * vAddHeader - add a page header
+ */
+static void
+vAddHeader(diagram_type *pDiag)
+{
+	const hdrftr_block_type *pHdrInfo;
+	const hdrftr_block_type *pFtrInfo;
+
+	fail(pDiag == NULL);
+
+	NO_DBG_MSG("vAddHeader");
+
+	pHdrInfo = pGetHdrFtrInfo(iSectionIndex, TRUE,
+					odd(iPageCount), bFirstInSection);
+	pFtrInfo = pGetHdrFtrInfo(iSectionIndex, FALSE,
+					odd(iPageCount), bFirstInSection);
+	/* Set the height of the footer of this page */
+	lFooterHeight = pFtrInfo == NULL ? 0 : pFtrInfo->lHeight;
+	fail(lFooterHeight < 0);
+
+	if (pHdrInfo == NULL ||
+	    pHdrInfo->pText == NULL ||
+	    pHdrInfo->lHeight <= 0) {
+		fail(pHdrInfo != NULL && pHdrInfo->lHeight < 0);
+		fail(pHdrInfo != NULL &&
+			pHdrInfo->pText != NULL &&
+			pHdrInfo->lHeight == 0);
+		return;
+	}
+
+	vAddHdrFtr(pDiag, pHdrInfo);
+
+	DBG_DEC_C(pHdrInfo->lHeight !=
+		lPageHeight - PS_TOP_MARGIN - pDiag->lYtop,
+		pHdrInfo->lHeight);
+	DBG_DEC_C(pHdrInfo->lHeight !=
+		lPageHeight - PS_TOP_MARGIN - pDiag->lYtop,
+		lPageHeight - PS_TOP_MARGIN - pDiag->lYtop);
+} /* end of vAddHeader */
+
+/*
+ * vAddFooter - add a page footer
+ */
+static void
+vAddFooter(diagram_type *pDiag)
+{
+	const hdrftr_block_type *pFtrInfo;
+
+	fail(pDiag == NULL);
+
+	NO_DBG_MSG("vAddFooter");
+
+	pFtrInfo = pGetHdrFtrInfo(iSectionIndex, FALSE,
+					odd(iPageCount), bFirstInSection);
+	bFirstInSection = FALSE;
+	if (pFtrInfo == NULL ||
+	    pFtrInfo->pText == NULL ||
+	    pFtrInfo->lHeight <= 0) {
+		fail(pFtrInfo != NULL && pFtrInfo->lHeight < 0);
+		fail(pFtrInfo != NULL &&
+			pFtrInfo->pText != NULL &&
+			pFtrInfo->lHeight == 0);
+		return;
+	}
+
+	bInFtrSpace = TRUE;
+
+	DBG_DEC_C(pFtrInfo->lHeight != lFooterHeight, pFtrInfo->lHeight);
+	DBG_DEC_C(pFtrInfo->lHeight != lFooterHeight, lFooterHeight);
+	DBG_DEC_C(pDiag->lYtop < lFooterHeight + PS_BOTTOM_MARGIN,
+			pDiag->lYtop);
+	DBG_DEC_C(pDiag->lYtop < lFooterHeight + PS_BOTTOM_MARGIN,
+			lFooterHeight + PS_BOTTOM_MARGIN);
+
+	if (pDiag->lYtop > lFooterHeight + PS_BOTTOM_MARGIN) {
+		/* Move down to the start of the footer */
+		pDiag->lYtop = lFooterHeight + PS_BOTTOM_MARGIN;
+		vMoveTo(pDiag, 0);
+	} else if (pDiag->lYtop < lFooterHeight + PS_BOTTOM_MARGIN / 2) {
+		DBG_FIXME();
+		/*
+		 * Move up to the start of the footer, to prevent moving
+		 * of the bottom edge of the paper
+		 */
+		pDiag->lYtop = lFooterHeight + PS_BOTTOM_MARGIN;
+		vMoveTo(pDiag, 0);
+	}
+
+	DBG_FLT_C(pDiag->lYtop < lFooterHeight + PS_BOTTOM_MARGIN,
+	dDrawUnits2Points(lFooterHeight + PS_BOTTOM_MARGIN - pDiag->lYtop));
+
+	vAddHdrFtr(pDiag, pFtrInfo);
+	bInFtrSpace = FALSE;
+} /* end of vAddFooter */
+
+/*
+ * vEndPageObject - end the current page object
+ */
+static void
+vEndPageObject(FILE *pOutFile)
+{
+	long	lStreamEnd;
+
+	if (lStreamStart < 0) {
+		/* There is no current page object */
+		return;
+	}
+
+	vFPprintf(pOutFile, "ET\n");
+	lStreamEnd = lFilePosition;
+	vFPprintf(pOutFile, "endstream\n");
+	vFPprintf(pOutFile, "endobj\n");
+
+	iObjectNumberCurr++;
+	vSetLocation(iObjectNumberCurr);
+	vFPprintf(pOutFile, "%d 0 obj\n", iObjectNumberCurr);
+	vFPprintf(pOutFile, "%lu\n", lStreamEnd - lStreamStart);
+	vFPprintf(pOutFile, "endobj\n");
+} /* end of vEndPageObject */
+
+/*
+ * vMove2NextPage - move to the start of the next page
+ */
+static void
+vMove2NextPage(diagram_type *pDiag, BOOL bNewSection)
+{
+	FILE	*pOutFile;
+
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+
+	pOutFile = pDiag->pOutFile;
+
+	vAddFooter(pDiag);
+	/* End the old page object */
+	vEndPageObject(pOutFile);
+	if (bNewSection) {
+		iSectionIndex++;
+		bFirstInSection = TRUE;
+	}
+
+	/* Start the new page object */
+	iObjectNumberCurr++;
+	vSetLocation(iObjectNumberCurr);
+	vFillNextPageObject();
+	vFPprintf(pOutFile, "%d 0 obj\n", iObjectNumberCurr);
+	vFPprintf(pOutFile, "<<\n");
+	vFPprintf(pOutFile, "/Type /Page\n");
+	vFPprintf(pOutFile, "/Parent 3 0 R\n");
+	vFPprintf(pOutFile, "/Resources 17 0 R\n");
+	vFPprintf(pOutFile, "/Contents %d 0 R\n", iObjectNumberCurr + 1);
+	vFPprintf(pOutFile, ">>\n");
+	vFPprintf(pOutFile, "endobj\n");
+
+	/* Start the new text object */
+	iObjectNumberCurr++;
+	vSetLocation(iObjectNumberCurr);
+	vFPprintf(pOutFile, "%d 0 obj\n", iObjectNumberCurr);
+	vFPprintf(pOutFile, "<<\n");
+	vFPprintf(pOutFile, "/Length %d 0 R\n", iObjectNumberCurr + 1);
+	vFPprintf(pOutFile, ">>\n");
+	vFPprintf(pOutFile, "stream\n");
+	lStreamStart = lFilePosition;
+	vFPprintf(pOutFile, "BT\n");
+
+	/* Set variables to their start of page values */
+	pDiag->lYtop = lPageHeight - PS_TOP_MARGIN;
+	tFontRefCurr = (drawfile_fontref)-1;
+	usFontSizeCurr = 0;
+	iFontColorCurr = -1;
+	lYtopCurr = -1;
+	vAddHeader(pDiag);
+} /* end of vMove2NextPage */
+
+/*
+ * vMoveTo - move to the specified X,Y coordinates
+ *
+ * Move the current position of the specified diagram to its X,Y coordinates,
+ * start on a new page if needed
+ */
+static void
+vMoveTo(diagram_type *pDiag, long lLastVerticalMovement)
+{
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+
+	if (pDiag->lYtop <= lFooterHeight + PS_BOTTOM_MARGIN && !bInFtrSpace) {
+		vMove2NextPage(pDiag, FALSE);
+		/* Repeat the last vertical movement on the new page */
+		pDiag->lYtop -= lLastVerticalMovement;
+	}
+
+	fail(pDiag->lYtop < lFooterHeight + PS_BOTTOM_MARGIN && !bInFtrSpace);
+	DBG_DEC_C(pDiag->lYtop < PS_BOTTOM_MARGIN, pDiag->lYtop);
+	fail(pDiag->lYtop < PS_BOTTOM_MARGIN / 3);
+
+	if (pDiag->lYtop != lYtopCurr) {
+		vFPprintf(pDiag->pOutFile, "1 0 0 1 %.2f %.2f Tm\n",
+			dDrawUnits2Points(pDiag->lXleft + PS_LEFT_MARGIN),
+			dDrawUnits2Points(pDiag->lYtop));
+		lYtopCurr = pDiag->lYtop;
+	}
+} /* end of vMoveTo */
+
+/*
+ * vProloguePDF - set options and perform the PDF initialization
+ */
+void
+vProloguePDF(diagram_type *pDiag,
+	const char *szTask, const options_type *pOptions)
+{
+	FILE	*pOutFile;
+
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+	fail(pOptions == NULL);
+
+	pOutFile = pDiag->pOutFile;
+
+	eEncoding = pOptions->eEncoding;
+
+	/* Create an empty location array */
+	tLocations = INITIAL_LOCATION_SIZE;
+	alLocation = xcalloc(tLocations, sizeof(long));
+
+	/* Create an empty pageobject array */
+	tMaxPageObjects = INITIAL_PAGEOBJECT_SIZE;
+	aiPageObject = xcalloc(tMaxPageObjects, sizeof(int));
+
+	if (pOptions->iPageHeight == INT_MAX) {
+		lPageHeight = LONG_MAX;
+	} else {
+		lPageHeight = lPoints2DrawUnits(pOptions->iPageHeight);
+	}
+	DBG_DEC(lPageHeight);
+	if (pOptions->iPageWidth == INT_MAX) {
+		lPageWidth = LONG_MAX;
+	} else {
+		lPageWidth = lPoints2DrawUnits(pOptions->iPageWidth);
+	}
+	DBG_DEC(lPageWidth);
+	lFooterHeight = 0;
+	bInFtrSpace = FALSE;
+
+	tFontRefCurr = (drawfile_fontref)-1;
+	usFontSizeCurr = 0;
+	iFontColorCurr = -1;
+	lYtopCurr = -1;
+	iPageCount = 0;
+	iImageCount = 0;
+	iSectionIndex = 0;
+	bFirstInSection = TRUE;
+	lFilePosition = 0;
+	iMaxLocationNumber = 0;
+	lStreamStart = -1;
+	iObjectNumberCurr = 17;
+	pDiag->lXleft = 0;
+	pDiag->lYtop = 0;
+
+	szProducer = szTask;
+
+	vFPprintf(pOutFile, "%%PDF-1.3\n");
+	vFPprintf(pOutFile, "%%%c%c%c%c\n", 0xe2, 0xe3, 0xcf, 0xd3);
+
+	/* Root catalog */
+	vSetLocation(1);
+	vFPprintf(pOutFile, "1 0 obj\n");
+	vFPprintf(pOutFile, "<<\n");
+	vFPprintf(pOutFile, "/Type /Catalog\n");
+	vFPprintf(pOutFile, "/Pages 3 0 R\n");
+	vFPprintf(pOutFile, ">>\n");
+	vFPprintf(pOutFile, "endobj\n");
+} /* end of vProloguePDF */
+
+/*
+ * vEpiloguePDF - clean up after everything is done
+ */
+void
+vEpiloguePDF(diagram_type *pDiag)
+{
+	FILE	*pOutFile;
+	long	lXref;
+	int	iIndex;
+
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+
+	pOutFile = pDiag->pOutFile;
+
+	vAddFooter(pDiag);
+	/* End the old page object */
+	vEndPageObject(pOutFile);
+
+	vSetLocation(3);
+	vFPprintf(pOutFile, "3 0 obj\n");
+	vFPprintf(pOutFile, "<<\n");
+	vFPprintf(pOutFile, "/Type /Pages\n");
+	vFPprintf(pOutFile, "/Count %d\n", iPageCount);
+	vFPprintf(pOutFile, "/MediaBox [ 0 0 %.0f %.0f ]\n",
+			dDrawUnits2Points(lPageWidth),
+			dDrawUnits2Points(lPageHeight));
+	vFPprintf(pOutFile, "/Kids [ ");
+	for (iIndex = 1; iIndex <= iPageCount; iIndex++) {
+		vFPprintf(pOutFile, "\t%d 0 R\n", aiPageObject[iIndex]);
+	}
+	vFPprintf(pOutFile, "]\n");
+	vFPprintf(pOutFile, ">>\n");
+	vFPprintf(pOutFile, "endobj\n");
+
+	lXref = lFilePosition;
+
+	vFPprintf(pOutFile, "xref\n");
+	vFPprintf(pOutFile, "0 %d\n", iMaxLocationNumber + 1);
+	vFPprintf(pOutFile, "0000000000 65535 f \n");
+	for (iIndex = 1; iIndex <= iMaxLocationNumber; iIndex++) {
+		vFPprintf(pOutFile, "%.10ld 00000 n \n", alLocation[iIndex]);
+	}
+
+	vFPprintf(pOutFile, "trailer\n");
+	vFPprintf(pOutFile, "<<\n");
+	vFPprintf(pOutFile, "/Size %d\n", iMaxLocationNumber + 1);
+	vFPprintf(pOutFile, "/Root 1 0 R\n");
+	vFPprintf(pOutFile, "/Info 2 0 R\n");
+	vFPprintf(pOutFile, ">>\n");
+
+	vFPprintf(pOutFile, "startxref\n");
+	vFPprintf(pOutFile, "%ld\n", lXref);
+	vFPprintf(pOutFile, "%%%%EOF\n");
+
+	szProducer = NULL;
+	aiPageObject = xfree(aiPageObject);
+	alLocation = xfree(alLocation);
+} /* end of vEpiloguePDF */
+
+/*
+ * vPrintPalette - print a pdf color space (palette)
+ */
+static void
+vPrintPalette(FILE *pOutFile, const imagedata_type *pImg)
+{
+	int	iIndex;
+
+	fail(pOutFile == NULL);
+	fail(pImg == NULL);
+	fail(pImg->iColorsUsed < 2);
+	fail(pImg->iColorsUsed > 256);
+
+	vFPprintf(pOutFile, "\t/ColorSpace [ /Indexed\n");
+	vFPprintf(pOutFile, "\t/Device%s %d\n",
+		pImg->bColorImage ? "RGB" : "Gray", pImg->iColorsUsed - 1);
+	vFPprintf(pOutFile, "<");
+	for (iIndex = 0; iIndex < pImg->iColorsUsed; iIndex++) {
+		vFPprintf(pOutFile, "%02x",
+				(unsigned int)pImg->aucPalette[iIndex][0]);
+		if (pImg->bColorImage) {
+			vFPprintf(pOutFile, "%02x%02x",
+				(unsigned int)pImg->aucPalette[iIndex][1],
+				(unsigned int)pImg->aucPalette[iIndex][2]);
+		}
+		if (iIndex % 8 == 7) {
+			vFPprintf(pOutFile, "\n");
+		} else {
+			vFPprintf(pOutFile, " ");
+		}
+	}
+	vFPprintf(pOutFile, "> ]\n");
+} /* end of vPrintPalette */
+
+/*
+ * vImageProloguePDF - perform the image initialization
+ */
+void
+vImageProloguePDF(diagram_type *pDiag, const imagedata_type *pImg)
+{
+	FILE	*pOutFile;
+
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+	fail(pImg == NULL);
+
+	if (pImg->iVerSizeScaled <= 0 || pImg->iHorSizeScaled <= 0) {
+		return;
+	}
+
+	iImageCount++;
+
+	DBG_DEC_C(pDiag->lXleft != 0, pDiag->lXleft);
+
+	pDiag->lYtop -= lPoints2DrawUnits(pImg->iVerSizeScaled);
+	vMoveTo(pDiag, lPoints2DrawUnits(pImg->iVerSizeScaled));
+
+	pOutFile = pDiag->pOutFile;
+
+	vFPprintf(pOutFile, "ET\n");
+	vFPprintf(pOutFile, "q %% Image %03d\n", iImageCount);
+	if (pImg->eImageType == imagetype_is_dib) {
+		/* Scanning from left to right and bottom to top */
+		vFPprintf(pOutFile, "%d 0 0 %d %.2f %.2f cm\n",
+			pImg->iHorSizeScaled, -pImg->iVerSizeScaled,
+			dDrawUnits2Points(pDiag->lXleft + PS_LEFT_MARGIN),
+			dDrawUnits2Points(pDiag->lYtop) + pImg->iVerSizeScaled);
+	} else {
+		/* Scanning from left to right and top to bottom */
+		vFPprintf(pOutFile, "%d 0 0 %d %.2f %.2f cm\n",
+			pImg->iHorSizeScaled, pImg->iVerSizeScaled,
+			dDrawUnits2Points(pDiag->lXleft + PS_LEFT_MARGIN),
+			dDrawUnits2Points(pDiag->lYtop));
+	}
+	vFPprintf(pOutFile, "BI\n");
+	vFPprintf(pOutFile, "\t/Width %d\n", pImg->iWidth);
+	vFPprintf(pOutFile, "\t/Height %d\n", pImg->iHeight);
+	switch (pImg->eImageType) {
+	case imagetype_is_jpeg:
+		switch (pImg->iComponents) {
+		case 1:
+			vFPprintf(pOutFile, "\t/ColorSpace /DeviceGray\n");
+			break;
+		case 3:
+			vFPprintf(pOutFile, "\t/ColorSpace /DeviceRGB\n");
+			break;
+		case 4:
+			vFPprintf(pOutFile, "\t/ColorSpace /DeviceCMYK\n");
+			if (pImg->bAdobe) {
+				/*
+				 * Adobe-conforming CMYK file
+				 * applying workaround for color inversion
+				 */
+				vFPprintf(pOutFile,
+					"\t/Decode [1 0 1 0 1 0 1 0]\n");
+			}
+			break;
+		default:
+			DBG_DEC(pImg->iComponents);
+			break;
+		}
+		vFPprintf(pOutFile, "\t/BitsPerComponent 8\n");
+		vFPprintf(pOutFile,
+			"\t/Filter [ /ASCII85Decode /DCTDecode ]\n");
+		break;
+	case imagetype_is_png:
+		if (pImg->iComponents == 3 || pImg->iComponents == 4) {
+			vFPprintf(pOutFile, "\t/ColorSpace /DeviceRGB\n");
+			vFPprintf(pOutFile, "\t/BitsPerComponent 8\n");
+		} else if (pImg->iColorsUsed > 0) {
+			vPrintPalette(pOutFile, pImg);
+			fail(pImg->uiBitsPerComponent > 8);
+			vFPprintf(pOutFile, "\t/BitsPerComponent %u\n",
+					pImg->uiBitsPerComponent);
+		} else {
+			vFPprintf(pOutFile, "\t/ColorSpace /DeviceGray\n");
+			vFPprintf(pOutFile, "\t/BitsPerComponent 8\n");
+		}
+		vFPprintf(pOutFile,
+			"\t/Filter [ /ASCII85Decode /FlateDecode ]\n");
+		vFPprintf(pOutFile, "\t/DecodeParms [ null <<\n");
+		vFPprintf(pOutFile, "\t\t/Predictor 10\n");
+		vFPprintf(pOutFile, "\t\t/Colors %d\n", pImg->iComponents);
+		vFPprintf(pOutFile, "\t\t/BitsPerComponent %u\n",
+						pImg->uiBitsPerComponent);
+		vFPprintf(pOutFile, "\t\t/Columns %d\n", pImg->iWidth);
+		vFPprintf(pOutFile, "\t\t>> ]\n");
+		break;
+	case imagetype_is_dib:
+		if (pImg->uiBitsPerComponent <= 8) {
+			vPrintPalette(pOutFile, pImg);
+		} else {
+			vFPprintf(pOutFile, "\t/ColorSpace /DeviceRGB\n");
+		}
+		vFPprintf(pOutFile, "\t/BitsPerComponent 8\n");
+		vFPprintf(pOutFile, "\t/Filter /ASCII85Decode\n");
+		break;
+	default:
+		vFPprintf(pOutFile, "\t/ColorSpace /Device%s\n",
+			pImg->bColorImage ? "RGB" : "Gray");
+		vFPprintf(pOutFile, "\t/BitsPerComponent 8\n");
+		vFPprintf(pOutFile, "\t/Filter /ASCIIHexDecode\n");
+		break;
+	}
+	vFPprintf(pOutFile, "ID\n");
+} /* end of vImageProloguePDF */
+
+/*
+ * vImageEpiloguePDF - clean up after the image
+ */
+void
+vImageEpiloguePDF(diagram_type *pDiag)
+{
+	FILE	*pOutFile;
+
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+
+	pOutFile = pDiag->pOutFile;
+
+	/* Correction for the image bytes */
+	lFilePosition = ftell(pOutFile);
+
+	vFPprintf(pOutFile, "EI\n");
+	vFPprintf(pOutFile, "Q\n");
+	vFPprintf(pOutFile, "BT\n");
+
+	pDiag->lXleft = 0;
+} /* end of vImageEpiloguePDF */
+
+/*
+ * bAddDummyImagePDF - add a dummy image
+ *
+ * return TRUE when successful, otherwise FALSE
+ */
+BOOL
+bAddDummyImagePDF(diagram_type *pDiag, const imagedata_type *pImg)
+{
+	FILE	*pOutFile;
+
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+	fail(pImg == NULL);
+
+	if (pImg->iVerSizeScaled <= 0 || pImg->iHorSizeScaled <= 0) {
+		return FALSE;
+	}
+
+	iImageCount++;
+
+	DBG_DEC_C(pDiag->lXleft != 0, pDiag->lXleft);
+
+	pDiag->lYtop -= lPoints2DrawUnits(pImg->iVerSizeScaled);
+	vMoveTo(pDiag, lPoints2DrawUnits(pImg->iVerSizeScaled));
+
+	pOutFile = pDiag->pOutFile;
+
+	vFPprintf(pOutFile, "ET\n");
+	vFPprintf(pOutFile, "q %% Image %03d\n", iImageCount);
+	vFPprintf(pOutFile, "\t1.0 w\n");
+	vFPprintf(pOutFile, "\t0.3 G\n");
+	vFPprintf(pOutFile, "\t%.2f %.2f %d %d re\n",
+			dDrawUnits2Points(pDiag->lXleft + PS_LEFT_MARGIN),
+			dDrawUnits2Points(pDiag->lYtop),
+			pImg->iHorSizeScaled,
+			pImg->iVerSizeScaled);
+	vFPprintf(pOutFile, "\tS\n");
+	vFPprintf(pOutFile, "Q\n");
+	vFPprintf(pOutFile, "BT\n");
+
+	pDiag->lXleft = 0;
+
+	return TRUE;
+} /* end of bAddDummyImagePDF */
+
+/*
+ * vAddFontsPDF - add the font information
+ */
+void
+vAddFontsPDF(diagram_type *pDiag)
+{
+	FILE	*pOutFile;
+	size_t	tIndex;
+
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+
+	pOutFile = pDiag->pOutFile;
+
+	/* The font encoding */
+	vSetLocation(4);
+	vFPprintf(pOutFile, "4 0 obj\n");
+	vFPprintf(pOutFile, "<<\n");
+	vFPprintf(pOutFile, "/Type /Encoding\n");
+	vFPprintf(pOutFile, "/BaseEncoding /StandardEncoding\n");
+	vFPprintf(pOutFile, "/Differences [\n");
+	switch (eEncoding) {
+	case encoding_latin_1:
+		for (tIndex = 0;
+		     tIndex < elementsof(iso_8859_1);
+		     tIndex++) {
+			vFPprintf(pOutFile, "%s\n", iso_8859_1[tIndex]);
+		}
+		break;
+	case encoding_latin_2:
+		for (tIndex = 0;
+		     tIndex < elementsof(iso_8859_2);
+		     tIndex++) {
+			vFPprintf(pOutFile, "%s\n", iso_8859_2[tIndex]);
+		}
+		break;
+	case encoding_cyrillic:
+		werr(1,
+		"The combination PDF and Cyrillic is not supported");
+		break;
+	case encoding_utf_8:
+		werr(1,
+		"The combination PDF and UTF-8 is not supported");
+		break;
+	default:
+		DBG_DEC(eEncoding);
+		break;
+	}
+	vFPprintf(pOutFile, "]\n");
+	vFPprintf(pOutFile, ">>\n");
+	vFPprintf(pOutFile, "endobj\n");
+
+	/* Twelve of the standard type 1 fonts */
+	for (tIndex = 0; tIndex < 12; tIndex++) {
+		vSetLocation(5 + tIndex);
+		vFPprintf(pOutFile, "%u 0 obj\n", 5 + tIndex);
+		vFPprintf(pOutFile, "<<\n");
+		vFPprintf(pOutFile, "/Type /Font\n");
+		vFPprintf(pOutFile, "/Subtype /Type1\n");
+		vFPprintf(pOutFile, "/Name /F%u\n", 1 + tIndex);
+		vFPprintf(pOutFile, "/BaseFont /%s\n",
+						atFontname[tIndex].szPDFname);
+		vFPprintf(pOutFile, "/Encoding 4 0 R\n");
+		vFPprintf(pOutFile, ">>\n");
+		vFPprintf(pOutFile, "endobj\n");
+	}
+
+	/* The Resources */
+	vSetLocation(17);
+	vFPprintf(pOutFile, "17 0 obj\n");
+	vFPprintf(pOutFile, "<<\n");
+	vFPprintf(pOutFile, "/ProcSet [ /PDF /Text ]\n");
+	vFPprintf(pOutFile, "/Font <<\n");
+	for (tIndex = 0; tIndex < 12; tIndex++) {
+		vFPprintf(pOutFile, "\t/F%u %u 0 R\n", 1 + tIndex, 5 + tIndex);
+	}
+	vFPprintf(pOutFile, "\t>>\n");
+	vFPprintf(pOutFile, ">>\n");
+	vFPprintf(pOutFile, "endobj\n");
+	vAddHeader(pDiag);
+} /* end of vAddFontsPDF */
+
+/*
+ * vPrintPDF - print a PDF string
+ */
+static void
+vPrintPDF(FILE *pFile, const char *szString, size_t tStringLength,
+	USHORT usFontstyle)
+{
+	const UCHAR	*aucBytes;
+	double	dMove;
+	size_t	tCount;
+
+	fail(szString == NULL);
+
+	if (szString == NULL || szString[0] == '\0' || tStringLength == 0) {
+		return;
+	}
+	DBG_DEC_C(usFontSizeCurr < MIN_FONT_SIZE, usFontSizeCurr);
+
+	dMove = 0.0;
+
+	/* Up for superscript */
+	if (bIsSuperscript(usFontstyle) && usFontSizeCurr != 0) {
+		dMove = (double)((usFontSizeCurr + 1) / 2) * 0.375;
+		vFPprintf(pFile, "%.2f Ts\n", dMove);
+	}
+
+	/* Down for subscript */
+	if (bIsSubscript(usFontstyle) && usFontSizeCurr != 0) {
+		dMove = (double)usFontSizeCurr * 0.125;
+		vFPprintf(pFile, "%.2f Ts\n", -dMove);
+	}
+
+	/* Generate and print the PDF output */
+	aucBytes = (UCHAR *)szString;
+	vFPprintf(pFile, "(");
+	for (tCount = 0; tCount < tStringLength ; tCount++) {
+		switch (aucBytes[tCount]) {
+		case '(':
+		case ')':
+		case '\\':
+			vFPprintf(pFile, "\\%c", szString[tCount]);
+			break;
+		default:
+			if (aucBytes[tCount] < 0x20 ||
+			    aucBytes[tCount] == 0x7f ||
+			    (aucBytes[tCount] >= 0x81 &&
+			     aucBytes[tCount] < 0x8c)) {
+				DBG_HEX(aucBytes[tCount]);
+				vFPprintf(pFile, " ");
+			} else if (aucBytes[tCount] >= 0x80) {
+				vFPprintf(pFile, "\\%03o",
+						(UINT)aucBytes[tCount]);
+			} else {
+				vFPprintf(pFile, "%c", szString[tCount]);
+			}
+			break;
+		}
+	}
+	vFPprintf(pFile, ") Tj\n");
+
+	/* Undo the superscript/subscript move */
+	if (dMove != 0.0) {
+		vFPprintf(pFile, "0 Ts\n");
+	}
+} /* end of vPrintPDF */
+
+/*
+ * vSetColor - move to the specified color
+ */
+static void
+vSetColor(FILE *pFile, UCHAR ucFontColor)
+{
+	ULONG	ulTmp, ulRed, ulGreen, ulBlue;
+
+	ulTmp = ulColor2Color(ucFontColor);
+	ulRed   = (ulTmp & 0x0000ff00) >> 8;
+	ulGreen = (ulTmp & 0x00ff0000) >> 16;
+	ulBlue  = (ulTmp & 0xff000000) >> 24;
+	vFPprintf(pFile, "%.3f %.3f %.3f rg\n",
+			ulRed / 255.0, ulGreen / 255.0, ulBlue / 255.0);
+} /* end of vSetColor */
+
+/*
+ * vMove2NextLinePDF - move to the next line
+ */
+void
+vMove2NextLinePDF(diagram_type *pDiag, USHORT usFontSize)
+{
+	fail(pDiag == NULL);
+	fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
+
+	pDiag->lYtop -= lComputeLeading(usFontSize);
+} /* end of vMove2NextLinePDF */
+
+/*
+ * vSubstringPDF - print a sub string
+ */
+void
+vSubstringPDF(diagram_type *pDiag,
+	char *szString, size_t tStringLength, long lStringWidth,
+	UCHAR ucFontColor, USHORT usFontstyle, drawfile_fontref tFontRef,
+	USHORT usFontSize, USHORT usMaxFontSize)
+{
+	size_t	tFontIndex;
+
+	fail(pDiag == NULL || szString == NULL);
+	fail(pDiag->pOutFile == NULL);
+	fail(pDiag->lXleft < 0);
+	fail(tStringLength != strlen(szString));
+	fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
+	fail(usMaxFontSize < MIN_FONT_SIZE || usMaxFontSize > MAX_FONT_SIZE);
+	fail(usFontSize > usMaxFontSize);
+
+	if (szString[0] == '\0' || tStringLength == 0) {
+		return;
+	}
+
+	vMoveTo(pDiag, lComputeLeading(usMaxFontSize));
+	if (tFontRef != tFontRefCurr || usFontSize != usFontSizeCurr) {
+		tFontIndex = tGetFontIndex(tFontRef);
+		vFPprintf(pDiag->pOutFile, "/F%u %.1f Tf\n",
+			 1 + tFontIndex, (double)usFontSize / 2.0);
+		tFontRefCurr = tFontRef;
+		usFontSizeCurr = usFontSize;
+	}
+	if ((int)ucFontColor != iFontColorCurr) {
+		vSetColor(pDiag->pOutFile, ucFontColor);
+		iFontColorCurr = (int)ucFontColor;
+	}
+	vPrintPDF(pDiag->pOutFile, szString, tStringLength, usFontstyle);
+	pDiag->lXleft += lStringWidth;
+} /* end of vSubstringPDF */
+
+/*
+ * Create an start of paragraph by moving the y-top mark
+ */
+void
+vStartOfParagraphPDF(diagram_type *pDiag, long lBeforeIndentation)
+{
+	fail(pDiag == NULL);
+	fail(lBeforeIndentation < 0);
+
+	pDiag->lXleft = 0;
+	pDiag->lYtop -= lMilliPoints2DrawUnits(lBeforeIndentation);
+} /* end of vStartOfParagraphPDF */
+
+/*
+ * Create an end of paragraph by moving the y-top mark
+ */
+void
+vEndOfParagraphPDF(diagram_type *pDiag,
+	USHORT usFontSize, long lAfterIndentation)
+{
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+	fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
+	fail(lAfterIndentation < 0);
+
+	if (pDiag->lXleft > 0) {
+		/* To the start of the line */
+		vMove2NextLinePDF(pDiag, usFontSize);
+	}
+
+	pDiag->lXleft = 0;
+	pDiag->lYtop -= lMilliPoints2DrawUnits(lAfterIndentation);
+} /* end of vEndOfParagraphPDF */
+
+/*
+ * Create an end of page
+ */
+void
+vEndOfPagePDF(diagram_type *pDiag, BOOL bNewSection)
+{
+	vMove2NextPage(pDiag, bNewSection);
+} /* end of vEndOfPagePDF */
diff --git a/pictlist.c b/pictlist.c
new file mode 100644
index 0000000..dd9e4bf
--- /dev/null
+++ b/pictlist.c
@@ -0,0 +1,109 @@
+/*
+ * pictlist.c
+ * Copyright (C) 2000-2004 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Build, read and destroy a list of Word picture information
+ */
+
+#include <stdlib.h>
+#include "antiword.h"
+
+
+/*
+ * Private structure to hide the way the information
+ * is stored from the rest of the program
+ */
+typedef struct picture_mem_tag {
+	picture_block_type      tInfo;
+	struct picture_mem_tag *pNext;
+} picture_mem_type;
+
+/* Variables needed to write the Picture Information List */
+static picture_mem_type	*pAnchor = NULL;
+static picture_mem_type	*pPictureLast = NULL;
+
+
+/*
+ * vDestroyPictInfoList - destroy the Picture Information List
+ */
+void
+vDestroyPictInfoList(void)
+{
+	picture_mem_type	*pCurr, *pNext;
+
+	DBG_MSG("vDestroyPictInfoList");
+
+	/* Free the Picture Information List */
+	pCurr = pAnchor;
+	while (pCurr != NULL) {
+		pNext = pCurr->pNext;
+		pCurr = xfree(pCurr);
+		pCurr = pNext;
+	}
+	pAnchor = NULL;
+	/* Reset all control variables */
+	pPictureLast = NULL;
+} /* end of vDestroyPictInfoList */
+
+/*
+ * vAdd2PictInfoList - Add an element to the Picture Information List
+ */
+void
+vAdd2PictInfoList(const picture_block_type *pPictureBlock)
+{
+	picture_mem_type	*pListMember;
+
+	fail(pPictureBlock == NULL);
+
+	NO_DBG_MSG("bAdd2PictInfoList");
+
+	if (pPictureBlock->ulFileOffset == FC_INVALID) {
+		/*
+		 * This offset is really past the end of the file,
+		 * so don't waste any memory by storing it.
+		 */
+		return;
+	}
+	if (pPictureBlock->ulFileOffsetPicture == FC_INVALID) {
+		/*
+		 * The place where this picture is supposed to be stored
+		 * doesn't exist.
+		 */
+		return;
+	}
+
+	NO_DBG_HEX(pPictureBlock->ulFileOffset);
+	NO_DBG_HEX(pPictureBlock->ulFileOffsetPicture);
+	NO_DBG_HEX(pPictureBlock->ulPictureOffset);
+
+	/* Create list member */
+	pListMember = xmalloc(sizeof(picture_mem_type));
+	/* Fill the list member */
+	pListMember->tInfo = *pPictureBlock;
+	pListMember->pNext = NULL;
+	/* Add the new member to the list */
+	if (pAnchor == NULL) {
+		pAnchor = pListMember;
+	} else {
+		fail(pPictureLast == NULL);
+		pPictureLast->pNext = pListMember;
+	}
+	pPictureLast = pListMember;
+} /* end of vAdd2PictInfoList */
+
+/*
+ * Get the info with the given file offset from the Picture Information List
+ */
+ULONG
+ulGetPictInfoListItem(ULONG ulFileOffset)
+{
+	picture_mem_type	*pCurr;
+
+	for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
+		if (pCurr->tInfo.ulFileOffset == ulFileOffset) {
+			return pCurr->tInfo.ulFileOffsetPicture;
+		}
+	}
+	return FC_INVALID;
+} /* end of ulGetPictInfoListItem */
diff --git a/png2eps.c b/png2eps.c
new file mode 100644
index 0000000..25d1755
--- /dev/null
+++ b/png2eps.c
@@ -0,0 +1,191 @@
+/*
+ * png2eps.c
+ * Copyright (C) 2000-2002 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Functions to translate png images into eps
+ *
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "antiword.h"
+
+#if defined(DEBUG)
+static int	iPicCounter = 0;
+#endif /* DEBUG */
+
+
+/*
+ * tSkipToData - skip until a IDAT chunk is found
+ *
+ * returns the length of the pixeldata or -1 in case of error
+ */
+static size_t
+tSkipToData(FILE *pFile, size_t tMaxBytes, size_t *ptSkipped)
+{
+	ULONG	ulName, ulTmp;
+	size_t	tDataLength, tToSkip;
+	int	iCounter;
+
+	fail(pFile == NULL);
+	fail(ptSkipped == NULL);
+
+	/* Examine chunks */
+	while (*ptSkipped + 8 < tMaxBytes) {
+		tDataLength = (size_t)ulNextLongBE(pFile);
+		DBG_DEC(tDataLength);
+		*ptSkipped += 4;
+
+		ulName = 0x00;
+		for (iCounter = 0; iCounter < 4; iCounter++) {
+			ulTmp = (ULONG)iNextByte(pFile);
+			if (!isalpha((int)ulTmp)) {
+				DBG_HEX(ulTmp);
+				return (size_t)-1;
+			}
+			ulName <<= 8;
+			ulName |= ulTmp;
+		}
+		DBG_HEX(ulName);
+		*ptSkipped += 4;
+
+		if (ulName == PNG_CN_IEND) {
+			break;
+		}
+		if (ulName == PNG_CN_IDAT) {
+			return tDataLength;
+		}
+
+		tToSkip = tDataLength + 4;
+		if (tToSkip >= tMaxBytes - *ptSkipped) {
+			DBG_DEC(tToSkip);
+			DBG_DEC(tMaxBytes - *ptSkipped);
+			return (size_t)-1;
+		}
+		(void)tSkipBytes(pFile, tToSkip);
+		*ptSkipped += tToSkip;
+	}
+
+	return (size_t)-1;
+} /* end of iSkipToData */
+
+/*
+ * iFindFirstPixelData - find the first pixeldata if a PNG image
+ *
+ * returns the length of the pixeldata or -1 in case of error
+ */
+static size_t
+tFindFirstPixelData(FILE *pFile, size_t tMaxBytes, size_t *ptSkipped)
+{
+	fail(pFile == NULL);
+	fail(tMaxBytes == 0);
+	fail(ptSkipped == NULL);
+
+	if (tMaxBytes < 8) {
+		DBG_DEC(tMaxBytes);
+		return (size_t)-1;
+	}
+
+	/* Skip over the PNG signature */
+	(void)tSkipBytes(pFile, 8);
+	*ptSkipped = 8;
+
+	return tSkipToData(pFile, tMaxBytes, ptSkipped);
+} /* end of iFindFirstPixelData */
+
+/*
+ * tFindNextPixelData - find the next pixeldata if a PNG image
+ *
+ * returns the length of the pixeldata or -1 in case of error
+ */
+static size_t
+tFindNextPixelData(FILE *pFile, size_t tMaxBytes, size_t *ptSkipped)
+{
+	fail(pFile == NULL);
+	fail(tMaxBytes == 0);
+	fail(ptSkipped == NULL);
+
+	if (tMaxBytes < 4) {
+		DBG_DEC(tMaxBytes);
+		return (size_t)-1;
+	}
+
+	/* Skip over the crc */
+	(void)tSkipBytes(pFile, 4);
+	*ptSkipped = 4;
+
+	return tSkipToData(pFile, tMaxBytes, ptSkipped);
+} /* end of tFindNextPixelData */
+
+#if defined(DEBUG)
+/*
+ * vCopy2File
+ */
+static void
+vCopy2File(FILE *pFile, ULONG ulFileOffset, size_t tPictureLen)
+{
+	FILE	*pOutFile;
+	size_t	tIndex;
+	int	iTmp;
+	char	szFilename[30];
+
+	if (!bSetDataOffset(pFile, ulFileOffset)) {
+		return;
+	}
+
+	sprintf(szFilename, "/tmp/pic/pic%04d.png", ++iPicCounter);
+	pOutFile = fopen(szFilename, "wb");
+	if (pOutFile == NULL) {
+		return;
+	}
+	for (tIndex = 0; tIndex < tPictureLen; tIndex++) {
+		iTmp = iNextByte(pFile);
+		if (putc(iTmp, pOutFile) == EOF) {
+			break;
+		}
+	}
+	(void)fclose(pOutFile);
+} /* end of vCopy2File */
+#endif /* DEBUG */
+
+/*
+ * bTranslatePNG - translate a PNG image
+ *
+ * This function translates an image from png to eps
+ *
+ * return TRUE when sucessful, otherwise FALSE
+ */
+BOOL
+bTranslatePNG(diagram_type *pDiag, FILE *pFile,
+	ULONG ulFileOffset, size_t tPictureLen, const imagedata_type *pImg)
+{
+	size_t	tMaxBytes, tDataLength, tSkipped;
+
+#if defined(DEBUG)
+	vCopy2File(pFile, ulFileOffset, tPictureLen);
+#endif /* DEBUG */
+
+	/* Seek to start position of PNG data */
+	if (!bSetDataOffset(pFile, ulFileOffset)) {
+		return FALSE;
+	}
+
+	tMaxBytes = tPictureLen;
+	tDataLength = tFindFirstPixelData(pFile, tMaxBytes, &tSkipped);
+	if (tDataLength == (size_t)-1) {
+		return FALSE;
+	}
+
+	vImagePrologue(pDiag, pImg);
+	do {
+		tMaxBytes -= tSkipped;
+		vASCII85EncodeArray(pFile, pDiag->pOutFile, tDataLength);
+		tMaxBytes -= tDataLength;
+		tDataLength = tFindNextPixelData(pFile, tMaxBytes, &tSkipped);
+	} while (tDataLength != (size_t)-1);
+	vASCII85EncodeByte(pDiag->pOutFile, EOF);
+	vImageEpilogue(pDiag);
+
+	return TRUE;
+} /* end of bTranslatePNG */
diff --git a/png2sprt.c b/png2sprt.c
new file mode 100644
index 0000000..d40ceb6
--- /dev/null
+++ b/png2sprt.c
@@ -0,0 +1,26 @@
+/*
+ * png2sprt.c
+ * Copyright (C) 2000 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Functions to translate png pictures into sprites
+ */
+
+#include <stdio.h>
+#include "antiword.h"
+
+
+/*
+ * bTranslatePNG - translate a PNG picture
+ *
+ * This function translates a picture from png to sprite
+ *
+ * return TRUE when sucessful, otherwise FALSE
+ */
+BOOL
+bTranslatePNG(diagram_type *pDiag, FILE *pFile,
+	ULONG ulFileOffset, size_t tPictureLen, const imagedata_type *pImg)
+{
+	/* PNG is not supported yet */
+	return bAddDummyImage(pDiag, pImg);
+} /* end of bTranslatePNG */
diff --git a/postscript.c b/postscript.c
new file mode 100644
index 0000000..fd20e53
--- /dev/null
+++ b/postscript.c
@@ -0,0 +1,1171 @@
+/*
+ * postscript.c
+ * Copyright (C) 1999-2005 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Functions to deal with the PostScript format
+ *
+ *================================================================
+ * The function vImagePrologue is based on:
+ * jpeg2ps - convert JPEG compressed images to PostScript Level 2
+ * Copyright (C) 1994-99 Thomas Merz (tm@muc.de)
+ *================================================================
+ * The credit should go to him, but all the bugs are mine.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <time.h>
+#include <string.h>
+#include "version.h"
+#include "antiword.h"
+
+/* The character set */
+static encoding_type	eEncoding = encoding_neutral;
+/* The image level */
+static image_level_enum	eImageLevel = level_default;
+/* The output must use landscape orientation */
+static BOOL		bUseLandscape = FALSE;
+/* The height and width of a PostScript page (in DrawUnits) */
+static long		lPageHeight = LONG_MAX;
+static long		lPageWidth = LONG_MAX;
+/* The height of the footer on the current page (in DrawUnits) */
+static long		lFooterHeight = 0;
+/* Inside a footer (to prevent an infinite loop when the footer is too big) */
+static BOOL		bInFtrSpace = FALSE;
+/* Current time for a PS header */
+static const char	*szCreationDate = NULL;
+/* Current creator for a PS header */
+static const char	*szCreator = NULL;
+/* Current font information */
+static drawfile_fontref	tFontRefCurr = (drawfile_fontref)-1;
+static USHORT		usFontSizeCurr = 0;
+static int		iFontColorCurr = -1;
+/* Current vertical position information */
+static long		lYtopCurr = -1;
+/* PostScript page counter */
+static int		iPageCount = 0;
+/* Image counter */
+static int		iImageCount = 0;
+/* Section index */
+static int		iSectionIndex = 0;
+/* Are we on the first page of the section? */
+static BOOL		bFirstInSection = TRUE;
+
+static void		vMoveTo(diagram_type *, long);
+
+static const char *iso_8859_1_data[] = {
+"/newcodes	% ISO-8859-1 character encodings",
+"[",
+"140/ellipsis 141/trademark 142/perthousand 143/bullet",
+"144/quoteleft 145/quoteright 146/guilsinglleft 147/guilsinglright",
+"148/quotedblleft 149/quotedblright 150/quotedblbase 151/endash 152/emdash",
+"153/minus 154/OE 155/oe 156/dagger 157/daggerdbl 158/fi 159/fl",
+"160/space 161/exclamdown 162/cent 163/sterling 164/currency",
+"165/yen 166/brokenbar 167/section 168/dieresis 169/copyright",
+"170/ordfeminine 171/guillemotleft 172/logicalnot 173/hyphen 174/registered",
+"175/macron 176/degree 177/plusminus 178/twosuperior 179/threesuperior",
+"180/acute 181/mu 182/paragraph 183/periodcentered 184/cedilla",
+"185/onesuperior 186/ordmasculine 187/guillemotright 188/onequarter",
+"189/onehalf 190/threequarters 191/questiondown 192/Agrave 193/Aacute",
+"194/Acircumflex 195/Atilde 196/Adieresis 197/Aring 198/AE 199/Ccedilla",
+"200/Egrave 201/Eacute 202/Ecircumflex 203/Edieresis 204/Igrave 205/Iacute",
+"206/Icircumflex 207/Idieresis 208/Eth 209/Ntilde 210/Ograve 211/Oacute",
+"212/Ocircumflex 213/Otilde 214/Odieresis 215/multiply 216/Oslash",
+"217/Ugrave 218/Uacute 219/Ucircumflex 220/Udieresis 221/Yacute 222/Thorn",
+"223/germandbls 224/agrave 225/aacute 226/acircumflex 227/atilde",
+"228/adieresis 229/aring 230/ae 231/ccedilla 232/egrave 233/eacute",
+"234/ecircumflex 235/edieresis 236/igrave 237/iacute 238/icircumflex",
+"239/idieresis 240/eth 241/ntilde 242/ograve 243/oacute 244/ocircumflex",
+"245/otilde 246/odieresis 247/divide 248/oslash 249/ugrave 250/uacute",
+"251/ucircumflex 252/udieresis 253/yacute 254/thorn 255/ydieresis",
+"] bind def",
+"",
+"/reencdict 12 dict def",
+"",
+};
+
+static const char *iso_8859_2_data[] = {
+"/newcodes	% ISO-8859-2 character encodings",
+"[",
+"160/space 161/Aogonek 162/breve 163/Lslash 164/currency 165/Lcaron",
+"166/Sacute 167/section 168/dieresis 169/Scaron 170/Scommaaccent",
+"171/Tcaron 172/Zacute 173/hyphen 174/Zcaron 175/Zdotaccent 176/degree",
+"177/aogonek 178/ogonek 179/lslash 180/acute 181/lcaron 182/sacute",
+"183/caron 184/cedilla 185/scaron 186/scommaaccent 187/tcaron",
+"188/zacute 189/hungarumlaut 190/zcaron 191/zdotaccent 192/Racute",
+"193/Aacute 194/Acircumflex 195/Abreve 196/Adieresis 197/Lacute",
+"198/Cacute 199/Ccedilla 200/Ccaron 201/Eacute 202/Eogonek",
+"203/Edieresis 204/Ecaron 205/Iacute 206/Icircumflex 207/Dcaron",
+"208/Dcroat 209/Nacute 210/Ncaron 211/Oacute 212/Ocircumflex",
+"213/Ohungarumlaut 214/Odieresis 215/multiply 216/Rcaron 217/Uring",
+"218/Uacute 219/Uhungarumlaut 220/Udieresis 221/Yacute 222/Tcommaaccent",
+"223/germandbls 224/racute 225/aacute 226/acircumflex 227/abreve",
+"228/adieresis 229/lacute 230/cacute 231/ccedilla 232/ccaron 233/eacute",
+"234/eogonek 235/edieresis 236/ecaron 237/iacute 238/icircumflex",
+"239/dcaron 240/dcroat 241/nacute 242/ncaron 243/oacute 244/ocircumflex",
+"245/ohungarumlaut 246/odieresis 247/divide 248/rcaron 249/uring",
+"250/uacute 251/uhungarumlaut 252/udieresis 253/yacute 254/tcommaaccent",
+"255/dotaccent",
+"] bind def",
+"",
+"/reencdict 12 dict def",
+"",
+};
+
+static const char *iso_8859_5_data[] = {
+"/newcodes	% ISO-8859-5 character encodings",
+"[",
+"160/space     161/afii10023 162/afii10051 163/afii10052 164/afii10053",
+"165/afii10054 166/afii10055 167/afii10056 168/afii10057 169/afii10058",
+"170/afii10059 171/afii10060 172/afii10061 173/hyphen    174/afii10062",
+"175/afii10145 176/afii10017 177/afii10018 178/afii10019 179/afii10020",
+"180/afii10021 181/afii10022 182/afii10024 183/afii10025 184/afii10026",
+"185/afii10027 186/afii10028 187/afii10029 188/afii10030 189/afii10031",
+"190/afii10032 191/afii10033 192/afii10034 193/afii10035 194/afii10036",
+"195/afii10037 196/afii10038 197/afii10039 198/afii10040 199/afii10041",
+"200/afii10042 201/afii10043 202/afii10044 203/afii10045 204/afii10046",
+"205/afii10047 206/afii10048 207/afii10049 208/afii10065 209/afii10066",
+"210/afii10067 211/afii10068 212/afii10069 213/afii10070 214/afii10072",
+"215/afii10073 216/afii10074 217/afii10075 218/afii10076 219/afii10077",
+"220/afii10078 221/afii10079 222/afii10080 223/afii10081 224/afii10082",
+"225/afii10083 226/afii10084 227/afii10085 228/afii10086 229/afii10087",
+"230/afii10088 231/afii10089 232/afii10090 233/afii10091 234/afii10092",
+"235/afii10093 236/afii10094 237/afii10095 238/afii10096 239/afii10097",
+"240/afii61352 241/afii10071 242/afii10099 243/afii10100 244/afii10101",
+"245/afii10102 246/afii10103 247/afii10104 248/afii10105 249/afii10106",
+"250/afii10107 251/afii10108 252/afii10109 253/section   254/afii10110",
+"255/afii10193",
+"] bind def",
+"",
+"/reencdict 12 dict def",
+"",
+};
+
+static const char *iso_8859_x_func[] = {
+"% change fonts using ISO-8859-x characters",
+"/ChgFnt		% size psname natname => font",
+"{",
+"	dup FontDirectory exch known		% is re-encoded name known?",
+"	{ exch pop }				% yes, get rid of long name",
+"	{ dup 3 1 roll ReEncode } ifelse	% no, re-encode it",
+"	findfont exch scalefont setfont",
+"} bind def",
+"",
+"/ReEncode",
+"{",
+"reencdict begin",
+"	/newname exch def",
+"	/basename exch def",
+"	/basedict basename findfont def",
+"	/newfont basedict maxlength dict def",
+"	basedict",
+"	{ exch dup /FID ne",
+"		{ dup /Encoding eq",
+"			{ exch dup length array copy newfont 3 1 roll put }",
+"			{ exch newfont 3 1 roll put } ifelse",
+"		}",
+"		{ pop pop } ifelse",
+"	} forall",
+"	newfont /FontName newname put",
+"	newcodes aload pop newcodes length 2 idiv",
+"	{ newfont /Encoding get 3 1 roll put } repeat",
+"	newname newfont definefont pop",
+"end",
+"} bind def",
+"",
+};
+
+static const char *misc_func[] = {
+"% draw a line and show the string",
+"/LineShow	% string linewidth movement",
+"{",
+"	gsave",
+"		0 exch rmoveto",
+"		setlinewidth",
+"		dup",
+"		stringwidth pop",
+"		0 rlineto stroke",
+"	grestore",
+"	show",
+"} bind def",
+"",
+"% begin an EPS file (level 2 and up)",
+"/BeginEPSF",
+"{",
+"	/b4_Inc_state save def",
+"	/dict_count countdictstack def",
+"	/op_count count 1 sub def",
+"	userdict begin",
+"		/showpage { } def",
+"		0 setgray 0 setlinecap",
+"		1 setlinewidth 0 setlinejoin",
+"		10 setmiterlimit [ ] 0 setdash newpath",
+"		false setstrokeadjust false setoverprint",
+"} bind def",
+"",
+"% end an EPS file",
+"/EndEPSF {",
+"	count op_count sub { pop } repeat",
+"	countdictstack dict_count sub { end } repeat",
+"	b4_Inc_state restore",
+"} bind def",
+"",
+};
+
+
+/*
+ * vAddPageSetup - add the page setup
+ */
+static void
+vAddPageSetup(FILE *pOutFile)
+{
+	if (bUseLandscape) {
+		fprintf(pOutFile, "%%%%BeginPageSetup\n");
+		fprintf(pOutFile, "90 rotate\n");
+		fprintf(pOutFile, "0.00 %.2f translate\n",
+					-dDrawUnits2Points(lPageHeight));
+		fprintf(pOutFile, "%%%%EndPageSetup\n");
+	}
+} /* end of vAddPageSetup */
+
+/*
+ * vAddHdrFtr - add a header or footer
+ */
+static void
+vAddHdrFtr(diagram_type *pDiag, const hdrftr_block_type *pHdrFtrInfo)
+{
+	output_type	*pStart, *pPrev, *pNext;
+
+	fail(pDiag == NULL);
+	fail(pHdrFtrInfo == NULL);
+
+	vStartOfParagraphPS(pDiag, 0);
+	pStart = pHdrFtrInfo->pText;
+	while (pStart != NULL) {
+		pNext = pStart;
+		while (pNext != NULL &&
+		       (pNext->tNextFree != 1 ||
+		        (pNext->szStorage[0] != PAR_END &&
+		         pNext->szStorage[0] != HARD_RETURN))) {
+			pNext = pNext->pNext;
+		}
+		if (pNext == NULL) {
+			if (bOutputContainsText(pStart)) {
+				vAlign2Window(pDiag, pStart,
+					lChar2MilliPoints(DEFAULT_SCREEN_WIDTH),
+					ALIGNMENT_LEFT);
+			} else {
+				vMove2NextLinePS(pDiag, pStart->usFontSize);
+			}
+			break;
+		}
+		fail(pNext->tNextFree != 1);
+		fail(pNext->szStorage[0] != PAR_END &&
+			pNext->szStorage[0] != HARD_RETURN);
+
+		if (pStart != pNext) {
+			/* There is something to print */
+			pPrev = pNext->pPrev;
+			fail(pPrev->pNext != pNext);
+			/* Cut the chain */
+			pPrev->pNext = NULL;
+			if (bOutputContainsText(pStart)) {
+				/* Print it */
+				vAlign2Window(pDiag, pStart,
+					lChar2MilliPoints(DEFAULT_SCREEN_WIDTH),
+					ALIGNMENT_LEFT);
+			} else {
+				/* Just an empty line */
+				vMove2NextLinePS(pDiag, pStart->usFontSize);
+			}
+			/* Repair the chain */
+			pPrev->pNext = pNext;
+		}
+		if (pNext->szStorage[0] == PAR_END) {
+			vEndOfParagraphPS(pDiag, pNext->usFontSize,
+					(long)pNext->usFontSize * 200);
+		}
+		pStart = pNext->pNext;
+	}
+} /* end of vAddHdrFtr */
+
+/*
+ * vAddHeader - add a page header
+ */
+static void
+vAddHeader(diagram_type *pDiag)
+{
+	const hdrftr_block_type	*pHdrInfo;
+	const hdrftr_block_type	*pFtrInfo;
+
+	fail(pDiag == NULL);
+
+	NO_DBG_MSG("vAddHeader");
+
+	pHdrInfo = pGetHdrFtrInfo(iSectionIndex, TRUE,
+					odd(iPageCount), bFirstInSection);
+	pFtrInfo = pGetHdrFtrInfo(iSectionIndex, FALSE,
+					odd(iPageCount), bFirstInSection);
+	/* Set the height of the footer of this page */
+	lFooterHeight = pFtrInfo == NULL ? 0 : pFtrInfo->lHeight;
+	fail(lFooterHeight < 0);
+
+	if (pHdrInfo == NULL ||
+	    pHdrInfo->pText == NULL ||
+	    pHdrInfo->lHeight <= 0) {
+		fail(pHdrInfo != NULL && pHdrInfo->lHeight < 0);
+		fail(pHdrInfo != NULL &&
+			pHdrInfo->pText != NULL &&
+			pHdrInfo->lHeight == 0);
+		return;
+	}
+
+	vAddHdrFtr(pDiag, pHdrInfo);
+
+	DBG_DEC_C(pHdrInfo->lHeight !=
+		lPageHeight - PS_TOP_MARGIN - pDiag->lYtop,
+		pHdrInfo->lHeight);
+	DBG_DEC_C(pHdrInfo->lHeight !=
+		lPageHeight - PS_TOP_MARGIN - pDiag->lYtop,
+		lPageHeight - PS_TOP_MARGIN - pDiag->lYtop);
+
+#if 0 /* defined(DEBUG) */
+	fprintf(pDiag->pOutFile,
+	"(HEADER: FileOffset 0x%04lx-0x%04lx; Height %ld-%ld) show\n",
+		ulCharPos2FileOffset(pHdrInfo->ulCharPosStart),
+		ulCharPos2FileOffset(pHdrInfo->ulCharPosNext),
+		pHdrInfo->lHeight,
+		lPageHeight - PS_TOP_MARGIN - pDiag->lYtop);
+#endif
+} /* end of vAddHeader */
+
+/*
+ * vAddFooter - add a page footer
+ */
+static void
+vAddFooter(diagram_type *pDiag)
+{
+	const hdrftr_block_type	*pFtrInfo;
+
+	fail(pDiag == NULL);
+
+	NO_DBG_MSG("vAddFooter");
+	pFtrInfo = pGetHdrFtrInfo(iSectionIndex, FALSE,
+					odd(iPageCount), bFirstInSection);
+	bFirstInSection = FALSE;
+	if (pFtrInfo == NULL ||
+	    pFtrInfo->pText == NULL ||
+	    pFtrInfo->lHeight <= 0) {
+		fail(pFtrInfo != NULL && pFtrInfo->lHeight < 0);
+		fail(pFtrInfo != NULL &&
+			pFtrInfo->pText != NULL &&
+			pFtrInfo->lHeight == 0);
+		return;
+	}
+
+	bInFtrSpace = TRUE;
+
+	DBG_DEC_C(pFtrInfo->lHeight != lFooterHeight, pFtrInfo->lHeight);
+	DBG_DEC_C(pFtrInfo->lHeight != lFooterHeight, lFooterHeight);
+	DBG_DEC_C(pDiag->lYtop < lFooterHeight + PS_BOTTOM_MARGIN,
+			pDiag->lYtop);
+	DBG_DEC_C(pDiag->lYtop < lFooterHeight + PS_BOTTOM_MARGIN,
+			lFooterHeight + PS_BOTTOM_MARGIN);
+
+	if (pDiag->lYtop > lFooterHeight + PS_BOTTOM_MARGIN) {
+		/* Move down to the start of the footer */
+		pDiag->lYtop = lFooterHeight + PS_BOTTOM_MARGIN;
+		vMoveTo(pDiag, 0);
+	} else if (pDiag->lYtop < lFooterHeight + PS_BOTTOM_MARGIN / 2) {
+		DBG_FIXME();
+		/*
+		 * Move up to the start of the footer, to prevent moving
+		 * of the bottom edge of the paper
+		 */
+		pDiag->lYtop = lFooterHeight + PS_BOTTOM_MARGIN;
+		vMoveTo(pDiag, 0);
+	}
+
+	DBG_FLT_C(pDiag->lYtop < lFooterHeight + PS_BOTTOM_MARGIN,
+	dDrawUnits2Points(lFooterHeight + PS_BOTTOM_MARGIN - pDiag->lYtop));
+
+#if 0 /* defined(DEBUG) */
+	fprintf(pDiag->pOutFile,
+	"(FOOTER: FileOffset 0x%04lx-0x%04lx; Bottom %ld-%ld) show\n",
+		ulCharPos2FileOffset(pFtrInfo->ulCharPosStart),
+		ulCharPos2FileOffset(pFtrInfo->ulCharPosNext),
+		pDiag->lYtop,
+		pFtrInfo->lHeight + PS_BOTTOM_MARGIN);
+#endif
+	vAddHdrFtr(pDiag, pFtrInfo);
+	bInFtrSpace = FALSE;
+} /* end of vAddFooter */
+
+/*
+ * vMove2NextPage - move to the start of the next page
+ */
+static void
+vMove2NextPage(diagram_type *pDiag, BOOL bNewSection)
+{
+	fail(pDiag == NULL);
+
+	vAddFooter(pDiag);
+	fprintf(pDiag->pOutFile, "showpage\n");
+	iPageCount++;
+	fprintf(pDiag->pOutFile, "%%%%Page: %d %d\n", iPageCount, iPageCount);
+	if (bNewSection) {
+		iSectionIndex++;
+		bFirstInSection = TRUE;
+	}
+	vAddPageSetup(pDiag->pOutFile);
+	pDiag->lYtop = lPageHeight - PS_TOP_MARGIN;
+	lYtopCurr = -1;
+	vAddHeader(pDiag);
+} /* end of vMove2NextPage */
+
+/*
+ * vMoveTo - move to the specified X,Y coordinates
+ *
+ * Move the current position of the specified diagram to its X,Y coordinates,
+ * start on a new page if needed
+ */
+static void
+vMoveTo(diagram_type *pDiag, long lLastVerticalMovement)
+{
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+
+	if (pDiag->lYtop <= lFooterHeight + PS_BOTTOM_MARGIN && !bInFtrSpace) {
+		vMove2NextPage(pDiag, FALSE);
+		/* Repeat the last vertical movement on the new page */
+		pDiag->lYtop -= lLastVerticalMovement;
+	}
+
+	fail(pDiag->lYtop < lFooterHeight + PS_BOTTOM_MARGIN && !bInFtrSpace);
+	DBG_DEC_C(pDiag->lYtop < PS_BOTTOM_MARGIN, pDiag->lYtop);
+	fail(pDiag->lYtop < PS_BOTTOM_MARGIN / 3);
+
+	if (pDiag->lYtop != lYtopCurr) {
+		fprintf(pDiag->pOutFile, "%.2f %.2f moveto\n",
+			dDrawUnits2Points(pDiag->lXleft + PS_LEFT_MARGIN),
+			dDrawUnits2Points(pDiag->lYtop));
+		lYtopCurr = pDiag->lYtop;
+	}
+} /* end of vMoveTo */
+
+/*
+ * vProloguePS - set options and perform the PostScript initialization
+ */
+void
+vProloguePS(diagram_type *pDiag,
+	const char *szTask, const char *szFilename,
+	const options_type *pOptions)
+{
+	FILE	*pOutFile;
+	const char	*szTmp;
+	time_t	tTime;
+
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+	fail(szTask == NULL || szTask[0] == '\0');
+	fail(pOptions == NULL);
+
+	pOutFile = pDiag->pOutFile;
+
+	bUseLandscape = pOptions->bUseLandscape;
+	eEncoding = pOptions->eEncoding;
+	eImageLevel = pOptions->eImageLevel;
+
+	if (pOptions->iPageHeight == INT_MAX) {
+		lPageHeight = LONG_MAX;
+	} else {
+		lPageHeight = lPoints2DrawUnits(pOptions->iPageHeight);
+	}
+	DBG_DEC(lPageHeight);
+	if (pOptions->iPageWidth == INT_MAX) {
+		lPageWidth = LONG_MAX;
+	} else {
+		lPageWidth = lPoints2DrawUnits(pOptions->iPageWidth);
+	}
+	DBG_DEC(lPageWidth);
+	lFooterHeight = 0;
+	bInFtrSpace = FALSE;
+
+	tFontRefCurr = (drawfile_fontref)-1;
+	usFontSizeCurr = 0;
+	iFontColorCurr = -1;
+	lYtopCurr = -1;
+	iPageCount = 0;
+	iImageCount = 0;
+	iSectionIndex = 0;
+	bFirstInSection = TRUE;
+	pDiag->lXleft = 0;
+	pDiag->lYtop = lPageHeight - PS_TOP_MARGIN;
+
+	szCreator = szTask;
+
+	fprintf(pOutFile, "%%!PS-Adobe-2.0\n");
+	fprintf(pOutFile, "%%%%Title: %s\n", szBasename(szFilename));
+	fprintf(pOutFile, "%%%%Creator: %s %s\n", szCreator, VERSIONSTRING);
+	szTmp = getenv("LOGNAME");
+	if (szTmp == NULL || szTmp[0] == '\0') {
+		szTmp = getenv("USER");
+		if (szTmp == NULL || szTmp[0] == '\0') {
+			szTmp = "unknown";
+		}
+	}
+	fprintf(pOutFile, "%%%%For: %.50s\n", szTmp);
+	errno = 0;
+	tTime = time(NULL);
+	if (tTime == (time_t)-1 && errno != 0) {
+		szCreationDate = NULL;
+	} else {
+		szCreationDate = ctime(&tTime);
+	}
+	if (szCreationDate == NULL || szCreationDate[0] == '\0') {
+		szCreationDate = "unknown\n";
+	}
+	fprintf(pOutFile, "%%%%CreationDate: %s", szCreationDate);
+	if (bUseLandscape) {
+		fprintf(pOutFile, "%%%%Orientation: Landscape\n");
+		fprintf(pOutFile, "%%%%BoundingBox: 0 0 %.0f %.0f\n",
+				dDrawUnits2Points(lPageHeight),
+				dDrawUnits2Points(lPageWidth));
+	} else {
+		fprintf(pOutFile, "%%%%Orientation: Portrait\n");
+		fprintf(pOutFile, "%%%%BoundingBox: 0 0 %.0f %.0f\n",
+				dDrawUnits2Points(lPageWidth),
+				dDrawUnits2Points(lPageHeight));
+	}
+} /* end of vProloguePS */
+
+/*
+ * vEpiloguePS - clean up after everything is done
+ */
+void
+vEpiloguePS(diagram_type *pDiag)
+{
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+
+	if (pDiag->lYtop < lPageHeight - PS_TOP_MARGIN) {
+		vAddFooter(pDiag);
+		fprintf(pDiag->pOutFile, "showpage\n");
+	}
+	fprintf(pDiag->pOutFile, "%%%%Trailer\n");
+	fprintf(pDiag->pOutFile, "%%%%Pages: %d\n", iPageCount);
+	fprintf(pDiag->pOutFile, "%%%%EOF\n");
+	szCreationDate = NULL;
+	szCreator = NULL;
+} /* end of vEpiloguePS */
+
+/*
+ * vPrintPalette - print a postscript palette
+ */
+static void
+vPrintPalette(FILE *pOutFile, const imagedata_type *pImg)
+{
+	int	iIndex;
+
+	fail(pOutFile == NULL);
+	fail(pImg == NULL);
+	fail(pImg->iColorsUsed < 2);
+	fail(pImg->iColorsUsed > 256);
+
+	fprintf(pOutFile, "[ /Indexed\n");
+	fprintf(pOutFile, "\t/Device%s %d\n",
+		pImg->bColorImage ? "RGB" : "Gray", pImg->iColorsUsed - 1);
+	fprintf(pOutFile, "<");
+	for (iIndex = 0; iIndex < pImg->iColorsUsed; iIndex++) {
+		fprintf(pOutFile, "%02x",
+				(unsigned int)pImg->aucPalette[iIndex][0]);
+		if (pImg->bColorImage) {
+			fprintf(pOutFile, "%02x%02x",
+				(unsigned int)pImg->aucPalette[iIndex][1],
+				(unsigned int)pImg->aucPalette[iIndex][2]);
+		}
+		if (iIndex % 8 == 7) {
+			fprintf(pOutFile, "\n");
+		} else {
+			fprintf(pOutFile, " ");
+		}
+	}
+	fprintf(pOutFile, ">\n");
+	fprintf(pOutFile, "] setcolorspace\n");
+} /* end of vPrintPalette */
+
+/*
+ * vImageProloguePS - perform the Encapsulated PostScript initialization
+ */
+void
+vImageProloguePS(diagram_type *pDiag, const imagedata_type *pImg)
+{
+	FILE	*pOutFile;
+
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+	fail(pImg == NULL);
+
+	if (pImg->iVerSizeScaled <= 0 || pImg->iHorSizeScaled <= 0) {
+		return;
+	}
+
+	fail(szCreationDate == NULL);
+	fail(szCreator == NULL);
+	fail(eImageLevel == level_no_images);
+
+	iImageCount++;
+
+	DBG_DEC_C(pDiag->lXleft != 0, pDiag->lXleft);
+
+	pDiag->lYtop -= lPoints2DrawUnits(pImg->iVerSizeScaled);
+	vMoveTo(pDiag, lPoints2DrawUnits(pImg->iVerSizeScaled));
+
+	pOutFile = pDiag->pOutFile;
+
+	fprintf(pOutFile, "BeginEPSF\n");
+	fprintf(pOutFile, "%%%%BeginDocument: image%03d.eps\n", iImageCount);
+	fprintf(pOutFile, "%%!PS-Adobe-2.0 EPSF-2.0\n");
+	fprintf(pOutFile, "%%%%Creator: %s %s\n", szCreator, VERSIONSTRING);
+	fprintf(pOutFile, "%%%%Title: Image %03d\n", iImageCount);
+	fprintf(pOutFile, "%%%%CreationDate: %s", szCreationDate);
+	fprintf(pOutFile, "%%%%BoundingBox: 0 0 %d %d\n",
+				pImg->iHorSizeScaled, pImg->iVerSizeScaled);
+	fprintf(pOutFile, "%%%%DocumentData: Clean7Bit\n");
+	fprintf(pOutFile, "%%%%LanguageLevel: 2\n");
+	fprintf(pOutFile, "%%%%EndComments\n");
+	fprintf(pOutFile, "%%%%BeginProlog\n");
+	fprintf(pOutFile, "%%%%EndProlog\n");
+	fprintf(pOutFile, "%%%%Page: 1 1\n");
+
+	fprintf(pOutFile, "save\n");
+
+	switch (pImg->eImageType) {
+	case imagetype_is_jpeg:
+		fprintf(pOutFile, "/Data1 currentfile ");
+		fprintf(pOutFile, "/ASCII85Decode filter def\n");
+		fprintf(pOutFile, "/Data Data1 << ");
+		fprintf(pOutFile, ">> /DCTDecode filter def\n");
+		switch (pImg->iComponents) {
+		case 1:
+			fprintf(pOutFile, "/DeviceGray setcolorspace\n");
+			break;
+		case 3:
+			fprintf(pOutFile, "/DeviceRGB setcolorspace\n");
+			break;
+		case 4:
+			fprintf(pOutFile, "/DeviceCMYK setcolorspace\n");
+			break;
+		default:
+			DBG_DEC(pImg->iComponents);
+			break;
+		}
+		break;
+	case imagetype_is_png:
+		if (eImageLevel == level_gs_special) {
+			fprintf(pOutFile,
+			"/Data2 currentfile /ASCII85Decode filter def\n");
+			fprintf(pOutFile,
+			"/Data1 Data2 << >> /FlateDecode filter def\n");
+			fprintf(pOutFile, "/Data Data1 <<\n");
+			fprintf(pOutFile, "\t/Colors %d\n", pImg->iComponents);
+			fprintf(pOutFile, "\t/BitsPerComponent %u\n",
+						pImg->uiBitsPerComponent);
+			fprintf(pOutFile, "\t/Columns %d\n", pImg->iWidth);
+			fprintf(pOutFile,
+				">> /PNGPredictorDecode filter def\n");
+		} else {
+			fprintf(pOutFile,
+			"/Data1 currentfile /ASCII85Decode filter def\n");
+			fprintf(pOutFile,
+			"/Data Data1 << >> /FlateDecode filter def\n");
+		}
+		if (pImg->iComponents == 3 || pImg->iComponents == 4) {
+			fprintf(pOutFile, "/DeviceRGB setcolorspace\n");
+		} else if (pImg->iColorsUsed > 0) {
+			vPrintPalette(pOutFile, pImg);
+		} else {
+			fprintf(pOutFile, "/DeviceGray setcolorspace\n");
+		}
+		break;
+	case imagetype_is_dib:
+		fprintf(pOutFile, "/Data currentfile ");
+		fprintf(pOutFile, "/ASCII85Decode filter def\n");
+		if (pImg->uiBitsPerComponent <= 8) {
+			vPrintPalette(pOutFile, pImg);
+		} else {
+			fprintf(pOutFile, "/DeviceRGB setcolorspace\n");
+		}
+		break;
+	default:
+		fprintf(pOutFile, "/Data currentfile ");
+		fprintf(pOutFile, "/ASCIIHexDecode filter def\n");
+		fprintf(pOutFile, "/Device%s setcolorspace\n",
+			pImg->bColorImage ? "RGB" : "Gray");
+		break;
+	}
+
+	/* Translate to lower left corner of image */
+	fprintf(pOutFile, "%.2f %.2f translate\n",
+			dDrawUnits2Points(pDiag->lXleft + PS_LEFT_MARGIN),
+			dDrawUnits2Points(pDiag->lYtop));
+
+	fprintf(pOutFile, "%d %d scale\n",
+				pImg->iHorSizeScaled, pImg->iVerSizeScaled);
+
+	fprintf(pOutFile, "{ <<\n");
+	fprintf(pOutFile, "\t/ImageType 1\n");
+	fprintf(pOutFile, "\t/Width %d\n", pImg->iWidth);
+	fprintf(pOutFile, "\t/Height %d\n", pImg->iHeight);
+	if (pImg->eImageType == imagetype_is_dib) {
+		/* Scanning from left to right and bottom to top */
+		fprintf(pOutFile, "\t/ImageMatrix [ %d 0 0 %d 0 0 ]\n",
+			pImg->iWidth, pImg->iHeight);
+	} else {
+		/* Scanning from left to right and top to bottom */
+		fprintf(pOutFile, "\t/ImageMatrix [ %d 0 0 %d 0 %d ]\n",
+			pImg->iWidth, -pImg->iHeight, pImg->iHeight);
+	}
+	fprintf(pOutFile, "\t/DataSource Data\n");
+
+	switch (pImg->eImageType) {
+	case imagetype_is_jpeg:
+		fprintf(pOutFile, "\t/BitsPerComponent 8\n");
+		switch (pImg->iComponents) {
+		case 1:
+			fprintf(pOutFile, "\t/Decode [0 1]\n");
+			break;
+		case 3:
+			fprintf(pOutFile, "\t/Decode [0 1 0 1 0 1]\n");
+			break;
+		case 4:
+			if (pImg->bAdobe) {
+				/*
+				 * Adobe-conforming CMYK file
+				 * applying workaround for color inversion
+				 */
+				fprintf(pOutFile,
+					"\t/Decode [1 0 1 0 1 0 1 0]\n");
+			} else {
+				fprintf(pOutFile,
+					"\t/Decode [0 1 0 1 0 1 0 1]\n");
+			}
+			break;
+		default:
+			DBG_DEC(pImg->iComponents);
+			break;
+		}
+		break;
+	case imagetype_is_png:
+		if (pImg->iComponents == 3) {
+			fprintf(pOutFile, "\t/BitsPerComponent 8\n");
+			fprintf(pOutFile, "\t/Decode [0 1 0 1 0 1]\n");
+		} else if (pImg->iColorsUsed > 0) {
+			fail(pImg->uiBitsPerComponent > 8);
+			fprintf(pOutFile, "\t/BitsPerComponent %u\n",
+					pImg->uiBitsPerComponent);
+			fprintf(pOutFile, "\t/Decode [0 %d]\n",
+					(1 << pImg->uiBitsPerComponent) - 1);
+		} else {
+			fprintf(pOutFile, "\t/BitsPerComponent 8\n");
+			fprintf(pOutFile, "\t/Decode [0 1]\n");
+		}
+		break;
+	case imagetype_is_dib:
+		fprintf(pOutFile, "\t/BitsPerComponent 8\n");
+		if (pImg->uiBitsPerComponent <= 8) {
+			fprintf(pOutFile, "\t/Decode [0 255]\n");
+		} else {
+			fprintf(pOutFile, "\t/Decode [0 1 0 1 0 1]\n");
+		}
+		break;
+	default:
+		fprintf(pOutFile, "\t/BitsPerComponent 8\n");
+		if (pImg->bColorImage) {
+			fprintf(pOutFile, "\t/Decode [0 1 0 1 0 1]\n");
+		} else {
+			fprintf(pOutFile, "\t/Decode [0 1]\n");
+		}
+		break;
+	}
+
+	fprintf(pOutFile, "  >> image\n");
+	fprintf(pOutFile, "  Data closefile\n");
+	fprintf(pOutFile, "  showpage\n");
+	fprintf(pOutFile, "  restore\n");
+	fprintf(pOutFile, "} exec\n");
+} /* end of vImageProloguePS */
+
+/*
+ * vImageEpiloguePS - clean up after Encapsulated PostScript
+ */
+void
+vImageEpiloguePS(diagram_type *pDiag)
+{
+	FILE	*pOutFile;
+
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+
+	pOutFile = pDiag->pOutFile;
+
+	fprintf(pOutFile, "%%%%EOF\n");
+	fprintf(pOutFile, "%%%%EndDocument\n");
+	fprintf(pOutFile, "EndEPSF\n");
+
+	pDiag->lXleft = 0;
+} /* end of vImageEpiloguePS */
+
+/*
+ * bAddDummyImagePS - add a dummy image
+ *
+ * return TRUE when successful, otherwise FALSE
+ */
+BOOL
+bAddDummyImagePS(diagram_type *pDiag, const imagedata_type *pImg)
+{
+	FILE	*pOutFile;
+
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+	fail(pImg == NULL);
+
+	if (pImg->iVerSizeScaled <= 0 || pImg->iHorSizeScaled <= 0) {
+		return FALSE;
+	}
+
+	iImageCount++;
+
+	DBG_DEC_C(pDiag->lXleft != 0, pDiag->lXleft);
+
+	pDiag->lYtop -= lPoints2DrawUnits(pImg->iVerSizeScaled);
+	vMoveTo(pDiag, lPoints2DrawUnits(pImg->iVerSizeScaled));
+
+	pOutFile = pDiag->pOutFile;
+
+	fprintf(pOutFile, "gsave %% Image %03d\n", iImageCount);
+	fprintf(pOutFile, "\tnewpath\n");
+	fprintf(pOutFile, "\t%.2f %.2f moveto\n",
+			dDrawUnits2Points(pDiag->lXleft + PS_LEFT_MARGIN),
+			dDrawUnits2Points(pDiag->lYtop));
+	fprintf(pOutFile, "\t1.0 setlinewidth\n");
+	fprintf(pOutFile, "\t0.3 setgray\n");
+	fprintf(pOutFile, "\t0 %d rlineto\n", pImg->iVerSizeScaled);
+	fprintf(pOutFile, "\t%d 0 rlineto\n", pImg->iHorSizeScaled);
+	fprintf(pOutFile, "\t0 %d rlineto\n", -pImg->iVerSizeScaled);
+	fprintf(pOutFile, "\tclosepath\n");
+	fprintf(pOutFile, "\tstroke\n");
+	fprintf(pOutFile, "grestore\n");
+
+	pDiag->lXleft = 0;
+
+	return TRUE;
+} /* end of bAddDummyImagePS */
+
+/*
+ * vAddFontsPS - add the list of fonts and complete the prologue
+ */
+void
+vAddFontsPS(diagram_type *pDiag)
+{
+	FILE	*pOutFile;
+	const font_table_type *pTmp, *pTmp2;
+	size_t	tIndex;
+	int	iLineLen, iOurFontnameLen;
+	BOOL	bFound;
+
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+
+	pOutFile = pDiag->pOutFile;
+	iLineLen = fprintf(pOutFile, "%%%%DocumentFonts:");
+
+	if (tGetFontTableLength() == 0) {
+		iLineLen += fprintf(pOutFile, " Courier");
+	} else {
+		pTmp = NULL;
+		while ((pTmp = pGetNextFontTableRecord(pTmp)) != NULL) {
+			/* Print the document fonts */
+			bFound = FALSE;
+			pTmp2 = NULL;
+			while ((pTmp2 = pGetNextFontTableRecord(pTmp2))
+					!= NULL && pTmp2 < pTmp) {
+				bFound = STREQ(pTmp2->szOurFontname,
+						pTmp->szOurFontname);
+				if (bFound) {
+					break;
+				}
+			}
+			iOurFontnameLen = (int)strlen(pTmp->szOurFontname);
+			if (bFound || iOurFontnameLen <= 0) {
+				continue;
+			}
+			if (iLineLen + iOurFontnameLen > 76) {
+				fprintf(pOutFile, "\n%%%%+");
+				iLineLen = 3;
+			}
+			iLineLen += fprintf(pOutFile,
+					" %s", pTmp->szOurFontname);
+		}
+	}
+	fprintf(pOutFile, "\n");
+	fprintf(pOutFile, "%%%%Pages: (atend)\n");
+	fprintf(pOutFile, "%%%%EndComments\n");
+	fprintf(pOutFile, "%%%%BeginProlog\n");
+
+	switch (eEncoding) {
+	case encoding_latin_1:
+		for (tIndex = 0;
+		     tIndex < elementsof(iso_8859_1_data);
+		     tIndex++) {
+			fprintf(pOutFile, "%s\n", iso_8859_1_data[tIndex]);
+		}
+		fprintf(pOutFile, "\n");
+		for (tIndex = 0;
+		     tIndex < elementsof(iso_8859_x_func);
+		     tIndex++) {
+			fprintf(pOutFile, "%s\n", iso_8859_x_func[tIndex]);
+		}
+		break;
+	case encoding_latin_2:
+		for (tIndex = 0;
+		     tIndex < elementsof(iso_8859_2_data);
+		     tIndex++) {
+			fprintf(pOutFile, "%s\n", iso_8859_2_data[tIndex]);
+		}
+		fprintf(pOutFile, "\n");
+		for (tIndex = 0;
+		     tIndex < elementsof(iso_8859_x_func);
+		     tIndex++) {
+			fprintf(pOutFile, "%s\n", iso_8859_x_func[tIndex]);
+		}
+		break;
+	case encoding_cyrillic:
+		for (tIndex = 0;
+		     tIndex < elementsof(iso_8859_5_data);
+		     tIndex++) {
+			fprintf(pOutFile, "%s\n", iso_8859_5_data[tIndex]);
+		}
+		fprintf(pOutFile, "\n");
+		for (tIndex = 0;
+		     tIndex < elementsof(iso_8859_x_func);
+		     tIndex++) {
+			fprintf(pOutFile, "%s\n", iso_8859_x_func[tIndex]);
+		}
+		break;
+	case encoding_utf_8:
+		werr(1,
+		"The combination PostScript and UTF-8 is not supported");
+		break;
+	default:
+		DBG_DEC(eEncoding);
+		break;
+	}
+
+	/* The rest of the functions */
+	for (tIndex = 0; tIndex < elementsof(misc_func); tIndex++) {
+		fprintf(pOutFile, "%s\n", misc_func[tIndex]);
+	}
+	fprintf(pOutFile, "%%%%EndProlog\n");
+	iPageCount = 1;
+	fprintf(pDiag->pOutFile, "%%%%Page: %d %d\n", iPageCount, iPageCount);
+	vAddPageSetup(pDiag->pOutFile);
+	vAddHeader(pDiag);
+} /* end of vAddFontsPS */
+
+/*
+ * vPrintPS - print a PostScript string
+ */
+static void
+vPrintPS(FILE *pFile, const char *szString, size_t tStringLength,
+		USHORT usFontstyle)
+{
+	double		dSuperscriptMove, dSubscriptMove;
+	const UCHAR	*ucBytes;
+	size_t		tCount;
+
+	fail(szString == NULL);
+
+	if (szString == NULL || szString[0] == '\0' || tStringLength == 0) {
+		return;
+	}
+	DBG_DEC_C(usFontSizeCurr < MIN_FONT_SIZE, usFontSizeCurr);
+
+	dSuperscriptMove = 0.0;
+	dSubscriptMove = 0.0;
+
+	/* Up for superscript */
+	if (bIsSuperscript(usFontstyle) && usFontSizeCurr != 0) {
+		dSuperscriptMove = (double)((usFontSizeCurr + 1) / 2) * 0.375;
+		fprintf(pFile, "0 %.2f rmoveto\n", dSuperscriptMove);
+	}
+
+	/* Down for subscript */
+	if (bIsSubscript(usFontstyle) && usFontSizeCurr != 0) {
+		dSubscriptMove = (double)usFontSizeCurr * 0.125;
+		fprintf(pFile, "0 %.2f rmoveto\n", -dSubscriptMove);
+	}
+
+	/* Generate and print the PostScript output */
+	ucBytes = (UCHAR *)szString;
+	(void)putc('(', pFile);
+	for (tCount = 0; tCount < tStringLength ; tCount++) {
+		switch (ucBytes[tCount]) {
+		case '(':
+		case ')':
+		case '\\':
+			(void)putc('\\', pFile);
+			(void)putc(szString[tCount], pFile);
+			break;
+		default:
+			if (ucBytes[tCount] < 0x20 ||
+			    (ucBytes[tCount] >= 0x7f &&
+			     ucBytes[tCount] < 0x8c)) {
+				DBG_HEX(ucBytes[tCount]);
+				(void)putc(' ', pFile);
+			} else if (ucBytes[tCount] >= 0x80) {
+				fprintf(pFile, "\\%03o", (UINT)ucBytes[tCount]);
+			} else {
+				(void)putc(szString[tCount], pFile);
+			}
+			break;
+		}
+	}
+	fprintf(pFile, ") ");
+	if ((bIsStrike(usFontstyle) || bIsMarkDel(usFontstyle)) &&
+			usFontSizeCurr != 0) {
+		fprintf(pFile, "%.2f %.2f LineShow\n",
+			(double)usFontSizeCurr * 0.02,
+			(double)usFontSizeCurr * 0.12);
+	} else if (bIsUnderline(usFontstyle) && usFontSizeCurr != 0) {
+		fprintf(pFile, "%.2f %.2f LineShow\n",
+			(double)usFontSizeCurr * 0.02,
+			(double)usFontSizeCurr * -0.06);
+	} else {
+		fprintf(pFile, "show\n");
+	}
+
+	/* Undo the superscript move */
+	if (bIsSuperscript(usFontstyle) && usFontSizeCurr != 0) {
+		fprintf(pFile, "0 %.2f rmoveto\n", -dSuperscriptMove);
+	}
+
+	/* Undo the subscript move */
+	if (bIsSubscript(usFontstyle) && usFontSizeCurr != 0) {
+		fprintf(pFile, "0 %.2f rmoveto\n", dSubscriptMove);
+	}
+} /* end of vPrintPS */
+
+/*
+ * vSetColor - move to the specified color
+ */
+static void
+vSetColor(FILE *pFile, UCHAR ucFontColor)
+{
+	ULONG	ulTmp, ulRed, ulGreen, ulBlue;
+
+	ulTmp = ulColor2Color(ucFontColor);
+	ulRed   = (ulTmp & 0x0000ff00) >> 8;
+	ulGreen = (ulTmp & 0x00ff0000) >> 16;
+	ulBlue  = (ulTmp & 0xff000000) >> 24;
+	fprintf(pFile, "%.3f %.3f %.3f setrgbcolor\n",
+				ulRed / 255.0, ulGreen / 255.0, ulBlue / 255.0);
+} /* end of vSetColor */
+
+/*
+ * vMove2NextLinePS - move to the next line
+ */
+void
+vMove2NextLinePS(diagram_type *pDiag, USHORT usFontSize)
+{
+	fail(pDiag == NULL);
+	fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
+
+	pDiag->lYtop -= lComputeLeading(usFontSize);
+} /* end of vMove2NextLinePS */
+
+/*
+ * vSubstringPS - print a sub string
+ */
+void
+vSubstringPS(diagram_type *pDiag,
+	char *szString, size_t tStringLength, long lStringWidth,
+	UCHAR ucFontColor, USHORT usFontstyle, drawfile_fontref tFontRef,
+	USHORT usFontSize, USHORT usMaxFontSize)
+{
+	const char	*szOurFontname;
+
+	fail(pDiag == NULL || szString == NULL);
+	fail(pDiag->pOutFile == NULL);
+	fail(pDiag->lXleft < 0);
+	fail(tStringLength != strlen(szString));
+	fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
+	fail(usMaxFontSize < MIN_FONT_SIZE || usMaxFontSize > MAX_FONT_SIZE);
+	fail(usFontSize > usMaxFontSize);
+
+	if (szString[0] == '\0' || tStringLength == 0) {
+		return;
+	}
+
+	if (tFontRef != tFontRefCurr || usFontSize != usFontSizeCurr) {
+		szOurFontname = szGetFontname(tFontRef);
+		fail(szOurFontname == NULL);
+		fprintf(pDiag->pOutFile,
+			"%.1f /%s /%s-ISO-8859-x ChgFnt\n",
+			(double)usFontSize / 2.0,
+			szOurFontname, szOurFontname);
+		tFontRefCurr = tFontRef;
+		usFontSizeCurr = usFontSize;
+	}
+	if ((int)ucFontColor != iFontColorCurr) {
+		vSetColor(pDiag->pOutFile, ucFontColor);
+		iFontColorCurr = (int)ucFontColor;
+	}
+	vMoveTo(pDiag, lComputeLeading(usMaxFontSize));
+	vPrintPS(pDiag->pOutFile, szString, tStringLength, usFontstyle);
+	pDiag->lXleft += lStringWidth;
+} /* end of vSubstringPS */
+
+/*
+ * Create an start of paragraph by moving the y-top mark
+ */
+void
+vStartOfParagraphPS(diagram_type *pDiag, long lBeforeIndentation)
+{
+	fail(pDiag == NULL);
+	fail(lBeforeIndentation < 0);
+
+	pDiag->lXleft = 0;
+	pDiag->lYtop -= lMilliPoints2DrawUnits(lBeforeIndentation);
+} /* end of vStartOfParagraphPS */
+
+/*
+ * Create an end of paragraph by moving the y-top mark
+ */
+void
+vEndOfParagraphPS(diagram_type *pDiag,
+	USHORT usFontSize, long lAfterIndentation)
+{
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+	fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
+	fail(lAfterIndentation < 0);
+
+	if (pDiag->lXleft > 0) {
+		/* To the start of the line */
+		vMove2NextLinePS(pDiag, usFontSize);
+	}
+
+	pDiag->lXleft = 0;
+	pDiag->lYtop -= lMilliPoints2DrawUnits(lAfterIndentation);
+} /* end of vEndOfParagraphPS */
+
+/*
+ * Create an end of page
+ */
+void
+vEndOfPagePS(diagram_type *pDiag, BOOL bNewSection)
+{
+	vMove2NextPage(pDiag, bNewSection);
+} /* end of vEndOfPagePS */
diff --git a/prop0.c b/prop0.c
new file mode 100644
index 0000000..bac2fbd
--- /dev/null
+++ b/prop0.c
@@ -0,0 +1,489 @@
+/*
+ * prop0.c
+ * Copyright (C) 2002-2004 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Read the property information from a Word for DOS file
+ */
+
+#include <string.h>
+#include <time.h>
+#include "antiword.h"
+
+
+/*
+ * tConvertDosDate - convert DOS date format
+ *
+ * returns Unix time_t or -1
+ */
+static time_t
+tConvertDosDate(const char *szDosDate)
+{
+	struct tm	tTime;
+	const char	*pcTmp;
+	time_t		tResult;
+
+	memset(&tTime, 0, sizeof(tTime));
+	pcTmp = szDosDate;
+	/* Get the month */
+	if (!isdigit(*pcTmp)) {
+		return (time_t)-1;
+	}
+	tTime.tm_mon = (int)(*pcTmp - '0');
+	pcTmp++;
+	if (isdigit(*pcTmp)) {
+		tTime.tm_mon *= 10;
+		tTime.tm_mon += (int)(*pcTmp - '0');
+		pcTmp++;
+	}
+	/* Get the first separater */
+	if (isalnum(*pcTmp)) {
+		return (time_t)-1;
+	}
+	pcTmp++;
+	/* Get the day */
+	if (!isdigit(*pcTmp)) {
+		return (time_t)-1;
+	}
+	tTime.tm_mday = (int)(*pcTmp - '0');
+	pcTmp++;
+	if (isdigit(*pcTmp)) {
+		tTime.tm_mday *= 10;
+		tTime.tm_mday += (int)(*pcTmp - '0');
+		pcTmp++;
+	}
+	/* Get the second separater */
+	if (isalnum(*pcTmp)) {
+		return (time_t)-1;
+	}
+	pcTmp++;
+	/* Get the year */
+	if (!isdigit(*pcTmp)) {
+		return (time_t)-1;
+	}
+	tTime.tm_year = (int)(*pcTmp - '0');
+	pcTmp++;
+	if (isdigit(*pcTmp)) {
+		tTime.tm_year *= 10;
+		tTime.tm_year += (int)(*pcTmp - '0');
+		pcTmp++;
+	}
+	/* Check the values */
+	if (tTime.tm_mon == 0 || tTime.tm_mday == 0 || tTime.tm_mday > 31) {
+		return (time_t)-1;
+	}
+	/* Correct the values */
+	tTime.tm_mon--;		/* From 01-12 to 00-11 */
+	if (tTime.tm_year < 80) {
+		tTime.tm_year += 100;	/* 00 means 2000 is 100 */
+	}
+	tTime.tm_isdst = -1;
+	tResult = mktime(&tTime);
+	NO_DBG_MSG(ctime(&tResult));
+	return tResult;
+} /* end of tConvertDosDate */
+
+/*
+ * Build the lists with Document Property Information for Word for DOS files
+ */
+void
+vGet0DopInfo(FILE *pFile, const UCHAR *aucHeader)
+{
+	document_block_type	tDocument;
+	UCHAR	*aucBuffer;
+	ULONG	ulBeginSumdInfo, ulBeginNextBlock;
+	size_t	tLen;
+	USHORT	usOffset;
+
+        tDocument.ucHdrFtrSpecification = 0;
+        tDocument.usDefaultTabWidth = usGetWord(0x70, aucHeader); /* dxaTab */
+        tDocument.tCreateDate = (time_t)-1;
+        tDocument.tRevisedDate = (time_t)-1;
+
+	ulBeginSumdInfo = 128 * (ULONG)usGetWord(0x1c, aucHeader);
+	DBG_HEX(ulBeginSumdInfo);
+	ulBeginNextBlock = 128 * (ULONG)usGetWord(0x6a, aucHeader);
+	DBG_HEX(ulBeginNextBlock);
+
+	if (ulBeginSumdInfo < ulBeginNextBlock && ulBeginNextBlock != 0) {
+		/* There is a summary information block */
+		tLen = (size_t)(ulBeginNextBlock - ulBeginSumdInfo);
+		aucBuffer = xmalloc(tLen);
+		/* Read the summary information block */
+		if (bReadBytes(aucBuffer, tLen, ulBeginSumdInfo, pFile)) {
+       			usOffset = usGetWord(12, aucBuffer);
+			if (aucBuffer[usOffset] != 0) {
+				NO_DBG_STRN(aucBuffer + usOffset, 8);
+				tDocument.tRevisedDate =
+				tConvertDosDate((char *)aucBuffer + usOffset);
+			}
+			usOffset = usGetWord(14, aucBuffer);
+			if (aucBuffer[usOffset] != 0) {
+				NO_DBG_STRN(aucBuffer + usOffset, 8);
+				tDocument.tCreateDate =
+				tConvertDosDate((char *)aucBuffer + usOffset);
+			}
+		}
+		aucBuffer = xfree(aucBuffer);
+	}
+        vCreateDocumentInfoList(&tDocument);
+} /* end of vGet0DopInfo */
+
+/*
+ * Fill the section information block with information
+ * from a Word for DOS file.
+ */
+static void
+vGet0SectionInfo(const UCHAR *aucGrpprl, size_t tBytes,
+		section_block_type *pSection)
+{
+	USHORT	usCcol;
+	UCHAR	ucTmp;
+
+	fail(aucGrpprl == NULL || pSection == NULL);
+
+	if (tBytes < 2) {
+		return;
+	}
+	/* bkc */
+	ucTmp = ucGetByte(1, aucGrpprl);
+	DBG_HEX(ucTmp);
+	ucTmp &= 0x07;
+	DBG_HEX(ucTmp);
+	pSection->bNewPage = ucTmp != 0 && ucTmp != 1;
+	if (tBytes < 18) {
+		return;
+	}
+	/* ccolM1 */
+	usCcol = (USHORT)ucGetByte(17, aucGrpprl);
+	DBG_DEC(usCcol);
+} /* end of vGet0SectionInfo */
+
+/*
+ * Build the lists with Section Property Information for Word for DOS files
+ */
+void
+vGet0SepInfo(FILE *pFile, const UCHAR *aucHeader)
+{
+	section_block_type	tSection;
+	UCHAR	*aucBuffer;
+	ULONG	ulBeginOfText, ulTextOffset, ulBeginSectInfo;
+	ULONG	ulCharPos, ulSectPage, ulBeginNextBlock;
+	size_t	tSectInfoLen, tIndex, tSections, tBytes;
+	UCHAR	aucTmp[2], aucFpage[35];
+
+	fail(pFile == NULL || aucHeader == NULL);
+
+	ulBeginOfText = 128;
+	NO_DBG_HEX(ulBeginOfText);
+	ulBeginSectInfo = 128 * (ULONG)usGetWord(0x18, aucHeader);
+	DBG_HEX(ulBeginSectInfo);
+	ulBeginNextBlock = 128 * (ULONG)usGetWord(0x1a, aucHeader);
+	DBG_HEX(ulBeginNextBlock);
+	if (ulBeginSectInfo == ulBeginNextBlock) {
+		/* There is no section information block */
+		return;
+	}
+
+	/* Get the the number of sections */
+	if (!bReadBytes(aucTmp, 2, ulBeginSectInfo, pFile)) {
+		return;
+	}
+	tSections = (size_t)usGetWord(0, aucTmp);
+	NO_DBG_DEC(tSections);
+
+	/* Read the Section Descriptors */
+	tSectInfoLen = 10 * tSections;
+	NO_DBG_DEC(tSectInfoLen);
+	aucBuffer = xmalloc(tSectInfoLen);
+	if (!bReadBytes(aucBuffer, tSectInfoLen, ulBeginSectInfo + 4, pFile)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tSectInfoLen);
+
+	/* Read the Section Properties */
+	for (tIndex = 0; tIndex < tSections; tIndex++) {
+		ulTextOffset = ulGetLong(10 * tIndex, aucBuffer);
+		NO_DBG_HEX(ulTextOffset);
+		ulCharPos = ulBeginOfText + ulTextOffset;
+		NO_DBG_HEX(ulTextOffset);
+		ulSectPage = ulGetLong(10 * tIndex + 6, aucBuffer);
+		NO_DBG_HEX(ulSectPage);
+		if (ulSectPage == FC_INVALID ||		/* Must use defaults */
+		    ulSectPage < 128 ||			/* Should not happen */
+		    ulSectPage >= ulBeginSectInfo) {	/* Should not happen */
+			DBG_HEX_C(ulSectPage != FC_INVALID, ulSectPage);
+			vDefault2SectionInfoList(ulCharPos);
+			continue;
+		}
+		/* Get the number of bytes to read */
+		if (!bReadBytes(aucTmp, 1, ulSectPage, pFile)) {
+			continue;
+		}
+		tBytes = 1 + (size_t)ucGetByte(0, aucTmp);
+		NO_DBG_DEC(tBytes);
+		if (tBytes > sizeof(aucFpage)) {
+			DBG_DEC(tBytes);
+			tBytes = sizeof(aucFpage);
+		}
+		/* Read the bytes */
+		if (!bReadBytes(aucFpage, tBytes, ulSectPage, pFile)) {
+			continue;
+		}
+		NO_DBG_PRINT_BLOCK(aucFpage, tBytes);
+		/* Process the bytes */
+		vGetDefaultSection(&tSection);
+		vGet0SectionInfo(aucFpage + 1, tBytes - 1, &tSection);
+		vAdd2SectionInfoList(&tSection, ulCharPos);
+	}
+	/* Clean up before you leave */
+	aucBuffer = xfree(aucBuffer);
+} /* end of vGet0SepInfo */
+
+/*
+ * Fill the style information block with information
+ * from a Word for DOS file.
+ */
+static void
+vGet0StyleInfo(int iFodo, const UCHAR *aucGrpprl, style_block_type *pStyle)
+{
+	int	iBytes;
+	UCHAR	ucTmp;
+
+	fail(iFodo <= 0 || aucGrpprl == NULL || pStyle == NULL);
+
+	pStyle->usIstdNext = ISTD_NORMAL;
+
+	iBytes = (int)ucGetByte(iFodo, aucGrpprl);
+	if (iBytes < 1) {
+		return;
+	}
+	/* stc if styled */
+	ucTmp = ucGetByte(iFodo + 1, aucGrpprl);
+	if ((ucTmp & BIT(0)) != 0) {
+		ucTmp >>= 1;
+		if (ucTmp >= 88 && ucTmp <= 94) {
+			/* Header levels 1 through 7 */
+			pStyle->usIstd = ucTmp - 87;
+			pStyle->ucNumLevel = 1;
+		}
+	}
+	if (iBytes < 2) {
+		return;
+	}
+	/* jc */
+	ucTmp = ucGetByte(iFodo + 2, aucGrpprl);
+	pStyle->ucAlignment = ucTmp & 0x02;
+	if (iBytes < 3) {
+		return;
+	}
+	/* stc */
+	ucTmp = ucGetByte(iFodo + 3, aucGrpprl);
+	ucTmp &= 0x7f;
+	if (ucTmp >= 88 && ucTmp <= 94) {
+		/* Header levels 1 through 7 */
+		pStyle->usIstd = ucTmp - 87;
+		pStyle->ucNumLevel = 1;
+	}
+	if (iBytes < 6) {
+		return;
+	}
+	/* dxaRight */
+	pStyle->sRightIndent = (short)usGetWord(iFodo + 5, aucGrpprl);
+	NO_DBG_DEC(pStyle->sRightIndent);
+	if (iBytes < 8) {
+		return;
+	}
+	/* dxaLeft */
+	pStyle->sLeftIndent = (short)usGetWord(iFodo + 7, aucGrpprl);
+	NO_DBG_DEC(pStyle->sLeftIndent);
+	if (iBytes < 10) {
+		return;
+	}
+	/* dxaLeft1 */
+	pStyle->sLeftIndent1 = (short)usGetWord(iFodo + 9, aucGrpprl);
+	NO_DBG_DEC(pStyle->sLeftIndent1);
+	if (iBytes < 14) {
+		return;
+	}
+	/* dyaBefore */
+	pStyle->usBeforeIndent = usGetWord(iFodo + 13, aucGrpprl);
+	NO_DBG_DEC(pStyle->usBeforeIndent);
+	if (iBytes < 16) {
+		return;
+	}
+	/* dyaAfter */
+	pStyle->usAfterIndent = usGetWord(iFodo + 15, aucGrpprl);
+	NO_DBG_DEC(pStyle->usAfterIndent);
+} /* end of vGet0StyleInfo */
+
+/*
+ * Build the lists with Paragraph Information for Word for DOS files
+ */
+void
+vGet0PapInfo(FILE *pFile, const UCHAR *aucHeader)
+{
+	style_block_type	tStyle;
+	ULONG	ulBeginParfInfo, ulCharPos, ulCharPosNext;
+	int	iIndex, iRun, iFodo;
+	UCHAR	aucFpage[128];
+
+	fail(pFile == NULL || aucHeader == NULL);
+
+	ulBeginParfInfo = 128 * (ULONG)usGetWord(0x12, aucHeader);
+	NO_DBG_HEX(ulBeginParfInfo);
+
+	do {
+		if (!bReadBytes(aucFpage, 128, ulBeginParfInfo, pFile)) {
+			return;
+		}
+		NO_DBG_PRINT_BLOCK(aucFpage, 128);
+		ulCharPosNext = ulGetLong(0, aucFpage);
+		iRun = (int)ucGetByte(0x7f, aucFpage);
+		NO_DBG_DEC(iRun);
+		for (iIndex = 0; iIndex < iRun; iIndex++) {
+			iFodo = (int)usGetWord(6 * iIndex + 8, aucFpage);
+			if (iFodo <= 0 || iFodo > 0x79) {
+				DBG_DEC_C(iFodo != (int)0xffff, iFodo);
+				continue;
+			}
+			vFillStyleFromStylesheet(0, &tStyle);
+			vGet0StyleInfo(iFodo, aucFpage + 4, &tStyle);
+			ulCharPos = ulCharPosNext;
+			ulCharPosNext = ulGetLong(6 * iIndex + 4, aucFpage);
+			tStyle.ulFileOffset = ulCharPos;
+			vAdd2StyleInfoList(&tStyle);
+		}
+		ulBeginParfInfo += 128;
+	} while (ulCharPosNext == ulBeginParfInfo);
+} /* end of vGet0PapInfo */
+
+/*
+ * Fill the font information block with information
+ * from a Word for DOS file.
+ */
+static void
+vGet0FontInfo(int iFodo, const UCHAR *aucGrpprl, font_block_type *pFont)
+{
+	int	iBytes;
+	UCHAR	ucTmp;
+
+	fail(iFodo <= 0 || aucGrpprl == NULL || pFont == NULL);
+
+	iBytes = (int)ucGetByte(iFodo, aucGrpprl);
+	if (iBytes < 2) {
+		return;
+	}
+	/* fBold, fItalic, cFtc */
+	ucTmp = ucGetByte(iFodo + 2, aucGrpprl);
+	if ((ucTmp & BIT(0)) != 0) {
+		pFont->usFontStyle |= FONT_BOLD;
+	}
+	if ((ucTmp & BIT(1)) != 0) {
+		pFont->usFontStyle |= FONT_ITALIC;
+	}
+	pFont->ucFontNumber = ucTmp >> 2;
+	NO_DBG_DEC(pFont->ucFontNumber);
+	if (iBytes < 3) {
+		return;
+	}
+	/* cHps */
+	pFont->usFontSize = (USHORT)ucGetByte(iFodo + 3, aucGrpprl);
+	NO_DBG_DEC(pFont->usFontSize);
+	if (iBytes < 4) {
+		return;
+	}
+	/* cKul, fStrike, fCaps, fSmallCaps, fVanish */
+	ucTmp = ucGetByte(iFodo + 4, aucGrpprl);
+	if ((ucTmp & BIT(0)) != 0 || (ucTmp & BIT(2)) != 0) {
+		pFont->usFontStyle |= FONT_UNDERLINE;
+	}
+	if ((ucTmp & BIT(1)) != 0) {
+		pFont->usFontStyle |= FONT_STRIKE;
+	}
+	if ((ucTmp & BIT(4)) != 0) {
+		pFont->usFontStyle |= FONT_CAPITALS;
+	}
+	if ((ucTmp & BIT(5)) != 0) {
+		pFont->usFontStyle |= FONT_SMALL_CAPITALS;
+	}
+	if ((ucTmp & BIT(7)) != 0) {
+		pFont->usFontStyle |= FONT_HIDDEN;
+	}
+	DBG_HEX(pFont->usFontStyle);
+	if (iBytes < 6) {
+		return;
+	}
+	/* cIss */
+	ucTmp = ucGetByte(iFodo + 6, aucGrpprl);
+	if (ucTmp != 0) {
+		if (ucTmp < 128) {
+			pFont->usFontStyle |= FONT_SUPERSCRIPT;
+			DBG_MSG("Superscript");
+		} else {
+			pFont->usFontStyle |= FONT_SUBSCRIPT;
+			DBG_MSG("Subscript");
+		}
+	}
+	if (iBytes < 7) {
+		return;
+	}
+	/* cIco */
+	ucTmp = ucGetByte(iFodo + 7, aucGrpprl);
+	switch (ucTmp & 0x07) {
+	case 0: pFont->ucFontColor = FONT_COLOR_BLACK; break;
+	case 1: pFont->ucFontColor = FONT_COLOR_RED; break;
+	case 2: pFont->ucFontColor = FONT_COLOR_GREEN; break;
+	case 3: pFont->ucFontColor = FONT_COLOR_BLUE; break;
+	case 4: pFont->ucFontColor = FONT_COLOR_CYAN; break;
+	case 5: pFont->ucFontColor = FONT_COLOR_MAGENTA; break;
+	case 6: pFont->ucFontColor = FONT_COLOR_YELLOW; break;
+	case 7: pFont->ucFontColor = FONT_COLOR_WHITE; break;
+	default:pFont->ucFontColor = FONT_COLOR_BLACK; break;
+	}
+	NO_DBG_DEC(pFont->ucFontColor);
+} /* end of vGet0FontInfo */
+
+/*
+ * Build the lists with Character Information for Word for DOS files
+ */
+void
+vGet0ChrInfo(FILE *pFile, const UCHAR *aucHeader)
+{
+	font_block_type		tFont;
+	ULONG	ulBeginCharInfo, ulCharPos, ulCharPosNext;
+	int	iIndex, iRun, iFodo;
+	UCHAR	aucFpage[128];
+
+	fail(pFile == NULL || aucHeader == NULL);
+
+	ulBeginCharInfo = ulGetLong(0x0e, aucHeader);
+	NO_DBG_HEX(ulBeginCharInfo);
+	ulBeginCharInfo = ROUND128(ulBeginCharInfo);
+	NO_DBG_HEX(ulBeginCharInfo);
+
+	do {
+		if (!bReadBytes(aucFpage, 128, ulBeginCharInfo, pFile)) {
+			return;
+		}
+		NO_DBG_PRINT_BLOCK(aucFpage, 128);
+		ulCharPosNext = ulGetLong(0, aucFpage);
+		iRun = (int)ucGetByte(0x7f, aucFpage);
+		NO_DBG_DEC(iRun);
+		for (iIndex = 0; iIndex < iRun; iIndex++) {
+			iFodo = (int)usGetWord(6 * iIndex + 8, aucFpage);
+			if (iFodo <= 0 || iFodo > 0x79) {
+				DBG_DEC_C(iFodo != (int)0xffff, iFodo);
+				continue;
+			}
+			vFillFontFromStylesheet(0, &tFont);
+			vGet0FontInfo(iFodo, aucFpage + 4, &tFont);
+			ulCharPos = ulCharPosNext;
+			ulCharPosNext = ulGetLong(6 * iIndex + 4, aucFpage);
+			tFont.ulFileOffset = ulCharPos;
+			vAdd2FontInfoList(&tFont);
+		}
+		ulBeginCharInfo += 128;
+	} while (ulCharPosNext == ulBeginCharInfo);
+} /* end of vGet0ChrInfo */
diff --git a/prop2.c b/prop2.c
new file mode 100644
index 0000000..eda108a
--- /dev/null
+++ b/prop2.c
@@ -0,0 +1,1067 @@
+/*
+ * prop2.c
+ * Copyright (C) 2002-2005 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Read the property information from a WinWord 1 or 2 file
+ */
+
+#include <string.h>
+#include "antiword.h"
+
+
+#define MAX_FILESIZE		0x2000000UL	/* 32 Mb */
+
+/*
+ * iGet2InfoLength - the length of the information for WinWord 1/2 files
+ */
+static int
+iGet2InfoLength(int iByteNbr, const UCHAR *aucGrpprl)
+{
+	int	iTmp, iDel, iAdd;
+
+	switch (ucGetByte(iByteNbr, aucGrpprl)) {
+	case   3: case  15: case  78: case 152: case 154: case 155:
+		return 2 + (int)ucGetByte(iByteNbr + 1, aucGrpprl);
+	case  16: case  17: case  18: case  19: case  21: case  22: case  26:
+	case  27: case  28: case  30: case  31: case  32: case  33: case  34:
+	case  35: case  36: case  38: case  39: case  40: case  41: case  42:
+	case  43: case  45: case  46: case  47: case  48: case  49: case  68:
+	case  71: case  72: case  82: case  83: case  96: case  97: case  98:
+	case  99: case 115: case 116: case 119: case 120: case 123: case 124:
+	case 129: case 130: case 131: case 132: case 135: case 136: case 139:
+	case 140: case 141: case 142: case 143: case 144: case 145: case 146:
+	case 147: case 148: case 153: case 159: case 161: case 162:
+		return 1 + 2;
+	case  23:
+		iTmp = (int)ucGetByte(iByteNbr + 1, aucGrpprl);
+		if (iTmp == 255) {
+			iDel = (int)ucGetByte(iByteNbr + 2, aucGrpprl);
+			iAdd = (int)ucGetByte(
+					iByteNbr + 3 + iDel * 4, aucGrpprl);
+			iTmp = 2 + iDel * 4 + iAdd * 3;
+		}
+		return 2 + iTmp;
+	case  70:
+		return 1 + 3;
+	case  95:
+		return 1 + 13;
+	case 157: case 163:
+		return 1 + 5;
+	case 158: case 160: case 164:
+		return 1 + 4;
+	default:
+		return 1 + 1;
+	}
+} /* end of iGet2InfoLength */
+
+/*
+ * Build the lists with Document Property Information for WinWord 1/2 files
+ */
+void
+vGet2DopInfo(FILE *pFile, const UCHAR *aucHeader)
+{
+	document_block_type	tDocument;
+	UCHAR	*aucBuffer;
+	ULONG	ulBeginDocpInfo, ulTmp;
+	size_t	tDocpInfoLen;
+	USHORT	usTmp;
+
+	ulBeginDocpInfo = ulGetLong(0x112, aucHeader); /* fcDop */
+	DBG_HEX(ulBeginDocpInfo);
+	tDocpInfoLen = (size_t)usGetWord(0x116, aucHeader); /* cbDop */
+	DBG_DEC(tDocpInfoLen);
+	if (tDocpInfoLen < 28) {
+		DBG_MSG("No Document information");
+		return;
+	}
+
+	aucBuffer = xmalloc(tDocpInfoLen);
+	if (!bReadBytes(aucBuffer, tDocpInfoLen, ulBeginDocpInfo, pFile)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+
+	usTmp = usGetWord(0x00, aucBuffer);
+	tDocument.ucHdrFtrSpecification = (UCHAR)(usTmp >> 8); /* grpfIhdt */
+	tDocument.usDefaultTabWidth = usGetWord(0x0a, aucBuffer); /* dxaTab */
+	ulTmp = ulGetLong(0x14, aucBuffer); /* dttmCreated */
+	tDocument.tCreateDate = tConvertDTTM(ulTmp);
+	ulTmp = ulGetLong(0x18, aucBuffer); /* dttmRevised */
+	tDocument.tRevisedDate = tConvertDTTM(ulTmp);
+	vCreateDocumentInfoList(&tDocument);
+
+	aucBuffer = xfree(aucBuffer);
+} /* end of vGet2DopInfo */
+
+/*
+ * Fill the section information block with information
+ * from a WinWord 1/2 file.
+ */
+static void
+vGet2SectionInfo(const UCHAR *aucGrpprl, size_t tBytes,
+		section_block_type *pSection)
+{
+	int	iFodoOff, iInfoLen;
+	USHORT	usCcol;
+	UCHAR	ucTmp;
+
+	fail(aucGrpprl == NULL || pSection == NULL);
+
+	iFodoOff = 0;
+	while (tBytes >= (size_t)iFodoOff + 1) {
+		switch (ucGetByte(iFodoOff, aucGrpprl)) {
+		case 117:	/* bkc */
+			ucTmp = ucGetByte(iFodoOff + 1, aucGrpprl);
+			DBG_DEC(ucTmp);
+			pSection->bNewPage = ucTmp != 0 && ucTmp != 1;
+			break;
+		case 119:	/* ccolM1 */
+			usCcol = 1 + usGetWord(iFodoOff + 1, aucGrpprl);
+			DBG_DEC(usCcol);
+			break;
+		case 128:	/* grpfIhdt */
+			pSection->ucHdrFtrSpecification =
+					ucGetByte(iFodoOff + 1, aucGrpprl);
+			break;
+		default:
+			break;
+		}
+		iInfoLen = iGet2InfoLength(iFodoOff, aucGrpprl);
+		fail(iInfoLen <= 0);
+		iFodoOff += iInfoLen;
+	}
+} /* end of vGet2SectionInfo */
+
+/*
+ * Build the lists with Section Property Information for WinWord 1/2 files
+ */
+void
+vGet2SepInfo(FILE *pFile, const UCHAR *aucHeader)
+{
+	section_block_type	tSection;
+	ULONG	*aulSectPage, *aulCharPos;
+	UCHAR	*aucBuffer, *aucFpage;
+	ULONG	ulBeginOfText, ulTextOffset, ulBeginSectInfo;
+	size_t	tSectInfoLen, tIndex, tOffset, tLen, tBytes;
+	UCHAR	aucTmp[1];
+
+	fail(pFile == NULL || aucHeader == NULL);
+
+	ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
+	NO_DBG_HEX(ulBeginOfText);
+	ulBeginSectInfo = ulGetLong(0x7c, aucHeader); /* fcPlcfsed */
+	DBG_HEX(ulBeginSectInfo);
+	tSectInfoLen = (size_t)usGetWord(0x80, aucHeader); /* cbPlcfsed */
+	DBG_DEC(tSectInfoLen);
+	if (tSectInfoLen < 4) {
+		DBG_DEC(tSectInfoLen);
+		return;
+	}
+
+	aucBuffer = xmalloc(tSectInfoLen);
+	if (!bReadBytes(aucBuffer, tSectInfoLen, ulBeginSectInfo, pFile)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tSectInfoLen);
+
+	/* Read the Section Descriptors */
+	tLen = (tSectInfoLen - 4) / 10;
+	/* Save the section offsets */
+	aulCharPos = xcalloc(tLen, sizeof(ULONG));
+	for (tIndex = 0, tOffset = 0;
+	     tIndex < tLen;
+	     tIndex++, tOffset += 4) {
+		ulTextOffset = ulGetLong(tOffset, aucBuffer);
+		NO_DBG_HEX(ulTextOffset);
+		aulCharPos[tIndex] = ulBeginOfText + ulTextOffset;
+		NO_DBG_HEX(aulCharPos[tIndex]);
+	}
+	/* Save the Sepx offsets */
+	aulSectPage = xcalloc(tLen, sizeof(ULONG));
+	for (tIndex = 0, tOffset = (tLen + 1) * 4;
+	     tIndex < tLen;
+	     tIndex++, tOffset += 6) {
+		aulSectPage[tIndex] = ulGetLong(tOffset + 2, aucBuffer);
+		NO_DBG_HEX(aulSectPage[tIndex]); /* fcSepx */
+	}
+	aucBuffer = xfree(aucBuffer);
+
+	/* Read the Section Properties */
+	for (tIndex = 0; tIndex < tLen; tIndex++) {
+		if (aulSectPage[tIndex] == FC_INVALID) {
+			vDefault2SectionInfoList(aulCharPos[tIndex]);
+			continue;
+		}
+		/* Get the number of bytes to read */
+		if (!bReadBytes(aucTmp, 1, aulSectPage[tIndex], pFile)) {
+			continue;
+		}
+		tBytes = 1 + (size_t)ucGetByte(0, aucTmp);
+		NO_DBG_DEC(tBytes);
+		/* Read the bytes */
+		aucFpage = xmalloc(tBytes);
+		if (!bReadBytes(aucFpage, tBytes, aulSectPage[tIndex], pFile)) {
+			aucFpage = xfree(aucFpage);
+			continue;
+		}
+		NO_DBG_PRINT_BLOCK(aucFpage, tBytes);
+		/* Process the bytes */
+		vGetDefaultSection(&tSection);
+		vGet2SectionInfo(aucFpage + 1, tBytes - 1, &tSection);
+		vAdd2SectionInfoList(&tSection, aulCharPos[tIndex]);
+		aucFpage = xfree(aucFpage);
+	}
+	aulCharPos = xfree(aulCharPos);
+	aulSectPage = xfree(aulSectPage);
+} /* end of vGet2SepInfo */
+
+/*
+ * Build the list with Header/Footer Information for WinWord 1/2 files
+ */
+void
+vGet2HdrFtrInfo(FILE *pFile, const UCHAR *aucHeader)
+{
+	ULONG	*aulCharPos;
+	UCHAR	*aucBuffer;
+	ULONG	ulHdrFtrOffset, ulBeginHdrFtrInfo;
+	size_t	tHdrFtrInfoLen, tIndex, tOffset, tLen;
+
+	fail(pFile == NULL || aucHeader == NULL);
+
+	ulBeginHdrFtrInfo = ulGetLong(0x9a, aucHeader); /* fcPlcfhdd */
+	NO_DBG_HEX(ulBeginHdrFtrInfo);
+	tHdrFtrInfoLen = (size_t)usGetWord(0x9e, aucHeader); /* cbPlcfhdd */
+	NO_DBG_DEC(tHdrFtrInfoLen);
+	if (tHdrFtrInfoLen < 8) {
+		DBG_DEC_C(tHdrFtrInfoLen != 0, tHdrFtrInfoLen);
+		return;
+	}
+
+	aucBuffer = xmalloc(tHdrFtrInfoLen);
+	if (!bReadBytes(aucBuffer, tHdrFtrInfoLen, ulBeginHdrFtrInfo, pFile)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tHdrFtrInfoLen);
+
+	tLen = tHdrFtrInfoLen / 4 - 1;
+	/* Save the header/footer offsets */
+	aulCharPos = xcalloc(tLen, sizeof(ULONG));
+	for (tIndex = 0, tOffset = 0;
+	     tIndex < tLen;
+	     tIndex++, tOffset += 4) {
+		ulHdrFtrOffset = ulGetLong(tOffset, aucBuffer);
+		NO_DBG_HEX(ulHdrFtrOffset);
+		aulCharPos[tIndex] = ulHdrFtrOffset2CharPos(ulHdrFtrOffset);
+		NO_DBG_HEX(aulCharPos[tIndex]);
+	}
+	vCreat2HdrFtrInfoList(aulCharPos, tLen);
+	aulCharPos = xfree(aulCharPos);
+	aucBuffer = xfree(aucBuffer);
+} /* end of vGet2HdrFtrInfo */
+
+/*
+ * Translate the rowinfo to a member of the row_info enumeration
+ */
+row_info_enum
+eGet2RowInfo(int iFodo,
+	const UCHAR *aucGrpprl, int iBytes, row_block_type *pRow)
+{
+	int	iFodoOff, iInfoLen;
+	int	iIndex, iSize, iCol;
+	int	iPosCurr, iPosPrev;
+	USHORT	usTmp;
+	BOOL	bFound24_0, bFound24_1, bFound25_0, bFound25_1, bFound154;
+
+	fail(iFodo < 0 || aucGrpprl == NULL || pRow == NULL);
+
+	iFodoOff = 0;
+	bFound24_0 = FALSE;
+	bFound24_1 = FALSE;
+	bFound25_0 = FALSE;
+	bFound25_1 = FALSE;
+	bFound154 = FALSE;
+	while (iBytes >= iFodoOff + 1) {
+		iInfoLen = 0;
+		switch (ucGetByte(iFodo + iFodoOff, aucGrpprl)) {
+		case  24:	/* fIntable */
+			if (odd(ucGetByte(iFodo + iFodoOff + 1, aucGrpprl))) {
+				bFound24_1 = TRUE;
+			} else {
+				bFound24_0 = TRUE;
+			}
+			break;
+		case  25:	/* fTtp */
+			if (odd(ucGetByte(iFodo + iFodoOff + 1, aucGrpprl))) {
+				bFound25_1 = TRUE;
+			} else {
+				bFound25_0 = TRUE;
+			}
+			break;
+		case 30:	/* brcTop10 */
+			usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
+			usTmp &= 0x01ff;
+			NO_DBG_DEC(usTmp >> 6);
+			if (usTmp == 0) {
+				pRow->ucBorderInfo &= ~TABLE_BORDER_TOP;
+			} else {
+				pRow->ucBorderInfo |= TABLE_BORDER_TOP;
+			}
+			break;
+		case 31:	/* brcLeft10 */
+			usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
+			usTmp &= 0x01ff;
+			NO_DBG_DEC(usTmp >> 6);
+			if (usTmp == 0) {
+				pRow->ucBorderInfo &= ~TABLE_BORDER_LEFT;
+			} else {
+				pRow->ucBorderInfo |= TABLE_BORDER_LEFT;
+			}
+			break;
+		case 32:	/* brcBottom10 */
+			usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
+			usTmp &= 0x01ff;
+			NO_DBG_DEC(usTmp >> 6);
+			if (usTmp == 0) {
+				pRow->ucBorderInfo &= ~TABLE_BORDER_BOTTOM;
+			} else {
+				pRow->ucBorderInfo |= TABLE_BORDER_BOTTOM;
+			}
+			break;
+		case 33:	/* brcRight10 */
+			usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
+			usTmp &= 0x01ff;
+			NO_DBG_DEC(usTmp >> 6);
+			if (usTmp == 0) {
+				pRow->ucBorderInfo &= ~TABLE_BORDER_RIGHT;
+			} else {
+				pRow->ucBorderInfo |= TABLE_BORDER_RIGHT;
+			}
+			break;
+		case 38:	/* brcTop */
+			usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
+			usTmp &= 0x0018;
+			NO_DBG_DEC(usTmp >> 3);
+			if (usTmp == 0) {
+				pRow->ucBorderInfo &= ~TABLE_BORDER_TOP;
+			} else {
+				pRow->ucBorderInfo |= TABLE_BORDER_TOP;
+			}
+			break;
+		case 39:	/* brcLeft */
+			usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
+			usTmp &= 0x0018;
+			NO_DBG_DEC(usTmp >> 3);
+			if (usTmp == 0) {
+				pRow->ucBorderInfo &= ~TABLE_BORDER_LEFT;
+			} else {
+				pRow->ucBorderInfo |= TABLE_BORDER_LEFT;
+			}
+			break;
+		case 40:	/* brcBottom */
+			usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
+			usTmp &= 0x0018;
+			NO_DBG_DEC(usTmp >> 3);
+			if (usTmp == 0) {
+				pRow->ucBorderInfo &= ~TABLE_BORDER_BOTTOM;
+			} else {
+				pRow->ucBorderInfo |= TABLE_BORDER_BOTTOM;
+			}
+			break;
+		case 41:	/* brcRight */
+			usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
+			usTmp &= 0x0018;
+			NO_DBG_DEC(usTmp >> 3);
+			if (usTmp == 0) {
+				pRow->ucBorderInfo &= ~TABLE_BORDER_RIGHT;
+			} else {
+				pRow->ucBorderInfo |= TABLE_BORDER_RIGHT;
+			}
+			break;
+		case 152:	/* cDefTable10 */
+		case 154:	/* cDefTable */
+			iSize = (int)usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
+			if (iSize < 6 || iBytes < iFodoOff + 7) {
+				DBG_DEC(iSize);
+				DBG_DEC(iBytes);
+				DBG_DEC(iFodoOff);
+				iInfoLen = 1;
+				break;
+			}
+			iCol = (int)ucGetByte(iFodo + iFodoOff + 3, aucGrpprl);
+			if (iCol < 1 ||
+			    iBytes < iFodoOff + 3 + (iCol + 1) * 2) {
+				DBG_DEC(iCol);
+				DBG_DEC(iBytes);
+				DBG_DEC(iFodoOff);
+				DBG_DEC(ucGetByte(iFodo + iFodoOff, aucGrpprl));
+				iInfoLen = 1;
+				break;
+			}
+			if (iCol >= (int)elementsof(pRow->asColumnWidth)) {
+				DBG_DEC(iCol);
+				werr(1, "The number of columns is corrupt");
+			}
+			pRow->ucNumberOfColumns = (UCHAR)iCol;
+			iPosPrev = (int)(short)usGetWord(
+					iFodo + iFodoOff + 4,
+					aucGrpprl);
+			for (iIndex = 0; iIndex < iCol; iIndex++) {
+				iPosCurr = (int)(short)usGetWord(
+					iFodo + iFodoOff + 6 + iIndex * 2,
+					aucGrpprl);
+				pRow->asColumnWidth[iIndex] =
+						(short)(iPosCurr - iPosPrev);
+				iPosPrev = iPosCurr;
+			}
+			bFound154 = TRUE;
+			break;
+		default:
+			break;
+		}
+		if (iInfoLen <= 0) {
+			iInfoLen =
+				iGet2InfoLength(iFodo + iFodoOff, aucGrpprl);
+			fail(iInfoLen <= 0);
+		}
+		iFodoOff += iInfoLen;
+	}
+	if (bFound24_1 && bFound25_1 && bFound154) {
+		return found_end_of_row;
+	}
+	if (bFound24_0 && bFound25_0 && !bFound154) {
+		return found_not_end_of_row;
+	}
+	if (bFound24_1) {
+		return found_a_cell;
+	}
+	if (bFound24_0) {
+		return found_not_a_cell;
+	}
+	return found_nothing;
+} /* end of eGet2RowInfo */
+
+/*
+ * Fill the style information block with information
+ * from a WinWord 1/2 file.
+ */
+void
+vGet2StyleInfo(int iFodo,
+	const UCHAR *aucGrpprl, int iBytes, style_block_type *pStyle)
+{
+	int	iFodoOff, iInfoLen;
+	int	iTmp, iDel, iAdd;
+	short	sTmp;
+	UCHAR	ucTmp;
+
+	fail(iFodo < 0 || aucGrpprl == NULL || pStyle == NULL);
+
+	NO_DBG_DEC(pStyle->usIstd);
+
+	iFodoOff = 0;
+	while (iBytes >= iFodoOff + 1) {
+		iInfoLen = 0;
+		switch (ucGetByte(iFodo + iFodoOff, aucGrpprl)) {
+		case   2:	/* istd */
+			sTmp = (short)ucGetByte(
+					iFodo + iFodoOff + 1, aucGrpprl);
+			NO_DBG_DEC(sTmp);
+			break;
+		case   5:	/* jc */
+			pStyle->ucAlignment = ucGetByte(
+					iFodo + iFodoOff + 1, aucGrpprl);
+			break;
+		case  12:	/* nfcSeqNumb */
+			pStyle->ucNFC = ucGetByte(
+					iFodo + iFodoOff + 1, aucGrpprl);
+			break;
+		case  13:	/* nLvlAnm */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
+			pStyle->ucNumLevel = ucTmp;
+			pStyle->bNumPause =
+				eGetNumType(ucTmp) == level_type_pause;
+			break;
+		case  15:	/* ChgTabsPapx */
+		case  23:	/* ChgTabs */
+			iTmp = (int)ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
+			if (iTmp < 2) {
+				iInfoLen = 1;
+				break;
+			}
+			NO_DBG_DEC(iTmp);
+			iDel = (int)ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
+			if (iTmp < 2 + 2 * iDel) {
+				iInfoLen = 1;
+				break;
+			}
+			NO_DBG_DEC(iDel);
+			iAdd = (int)ucGetByte(
+				iFodo + iFodoOff + 3 + 2 * iDel, aucGrpprl);
+			if (iTmp < 2 + 2 * iDel + 2 * iAdd) {
+				iInfoLen = 1;
+				break;
+			}
+			NO_DBG_DEC(iAdd);
+			break;
+		case  16:	/* dxaRight */
+			pStyle->sRightIndent = (short)usGetWord(
+					iFodo + iFodoOff + 1, aucGrpprl);
+			NO_DBG_DEC(pStyle->sRightIndent);
+			break;
+		case  17:	/* dxaLeft */
+			pStyle->sLeftIndent = (short)usGetWord(
+					iFodo + iFodoOff + 1, aucGrpprl);
+			NO_DBG_DEC(pStyle->sLeftIndent);
+			break;
+		case  18:	/* Nest dxaLeft */
+			sTmp = (short)usGetWord(
+					iFodo + iFodoOff + 1, aucGrpprl);
+			pStyle->sLeftIndent += sTmp;
+			if (pStyle->sLeftIndent < 0) {
+				pStyle->sLeftIndent = 0;
+			}
+			NO_DBG_DEC(sTmp);
+			NO_DBG_DEC(pStyle->sLeftIndent);
+			break;
+		case  19:	/* dxaLeft1 */
+			pStyle->sLeftIndent1 = (short)usGetWord(
+					iFodo + iFodoOff + 1, aucGrpprl);
+			NO_DBG_DEC(pStyle->sLeftIndent1);
+			break;
+		case  21:	/* dyaBefore */
+			pStyle->usBeforeIndent = usGetWord(
+					iFodo + iFodoOff + 1, aucGrpprl);
+			NO_DBG_DEC(pStyle->usBeforeIndent);
+			break;
+		case  22:	/* dyaAfter */
+			pStyle->usAfterIndent = usGetWord(
+					iFodo + iFodoOff + 1, aucGrpprl);
+			NO_DBG_DEC(pStyle->usAfterIndent);
+			break;
+		default:
+			break;
+		}
+		if (iInfoLen <= 0) {
+			iInfoLen =
+				iGet2InfoLength(iFodo + iFodoOff, aucGrpprl);
+			fail(iInfoLen <= 0);
+		}
+		iFodoOff += iInfoLen;
+	}
+} /* end of vGet2StyleInfo */
+
+/*
+ * Build the lists with Paragraph Information for WinWord 1/2 files
+ */
+void
+vGet2PapInfo(FILE *pFile, const UCHAR *aucHeader)
+{
+	row_block_type		tRow;
+	style_block_type	tStyle;
+	USHORT	*ausParfPage;
+	UCHAR	*aucBuffer;
+	ULONG	ulCharPos, ulCharPosFirst, ulCharPosLast;
+	ULONG	ulBeginParfInfo;
+	size_t	tParfInfoLen, tParfPageNum, tOffset, tSize, tLenOld, tLen;
+	int	iIndex, iIndex2, iRun, iFodo, iLen;
+	row_info_enum	eRowInfo;
+	USHORT	usParfFirstPage, usCount, usIstd;
+	UCHAR	ucStc;
+	UCHAR	aucFpage[BIG_BLOCK_SIZE];
+
+	fail(pFile == NULL || aucHeader == NULL);
+
+	ulBeginParfInfo = ulGetLong(0xa6, aucHeader); /* fcPlcfbtePapx */
+	NO_DBG_HEX(ulBeginParfInfo);
+	tParfInfoLen = (size_t)usGetWord(0xaa, aucHeader); /* cbPlcfbtePapx */
+	NO_DBG_DEC(tParfInfoLen);
+	if (tParfInfoLen < 4) {
+		DBG_DEC(tParfInfoLen);
+		return;
+	}
+
+	aucBuffer = xmalloc(tParfInfoLen);
+	if (!bReadBytes(aucBuffer, tParfInfoLen, ulBeginParfInfo, pFile)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tParfInfoLen);
+
+	tLen = (tParfInfoLen - 4) / 6;
+	ausParfPage = xcalloc(tLen, sizeof(USHORT));
+	for (iIndex = 0, tOffset = (tLen + 1) * 4;
+	     iIndex < (int)tLen;
+	     iIndex++, tOffset += 2) {
+		ausParfPage[iIndex] = usGetWord(tOffset, aucBuffer);
+		NO_DBG_DEC(ausParfPage[iIndex]);
+	}
+	DBG_HEX(ulGetLong(0, aucBuffer));
+	aucBuffer = xfree(aucBuffer);
+	tParfPageNum = (size_t)usGetWord(0x144, aucHeader); /* cpnBtePap */
+	DBG_DEC(tParfPageNum);
+	if (tLen < tParfPageNum) {
+		/* Replace ParfPage by a longer version */
+		tLenOld = tLen;
+		usParfFirstPage = usGetWord(0x140, aucHeader); /* pnPapFirst */
+		DBG_DEC(usParfFirstPage);
+		tLen += tParfPageNum - 1;
+		tSize = tLen * sizeof(USHORT);
+		ausParfPage = xrealloc(ausParfPage, tSize);
+		/* Add new values */
+		usCount = usParfFirstPage + 1;
+		for (iIndex = (int)tLenOld; iIndex < (int)tLen; iIndex++) {
+			ausParfPage[iIndex] = usCount;
+			NO_DBG_DEC(ausParfPage[iIndex]);
+			usCount++;
+		}
+	}
+
+	(void)memset(&tRow, 0, sizeof(tRow));
+	ulCharPosFirst = CP_INVALID;
+	for (iIndex = 0; iIndex < (int)tLen; iIndex++) {
+		if (!bReadBytes(aucFpage, BIG_BLOCK_SIZE,
+				(ULONG)ausParfPage[iIndex] * BIG_BLOCK_SIZE,
+				pFile)) {
+			break;
+		}
+		NO_DBG_PRINT_BLOCK(aucFpage, BIG_BLOCK_SIZE);
+		iRun = (int)ucGetByte(0x1ff, aucFpage);
+		NO_DBG_DEC(iRun);
+		for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) {
+			if ((iRun + 1) * 4 + iIndex2 * 1 >= BIG_BLOCK_SIZE) {
+				break;
+			}
+			NO_DBG_HEX(ulGetLong(iIndex2 * 4, aucFpage));
+			iFodo = 2 * (int)ucGetByte(
+				(iRun + 1) * 4 + iIndex2 * 1, aucFpage);
+			if (iFodo <= 0) {
+				continue;
+			}
+
+			iLen = 2 * (int)ucGetByte(iFodo, aucFpage);
+
+			ucStc = ucGetByte(iFodo + 1, aucFpage);
+			usIstd = usStc2istd(ucStc);
+
+			vFillStyleFromStylesheet(usIstd, &tStyle);
+			vGet2StyleInfo(iFodo, aucFpage + 8, iLen - 8, &tStyle);
+			ulCharPos = ulGetLong(iIndex2 * 4, aucFpage);
+			NO_DBG_HEX(ulCharPos);
+			tStyle.ulFileOffset = ulCharPos;
+			vAdd2StyleInfoList(&tStyle);
+
+			eRowInfo = eGet2RowInfo(iFodo,
+					aucFpage + 8, iLen - 8, &tRow);
+
+			switch(eRowInfo) {
+			case found_a_cell:
+				if (ulCharPosFirst != CP_INVALID) {
+					break;
+				}
+				ulCharPosFirst = ulGetLong(
+						iIndex2 * 4, aucFpage);
+				NO_DBG_HEX(ulCharPosFirst);
+				tRow.ulCharPosStart = ulCharPosFirst;
+				tRow.ulFileOffsetStart = ulCharPosFirst;
+				break;
+			case found_end_of_row:
+				ulCharPosLast = ulGetLong(
+						iIndex2 * 4, aucFpage);
+				NO_DBG_HEX(ulCharPosLast);
+				tRow.ulCharPosEnd = ulCharPosLast;
+				/* Add 1 for compatiblity with Word 6 and up */
+				tRow.ulFileOffsetEnd = ulCharPosLast + 1;
+				vAdd2RowInfoList(&tRow);
+				(void)memset(&tRow, 0, sizeof(tRow));
+				ulCharPosFirst = CP_INVALID;
+				break;
+			case found_nothing:
+				break;
+			default:
+				DBG_DEC(eRowInfo);
+				break;
+			}
+		}
+	}
+	ausParfPage = xfree(ausParfPage);
+} /* end of vGet2PapInfo */
+
+/*
+ * Fill the font information block with information
+ * from a WinWord 1 file.
+ */
+void
+vGet1FontInfo(int iFodo,
+	const UCHAR *aucGrpprl, size_t tBytes, font_block_type *pFont)
+{
+	BOOL	bIcoChange, bFtcChange, bHpsChange, bKulChange;
+	USHORT	usTmp;
+	UCHAR	ucTmp;
+	UCHAR	aucChpx[12];
+
+	fail(iFodo < 0 || aucGrpprl == NULL || pFont == NULL);
+
+	if (tBytes > sizeof(aucChpx)) {
+		NO_DBG_PRINT_BLOCK(aucGrpprl + iFodo, tBytes);
+		return;
+	}
+
+	/* Build the CHPX structure */
+	(void)memset(aucChpx, 0, sizeof(aucChpx));
+	(void)memcpy(aucChpx, aucGrpprl + iFodo, min(tBytes, sizeof(aucChpx)));
+
+	usTmp = usGetWord(0, aucChpx);
+	if ((usTmp & BIT(0)) != 0) {
+		pFont->usFontStyle ^= FONT_BOLD;
+	}
+	if ((usTmp & BIT(1)) != 0) {
+		pFont->usFontStyle ^= FONT_ITALIC;
+	}
+	if ((usTmp & BIT(2)) != 0) {
+		pFont->usFontStyle ^= FONT_STRIKE;
+	}
+	if ((usTmp & BIT(5)) != 0) {
+		pFont->usFontStyle ^= FONT_SMALL_CAPITALS;
+	}
+	if ((usTmp & BIT(6)) != 0) {
+		pFont->usFontStyle ^= FONT_CAPITALS;
+	}
+	if ((usTmp & BIT(7)) != 0) {
+		pFont->usFontStyle ^= FONT_HIDDEN;
+	}
+
+	ucTmp = ucGetByte(5, aucChpx);
+	if (ucTmp != 0) {
+		if (ucTmp < 128) {
+			pFont->usFontStyle |= FONT_SUPERSCRIPT;
+			DBG_MSG("Superscript");
+		} else {
+			pFont->usFontStyle |= FONT_SUBSCRIPT;
+			DBG_MSG("Subscript");
+		}
+	}
+
+	bIcoChange = (usTmp & BIT(10)) != 0;
+	bFtcChange = (usTmp & BIT(11)) != 0;
+	bHpsChange = (usTmp & BIT(12)) != 0;
+	bKulChange = (usTmp & BIT(13)) != 0;
+
+	if (bFtcChange) {
+		usTmp = usGetWord(2, aucChpx);
+		if (usTmp <= (USHORT)UCHAR_MAX) {
+			pFont->ucFontNumber = (UCHAR)usTmp;
+		} else {
+			pFont->ucFontNumber = 0;
+		}
+	}
+
+	if (bHpsChange) {
+		pFont->usFontSize = (USHORT)ucGetByte(4, aucChpx);
+	}
+
+	if (bIcoChange || bKulChange) {
+		usTmp = usGetWord(6, aucChpx);
+		if (bIcoChange) {
+			pFont->ucFontColor = (UCHAR)((usTmp & 0x0f00) >> 8);
+			if (pFont->ucFontColor <= 7) {
+				/* Add 1 for compatibility with Word 2 and up */
+				pFont->ucFontColor++;
+			} else {
+				DBG_DEC(pFont->ucFontColor);
+				pFont->ucFontColor = 0;
+			}
+		}
+		if (bKulChange) {
+			usTmp = (usTmp & 0x7000) >> 12;
+			DBG_DEC_C(usTmp > 4, usTmp);
+			if (usTmp == 0) {
+				pFont->usFontStyle &= ~FONT_UNDERLINE;
+			} else {
+				pFont->usFontStyle |= FONT_UNDERLINE;
+			}
+		}
+	}
+} /* end of vGet1FontInfo */
+
+/*
+ * Fill the font information block with information
+ * from a WinWord 1/2 file.
+ */
+void
+vGet2FontInfo(int iFodo,
+	const UCHAR *aucGrpprl, size_t tBytes, font_block_type *pFont)
+{
+	BOOL	bIcoChange, bFtcChange, bHpsChange, bKulChange;
+	USHORT	usTmp;
+	UCHAR	ucTmp;
+	UCHAR	aucChpx[18];
+
+	fail(iFodo < 0 || aucGrpprl == NULL || pFont == NULL);
+
+	if (tBytes > sizeof(aucChpx)) {
+		NO_DBG_PRINT_BLOCK(aucGrpprl + iFodo, tBytes);
+		return;
+	}
+
+	/* Build the CHPX structure */
+	(void)memset(aucChpx, 0, sizeof(aucChpx));
+	(void)memcpy(aucChpx, aucGrpprl + iFodo, min(tBytes, sizeof(aucChpx)));
+
+	usTmp = usGetWord(0, aucChpx);
+	if ((usTmp & BIT(0)) != 0) {
+		pFont->usFontStyle ^= FONT_BOLD;
+	}
+	if ((usTmp & BIT(1)) != 0) {
+		pFont->usFontStyle ^= FONT_ITALIC;
+	}
+	if (usTmp & BIT(3)) {
+		pFont->usFontStyle ^= FONT_MARKDEL;
+	}
+	if ((usTmp & BIT(5)) != 0) {
+		pFont->usFontStyle ^= FONT_SMALL_CAPITALS;
+	}
+	if ((usTmp & BIT(6)) != 0) {
+		pFont->usFontStyle ^= FONT_CAPITALS;
+	}
+	if ((usTmp & BIT(7)) != 0) {
+		pFont->usFontStyle ^= FONT_HIDDEN;
+	}
+	if (usTmp & BIT(10)) {
+		pFont->usFontStyle ^= FONT_STRIKE;
+	}
+
+	ucTmp = ucGetByte(10, aucChpx);
+	DBG_MSG_C(ucTmp != 0 && ucTmp < 128, "Superscript");
+	DBG_MSG_C(ucTmp >= 128, "Subscript");
+
+	usTmp = usGetWord(2, aucChpx);
+	if (usTmp == 0) {
+		/* No changes, nothing to do */
+		return;
+	}
+
+	bIcoChange = (usTmp & BIT(0)) != 0;
+	bFtcChange = (usTmp & BIT(1)) != 0;
+	bHpsChange = (usTmp & BIT(2)) != 0;
+	bKulChange = (usTmp & BIT(3)) != 0;
+
+	if (bFtcChange) {
+		usTmp = usGetWord(4, aucChpx);
+		if (usTmp <= (USHORT)UCHAR_MAX) {
+			pFont->ucFontNumber = (UCHAR)usTmp;
+		} else {
+			pFont->ucFontNumber = 0;
+		}
+	}
+
+	if (bHpsChange) {
+		pFont->usFontSize = usGetWord(6, aucChpx);
+	}
+
+	if (bIcoChange || bKulChange) {
+		ucTmp = ucGetByte(9, aucChpx);
+		if (bIcoChange) {
+			pFont->ucFontColor = ucTmp & 0x1f;
+			if (pFont->ucFontColor > 16) {
+				DBG_DEC(pFont->ucFontColor);
+				pFont->ucFontColor = 0;
+			}
+		}
+		if (bKulChange) {
+			ucTmp = (ucTmp & 0xe0) >> 5;
+			DBG_DEC_C(ucTmp > 4, ucTmp);
+			if (ucTmp == 0) {
+				pFont->usFontStyle &= ~FONT_UNDERLINE;
+			} else {
+				pFont->usFontStyle |= FONT_UNDERLINE;
+			}
+		}
+	}
+} /* end of vGet2FontInfo */
+
+/*
+ * Fill the picture information block with information from a WinWord 1 file.
+ * Returns TRUE when successful, otherwise FALSE
+ */
+static BOOL
+bGet1PicInfo(int iFodo,
+	const UCHAR *aucGrpprl, size_t tBytes, picture_block_type *pPicture)
+{
+	ULONG	ulTmp;
+	UCHAR	aucChpx[12];
+
+	fail(iFodo < 0 || aucGrpprl == NULL || pPicture == NULL);
+
+	if (tBytes > sizeof(aucChpx)) {
+		NO_DBG_PRINT_BLOCK(aucGrpprl + iFodo, tBytes);
+		tBytes = sizeof(aucChpx);
+	}
+
+	/* Build the CHPX structure */
+	(void)memset(aucChpx, 0, sizeof(aucChpx));
+	(void)memcpy(aucChpx, aucGrpprl + iFodo, min(tBytes, sizeof(aucChpx)));
+
+	ulTmp = ulGetLong(8, aucChpx);
+	if (ulTmp != 0 && ulTmp < MAX_FILESIZE) {
+		pPicture->ulPictureOffset = ulTmp;
+		DBG_HEX(pPicture->ulPictureOffset);
+		return TRUE;
+	}
+	return FALSE;
+} /* end of bGet1PicInfo */
+
+/*
+ * Fill the picture information block with information from a WinWord 2 file.
+ * Returns TRUE when successful, otherwise FALSE
+ */
+static BOOL
+bGet2PicInfo(int iFodo,
+	const UCHAR *aucGrpprl, size_t tBytes, picture_block_type *pPicture)
+{
+	ULONG	ulTmp;
+	UCHAR	aucChpx[18];
+
+	fail(iFodo < 0 || aucGrpprl == NULL || pPicture == NULL);
+
+	if (tBytes > sizeof(aucChpx)) {
+		NO_DBG_PRINT_BLOCK(aucGrpprl + iFodo, tBytes);
+		tBytes = sizeof(aucChpx);
+	}
+
+	/* Build the CHPX structure */
+	(void)memset(aucChpx, 0, sizeof(aucChpx));
+	(void)memcpy(aucChpx, aucGrpprl + iFodo, min(tBytes, sizeof(aucChpx)));
+
+	ulTmp = ulGetLong(14, aucChpx);
+	if (ulTmp != 0 && ulTmp < MAX_FILESIZE) {
+		pPicture->ulPictureOffset = ulTmp;
+		DBG_HEX(pPicture->ulPictureOffset);
+		DBG_DEC(tBytes);
+		return TRUE;
+	}
+	return FALSE;
+} /* end of bGet2PicInfo */
+
+/*
+ * Build the lists with Character Information for WinWord 1/2 files
+ */
+void
+vGet2ChrInfo(FILE *pFile, int iWordVersion, const UCHAR *aucHeader)
+{
+	font_block_type		tFont;
+	picture_block_type	tPicture;
+	USHORT	*ausCharPage;
+	UCHAR	*aucBuffer;
+	ULONG	ulFileOffset, ulCharPos, ulBeginCharInfo;
+	size_t	tCharInfoLen, tOffset, tSize, tChrLen, tCharPageNum;
+	size_t	tLenOld, tLen;
+	int	iIndex, iIndex2, iRun, iFodo;
+	BOOL	bSuccess1, bSuccess2;
+	USHORT	usCharFirstPage, usCount, usIstd;
+	UCHAR	aucFpage[BIG_BLOCK_SIZE];
+
+	fail(pFile == NULL || aucHeader == NULL);
+	fail(iWordVersion != 1 && iWordVersion != 2);
+
+	ulBeginCharInfo = ulGetLong(0xa0, aucHeader); /* fcPlcfbteChpx */
+	DBG_HEX(ulBeginCharInfo);
+	tCharInfoLen = (size_t)usGetWord(0xa4, aucHeader); /* cbPlcfbteChpx */
+	DBG_DEC(tCharInfoLen);
+	if (tCharInfoLen < 4) {
+		DBG_DEC(tCharInfoLen);
+		return;
+	}
+
+	aucBuffer = xmalloc(tCharInfoLen);
+	if (!bReadBytes(aucBuffer, tCharInfoLen, ulBeginCharInfo, pFile)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tCharInfoLen);
+
+	tLen = (tCharInfoLen - 4) / 6;
+	ausCharPage = xcalloc(tLen, sizeof(USHORT));
+	for (iIndex = 0, tOffset = (tLen + 1) * 4;
+	     iIndex < (int)tLen;
+	     iIndex++, tOffset += 2) {
+		ausCharPage[iIndex] = usGetWord(tOffset, aucBuffer);
+		NO_DBG_DEC(ausCharPage[iIndex]);
+	}
+	DBG_HEX(ulGetLong(0, aucBuffer));
+	aucBuffer = xfree(aucBuffer);
+	tCharPageNum = (size_t)usGetWord(0x142, aucHeader); /* cpnBteChp */
+	DBG_DEC(tCharPageNum);
+	if (tLen < tCharPageNum) {
+		/* Replace CharPage by a longer version */
+		tLenOld = tLen;
+		usCharFirstPage = usGetWord(0x13e, aucHeader); /* pnChrFirst */
+		NO_DBG_DEC(usCharFirstPage);
+		tLen += tCharPageNum - 1;
+		tSize = tLen * sizeof(USHORT);
+		ausCharPage = xrealloc(ausCharPage, tSize);
+		/* Add new values */
+		usCount = usCharFirstPage + 1;
+		for (iIndex = (int)tLenOld; iIndex < (int)tLen; iIndex++) {
+			ausCharPage[iIndex] = usCount;
+			NO_DBG_DEC(ausCharPage[iIndex]);
+			usCount++;
+		}
+	}
+
+	for (iIndex = 0; iIndex < (int)tLen; iIndex++) {
+		if (!bReadBytes(aucFpage, BIG_BLOCK_SIZE,
+				(ULONG)ausCharPage[iIndex] * BIG_BLOCK_SIZE,
+				pFile)) {
+			break;
+		}
+		NO_DBG_PRINT_BLOCK(aucFpage, BIG_BLOCK_SIZE);
+		iRun = (int)ucGetByte(0x1ff, aucFpage);
+		NO_DBG_DEC(iRun);
+		for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) {
+			if ((iRun + 1) * 4 + iIndex2 >= BIG_BLOCK_SIZE) {
+				break;
+			}
+			ulCharPos = ulGetLong(iIndex2 * 4, aucFpage);
+			ulFileOffset = ulCharPos;
+			iFodo = 2 * (int)ucGetByte(
+				(iRun + 1) * 4 + iIndex2, aucFpage);
+
+			tChrLen = (size_t)ucGetByte(iFodo, aucFpage);
+
+			usIstd = usGetIstd(ulFileOffset);
+			vFillFontFromStylesheet(usIstd, &tFont);
+			if (iFodo != 0) {
+				if (iWordVersion == 1) {
+					vGet1FontInfo(iFodo,
+						aucFpage + 1, tChrLen, &tFont);
+				} else if (iWordVersion == 2) {
+					vGet2FontInfo(iFodo,
+						aucFpage + 1, tChrLen, &tFont);
+				}
+			}
+			tFont.ulFileOffset = ulFileOffset;
+			vAdd2FontInfoList(&tFont);
+
+			if (iFodo <= 0) {
+				continue;
+			}
+
+			(void)memset(&tPicture, 0, sizeof(tPicture));
+			bSuccess1 = iWordVersion == 1 &&
+					bGet1PicInfo(iFodo, aucFpage + 1,
+						tChrLen, &tPicture);
+			bSuccess2 = iWordVersion == 2 &&
+					bGet2PicInfo(iFodo, aucFpage + 1,
+						tChrLen, &tPicture);
+			if (bSuccess1 || bSuccess2) {
+				tPicture.ulFileOffset = ulFileOffset;
+				tPicture.ulFileOffsetPicture =
+						tPicture.ulPictureOffset;
+				vAdd2PictInfoList(&tPicture);
+			}
+		}
+	}
+	ausCharPage = xfree(ausCharPage);
+} /* end of vGet2ChrInfo */
diff --git a/prop6.c b/prop6.c
new file mode 100644
index 0000000..e4c468d
--- /dev/null
+++ b/prop6.c
@@ -0,0 +1,1141 @@
+/*
+ * prop6.c
+ * Copyright (C) 1998-2005 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Read the property information from a MS Word 6 or 7 file
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "antiword.h"
+
+
+/*
+ * iGet6InfoLength - the length of the information for Word 6/7 files
+ */
+static int
+iGet6InfoLength(int iByteNbr, const UCHAR *aucGrpprl)
+{
+	int	iTmp, iDel, iAdd;
+
+	switch (ucGetByte(iByteNbr, aucGrpprl)) {
+	case   2: case  16: case  17: case  18: case  19: case  21: case  22:
+	case  26: case  27: case  28: case  30: case  31: case  32: case  33:
+	case  34: case  35: case  36: case  38: case  39: case  40: case  41:
+	case  42: case  43: case  45: case  46: case  47: case  48: case  49:
+	case  69: case  72: case  80: case  93: case  96: case  97: case  99:
+	case 101: case 105: case 106: case 107: case 109: case 110: case 121:
+	case 122: case 123: case 124: case 140: case 141: case 144: case 145:
+	case 148: case 149: case 154: case 155: case 156: case 157: case 160:
+	case 161: case 164: case 165: case 166: case 167: case 168: case 169:
+	case 170: case 171: case 182: case 183: case 184: case 189: case 195:
+	case 197: case 198:
+		return 1 + 2;
+	case   3: case  12: case  15: case  81: case 103: case 108: case 188:
+	case 190: case 191:
+		return 2 + (int)ucGetByte(iByteNbr + 1, aucGrpprl);
+	case  20: case  70: case  74: case 192: case 194: case 196: case 200:
+		return 1 + 4;
+	case  23:
+		iTmp = (int)ucGetByte(iByteNbr + 1, aucGrpprl);
+		if (iTmp == 255) {
+			iDel = (int)ucGetByte(iByteNbr + 2, aucGrpprl);
+			iAdd = (int)ucGetByte(
+					iByteNbr + 3 + iDel * 4, aucGrpprl);
+			iTmp = 2 + iDel * 4 + iAdd * 3;
+		}
+		return 2 + iTmp;
+	case  68: case 193: case 199:
+		return 1 + 5;
+	case  73: case  95: case 136: case 137:
+		return 1 + 3;
+	case 120: case 187:
+		return 1 + 12;
+	default:
+		return 1 + 1;
+	}
+} /* end of iGet6InfoLength */
+
+/*
+ * Build the lists with Document Property Information for Word 6/7 files
+ */
+void
+vGet6DopInfo(FILE *pFile, ULONG ulStartBlock,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const UCHAR *aucHeader)
+{
+	document_block_type	tDocument;
+	UCHAR	*aucBuffer;
+	ULONG	ulBeginDocpInfo, ulTmp;
+	size_t	tDocpInfoLen;
+	USHORT	usTmp;
+
+	ulBeginDocpInfo = ulGetLong(0x150, aucHeader); /* fcDop */
+	DBG_HEX(ulBeginDocpInfo);
+	tDocpInfoLen = (size_t)ulGetLong(0x154, aucHeader); /* lcbDop */
+	DBG_DEC(tDocpInfoLen);
+	if (tDocpInfoLen < 28) {
+		DBG_MSG("No Document information");
+		return;
+	}
+
+	aucBuffer = xmalloc(tDocpInfoLen);
+	if (!bReadBuffer(pFile, ulStartBlock,
+			aulBBD, tBBDLen, BIG_BLOCK_SIZE,
+			aucBuffer, ulBeginDocpInfo, tDocpInfoLen)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+
+	usTmp = usGetWord(0x00, aucBuffer);
+	tDocument.ucHdrFtrSpecification = (UCHAR)(usTmp >> 8); /* grpfIhdt */
+	tDocument.usDefaultTabWidth = usGetWord(0x0a, aucBuffer); /* dxaTab */
+	ulTmp = ulGetLong(0x14, aucBuffer); /* dttmCreated */
+	tDocument.tCreateDate = tConvertDTTM(ulTmp);
+	ulTmp = ulGetLong(0x18, aucBuffer); /* dttmRevised */
+	tDocument.tRevisedDate = tConvertDTTM(ulTmp);
+	vCreateDocumentInfoList(&tDocument);
+
+	aucBuffer = xfree(aucBuffer);
+} /* end of vGet6DopInfo */
+
+/*
+ * Fill the section information block with information
+ * from a Word 6/7 file.
+ */
+static void
+vGet6SectionInfo(const UCHAR *aucGrpprl, size_t tBytes,
+		section_block_type *pSection)
+{
+	UINT	uiIndex;
+	int	iFodoOff, iInfoLen, iSize, iTmp;
+	USHORT	usCcol;
+	UCHAR	ucTmp;
+
+	fail(aucGrpprl == NULL || pSection == NULL);
+
+	iFodoOff = 0;
+	while (tBytes >= (size_t)iFodoOff + 1) {
+		iInfoLen = 0;
+		switch (ucGetByte(iFodoOff, aucGrpprl)) {
+		case 133:	/* olstAnm */
+			iSize = (int)ucGetByte(iFodoOff + 1, aucGrpprl);
+			DBG_DEC_C(iSize != 212, iSize);
+			for (uiIndex = 0, iTmp = iFodoOff + 2;
+			     uiIndex < 9 && iTmp < iFodoOff + 2 + iSize - 15;
+			     uiIndex++, iTmp += 16) {
+				pSection->aucNFC[uiIndex] =
+						ucGetByte(iTmp, aucGrpprl);
+				NO_DBG_DEC(pSection->aucNFC[uiIndex]);
+				ucTmp = ucGetByte(iTmp + 3, aucGrpprl);
+				NO_DBG_HEX(ucTmp);
+				if ((ucTmp & BIT(2)) != 0) {
+					pSection->usNeedPrevLvl |=
+							(USHORT)BIT(uiIndex);
+				}
+				if ((ucTmp & BIT(3)) != 0) {
+					pSection->usHangingIndent |=
+							(USHORT)BIT(uiIndex);
+				}
+			}
+			DBG_HEX(pSection->usNeedPrevLvl);
+			DBG_HEX(pSection->usHangingIndent);
+			break;
+		case 142:	/* bkc */
+			ucTmp = ucGetByte(iFodoOff + 1, aucGrpprl);
+			DBG_DEC(ucTmp);
+			pSection->bNewPage = ucTmp != 0 && ucTmp != 1;
+			break;
+		case 144:	/* ccolM1 */
+			usCcol = 1 + usGetWord(iFodoOff + 1, aucGrpprl);
+			DBG_DEC(usCcol);
+			break;
+		case 153:	/* grpfIhdt */
+			pSection->ucHdrFtrSpecification =
+					ucGetByte(iFodoOff + 1, aucGrpprl);
+			break;
+		default:
+			break;
+		}
+		if (iInfoLen <= 0) {
+			iInfoLen = iGet6InfoLength(iFodoOff, aucGrpprl);
+			fail(iInfoLen <= 0);
+		}
+		iFodoOff += iInfoLen;
+	}
+} /* end of vGet6SectionInfo */
+
+/*
+ * Build the lists with Section Property Information for Word 6/7 files
+ */
+void
+vGet6SepInfo(FILE *pFile, ULONG ulStartBlock,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const UCHAR *aucHeader)
+{
+	section_block_type	tSection;
+	ULONG		*aulSectPage, *aulCharPos;
+	UCHAR	*aucBuffer, *aucFpage;
+	ULONG	ulBeginOfText, ulTextOffset, ulBeginSectInfo;
+	size_t	tSectInfoLen, tIndex, tOffset, tLen, tBytes;
+	UCHAR	aucTmp[2];
+
+	fail(pFile == NULL || aucHeader == NULL);
+	fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
+	fail(aulBBD == NULL);
+
+        ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
+        NO_DBG_HEX(ulBeginOfText);
+	ulBeginSectInfo = ulGetLong(0x88, aucHeader); /* fcPlcfsed */
+	DBG_HEX(ulBeginSectInfo);
+	tSectInfoLen = (size_t)ulGetLong(0x8c, aucHeader); /* lcbPlcfsed */
+	DBG_DEC(tSectInfoLen);
+	if (tSectInfoLen < 4) {
+		DBG_DEC(tSectInfoLen);
+		return;
+	}
+
+	aucBuffer = xmalloc(tSectInfoLen);
+	if (!bReadBuffer(pFile, ulStartBlock,
+			aulBBD, tBBDLen, BIG_BLOCK_SIZE,
+			aucBuffer, ulBeginSectInfo, tSectInfoLen)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tSectInfoLen);
+
+	/* Read the Section Descriptors */
+	tLen = (tSectInfoLen - 4) / 16;
+	/* Save the section offsets */
+	aulCharPos = xcalloc(tLen, sizeof(ULONG));
+	for (tIndex = 0, tOffset = 0; tIndex < tLen; tIndex++, tOffset += 4) {
+		ulTextOffset = ulGetLong(tOffset, aucBuffer);
+		NO_DBG_HEX(ulTextOffset);
+		aulCharPos[tIndex] = ulBeginOfText + ulTextOffset;
+		NO_DBG_HEX(aulCharPos[tIndex]);
+	}
+	/* Save the Sepx offsets */
+	aulSectPage = xcalloc(tLen, sizeof(ULONG));
+	for (tIndex = 0, tOffset = (tLen + 1) * 4;
+	     tIndex < tLen;
+	     tIndex++, tOffset += 12) {
+		aulSectPage[tIndex] = ulGetLong(tOffset + 2, aucBuffer);
+		NO_DBG_HEX(aulSectPage[tIndex]); /* fcSepx */
+	}
+	aucBuffer = xfree(aucBuffer);
+
+	/* Read the Section Properties */
+	for (tIndex = 0; tIndex < tLen; tIndex++) {
+		if (aulSectPage[tIndex] == FC_INVALID) {
+			vDefault2SectionInfoList(aulCharPos[tIndex]);
+			continue;
+		}
+		/* Get the number of bytes to read */
+		if (!bReadBuffer(pFile, ulStartBlock,
+				aulBBD, tBBDLen, BIG_BLOCK_SIZE,
+				aucTmp, aulSectPage[tIndex], 2)) {
+			continue;
+		}
+		tBytes = 2 + (size_t)usGetWord(0, aucTmp);
+		NO_DBG_DEC(tBytes);
+		/* Read the bytes */
+		aucFpage = xmalloc(tBytes);
+		if (!bReadBuffer(pFile, ulStartBlock,
+				aulBBD, tBBDLen, BIG_BLOCK_SIZE,
+				aucFpage, aulSectPage[tIndex], tBytes)) {
+			aucFpage = xfree(aucFpage);
+			continue;
+		}
+		NO_DBG_PRINT_BLOCK(aucFpage, tBytes);
+		/* Process the bytes */
+		vGetDefaultSection(&tSection);
+		vGet6SectionInfo(aucFpage + 2, tBytes - 2, &tSection);
+		vAdd2SectionInfoList(&tSection, aulCharPos[tIndex]);
+		aucFpage = xfree(aucFpage);
+	}
+	aulCharPos = xfree(aulCharPos);
+	aulSectPage = xfree(aulSectPage);
+} /* end of vGet6SepInfo */
+
+/*
+ * Build the list with Header/Footer Information for Word 6/7 files
+ */
+void
+vGet6HdrFtrInfo(FILE *pFile, ULONG ulStartBlock,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const UCHAR *aucHeader)
+{
+	ULONG	*aulCharPos;
+	UCHAR	*aucBuffer;
+	ULONG	ulHdrFtrOffset, ulBeginHdrFtrInfo;
+	size_t	tHdrFtrInfoLen, tIndex, tOffset, tLen;
+
+	fail(pFile == NULL || aucHeader == NULL);
+	fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
+	fail(aulBBD == NULL);
+
+	ulBeginHdrFtrInfo = ulGetLong(0xb0, aucHeader); /* fcPlcfhdd */
+	NO_DBG_HEX(ulBeginHdrFtrInfo);
+	tHdrFtrInfoLen = (size_t)ulGetLong(0xb4, aucHeader); /* lcbPlcfhdd */
+	NO_DBG_DEC(tHdrFtrInfoLen);
+	if (tHdrFtrInfoLen < 8) {
+		DBG_DEC_C(tHdrFtrInfoLen != 0, tHdrFtrInfoLen);
+		return;
+	}
+
+	aucBuffer = xmalloc(tHdrFtrInfoLen);
+	if (!bReadBuffer(pFile, ulStartBlock,
+			aulBBD, tBBDLen, BIG_BLOCK_SIZE,
+			aucBuffer, ulBeginHdrFtrInfo, tHdrFtrInfoLen)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tHdrFtrInfoLen);
+
+	tLen = tHdrFtrInfoLen / 4 - 1;
+	/* Save the header/footer offsets */
+	aulCharPos = xcalloc(tLen, sizeof(ULONG));
+	for (tIndex = 0, tOffset = 0;
+	     tIndex < tLen;
+	     tIndex++, tOffset += 4) {
+		ulHdrFtrOffset = ulGetLong(tOffset, aucBuffer);
+		NO_DBG_HEX(ulHdrFtrOffset);
+		aulCharPos[tIndex] = ulHdrFtrOffset2CharPos(ulHdrFtrOffset);
+		NO_DBG_HEX(aulCharPos[tIndex]);
+	}
+	vCreat6HdrFtrInfoList(aulCharPos, tLen);
+	aulCharPos = xfree(aulCharPos);
+	aucBuffer = xfree(aucBuffer);
+} /* end of vGet6HdrFtrInfo */
+
+/*
+ * Translate the rowinfo to a member of the row_info enumeration
+ */
+row_info_enum
+eGet6RowInfo(int iFodo,
+	const UCHAR *aucGrpprl, int iBytes, row_block_type *pRow)
+{
+	int	iFodoOff, iInfoLen;
+	int	iIndex, iSize, iCol;
+	int	iPosCurr, iPosPrev;
+	USHORT	usTmp;
+	BOOL	bFound24_0, bFound24_1, bFound25_0, bFound25_1, bFound190;
+
+	fail(iFodo < 0 || aucGrpprl == NULL || pRow == NULL);
+
+	iFodoOff = 0;
+	bFound24_0 = FALSE;
+	bFound24_1 = FALSE;
+	bFound25_0 = FALSE;
+	bFound25_1 = FALSE;
+	bFound190 = FALSE;
+	while (iBytes >= iFodoOff + 1) {
+		iInfoLen = 0;
+		switch (ucGetByte(iFodo + iFodoOff, aucGrpprl)) {
+		case  24:	/* fInTable */
+			if (odd(ucGetByte(iFodo + iFodoOff + 1, aucGrpprl))) {
+				bFound24_1 = TRUE;
+			} else {
+				bFound24_0 = TRUE;
+			}
+			break;
+		case  25:	/* fTtp */
+			if (odd(ucGetByte(iFodo + iFodoOff + 1, aucGrpprl))) {
+				bFound25_1 = TRUE;
+			} else {
+				bFound25_0 = TRUE;
+			}
+			break;
+		case 38:	/* brcTop */
+			usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
+			usTmp &= 0x0018;
+			NO_DBG_DEC(usTmp >> 3);
+			if (usTmp == 0) {
+				pRow->ucBorderInfo &= ~TABLE_BORDER_TOP;
+			} else {
+				pRow->ucBorderInfo |= TABLE_BORDER_TOP;
+			}
+			break;
+		case 39:	/* brcLeft */
+			usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
+			usTmp &= 0x0018;
+			NO_DBG_DEC(usTmp >> 3);
+			if (usTmp == 0) {
+				pRow->ucBorderInfo &= ~TABLE_BORDER_LEFT;
+			} else {
+				pRow->ucBorderInfo |= TABLE_BORDER_LEFT;
+			}
+			break;
+		case 40:	/* brcBottom */
+			usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
+			usTmp &= 0x0018;
+			NO_DBG_DEC(usTmp >> 3);
+			if (usTmp == 0) {
+				pRow->ucBorderInfo &= ~TABLE_BORDER_BOTTOM;
+			} else {
+				pRow->ucBorderInfo |= TABLE_BORDER_BOTTOM;
+			}
+			break;
+		case 41:	/* brcRight */
+			usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
+			usTmp &= 0x0018;
+			NO_DBG_DEC(usTmp >> 3);
+			if (usTmp == 0) {
+				pRow->ucBorderInfo &= ~TABLE_BORDER_RIGHT;
+			} else {
+				pRow->ucBorderInfo |= TABLE_BORDER_RIGHT;
+			}
+			break;
+		case 188:	/* cDefTable10 */
+			DBG_MSG("188: sprmTDefTable10");
+			iSize = (int)usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
+			DBG_DEC(iSize);
+			break;
+		case 190:	/* cDefTable */
+			iSize = (int)usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
+			if (iSize < 6 || iBytes < iFodoOff + 7) {
+				DBG_DEC(iSize);
+				DBG_DEC(iFodoOff);
+				iInfoLen = 1;
+				break;
+			}
+			iCol = (int)ucGetByte(iFodo + iFodoOff + 3, aucGrpprl);
+			if (iCol < 1 ||
+			    iBytes < iFodoOff + 3 + (iCol + 1) * 2) {
+				DBG_DEC(iCol);
+				DBG_DEC(iFodoOff);
+				iInfoLen = 1;
+				break;
+			}
+			if (iCol >= (int)elementsof(pRow->asColumnWidth)) {
+				DBG_DEC(iCol);
+				werr(1, "The number of columns is corrupt");
+			}
+			pRow->ucNumberOfColumns = (UCHAR)iCol;
+			iPosPrev = (int)(short)usGetWord(
+					iFodo + iFodoOff + 4,
+					aucGrpprl);
+			for (iIndex = 0; iIndex < iCol; iIndex++) {
+				iPosCurr = (int)(short)usGetWord(
+					iFodo + iFodoOff + 6 + iIndex * 2,
+					aucGrpprl);
+				pRow->asColumnWidth[iIndex] =
+						(short)(iPosCurr - iPosPrev);
+				iPosPrev = iPosCurr;
+			}
+			bFound190 = TRUE;
+			break;
+		default:
+			break;
+		}
+		if (iInfoLen <= 0) {
+			iInfoLen =
+				iGet6InfoLength(iFodo + iFodoOff, aucGrpprl);
+			fail(iInfoLen <= 0);
+		}
+		iFodoOff += iInfoLen;
+	}
+
+	if (bFound25_1 && bFound190) {
+		return found_end_of_row;
+	}
+	if (bFound25_0 && !bFound190) {
+		return found_not_end_of_row;
+	}
+	if (bFound24_1) {
+		return found_a_cell;
+	}
+	if (bFound24_0) {
+		return found_not_a_cell;
+	}
+	return found_nothing;
+} /* end of eGet6RowInfo */
+
+/*
+ * Fill the style information block with information
+ * from a Word 6/7 file.
+ */
+void
+vGet6StyleInfo(int iFodo,
+	const UCHAR *aucGrpprl, int iBytes, style_block_type *pStyle)
+{
+	int	iFodoOff, iInfoLen;
+	int	iTmp, iDel, iAdd, iBefore;
+	short	sTmp;
+	UCHAR	ucTmp;
+
+	fail(iFodo < 0 || aucGrpprl == NULL || pStyle == NULL);
+
+	NO_DBG_DEC(pStyle->usIstd);
+
+	iFodoOff = 0;
+	while (iBytes >= iFodoOff + 1) {
+		iInfoLen = 0;
+		switch (ucGetByte(iFodo + iFodoOff, aucGrpprl)) {
+		case   2:	/* istd */
+			sTmp = (short)ucGetByte(
+					iFodo + iFodoOff + 1, aucGrpprl);
+			NO_DBG_DEC(sTmp);
+			break;
+		case   5:	/* jc */
+			pStyle->ucAlignment = ucGetByte(
+					iFodo + iFodoOff + 1, aucGrpprl);
+			break;
+		case  12:	/* anld */
+			iTmp = (int)ucGetByte(
+					iFodo + iFodoOff + 1, aucGrpprl);
+			DBG_DEC_C(iTmp < 52, iTmp);
+			if (iTmp >= 1) {
+				pStyle->ucNFC = ucGetByte(
+					iFodo + iFodoOff + 2, aucGrpprl);
+			}
+			if (pStyle->ucNFC != LIST_BULLETS && iTmp >= 2) {
+				iBefore = (int)ucGetByte(
+					iFodo + iFodoOff + 3, aucGrpprl);
+			} else {
+				iBefore = 0;
+			}
+			if (iTmp >= 12) {
+				pStyle->usStartAt = usGetWord(
+					iFodo + iFodoOff + 12, aucGrpprl);
+			}
+			if (iTmp >= iBefore + 21) {
+				pStyle->usListChar = (USHORT)ucGetByte(
+					iFodo + iFodoOff + iBefore + 22,
+					aucGrpprl);
+				NO_DBG_HEX(pStyle->usListChar);
+			}
+			break;
+		case  13:	/* nLvlAnm */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
+			pStyle->ucNumLevel = ucTmp;
+			pStyle->bNumPause =
+				eGetNumType(ucTmp) == level_type_pause;
+			break;
+		case  15:	/* ChgTabsPapx */
+		case  23:	/* ChgTabs */
+			iTmp = (int)ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
+			if (iTmp < 2) {
+				iInfoLen = 1;
+				break;
+			}
+			NO_DBG_DEC(iTmp);
+			iDel = (int)ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
+			if (iTmp < 2 + 2 * iDel) {
+				iInfoLen = 1;
+				break;
+			}
+			NO_DBG_DEC(iDel);
+			iAdd = (int)ucGetByte(
+				iFodo + iFodoOff + 3 + 2 * iDel, aucGrpprl);
+			if (iTmp < 2 + 2 * iDel + 2 * iAdd) {
+				iInfoLen = 1;
+				break;
+			}
+			NO_DBG_DEC(iAdd);
+			break;
+		case  16:	/* dxaRight */
+			pStyle->sRightIndent = (short)usGetWord(
+					iFodo + iFodoOff + 1, aucGrpprl);
+			NO_DBG_DEC(pStyle->sRightIndent);
+			break;
+		case  17:	/* dxaLeft */
+			pStyle->sLeftIndent = (short)usGetWord(
+					iFodo + iFodoOff + 1, aucGrpprl);
+			NO_DBG_DEC(pStyle->sLeftIndent);
+			break;
+		case  18:	/* Nest dxaLeft */
+			sTmp = (short)usGetWord(
+					iFodo + iFodoOff + 1, aucGrpprl);
+			pStyle->sLeftIndent += sTmp;
+			if (pStyle->sLeftIndent < 0) {
+				pStyle->sLeftIndent = 0;
+			}
+			NO_DBG_DEC(sTmp);
+			NO_DBG_DEC(pStyle->sLeftIndent);
+			break;
+		case  19:	/* dxaLeft1 */
+			pStyle->sLeftIndent1 = (short)usGetWord(
+					iFodo + iFodoOff + 1, aucGrpprl);
+			NO_DBG_DEC(pStyle->sLeftIndent1);
+			break;
+		case  21:	/* dyaBefore */
+			pStyle->usBeforeIndent = usGetWord(
+					iFodo + iFodoOff + 1, aucGrpprl);
+			NO_DBG_DEC(pStyle->usBeforeIndent);
+			break;
+		case  22:	/* dyaAfter */
+			pStyle->usAfterIndent = usGetWord(
+					iFodo + iFodoOff + 1, aucGrpprl);
+			NO_DBG_DEC(pStyle->usAfterIndent);
+			break;
+		default:
+			break;
+		}
+		if (iInfoLen <= 0) {
+			iInfoLen =
+				iGet6InfoLength(iFodo + iFodoOff, aucGrpprl);
+			fail(iInfoLen <= 0);
+		}
+		iFodoOff += iInfoLen;
+	}
+} /* end of vGet6StyleInfo */
+
+/*
+ * Build the lists with Paragraph Information for Word 6/7 files
+ */
+void
+vGet6PapInfo(FILE *pFile, ULONG ulStartBlock,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const UCHAR *aucHeader)
+{
+	row_block_type		tRow;
+	style_block_type	tStyle;
+	USHORT	*ausParfPage;
+	UCHAR	*aucBuffer;
+	ULONG	ulCharPos, ulCharPosFirst, ulCharPosLast;
+	ULONG	ulBeginParfInfo;
+	size_t	tParfInfoLen, tParfPageNum, tOffset, tSize, tLenOld, tLen;
+	size_t	tIndex, tIndex2, tRun;
+	int	iFodo, iLen;
+	row_info_enum	eRowInfo;
+	USHORT	usParfFirstPage, usCount, usIstd;
+	UCHAR	aucFpage[BIG_BLOCK_SIZE];
+
+	fail(pFile == NULL || aucHeader == NULL);
+	fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
+	fail(aulBBD == NULL);
+
+	ulBeginParfInfo = ulGetLong(0xc0, aucHeader); /* fcPlcfbtePapx */
+	NO_DBG_HEX(ulBeginParfInfo);
+	tParfInfoLen = (size_t)ulGetLong(0xc4, aucHeader); /* lcbPlcfbtePapx */
+	NO_DBG_DEC(tParfInfoLen);
+	if (tParfInfoLen < 4) {
+		DBG_DEC(tParfInfoLen);
+		return;
+	}
+
+	aucBuffer = xmalloc(tParfInfoLen);
+	if (!bReadBuffer(pFile, ulStartBlock,
+			aulBBD, tBBDLen, BIG_BLOCK_SIZE,
+			aucBuffer, ulBeginParfInfo, tParfInfoLen)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tParfInfoLen);
+
+	tLen = (tParfInfoLen - 4) / 6;
+	ausParfPage = xcalloc(tLen, sizeof(USHORT));
+	for (tIndex = 0, tOffset = (tLen + 1) * 4;
+	     tIndex < tLen;
+	     tIndex++, tOffset += 2) {
+		 ausParfPage[tIndex] = usGetWord(tOffset, aucBuffer);
+		 NO_DBG_DEC(ausParfPage[tIndex]);
+	}
+	DBG_HEX(ulGetLong(0, aucBuffer));
+	aucBuffer = xfree(aucBuffer);
+	tParfPageNum = (size_t)usGetWord(0x190, aucHeader); /* cpnBtePap */
+	DBG_DEC(tParfPageNum);
+	if (tLen < tParfPageNum) {
+		/* Replace ParfPage by a longer version */
+		tLenOld = tLen;
+		usParfFirstPage = usGetWord(0x18c, aucHeader); /* pnPapFirst */
+		DBG_DEC(usParfFirstPage);
+		tLen += tParfPageNum - 1;
+		tSize = tLen * sizeof(USHORT);
+		ausParfPage = xrealloc(ausParfPage, tSize);
+		/* Add new values */
+		usCount = usParfFirstPage + 1;
+		for (tIndex = tLenOld; tIndex < tLen; tIndex++) {
+			ausParfPage[tIndex] = usCount;
+			NO_DBG_DEC(ausParfPage[tIndex]);
+			usCount++;
+		}
+	}
+
+	(void)memset(&tRow, 0, sizeof(tRow));
+	ulCharPosFirst = CP_INVALID;
+	for (tIndex = 0; tIndex < tLen; tIndex++) {
+		if (!bReadBuffer(pFile, ulStartBlock,
+				aulBBD, tBBDLen, BIG_BLOCK_SIZE,
+				aucFpage,
+				(ULONG)ausParfPage[tIndex] * BIG_BLOCK_SIZE,
+				BIG_BLOCK_SIZE)) {
+			break;
+		}
+		tRun = (size_t)ucGetByte(0x1ff, aucFpage);
+		NO_DBG_DEC(tRun);
+		for (tIndex2 = 0; tIndex2 < tRun; tIndex2++) {
+			NO_DBG_HEX(ulGetLong(tIndex2 * 4, aucFpage));
+			iFodo = 2 * (int)ucGetByte(
+				(tRun + 1) * 4 + tIndex2 * 7, aucFpage);
+			if (iFodo <= 0) {
+				continue;
+			}
+
+			iLen = 2 * (int)ucGetByte(iFodo, aucFpage);
+
+			usIstd = (USHORT)ucGetByte(iFodo + 1, aucFpage);
+			vFillStyleFromStylesheet(usIstd, &tStyle);
+			vGet6StyleInfo(iFodo, aucFpage + 3, iLen - 3, &tStyle);
+			ulCharPos = ulGetLong(tIndex2 * 4, aucFpage);
+			NO_DBG_HEX(ulCharPos);
+			tStyle.ulFileOffset = ulCharPos2FileOffsetX(
+				ulCharPos, &tStyle.eListID);
+			vAdd2StyleInfoList(&tStyle);
+
+			eRowInfo = eGet6RowInfo(iFodo,
+					aucFpage + 3, iLen - 3, &tRow);
+			switch(eRowInfo) {
+			case found_a_cell:
+				if (ulCharPosFirst != CP_INVALID) {
+					break;
+				}
+				ulCharPosFirst = ulGetLong(
+						tIndex2 * 4, aucFpage);
+				NO_DBG_HEX(ulCharPosFirst);
+				tRow.ulCharPosStart = ulCharPosFirst;
+				tRow.ulFileOffsetStart =
+					ulCharPos2FileOffset(ulCharPosFirst);
+				DBG_HEX_C(tRow.ulFileOffsetStart == FC_INVALID,
+							ulCharPosFirst);
+				break;
+			case found_end_of_row:
+				ulCharPosLast = ulGetLong(
+						tIndex2 * 4, aucFpage);
+				NO_DBG_HEX(ulCharPosLast);
+				tRow.ulCharPosEnd = ulCharPosLast;
+				tRow.ulFileOffsetEnd =
+					ulCharPos2FileOffset(ulCharPosLast);
+				DBG_HEX_C(tRow.ulFileOffsetEnd == FC_INVALID,
+							ulCharPosLast);
+				vAdd2RowInfoList(&tRow);
+				(void)memset(&tRow, 0, sizeof(tRow));
+				ulCharPosFirst = CP_INVALID;
+				break;
+			case found_nothing:
+				break;
+			default:
+				DBG_DEC(eRowInfo);
+				break;
+			}
+		}
+	}
+	ausParfPage = xfree(ausParfPage);
+} /* end of vGet6PapInfo */
+
+/*
+ * Fill the font information block with information
+ * from a Word 6/7 file.
+ * Returns TRUE when successful, otherwise FALSE
+ */
+void
+vGet6FontInfo(int iFodo, USHORT usIstd,
+	const UCHAR *aucGrpprl, int iBytes, font_block_type *pFont)
+{
+	long	lTmp;
+	int	iFodoOff, iInfoLen;
+	USHORT	usTmp;
+	UCHAR	ucTmp;
+
+	TRACE_MSG("vGet6FontInfo");
+
+	fail(iFodo < 0 || aucGrpprl == NULL || pFont == NULL);
+
+	iFodoOff = 0;
+	while (iBytes >= iFodoOff + 1) {
+		switch (ucGetByte(iFodo + iFodoOff, aucGrpprl)) {
+		case  65:	/* fRMarkDel */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
+			if (ucTmp == 0) {
+				pFont->usFontStyle &= ~FONT_MARKDEL;
+			} else {
+				pFont->usFontStyle |= FONT_MARKDEL;
+			}
+			break;
+		case  80:	/* cIstd */
+			usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
+			NO_DBG_DEC(usTmp);
+			break;
+		case  82:	/* cDefault */
+			pFont->usFontStyle &= FONT_HIDDEN;
+			pFont->ucFontColor = FONT_COLOR_DEFAULT;
+			break;
+		case  83:	/* cPlain */
+			DBG_MSG("83: cPlain");
+			vFillFontFromStylesheet(usIstd, pFont);
+			break;
+		case  85:	/* fBold */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
+			switch (ucTmp) {
+			case   0:	/* Unset */
+				pFont->usFontStyle &= ~FONT_BOLD;
+				break;
+			case   1:	/* Set */
+				pFont->usFontStyle |= FONT_BOLD;
+				break;
+			case 128:	/* Unchanged */
+				break;
+			case 129:	/* Negation */
+				pFont->usFontStyle ^= FONT_BOLD;
+				break;
+			default:
+				DBG_DEC(ucTmp);
+				DBG_FIXME();
+				break;
+			}
+			break;
+		case  86:	/* fItalic */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
+			switch (ucTmp) {
+			case   0:	/* Unset */
+				pFont->usFontStyle &= ~FONT_ITALIC;
+				break;
+			case   1:	/* Set */
+				pFont->usFontStyle |= FONT_ITALIC;
+				break;
+			case 128:	/* Unchanged */
+				break;
+			case 129:	/* Negation */
+				pFont->usFontStyle ^= FONT_ITALIC;
+				break;
+			default:
+				DBG_DEC(ucTmp);
+				DBG_FIXME();
+				break;
+			}
+			break;
+		case  87:	/* fStrike */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
+			switch (ucTmp) {
+			case   0:	/* Unset */
+				pFont->usFontStyle &= ~FONT_STRIKE;
+				break;
+			case   1:	/* Set */
+				pFont->usFontStyle |= FONT_STRIKE;
+				break;
+			case 128:	/* Unchanged */
+				break;
+			case 129:	/* Negation */
+				pFont->usFontStyle ^= FONT_STRIKE;
+				break;
+			default:
+				DBG_DEC(ucTmp);
+				DBG_FIXME();
+				break;
+			}
+			break;
+		case  90:	/* fSmallCaps */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
+			switch (ucTmp) {
+			case   0:	/* Unset */
+				pFont->usFontStyle &= ~FONT_SMALL_CAPITALS;
+				break;
+			case   1:	/* Set */
+				pFont->usFontStyle |= FONT_SMALL_CAPITALS;
+				break;
+			case 128:	/* Unchanged */
+				break;
+			case 129:	/* Negation */
+				pFont->usFontStyle ^= FONT_SMALL_CAPITALS;
+				break;
+			default:
+				DBG_DEC(ucTmp);
+				DBG_FIXME();
+				break;
+			}
+			break;
+		case  91:	/* fCaps */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
+			switch (ucTmp) {
+			case   0:	/* Unset */
+				pFont->usFontStyle &= ~FONT_CAPITALS;
+				break;
+			case   1:	/* Set */
+				pFont->usFontStyle |= FONT_CAPITALS;
+				break;
+			case 128:	/* Unchanged */
+				break;
+			case 129:	/* Negation */
+				pFont->usFontStyle ^= FONT_CAPITALS;
+				break;
+			default:
+				DBG_DEC(ucTmp);
+				DBG_FIXME();
+				break;
+			}
+			break;
+		case  92:	/* fVanish */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
+			switch (ucTmp) {
+			case   0:	/* Unset */
+				pFont->usFontStyle &= ~FONT_HIDDEN;
+				break;
+			case   1:	/* Set */
+				pFont->usFontStyle |= FONT_HIDDEN;
+				break;
+			case 128:	/* Unchanged */
+				break;
+			case 129:	/* Negation */
+				pFont->usFontStyle ^= FONT_HIDDEN;
+				break;
+			default:
+				DBG_DEC(ucTmp);
+				DBG_FIXME();
+				break;
+			}
+			break;
+		case  93:	/* cFtc */
+			usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
+			if (usTmp <= (USHORT)UCHAR_MAX) {
+				pFont->ucFontNumber = (UCHAR)usTmp;
+			} else {
+				DBG_DEC(usTmp);
+				DBG_FIXME();
+				pFont->ucFontNumber = 0;
+			}
+			break;
+		case  94:	/* cKul */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
+			if (ucTmp == 0 || ucTmp == 5) {
+				pFont->usFontStyle &= ~FONT_UNDERLINE;
+			} else {
+				NO_DBG_MSG("Underline text");
+				pFont->usFontStyle |= FONT_UNDERLINE;
+				if (ucTmp == 6) {
+					DBG_MSG("Bold text");
+					pFont->usFontStyle |= FONT_BOLD;
+				}
+			}
+			break;
+		case  95:	/* cHps, cHpsPos */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
+			DBG_DEC(ucTmp);
+			if (ucTmp != 0) {
+				pFont->usFontSize = (USHORT)ucTmp;
+			}
+			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
+			DBG_DEC(ucTmp);
+			break;
+		case  98:	/* cIco */
+			pFont->ucFontColor =
+				ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
+			break;
+		case  99:	/* cHps */
+			pFont->usFontSize =
+				usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
+			break;
+		case 100:	/* cHpsInc */
+			DBG_MSG("100: sprmCHpsInc");
+			ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
+			DBG_DEC(ucTmp);
+			break;
+		case 103:	/* cMajority */
+			DBG_MSG("103: sprmCMajority");
+			break;
+		case 104:	/* cIss */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
+			ucTmp &= 0x07;
+			if (ucTmp == 1) {
+				pFont->usFontStyle |= FONT_SUPERSCRIPT;
+				NO_DBG_MSG("Superscript");
+			} else if (ucTmp == 2) {
+				pFont->usFontStyle |= FONT_SUBSCRIPT;
+				NO_DBG_MSG("Subscript");
+			}
+			break;
+		case 106:	/* cHpsInc1 */
+			usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
+			lTmp = (long)pFont->usFontSize + (long)usTmp;
+			if (lTmp < 8) {
+				pFont->usFontSize = 8;
+			} else if (lTmp > 32766) {
+				pFont->usFontSize = 32766;
+			} else {
+				pFont->usFontSize = (USHORT)lTmp;
+			}
+			break;
+		case 108:	/* cMajority50 */
+			DBG_MSG("108: sprmCMajority50");
+			break;
+		case 109:	/* cHpsMul */
+			DBG_MSG("109: sprmCHpsMul");
+			usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
+			DBG_DEC(usTmp);
+			break;
+		default:
+			break;
+		}
+		iInfoLen = iGet6InfoLength(iFodo + iFodoOff, aucGrpprl);
+		fail(iInfoLen <= 0);
+		iFodoOff += iInfoLen;
+	}
+} /* end of vGet6FontInfo */
+
+/*
+ * Fill the picture information block with information
+ * from a Word 6/7 file.
+ * Returns TRUE when successful, otherwise FALSE
+ */
+static BOOL
+bGet6PicInfo(int iFodo,
+	const UCHAR *aucGrpprl, int iBytes, picture_block_type *pPicture)
+{
+	int	iFodoOff, iInfoLen;
+	BOOL	bFound;
+	UCHAR	ucTmp;
+
+	TRACE_MSG("vGet6PicInfo");
+
+	fail(iFodo < 0 || aucGrpprl == NULL || pPicture == NULL);
+
+	iFodoOff = 0;
+	bFound = FALSE;
+	while (iBytes >= iFodoOff + 1) {
+		switch (ucGetByte(iFodo + iFodoOff, aucGrpprl)) {
+		case  68:	/* fcPic */
+			pPicture->ulPictureOffset = ulGetLong(
+					iFodo + iFodoOff + 2, aucGrpprl);
+			bFound = TRUE;
+			break;
+#if 0
+		case  71:	/* fData */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
+			if (ucTmp == 0x01) {
+				/* Not a picture, but a form field */
+				return FALSE;
+			}
+			DBG_DEC_C(ucTmp != 0, ucTmp);
+			break;
+#endif
+		case  75:	/* fOle2 */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
+			if (ucTmp == 0x01) {
+				/* Not a picture, but an OLE object */
+				return FALSE;
+			}
+			DBG_DEC_C(ucTmp != 0, ucTmp);
+			break;
+		default:
+			break;
+		}
+		iInfoLen = iGet6InfoLength(iFodo + iFodoOff, aucGrpprl);
+		fail(iInfoLen <= 0);
+		iFodoOff += iInfoLen;
+	}
+	return bFound;
+} /* end of bGet6PicInfo */
+
+/*
+ * Build the lists with Character Information for Word 6/7 files
+ */
+void
+vGet6ChrInfo(FILE *pFile, ULONG ulStartBlock,
+	const ULONG *aulBBD, size_t tBBDLen, const UCHAR *aucHeader)
+{
+	font_block_type		tFont;
+	picture_block_type	tPicture;
+	USHORT	*ausCharPage;
+	UCHAR	*aucBuffer;
+	ULONG	ulFileOffset, ulCharPos, ulBeginCharInfo;
+	size_t	tCharInfoLen, tOffset, tSize, tLenOld, tLen, tCharPageNum;
+	size_t	tIndex, tIndex2, tRun;
+	int	iFodo, iLen;
+	USHORT	usCharFirstPage, usCount, usIstd;
+	UCHAR	aucFpage[BIG_BLOCK_SIZE];
+
+	fail(pFile == NULL || aucHeader == NULL);
+	fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
+	fail(aulBBD == NULL);
+
+	ulBeginCharInfo = ulGetLong(0xb8, aucHeader); /* fcPlcfbteChpx */
+	NO_DBG_HEX(lBeginCharInfo);
+	tCharInfoLen = (size_t)ulGetLong(0xbc, aucHeader); /* lcbPlcfbteChpx */
+	NO_DBG_DEC(tCharInfoLen);
+	if (tCharInfoLen < 4) {
+		DBG_DEC(tCharInfoLen);
+		return;
+	}
+
+	aucBuffer = xmalloc(tCharInfoLen);
+	if (!bReadBuffer(pFile, ulStartBlock,
+			aulBBD, tBBDLen, BIG_BLOCK_SIZE,
+			aucBuffer, ulBeginCharInfo, tCharInfoLen)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+
+	tLen = (tCharInfoLen - 4) / 6;
+	ausCharPage = xcalloc(tLen, sizeof(USHORT));
+	for (tIndex = 0, tOffset = (tLen + 1) * 4;
+	     tIndex < tLen;
+	     tIndex++, tOffset += 2) {
+		 ausCharPage[tIndex] = usGetWord(tOffset, aucBuffer);
+		 NO_DBG_DEC(ausCharPage[tIndex]);
+	}
+	DBG_HEX(ulGetLong(0, aucBuffer));
+	aucBuffer = xfree(aucBuffer);
+	tCharPageNum = (size_t)usGetWord(0x18e, aucHeader); /* cpnBteChp */
+	DBG_DEC(tCharPageNum);
+	if (tLen < tCharPageNum) {
+		/* Replace CharPage by a longer version */
+		tLenOld = tLen;
+		usCharFirstPage = usGetWord(0x18a, aucHeader); /* pnChrFirst */
+		DBG_DEC(usCharFirstPage);
+		tLen += tCharPageNum - 1;
+		tSize = tLen * sizeof(USHORT);
+		ausCharPage = xrealloc(ausCharPage, tSize);
+		/* Add new values */
+		usCount = usCharFirstPage + 1;
+		for (tIndex = tLenOld; tIndex < tLen; tIndex++) {
+			ausCharPage[tIndex] = usCount;
+			NO_DBG_DEC(ausCharPage[tIndex]);
+			usCount++;
+		}
+	}
+
+	for (tIndex = 0; tIndex < tLen; tIndex++) {
+		if (!bReadBuffer(pFile, ulStartBlock,
+				aulBBD, tBBDLen, BIG_BLOCK_SIZE,
+				aucFpage,
+				(ULONG)ausCharPage[tIndex] * BIG_BLOCK_SIZE,
+				BIG_BLOCK_SIZE)) {
+			break;
+		}
+		tRun = (size_t)ucGetByte(0x1ff, aucFpage);
+		NO_DBG_DEC(tRun);
+		for (tIndex2 = 0; tIndex2 < tRun; tIndex2++) {
+		  	ulCharPos = ulGetLong(tIndex2 * 4, aucFpage);
+			ulFileOffset = ulCharPos2FileOffset(ulCharPos);
+			iFodo = 2 * (int)ucGetByte(
+				(tRun + 1) * 4 + tIndex2, aucFpage);
+
+			iLen = (int)ucGetByte(iFodo, aucFpage);
+
+			usIstd = usGetIstd(ulFileOffset);
+			vFillFontFromStylesheet(usIstd, &tFont);
+			if (iFodo != 0) {
+				vGet6FontInfo(iFodo, usIstd,
+					aucFpage + 1, iLen - 1, &tFont);
+			}
+			tFont.ulFileOffset = ulFileOffset;
+			vAdd2FontInfoList(&tFont);
+
+			if (iFodo <= 0) {
+				continue;
+			}
+
+			(void)memset(&tPicture, 0, sizeof(tPicture));
+			if (bGet6PicInfo(iFodo, aucFpage + 1,
+						iLen - 1, &tPicture)) {
+				tPicture.ulFileOffset = ulFileOffset;
+				tPicture.ulFileOffsetPicture =
+					ulDataPos2FileOffset(
+						tPicture.ulPictureOffset);
+				vAdd2PictInfoList(&tPicture);
+			}
+		}
+	}
+	ausCharPage = xfree(ausCharPage);
+} /* end of vGet6ChrInfo */
diff --git a/prop8.c b/prop8.c
new file mode 100644
index 0000000..c31204e
--- /dev/null
+++ b/prop8.c
@@ -0,0 +1,1496 @@
+/*
+ * prop8.c
+ * Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Read the property information from a MS Word 8, 9,10 or 11 file
+ *
+ * Word  8 is better known as Word 97 or as Word 98 for Mac
+ * Word  9 is better known as Word 2000 or as Word 2001 for Mac
+ * Word 10 is better known as Word 2002 or as Word XP
+ * Word 11 is better known as Word 2003
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "antiword.h"
+
+#define DEFAULT_LISTCHAR	0x002e	/* A full stop */
+
+
+/*
+ * iGet8InfoLength - the length of the information for Word 8/9/10/11 files
+ */
+static int
+iGet8InfoLength(int iByteNbr, const UCHAR *aucGrpprl)
+{
+	int	iTmp, iDel, iAdd;
+	USHORT	usOpCode;
+
+	usOpCode = usGetWord(iByteNbr, aucGrpprl);
+
+	switch (usOpCode & 0xe000) {
+	case 0x0000: case 0x2000:
+		return 3;
+	case 0x4000: case 0x8000: case 0xa000:
+		return 4;
+	case 0xe000:
+		return 5;
+	case 0x6000:
+		return 6;
+	case 0xc000:
+		iTmp = (int)ucGetByte(iByteNbr + 2, aucGrpprl);
+		if (usOpCode == 0xc615 && iTmp == 255) {
+			iDel = (int)ucGetByte(iByteNbr + 3, aucGrpprl);
+			iAdd = (int)ucGetByte(
+					iByteNbr + 4 + iDel * 4, aucGrpprl);
+			iTmp = 2 + iDel * 4 + iAdd * 3;
+		}
+		return 3 + iTmp;
+	default:
+		DBG_HEX(usOpCode);
+		DBG_FIXME();
+		return 1;
+	}
+} /* end of iGet8InfoLength */
+
+/*
+ * aucFillInfoBuffer - fill the information buffer
+ *
+ * Returns the information buffer when successful, otherwise NULL
+ */
+static UCHAR *
+aucFillInfoBuffer(FILE *pFile, const pps_type *pTable,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const ULONG *aulSBD, size_t tSBDLen,
+	ULONG ulBeginInfo, size_t tInfoLen)
+{
+	const ULONG	*aulBlockDepot;
+	UCHAR	*aucBuffer;
+	size_t	tBlockDepotLen, tBlockSize;
+
+	fail(pFile == NULL || pTable == NULL);
+	fail(aulBBD == NULL || aulSBD == NULL);
+	fail(tInfoLen == 0);
+
+	NO_DBG_DEC(pTable->ulSB);
+	NO_DBG_HEX(pTable->ulSize);
+	if (pTable->ulSize == 0) {
+		DBG_MSG("No information");
+		return NULL;
+	}
+
+	if (pTable->ulSize < MIN_SIZE_FOR_BBD_USE) {
+		/* Use the Small Block Depot */
+		aulBlockDepot = aulSBD;
+		tBlockDepotLen = tSBDLen;
+		tBlockSize = SMALL_BLOCK_SIZE;
+	} else {
+		/* Use the Big Block Depot */
+		aulBlockDepot = aulBBD;
+		tBlockDepotLen = tBBDLen;
+		tBlockSize = BIG_BLOCK_SIZE;
+	}
+	aucBuffer = xmalloc(tInfoLen);
+	if (!bReadBuffer(pFile, pTable->ulSB,
+			aulBlockDepot, tBlockDepotLen, tBlockSize,
+			aucBuffer, ulBeginInfo, tInfoLen)) {
+		aucBuffer = xfree(aucBuffer);
+		return NULL;
+	}
+	return aucBuffer;
+} /* end of aucFillInfoBuffer */
+
+/*
+ * Build the lists with Document Property Information for Word 8/9/10/11 files
+ */
+void
+vGet8DopInfo(FILE *pFile, const pps_type *pTable,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const ULONG *aulSBD, size_t tSBDLen,
+	const UCHAR *aucHeader)
+{
+	document_block_type	tDocument;
+	UCHAR	*aucBuffer;
+	ULONG	ulBeginDocpInfo, ulTmp;
+	size_t	tDocpInfoLen;
+	USHORT	usTmp;
+
+	fail(pFile == NULL || pTable == NULL || aucHeader == NULL);
+	fail(aulBBD == NULL || aulSBD == NULL);
+
+	ulBeginDocpInfo = ulGetLong(0x192, aucHeader); /* fcDop */
+	NO_DBG_HEX(ulBeginSectInfo);
+	tDocpInfoLen = (size_t)ulGetLong(0x196, aucHeader); /* lcbDop */
+	NO_DBG_DEC(tSectInfoLen);
+	if (tDocpInfoLen < 28) {
+		DBG_MSG("No Document information");
+		return;
+	}
+
+	aucBuffer = aucFillInfoBuffer(pFile, pTable,
+			aulBBD, tBBDLen, aulSBD, tSBDLen,
+			ulBeginDocpInfo, tDocpInfoLen);
+	if (aucBuffer == NULL) {
+		return;
+	}
+
+	usTmp = usGetWord(0x00, aucBuffer);
+	tDocument.ucHdrFtrSpecification = (UCHAR)(usTmp >> 8); /* grpfIhdt */
+	tDocument.usDefaultTabWidth = usGetWord(0x0a, aucBuffer); /* dxaTab */
+	ulTmp = ulGetLong(0x14, aucBuffer); /* dttmCreated */
+	tDocument.tCreateDate = tConvertDTTM(ulTmp);
+	ulTmp = ulGetLong(0x18, aucBuffer); /* dttmRevised */
+	tDocument.tRevisedDate = tConvertDTTM(ulTmp);
+	vCreateDocumentInfoList(&tDocument);
+
+	aucBuffer = xfree(aucBuffer);
+} /* end of vGet8DopInfo */
+
+/*
+ * Fill the section information block with information
+ * from a Word 8/9/10/11 file.
+ */
+static void
+vGet8SectionInfo(const UCHAR *aucGrpprl, size_t tBytes,
+		section_block_type *pSection)
+{
+	UINT	uiIndex;
+	int	iFodoOff, iInfoLen, iSize, iTmp;
+	USHORT	usCcol;
+	UCHAR	ucTmp;
+
+	fail(aucGrpprl == NULL || pSection == NULL);
+
+	iFodoOff = 0;
+	while (tBytes >= (size_t)iFodoOff + 2) {
+		iInfoLen = 0;
+		switch (usGetWord(iFodoOff, aucGrpprl)) {
+		case 0x3009:	/* bkc */
+			ucTmp = ucGetByte(iFodoOff + 2, aucGrpprl);
+			DBG_DEC(ucTmp);
+			pSection->bNewPage = ucTmp != 0 && ucTmp != 1;
+			break;
+		case 0x3014:	/* grpfIhdt */
+			pSection->ucHdrFtrSpecification =
+					ucGetByte(iFodoOff + 2, aucGrpprl);
+			break;
+		case 0x500b:	/* ccolM1 */
+			usCcol = 1 + usGetWord(iFodoOff + 2, aucGrpprl);
+			DBG_DEC(usCcol);
+			break;
+		case 0xd202:	/* olstAnm */
+			iSize = (int)ucGetByte(iFodoOff + 2, aucGrpprl);
+			DBG_DEC_C(iSize != 212, iSize);
+			for (uiIndex = 0, iTmp = iFodoOff + 3;
+			     uiIndex < 9 && iTmp < iFodoOff + 3 + iSize - 15;
+			     uiIndex++, iTmp += 16) {
+				pSection->aucNFC[uiIndex] =
+						ucGetByte(iTmp, aucGrpprl);
+				DBG_DEC(pSection->aucNFC[uiIndex]);
+				ucTmp = ucGetByte(iTmp + 3, aucGrpprl);
+				DBG_HEX(ucTmp);
+				if ((ucTmp & BIT(2)) != 0) {
+					pSection->usNeedPrevLvl |=
+							(USHORT)BIT(uiIndex);
+				}
+				if ((ucTmp & BIT(3)) != 0) {
+					pSection->usHangingIndent |=
+							(USHORT)BIT(uiIndex);
+				}
+			}
+			DBG_HEX(pSection->usNeedPrevLvl);
+			DBG_HEX(pSection->usHangingIndent);
+			break;
+		default:
+			break;
+		}
+		if (iInfoLen <= 0) {
+			iInfoLen = iGet8InfoLength(iFodoOff, aucGrpprl);
+			fail(iInfoLen <= 0);
+		}
+		iFodoOff += iInfoLen;
+	}
+} /* end of vGet8SectionInfo */
+
+/*
+ * Build the lists with Section Property Information for Word 8/9/10/11 files
+ */
+void
+vGet8SepInfo(FILE *pFile, const pps_info_type *pPPS,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const ULONG *aulSBD, size_t tSBDLen,
+	const UCHAR *aucHeader)
+{
+	section_block_type	tSection;
+	ULONG	*aulSectPage, *aulCharPos;
+	UCHAR	*aucBuffer, *aucFpage;
+	ULONG	ulBeginOfText, ulTextOffset, ulBeginSectInfo;
+	size_t	tSectInfoLen, tIndex, tOffset, tLen, tBytes;
+	UCHAR	aucTmp[2];
+
+	fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
+	fail(aulBBD == NULL || aulSBD == NULL);
+
+	ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
+	NO_DBG_HEX(ulBeginOfText);
+	ulBeginSectInfo = ulGetLong(0xca, aucHeader); /* fcPlcfsed */
+	NO_DBG_HEX(ulBeginSectInfo);
+	tSectInfoLen = (size_t)ulGetLong(0xce, aucHeader); /* lcbPlcfsed */
+	NO_DBG_DEC(tSectInfoLen);
+	if (tSectInfoLen < 4) {
+		DBG_DEC(tSectInfoLen);
+		return;
+	}
+
+	aucBuffer = aucFillInfoBuffer(pFile, &pPPS->tTable,
+			aulBBD, tBBDLen, aulSBD, tSBDLen,
+			ulBeginSectInfo, tSectInfoLen);
+	if (aucBuffer == NULL) {
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tSectInfoLen);
+
+	/* Read the Section Descriptors */
+	tLen = (tSectInfoLen - 4) / 16;
+	/* Save the section offsets */
+	aulCharPos = xcalloc(tLen, sizeof(ULONG));
+	for (tIndex = 0, tOffset = 0;
+	     tIndex < tLen;
+	     tIndex++, tOffset += 4) {
+		ulTextOffset = ulGetLong(tOffset, aucBuffer);
+		NO_DBG_HEX(ulTextOffset);
+		aulCharPos[tIndex] = ulBeginOfText + ulTextOffset;
+		NO_DBG_HEX(aulCharPos[tIndex]);
+	}
+	/* Save the Sepx offsets */
+	aulSectPage = xcalloc(tLen, sizeof(ULONG));
+	for (tIndex = 0, tOffset = (tLen + 1) * 4;
+	     tIndex < tLen;
+	     tIndex++, tOffset += 12) {
+		 aulSectPage[tIndex] = ulGetLong(tOffset + 2, aucBuffer);
+		 NO_DBG_HEX(aulSectPage[tIndex]); /* fcSepx */
+	}
+	aucBuffer = xfree(aucBuffer);
+
+	/* Read the Section Properties */
+	for (tIndex = 0; tIndex < tLen; tIndex++) {
+		if (aulSectPage[tIndex] == FC_INVALID) {
+			vDefault2SectionInfoList(aulCharPos[tIndex]);
+			continue;
+		}
+		/* Get the number of bytes to read */
+		if (!bReadBuffer(pFile, pPPS->tWordDocument.ulSB,
+				aulBBD, tBBDLen, BIG_BLOCK_SIZE,
+				aucTmp, aulSectPage[tIndex], 2)) {
+			continue;
+		}
+		tBytes = 2 + (size_t)usGetWord(0, aucTmp);
+		NO_DBG_DEC(tBytes);
+		/* Read the bytes */
+		aucFpage = xmalloc(tBytes);
+		if (!bReadBuffer(pFile, pPPS->tWordDocument.ulSB,
+				aulBBD, tBBDLen, BIG_BLOCK_SIZE,
+				aucFpage, aulSectPage[tIndex], tBytes)) {
+			aucFpage = xfree(aucFpage);
+			continue;
+		}
+		NO_DBG_PRINT_BLOCK(aucFpage, tBytes);
+		/* Process the bytes */
+		vGetDefaultSection(&tSection);
+		vGet8SectionInfo(aucFpage + 2, tBytes - 2, &tSection);
+		vAdd2SectionInfoList(&tSection, aulCharPos[tIndex]);
+		aucFpage = xfree(aucFpage);
+	}
+	aulCharPos = xfree(aulCharPos);
+	aulSectPage = xfree(aulSectPage);
+} /* end of vGet8SepInfo */
+
+/*
+ * Build the list with Header/Footer Information for Word 8/9/10/11 files
+ */
+void
+vGet8HdrFtrInfo(FILE *pFile, const pps_type *pTable,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const ULONG *aulSBD, size_t tSBDLen,
+	const UCHAR *aucHeader)
+{
+	ULONG	*aulCharPos;
+	UCHAR	*aucBuffer;
+	ULONG	ulHdrFtrOffset, ulBeginHdrFtrInfo;
+	size_t	tHdrFtrInfoLen, tIndex, tOffset, tLen;
+
+	fail(pFile == NULL || pTable == NULL || aucHeader == NULL);
+	fail(aulBBD == NULL || aulSBD == NULL);
+
+	ulBeginHdrFtrInfo = ulGetLong(0xf2, aucHeader); /* fcPlcfhdd */
+	NO_DBG_HEX(ulBeginHdrFtrInfo);
+	tHdrFtrInfoLen = (size_t)ulGetLong(0xf6, aucHeader); /* lcbPlcfhdd */
+	NO_DBG_DEC(tHdrFtrInfoLen);
+	if (tHdrFtrInfoLen < 8) {
+		DBG_DEC_C(tHdrFtrInfoLen != 0, tHdrFtrInfoLen);
+		return;
+	}
+
+	aucBuffer = aucFillInfoBuffer(pFile, pTable,
+			aulBBD, tBBDLen, aulSBD, tSBDLen,
+			ulBeginHdrFtrInfo, tHdrFtrInfoLen);
+	if (aucBuffer == NULL) {
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tHdrFtrInfoLen);
+
+	tLen = tHdrFtrInfoLen / 4 - 1;
+	DBG_DEC_C(tLen % 12 != 1 && tLen % 12 != 7, tLen);
+	/* Save the header/footer offsets */
+	aulCharPos = xcalloc(tLen, sizeof(ULONG));
+	for (tIndex = 0, tOffset = 0;
+	     tIndex < tLen;
+	     tIndex++, tOffset += 4) {
+		ulHdrFtrOffset = ulGetLong(tOffset, aucBuffer);
+		NO_DBG_HEX(ulHdrFtrOffset);
+		aulCharPos[tIndex] = ulHdrFtrOffset2CharPos(ulHdrFtrOffset);
+		NO_DBG_HEX(aulCharPos[tIndex]);
+	}
+	vCreat8HdrFtrInfoList(aulCharPos, tLen);
+	/* Clean up and leave */
+	aulCharPos = xfree(aulCharPos);
+	aucBuffer = xfree(aucBuffer);
+} /* end of vGet8HdrFtrInfo */
+
+/*
+ * Translate the rowinfo to a member of the row_info enumeration
+ */
+row_info_enum
+eGet8RowInfo(int iFodo,
+	const UCHAR *aucGrpprl, int iBytes, row_block_type *pRow)
+{
+	int	iFodoOff, iInfoLen;
+	int	iIndex, iSize, iCol;
+	int	iPosCurr, iPosPrev;
+	USHORT	usTmp;
+	BOOL	bFound2416_0, bFound2416_1, bFound2417_0, bFound2417_1;
+	BOOL	bFound244b_0, bFound244b_1, bFound244c_0, bFound244c_1;
+	BOOL	bFoundd608;
+
+	fail(iFodo < 0 || aucGrpprl == NULL || pRow == NULL);
+
+	iFodoOff = 0;
+	bFound2416_0 = FALSE;
+	bFound2416_1 = FALSE;
+	bFound2417_0 = FALSE;
+	bFound2417_1 = FALSE;
+	bFound244b_0 = FALSE;
+	bFound244b_1 = FALSE;
+	bFound244c_0 = FALSE;
+	bFound244c_1 = FALSE;
+	bFoundd608 = FALSE;
+	while (iBytes >= iFodoOff + 2) {
+		iInfoLen = 0;
+		switch (usGetWord(iFodo + iFodoOff, aucGrpprl)) {
+		case 0x2416:	/* fInTable */
+			if (odd(ucGetByte(iFodo + iFodoOff + 2, aucGrpprl))) {
+				bFound2416_1 = TRUE;
+			} else {
+				bFound2416_0 = TRUE;
+			}
+			break;
+		case 0x2417:	/* fTtp */
+			if (odd(ucGetByte(iFodo + iFodoOff + 2, aucGrpprl))) {
+				bFound2417_1 = TRUE;
+			} else {
+				bFound2417_0 = TRUE;
+			}
+			break;
+		case 0x244b:	/* sub-table fInTable */
+			if (odd(ucGetByte(iFodo + iFodoOff + 2, aucGrpprl))) {
+				bFound244b_1 = TRUE;
+			} else {
+				bFound244b_0 = TRUE;
+			}
+			break;
+		case 0x244c:	/* sub-table fTtp */
+			if (odd(ucGetByte(iFodo + iFodoOff + 2, aucGrpprl))) {
+				bFound244c_1 = TRUE;
+			} else {
+				bFound244c_0 = TRUE;
+			}
+			break;
+		case 0x6424:	/* brcTop */
+			usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
+			usTmp &= 0xff00;
+			NO_DBG_DEC(usTmp >> 8);
+			if (usTmp == 0) {
+				pRow->ucBorderInfo &= ~TABLE_BORDER_TOP;
+			} else {
+				pRow->ucBorderInfo |= TABLE_BORDER_TOP;
+			}
+			break;
+		case 0x6425:	/* brcLeft */
+			usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
+			usTmp &= 0xff00;
+			NO_DBG_DEC(usTmp >> 8);
+			if (usTmp == 0) {
+				pRow->ucBorderInfo &= ~TABLE_BORDER_LEFT;
+			} else {
+				pRow->ucBorderInfo |= TABLE_BORDER_LEFT;
+			}
+			break;
+		case 0x6426:	/* brcBottom */
+			usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
+			usTmp &= 0xff00;
+			NO_DBG_DEC(usTmp >> 8);
+			if (usTmp == 0) {
+				pRow->ucBorderInfo &= ~TABLE_BORDER_BOTTOM;
+			} else {
+				pRow->ucBorderInfo |= TABLE_BORDER_BOTTOM;
+			}
+			break;
+		case 0x6427:	/* brcRight */
+			usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
+			usTmp &= 0xff00;
+			NO_DBG_DEC(usTmp >> 8);
+			if (usTmp == 0) {
+				pRow->ucBorderInfo &= ~TABLE_BORDER_RIGHT;
+			} else {
+				pRow->ucBorderInfo |= TABLE_BORDER_RIGHT;
+			}
+			break;
+		case 0xd606:	/* cDefTable10 */
+			DBG_MSG("0xd606: sprmTDefTable10");
+			iSize = (int)usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
+			DBG_DEC(iSize);
+			break;
+		case 0xd608:	/* cDefTable */
+			iSize = (int)usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
+			if (iSize < 6 || iBytes < iFodoOff + 8) {
+				DBG_DEC(iSize);
+				DBG_DEC(iFodoOff);
+				iInfoLen = 2;
+				break;
+			}
+			iCol = (int)ucGetByte(iFodo + iFodoOff + 4, aucGrpprl);
+			if (iCol < 1 ||
+			    iBytes < iFodoOff + 4 + (iCol + 1) * 2) {
+				DBG_DEC(iCol);
+				DBG_DEC(iFodoOff);
+				iInfoLen = 2;
+				break;
+			}
+			if (iCol >= (int)elementsof(pRow->asColumnWidth)) {
+				DBG_DEC(iCol);
+				werr(1, "The number of columns is corrupt");
+			}
+			pRow->ucNumberOfColumns = (UCHAR)iCol;
+			iPosPrev = (int)(short)usGetWord(
+					iFodo + iFodoOff + 5,
+					aucGrpprl);
+			for (iIndex = 0; iIndex < iCol; iIndex++) {
+				iPosCurr = (int)(short)usGetWord(
+					iFodo + iFodoOff + 7 + iIndex * 2,
+					aucGrpprl);
+				pRow->asColumnWidth[iIndex] =
+						(short)(iPosCurr - iPosPrev);
+				iPosPrev = iPosCurr;
+			}
+			bFoundd608 = TRUE;
+			break;
+		default:
+			break;
+		}
+		if (iInfoLen <= 0) {
+			iInfoLen =
+				iGet8InfoLength(iFodo + iFodoOff, aucGrpprl);
+			fail(iInfoLen <= 0);
+		}
+		iFodoOff += iInfoLen;
+	}
+
+	if (bFound2417_1 && bFoundd608) {
+		return found_end_of_row;
+	}
+	if (bFound2417_0 && !bFoundd608) {
+		return found_not_end_of_row;
+	}
+	if (bFound2416_1 || bFound244b_1) {
+		return found_a_cell;
+	}
+	if (bFound2416_0 || bFound244b_0) {
+		return found_not_a_cell;
+	}
+	return found_nothing;
+} /* end of eGet8RowInfo */
+
+/*
+ * Fill the style information block with information
+ * from a Word 8/9/10/11 file.
+ */
+void
+vGet8StyleInfo(int iFodo,
+	const UCHAR *aucGrpprl, int iBytes, style_block_type *pStyle)
+{
+	list_block_type	tList6;
+	const list_block_type	*pList;
+	int	iFodoOff, iInfoLen;
+	int	iTmp, iDel, iAdd, iBefore;
+	USHORT	usOpCode, usTmp;
+	short	sTmp;
+
+	fail(iFodo < 0 || aucGrpprl == NULL || pStyle == NULL);
+
+	NO_DBG_DEC_C(pStyle->usListIndex != 0, pStyle->usIstd);
+	NO_DBG_DEC_C(pStyle->usListIndex != 0, pStyle->usListIndex);
+
+	(void)memset(&tList6, 0, sizeof(tList6));
+
+	iFodoOff = 0;
+	while (iBytes >= iFodoOff + 2) {
+		iInfoLen = 0;
+		usOpCode = usGetWord(iFodo + iFodoOff, aucGrpprl);
+		switch (usOpCode) {
+		case 0x2403:	/* jc */
+			pStyle->ucAlignment = ucGetByte(
+					iFodo + iFodoOff + 2, aucGrpprl);
+			break;
+		case 0x260a:	/* ilvl */
+			pStyle->ucListLevel =
+				ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
+			NO_DBG_DEC(pStyle->ucListLevel);
+			pStyle->ucNumLevel = pStyle->ucListLevel;
+			break;
+		case 0x4600:	/* istd */
+			usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
+			NO_DBG_DEC(usTmp);
+			break;
+		case 0x460b:	/* ilfo */
+			pStyle->usListIndex =
+				usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
+			NO_DBG_DEC(pStyle->usListIndex);
+			break;
+		case 0x4610: /* Nest dxaLeft */
+			sTmp = (short)usGetWord(
+					iFodo + iFodoOff + 2, aucGrpprl);
+			pStyle->sLeftIndent += sTmp;
+			if (pStyle->sLeftIndent < 0) {
+				pStyle->sLeftIndent = 0;
+			}
+			DBG_DEC(sTmp);
+			DBG_DEC(pStyle->sLeftIndent);
+			break;
+		case 0xc60d:	/* ChgTabsPapx */
+		case 0xc615:	/* ChgTabs */
+			iTmp = (int)ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
+			if (iTmp < 2) {
+				iInfoLen = 1;
+				break;
+			}
+			NO_DBG_DEC(iTmp);
+			iDel = (int)ucGetByte(iFodo + iFodoOff + 3, aucGrpprl);
+			if (iTmp < 2 + 2 * iDel) {
+				iInfoLen = 1;
+				break;
+			}
+			NO_DBG_DEC(iDel);
+			iAdd = (int)ucGetByte(
+				iFodo + iFodoOff + 4 + 2 * iDel, aucGrpprl);
+			if (iTmp < 2 + 2 * iDel + 2 * iAdd) {
+				iInfoLen = 1;
+				break;
+			}
+			NO_DBG_DEC(iAdd);
+			break;
+		case 0x840e:	/* dxaRight */
+			pStyle->sRightIndent = (short)usGetWord(
+					iFodo + iFodoOff + 2, aucGrpprl);
+			NO_DBG_DEC(pStyle->sRightIndent);
+			break;
+		case 0x840f:	/* dxaLeft */
+			pStyle->sLeftIndent = (short)usGetWord(
+					iFodo + iFodoOff + 2, aucGrpprl);
+			NO_DBG_DEC(pStyle->sLeftIndent);
+			break;
+		case 0x8411:	/* dxaLeft1 */
+			pStyle->sLeftIndent1 = (short)usGetWord(
+					iFodo + iFodoOff + 2, aucGrpprl);
+			NO_DBG_DEC(pStyle->sLeftIndent1);
+			break;
+		case 0xa413:	/* dyaBefore */
+			pStyle->usBeforeIndent = usGetWord(
+					iFodo + iFodoOff + 2, aucGrpprl);
+			NO_DBG_DEC(pStyle->usBeforeIndent);
+			break;
+		case 0xa414:	/* dyaAfter */
+			pStyle->usAfterIndent = usGetWord(
+					iFodo + iFodoOff + 2, aucGrpprl);
+			NO_DBG_DEC(pStyle->usAfterIndent);
+			break;
+		case 0xc63e:	/* anld */
+			iTmp = (int)ucGetByte(
+					iFodo + iFodoOff + 2, aucGrpprl);
+			DBG_DEC_C(iTmp < 84, iTmp);
+			if (iTmp >= 1) {
+				tList6.ucNFC = ucGetByte(
+					iFodo + iFodoOff + 3, aucGrpprl);
+			}
+			if (tList6.ucNFC != LIST_BULLETS && iTmp >= 2) {
+				iBefore = (int)ucGetByte(
+					iFodo + iFodoOff + 4, aucGrpprl);
+			} else {
+				iBefore = 0;
+			}
+			if (iTmp >= 12) {
+				tList6.ulStartAt = (ULONG)usGetWord(
+					iFodo + iFodoOff + 13, aucGrpprl);
+			}
+			if (iTmp >= iBefore + 22) {
+				tList6.usListChar = usGetWord(
+					iFodo + iFodoOff + iBefore + 23,
+					aucGrpprl);
+				DBG_HEX(tList6.usListChar);
+			}
+			break;
+		default:
+			NO_DBG_HEX(usOpCode);
+			break;
+		}
+		if (iInfoLen <= 0) {
+			iInfoLen =
+				iGet8InfoLength(iFodo + iFodoOff, aucGrpprl);
+			fail(iInfoLen <= 0);
+		}
+		iFodoOff += iInfoLen;
+	}
+
+	if (pStyle->usListIndex == 2047) {
+		/* Old style list */
+		pStyle->usStartAt = (USHORT)tList6.ulStartAt;
+		pStyle->usListChar = tList6.usListChar;
+		pStyle->ucNFC = tList6.ucNFC;
+	} else {
+		/* New style list */
+		pList = pGetListInfo(pStyle->usListIndex, pStyle->ucListLevel);
+		if (pList != NULL) {
+			pStyle->bNoRestart = pList->bNoRestart;
+			fail(pList->ulStartAt > (ULONG)USHRT_MAX);
+			pStyle->usStartAt = (USHORT)pList->ulStartAt;
+			pStyle->usListChar = pList->usListChar;
+			pStyle->ucNFC = pList->ucNFC;
+			if (pStyle->sLeftIndent <= 0) {
+				pStyle->sLeftIndent = pList->sLeftIndent;
+			}
+		}
+	}
+} /* end of vGet8StyleInfo */
+
+/*
+ * Get the left indentation value from the style information block
+ *
+ * Returns the value when found, otherwise 0
+ */
+static short
+sGetLeftIndent(const UCHAR *aucGrpprl, size_t tBytes)
+{
+	int	iOffset, iInfoLen;
+	USHORT	usOpCode, usTmp;
+
+	fail(aucGrpprl == NULL);
+
+	iOffset = 0;
+	while (tBytes >= (size_t)iOffset + 4) {
+		usOpCode = usGetWord(iOffset, aucGrpprl);
+		if (usOpCode == 0x840f) {	/* dxaLeft */
+			usTmp = usGetWord(iOffset + 2, aucGrpprl);
+			if (usTmp <= 0x7fff) {
+				NO_DBG_DEC(usTmp);
+				return (short)usTmp;
+			}
+		}
+		iInfoLen = iGet8InfoLength(iOffset, aucGrpprl);
+		fail(iInfoLen <= 0);
+		iOffset += iInfoLen;
+	}
+	return 0;
+} /* end of sGetLeftIndent */
+
+/*
+ * Build the list with List Information for Word 8/9/10/11 files
+ */
+void
+vGet8LstInfo(FILE *pFile, const pps_info_type *pPPS,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const ULONG *aulSBD, size_t tSBDLen,
+	const UCHAR *aucHeader)
+{
+	list_block_type	tList;
+	const ULONG	*aulBlockDepot;
+	UCHAR	*aucLfoInfo, *aucLstfInfo, *aucPapx, *aucXString;
+	ULONG	ulBeginLfoInfo, ulBeginLstfInfo, ulBeginLvlfInfo;
+	ULONG	ulListID, ulStart;
+	size_t	tBlockDepotLen, tBlockSize;
+	size_t	tLfoInfoLen, tLstfInfoLen, tPapxLen, tXstLen, tOff;
+	size_t	tLstfRecords, tStart, tIndex;
+	int	iNums;
+	USHORT	usIstd;
+	UCHAR	ucTmp, ucListLevel, ucMaxLevel, ucChpxLen;
+	UCHAR	aucLvlfInfo[28], aucXst[2];
+
+	fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
+	fail(aulBBD == NULL || aulSBD == NULL);
+
+	NO_DBG_DEC(pPPS->tTable.ulSB);
+	NO_DBG_HEX(pPPS->tTable.ulSize);
+	if (pPPS->tTable.ulSize == 0) {
+		DBG_MSG("No list information");
+		return;
+	}
+
+	if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
+		/* Use the Small Block Depot */
+		aulBlockDepot = aulSBD;
+		tBlockDepotLen = tSBDLen;
+		tBlockSize = SMALL_BLOCK_SIZE;
+	} else {
+		/* Use the Big Block Depot */
+		aulBlockDepot = aulBBD;
+		tBlockDepotLen = tBBDLen;
+		tBlockSize = BIG_BLOCK_SIZE;
+	}
+
+	/* LFO (List Format Override) */
+	ulBeginLfoInfo = ulGetLong(0x2ea, aucHeader); /* fcPlfLfo */
+	DBG_HEX(ulBeginLfoInfo);
+	tLfoInfoLen = (size_t)ulGetLong(0x2ee, aucHeader); /* lcbPlfLfo */
+	DBG_DEC(tLfoInfoLen);
+	if (tLfoInfoLen == 0) {
+		DBG_MSG("No lists in this document");
+		return;
+	}
+
+	aucLfoInfo = xmalloc(tLfoInfoLen);
+	if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
+			aulBlockDepot, tBlockDepotLen, tBlockSize,
+			aucLfoInfo, ulBeginLfoInfo, tLfoInfoLen)) {
+		aucLfoInfo = xfree(aucLfoInfo);
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucLfoInfo, tLfoInfoLen);
+	vBuildLfoList(aucLfoInfo, tLfoInfoLen);
+	aucLfoInfo = xfree(aucLfoInfo);
+
+	/* LSTF (LiST data on File) */
+	ulBeginLstfInfo = ulGetLong(0x2e2, aucHeader); /* fcPlcfLst */
+	DBG_HEX(ulBeginLstfInfo);
+	tLstfInfoLen = (size_t)ulGetLong(0x2e6, aucHeader); /* lcbPlcfLst */
+	DBG_DEC(tLstfInfoLen);
+	if (tLstfInfoLen == 0) {
+		DBG_MSG("No list data on file");
+		return;
+	}
+
+	aucLstfInfo = xmalloc(tLstfInfoLen);
+	if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
+			aulBlockDepot, tBlockDepotLen, tBlockSize,
+			aucLstfInfo, ulBeginLstfInfo, tLstfInfoLen)) {
+		aucLstfInfo = xfree(aucLstfInfo);
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucLstfInfo, tLstfInfoLen);
+
+	tLstfRecords = (size_t)usGetWord(0, aucLstfInfo);
+	if (2 + tLstfRecords * 28 < tLstfInfoLen) {
+		DBG_DEC(2 + tLstfRecords * 28);
+		DBG_DEC(tLstfInfoLen);
+		aucLstfInfo = xfree(aucLstfInfo);
+		return;
+	}
+
+	/* LVLF (List leVeL on File) */
+	ulBeginLvlfInfo = ulBeginLstfInfo + tLstfInfoLen;
+	DBG_HEX(ulBeginLvlfInfo);
+
+	aucXString = NULL;
+	ulStart = ulBeginLvlfInfo;
+
+	for (tIndex = 0, tStart = 2;
+	     tIndex < tLstfRecords;
+	     tIndex++, tStart += 28) {
+		ulListID = ulGetLong(tStart, aucLstfInfo);
+		NO_DBG_HEX(ulListID);
+		ucTmp = ucGetByte(tStart + 26, aucLstfInfo);
+		ucMaxLevel = odd(ucTmp) ? 1 : 9;
+		for (ucListLevel = 0; ucListLevel < ucMaxLevel; ucListLevel++) {
+			fail(aucXString != NULL);
+			usIstd = usGetWord(
+					tStart + 8 + 2 * (size_t)ucListLevel,
+					aucLstfInfo);
+			DBG_DEC_C(usIstd != STI_NIL, usIstd);
+			NO_DBG_HEX(ulStart);
+			(void)memset(&tList, 0, sizeof(tList));
+			/* Read the lvlf (List leVeL on File) */
+			if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
+					aulBlockDepot, tBlockDepotLen,
+					tBlockSize, aucLvlfInfo,
+					ulStart, sizeof(aucLvlfInfo))) {
+				aucLstfInfo = xfree(aucLstfInfo);
+				return;
+			}
+			NO_DBG_PRINT_BLOCK(aucLvlfInfo, sizeof(aucLvlfInfo));
+			if (bAllZero(aucLvlfInfo, sizeof(aucLvlfInfo))) {
+				tList.ulStartAt = 1;
+				tList.ucNFC = 0x00;
+				tList.bNoRestart = FALSE;
+			} else {
+				tList.ulStartAt = ulGetLong(0, aucLvlfInfo);
+				tList.ucNFC = ucGetByte(4, aucLvlfInfo);
+				ucTmp = ucGetByte(5, aucLvlfInfo);
+				tList.bNoRestart = (ucTmp & BIT(3)) != 0;
+				DBG_MSG_C((ucTmp & BIT(4)) != 0 &&
+					(ucTmp & BIT(6)) != 0, "Found one");
+			}
+			ulStart += sizeof(aucLvlfInfo);
+			tPapxLen = (size_t)ucGetByte(25, aucLvlfInfo);
+			if (tPapxLen != 0) {
+				aucPapx = xmalloc(tPapxLen);
+				/* Read the Papx */
+				if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
+						aulBlockDepot, tBlockDepotLen,
+						tBlockSize, aucPapx,
+						ulStart, tPapxLen)) {
+					aucPapx = xfree(aucPapx);
+					aucLstfInfo = xfree(aucLstfInfo);
+					return;
+				}
+				NO_DBG_PRINT_BLOCK(aucPapx, tPapxLen);
+				tList.sLeftIndent =
+					sGetLeftIndent(aucPapx, tPapxLen);
+				aucPapx = xfree(aucPapx);
+			}
+			ulStart += tPapxLen;
+			ucChpxLen = ucGetByte(24, aucLvlfInfo);
+			ulStart += (ULONG)ucChpxLen;
+			/* Read the length of the XString */
+			if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
+					aulBlockDepot, tBlockDepotLen,
+					tBlockSize, aucXst,
+					ulStart, sizeof(aucXst))) {
+				aucLstfInfo = xfree(aucLstfInfo);
+				return;
+			}
+			NO_DBG_PRINT_BLOCK(aucXst, sizeof(aucXst));
+			tXstLen = (size_t)usGetWord(0, aucXst);
+			ulStart += sizeof(aucXst);
+			if (tXstLen == 0) {
+				tList.usListChar = DEFAULT_LISTCHAR;
+				vAdd2ListInfoList(ulListID,
+						usIstd,
+						ucListLevel,
+						&tList);
+				continue;
+			}
+			tXstLen *= 2;	/* Length in chars to length in bytes */
+			aucXString = xmalloc(tXstLen);
+			/* Read the XString */
+			if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
+					aulBlockDepot, tBlockDepotLen,
+					tBlockSize, aucXString,
+					ulStart, tXstLen)) {
+				aucXString = xfree(aucXString);
+				aucLstfInfo = xfree(aucLstfInfo);
+				return;
+			}
+			NO_DBG_PRINT_BLOCK(aucXString, tXstLen);
+			tOff = 0;
+			for (iNums = 6; iNums < 15; iNums++) {
+				ucTmp = ucGetByte(iNums, aucLvlfInfo);
+				if (ucTmp == 0) {
+					break;
+				}
+				tOff = (size_t)ucTmp;
+			}
+			tOff *= 2;	/* Offset in chars to offset in bytes */
+			NO_DBG_DEC(tOff);
+			if (tList.ucNFC == LIST_SPECIAL ||
+			    tList.ucNFC == LIST_SPECIAL2 ||
+			    tList.ucNFC == LIST_BULLETS) {
+				tList.usListChar = usGetWord(0, aucXString);
+			} else if (tOff != 0 && tOff < tXstLen) {
+				tList.usListChar = usGetWord(tOff, aucXString);
+			} else {
+				tList.usListChar = DEFAULT_LISTCHAR;
+			}
+			vAdd2ListInfoList(ulListID,
+					usIstd,
+					ucListLevel,
+					&tList);
+			ulStart += tXstLen;
+			aucXString = xfree(aucXString);
+		}
+	}
+	aucLstfInfo = xfree(aucLstfInfo);
+} /* end of vGet8LstInfo */
+
+/*
+ * Build the lists with Paragraph Information for Word 8/9/10/11 files
+ */
+void
+vGet8PapInfo(FILE *pFile, const pps_info_type *pPPS,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const ULONG *aulSBD, size_t tSBDLen,
+	const UCHAR *aucHeader)
+{
+	row_block_type		tRow;
+	style_block_type	tStyle;
+	ULONG		*aulParfPage;
+	UCHAR	*aucBuffer;
+	ULONG	ulCharPos, ulCharPosFirst, ulCharPosLast;
+	ULONG	ulBeginParfInfo;
+	size_t	tParfInfoLen, tOffset, tLen;
+	int	iIndex, iIndex2, iRun, iFodo, iLen;
+	row_info_enum	eRowInfo;
+	USHORT	usIstd;
+	UCHAR	aucFpage[BIG_BLOCK_SIZE];
+
+	fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
+	fail(aulBBD == NULL || aulSBD == NULL);
+
+	ulBeginParfInfo = ulGetLong(0x102, aucHeader); /* fcPlcfbtePapx */
+	NO_DBG_HEX(ulBeginParfInfo);
+	tParfInfoLen = (size_t)ulGetLong(0x106, aucHeader); /* lcbPlcfbtePapx */
+	NO_DBG_DEC(tParfInfoLen);
+	if (tParfInfoLen < 4) {
+		DBG_DEC(tParfInfoLen);
+		return;
+	}
+
+	aucBuffer = aucFillInfoBuffer(pFile, &pPPS->tTable,
+			aulBBD, tBBDLen, aulSBD, tSBDLen,
+			ulBeginParfInfo, tParfInfoLen);
+	if (aucBuffer == NULL) {
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tParfInfoLen);
+
+	tLen = (tParfInfoLen / 4 - 1) / 2;
+	aulParfPage = xcalloc(tLen, sizeof(ULONG));
+	for (iIndex = 0, tOffset = (tLen + 1) * 4;
+	     iIndex < (int)tLen;
+	     iIndex++, tOffset += 4) {
+		 aulParfPage[iIndex] = ulGetLong(tOffset, aucBuffer);
+		 NO_DBG_DEC(aulParfPage[iIndex]);
+	}
+	DBG_HEX(ulGetLong(0, aucBuffer));
+	aucBuffer = xfree(aucBuffer);
+	NO_DBG_PRINT_BLOCK(aucHeader, HEADER_SIZE);
+
+	(void)memset(&tRow, 0, sizeof(tRow));
+	ulCharPosFirst = CP_INVALID;
+	for (iIndex = 0; iIndex < (int)tLen; iIndex++) {
+		fail(aulParfPage[iIndex] > ULONG_MAX / BIG_BLOCK_SIZE);
+		if (!bReadBuffer(pFile, pPPS->tWordDocument.ulSB,
+				aulBBD, tBBDLen, BIG_BLOCK_SIZE,
+				aucFpage,
+				aulParfPage[iIndex] * BIG_BLOCK_SIZE,
+				BIG_BLOCK_SIZE)) {
+			break;
+		}
+		NO_DBG_PRINT_BLOCK(aucFpage, BIG_BLOCK_SIZE);
+		iRun = (int)ucGetByte(0x1ff, aucFpage);
+		NO_DBG_DEC(iRun);
+		for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) {
+			NO_DBG_HEX(ulGetLong(iIndex2 * 4, aucFpage));
+			iFodo = 2 * (int)ucGetByte(
+				(iRun + 1) * 4 + iIndex2 * 13, aucFpage);
+			if (iFodo <= 0) {
+				continue;
+			}
+
+			iLen = 2 * (int)ucGetByte(iFodo, aucFpage);
+			if (iLen == 0) {
+				iFodo++;
+				iLen = 2 * (int)ucGetByte(iFodo, aucFpage);
+			}
+
+			usIstd = usGetWord(iFodo + 1, aucFpage);
+			vFillStyleFromStylesheet(usIstd, &tStyle);
+			vGet8StyleInfo(iFodo, aucFpage + 3, iLen - 3, &tStyle);
+			ulCharPos = ulGetLong(iIndex2 * 4, aucFpage);
+			NO_DBG_HEX(ulCharPos);
+			tStyle.ulFileOffset = ulCharPos2FileOffsetX(
+						ulCharPos, &tStyle.eListID);
+			vAdd2StyleInfoList(&tStyle);
+
+			eRowInfo = eGet8RowInfo(iFodo,
+					aucFpage + 3, iLen - 3, &tRow);
+			switch (eRowInfo) {
+			case found_a_cell:
+				if (ulCharPosFirst != CP_INVALID) {
+					break;
+				}
+				ulCharPosFirst = ulGetLong(
+						iIndex2 * 4, aucFpage);
+				NO_DBG_HEX(ulCharPosFirst);
+				tRow.ulCharPosStart = ulCharPosFirst;
+				tRow.ulFileOffsetStart =
+					ulCharPos2FileOffset(ulCharPosFirst);
+				NO_DBG_HEX_C(
+					tRow.ulFileOffsetStart == FC_INVALID,
+					ulCharPosFirst);
+				break;
+			case found_end_of_row:
+				ulCharPosLast = ulGetLong(
+						iIndex2 * 4, aucFpage);
+				NO_DBG_HEX(ulCharPosLast);
+				tRow.ulCharPosEnd = ulCharPosLast;
+				tRow.ulFileOffsetEnd =
+					ulCharPos2FileOffset(ulCharPosLast);
+				NO_DBG_HEX_C(tRow.ulFileOffsetEnd == FC_INVALID,
+							ulCharPosLast);
+				vAdd2RowInfoList(&tRow);
+				(void)memset(&tRow, 0, sizeof(tRow));
+				ulCharPosFirst = CP_INVALID;
+				break;
+			case found_nothing:
+				break;
+			default:
+				DBG_DEC(eRowInfo);
+				break;
+			}
+		}
+	}
+	aulParfPage = xfree(aulParfPage);
+} /* end of vGet8PapInfo */
+
+/*
+ * Fill the font information block with information
+ * from a Word 8/9/10/11 file.
+ */
+void
+vGet8FontInfo(int iFodo, USHORT usIstd,
+	const UCHAR *aucGrpprl, int iBytes, font_block_type *pFont)
+{
+	long	lTmp;
+	int	iFodoOff, iInfoLen;
+	USHORT	usFtc0, usFtc1, usFtc2, usTmp;
+	UCHAR	ucTmp;
+
+	fail(iFodo < 0 || aucGrpprl == NULL || pFont == NULL);
+
+	usFtc0 = USHRT_MAX;
+	usFtc1 = USHRT_MAX;
+	usFtc2 = USHRT_MAX;
+
+	iFodoOff = 0;
+	while (iBytes >= iFodoOff + 2) {
+		switch (usGetWord(iFodo + iFodoOff, aucGrpprl)) {
+		case 0x0800:	/* fRMarkDel */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
+			if (ucTmp == 0) {
+				pFont->usFontStyle &= ~FONT_MARKDEL;
+			} else {
+				pFont->usFontStyle |= FONT_MARKDEL;
+			}
+			break;
+		case 0x0835:	/* fBold */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
+			switch (ucTmp) {
+			case   0:	/* Unset */
+				pFont->usFontStyle &= ~FONT_BOLD;
+				break;
+			case   1:	/* Set */
+				pFont->usFontStyle |= FONT_BOLD;
+				break;
+			case 128:	/* Unchanged */
+				break;
+			case 129:	/* Negation */
+				pFont->usFontStyle ^= FONT_BOLD;
+				break;
+			default:
+				DBG_DEC(ucTmp);
+				DBG_FIXME();
+				break;
+			}
+			break;
+		case 0x0836:	/* fItalic */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
+			switch (ucTmp) {
+			case   0:	/* Unset */
+				pFont->usFontStyle &= ~FONT_ITALIC;
+				break;
+			case   1:	/* Set */
+				pFont->usFontStyle |= FONT_ITALIC;
+				break;
+			case 128:	/* Unchanged */
+				break;
+			case 129:	/* Negation */
+				pFont->usFontStyle ^= FONT_ITALIC;
+				break;
+			default:
+				DBG_DEC(ucTmp);
+				DBG_FIXME();
+				break;
+			}
+			break;
+		case 0x0837:	/* fStrike */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
+			switch (ucTmp) {
+			case   0:	/* Unset */
+				pFont->usFontStyle &= ~FONT_STRIKE;
+				break;
+			case   1:	/* Set */
+				pFont->usFontStyle |= FONT_STRIKE;
+				break;
+			case 128:	/* Unchanged */
+				break;
+			case 129:	/* Negation */
+				pFont->usFontStyle ^= FONT_STRIKE;
+				break;
+			default:
+				DBG_DEC(ucTmp);
+				DBG_FIXME();
+				break;
+			}
+			break;
+		case 0x083a:	/* fSmallCaps */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
+			switch (ucTmp) {
+			case   0:	/* Unset */
+				pFont->usFontStyle &= ~FONT_SMALL_CAPITALS;
+				break;
+			case   1:	/* Set */
+				pFont->usFontStyle |= FONT_SMALL_CAPITALS;
+				break;
+			case 128:	/* Unchanged */
+				break;
+			case 129:	/* Negation */
+				pFont->usFontStyle ^= FONT_SMALL_CAPITALS;
+				break;
+			default:
+				DBG_DEC(ucTmp);
+				DBG_FIXME();
+				break;
+			}
+			break;
+		case 0x083b:	/* fCaps */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
+			switch (ucTmp) {
+			case   0:	/* Unset */
+				pFont->usFontStyle &= ~FONT_CAPITALS;
+				break;
+			case   1:	/* Set */
+				pFont->usFontStyle |= FONT_CAPITALS;
+				break;
+			case 128:	/* Unchanged */
+				break;
+			case 129:	/* Negation */
+				pFont->usFontStyle ^= FONT_CAPITALS;
+				break;
+			default:
+				DBG_DEC(ucTmp);
+				DBG_FIXME();
+				break;
+			}
+			break;
+		case 0x083c:	/* fVanish */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
+			switch (ucTmp) {
+			case   0:	/* Unset */
+				pFont->usFontStyle &= ~FONT_HIDDEN;
+				break;
+			case   1:	/* Set */
+				pFont->usFontStyle |= FONT_HIDDEN;
+				break;
+			case 128:	/* Unchanged */
+				break;
+			case 129:	/* Negation */
+				pFont->usFontStyle ^= FONT_HIDDEN;
+				break;
+			default:
+				DBG_DEC(ucTmp);
+				DBG_FIXME();
+				break;
+			}
+			break;
+		case 0x2a32:	/* cDefault */
+			pFont->usFontStyle &= FONT_HIDDEN;
+			pFont->ucFontColor = FONT_COLOR_DEFAULT;
+			break;
+		case 0x2a33:	/* cPlain */
+			DBG_MSG("2a33: cPlain");
+			vFillFontFromStylesheet(usIstd, pFont);
+			break;
+		case 0x2a3e:	/* cKul */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
+			if (ucTmp == 0 || ucTmp == 5) {
+				pFont->usFontStyle &= ~FONT_UNDERLINE;
+			} else {
+				NO_DBG_MSG("Underline text");
+				pFont->usFontStyle |= FONT_UNDERLINE;
+				if (ucTmp == 6) {
+					DBG_MSG("Bold text");
+					pFont->usFontStyle |= FONT_BOLD;
+				}
+			}
+			break;
+		case 0x2a42:	/* cIco */
+			pFont->ucFontColor =
+				ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
+			NO_DBG_DEC(pFont->ucFontColor);
+			break;
+		case 0x2a44:	/* cHpsInc */
+			DBG_MSG("0x2a44: sprmCHpsInc");
+			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
+			DBG_DEC(ucTmp);
+			break;
+		case 0x2a48:	/* cIss */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
+			ucTmp &= 0x07;
+			if (ucTmp == 1) {
+				pFont->usFontStyle |= FONT_SUPERSCRIPT;
+				NO_DBG_MSG("Superscript");
+			} else if (ucTmp == 2) {
+				pFont->usFontStyle |= FONT_SUBSCRIPT;
+				NO_DBG_MSG("Subscript");
+			}
+			break;
+		case 0x4a30:	/* cIstd */
+			usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
+			NO_DBG_DEC(usTmp);
+			break;
+		case 0x4a43:	/* cHps */
+			pFont->usFontSize =
+				usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
+			NO_DBG_DEC(pFont->usFontSize);
+			break;
+		case 0x4a4d:	/* cHpsMul */
+			DBG_MSG("0x4a4d: sprmCHpsMul");
+			usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
+			DBG_DEC(usTmp);
+			break;
+		case 0x4a4f:	/* cFtc0 */
+			usFtc0 = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
+			break;
+		case 0x4a50:	/* cFtc1 */
+			usFtc1 = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
+			break;
+		case 0x4a51:	/* cFtc2 */
+			usFtc2 = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
+			break;
+		case 0xca47:	/* cMajority */
+			DBG_MSG("0xca47: sprmCMajority");
+			break;
+		case 0xca4a:	/* cHpsInc1 */
+			usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
+			lTmp = (long)pFont->usFontSize + (long)usTmp;
+			if (lTmp < 8) {
+				pFont->usFontSize = 8;
+			} else if (lTmp > 32766) {
+				pFont->usFontSize = 32766;
+			} else {
+				pFont->usFontSize = (USHORT)lTmp;
+			}
+			break;
+		case 0xca4c:	/* cMajority50 */
+			DBG_MSG("0xca4c: sprmCMajority50");
+			break;
+		case 0xea3f:	/* cHps, cHpsPos */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
+			DBG_DEC(ucTmp);
+			if (ucTmp != 0) {
+				pFont->usFontSize = (USHORT)ucTmp;
+			}
+			ucTmp = ucGetByte(iFodo + iFodoOff + 3, aucGrpprl);
+			DBG_DEC(ucTmp);
+			break;
+		default:
+			break;
+		}
+		iInfoLen = iGet8InfoLength(iFodo + iFodoOff, aucGrpprl);
+		fail(iInfoLen <= 0);
+		iFodoOff += iInfoLen;
+	}
+
+	/* Combine the Ftc's to a FontNumber */
+	NO_DBG_DEC_C(usFtc0 != USHRT_MAX, usFtc0);
+	NO_DBG_DEC_C(usFtc2 != USHRT_MAX, usFtc2);
+	NO_DBG_DEC_C(usFtc1 != USHRT_MAX, usFtc1);
+	if (usFtc0 <= 0x7fff) {
+		if (usFtc0 <= (USHORT)UCHAR_MAX) {
+			pFont->ucFontNumber = (UCHAR)usFtc0;
+		} else {
+			DBG_DEC(usFtc0);
+			DBG_FIXME();
+			pFont->ucFontNumber = 0;
+		}
+	} else if (usFtc2 <= 0x7fff) {
+		if (usFtc2 <= (USHORT)UCHAR_MAX) {
+			pFont->ucFontNumber = (UCHAR)usFtc2;
+		} else {
+			DBG_DEC(usFtc2);
+			DBG_FIXME();
+			pFont->ucFontNumber = 0;
+		}
+	} else if (usFtc1 <= 0x7fff) {
+		if (usFtc1 <= (USHORT)UCHAR_MAX) {
+			pFont->ucFontNumber = (UCHAR)usFtc1;
+		} else {
+			DBG_DEC(usFtc1);
+			DBG_FIXME();
+			pFont->ucFontNumber = 0;
+		}
+	}
+} /* end of vGet8FontInfo */
+
+/*
+ * Fill the picture information block with information
+ * from a Word 8/9/10/11 file.
+ * Returns TRUE when successful, otherwise FALSE
+ */
+static BOOL
+bGet8PicInfo(int iFodo,
+	const UCHAR *aucGrpprl, int iBytes, picture_block_type *pPicture)
+{
+	ULONG	ulTmp;
+	int	iFodoOff, iInfoLen;
+	BOOL	bFound;
+	UCHAR	ucTmp;
+
+	fail(iFodo <= 0 || aucGrpprl == NULL || pPicture == NULL);
+
+	iFodoOff = 0;
+	bFound = FALSE;
+	while (iBytes >= iFodoOff + 2) {
+		switch (usGetWord(iFodo + iFodoOff, aucGrpprl)) {
+#if 0
+		case 0x0806:	/* fData */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
+			if (ucTmp == 0x01) {
+				/* Not a picture, but a form field */
+				return FALSE;
+			}
+			DBG_DEC_C(ucTmp != 0, ucTmp);
+			break;
+#endif
+		case 0x080a:	/* fOle2 */
+			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
+			if (ucTmp == 0x01) {
+				/* Not a picture, but an OLE object */
+				return FALSE;
+			}
+			DBG_DEC_C(ucTmp != 0, ucTmp);
+			break;
+		case 0x680e:	/* fcObj */
+			ulTmp = ulGetLong(iFodo + iFodoOff + 2, aucGrpprl);
+			DBG_HEX(ulTmp);
+			break;
+		case 0x6a03:	/* fcPic */
+			pPicture->ulPictureOffset = ulGetLong(
+					iFodo + iFodoOff + 2, aucGrpprl);
+			bFound = TRUE;
+			break;
+		default:
+			break;
+		}
+		iInfoLen = iGet8InfoLength(iFodo + iFodoOff, aucGrpprl);
+		fail(iInfoLen <= 0);
+		iFodoOff += iInfoLen;
+	}
+	return bFound;
+} /* end of bGet8PicInfo */
+
+/*
+ * Build the lists with Character Information for Word 8/9/10/11 files
+ */
+void
+vGet8ChrInfo(FILE *pFile, const pps_info_type *pPPS,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const ULONG *aulSBD, size_t tSBDLen,
+	const UCHAR *aucHeader)
+{
+	font_block_type		tFont;
+	picture_block_type	tPicture;
+	ULONG		*aulCharPage;
+	UCHAR	*aucBuffer;
+	ULONG	ulFileOffset, ulCharPos, ulBeginCharInfo;
+	size_t	tCharInfoLen, tOffset, tLen;
+	int	iIndex, iIndex2, iRun, iFodo, iLen;
+	USHORT	usIstd;
+	UCHAR	aucFpage[BIG_BLOCK_SIZE];
+
+	fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
+	fail(aulBBD == NULL || aulSBD == NULL);
+
+	ulBeginCharInfo = ulGetLong(0xfa, aucHeader); /* fcPlcfbteChpx */
+	NO_DBG_HEX(ulBeginCharInfo);
+	tCharInfoLen = (size_t)ulGetLong(0xfe, aucHeader); /* lcbPlcfbteChpx */
+	NO_DBG_DEC(tCharInfoLen);
+	if (tCharInfoLen < 4) {
+		DBG_DEC(tCharInfoLen);
+		return;
+	}
+
+	aucBuffer = aucFillInfoBuffer(pFile, &pPPS->tTable,
+			aulBBD, tBBDLen, aulSBD, tSBDLen,
+			ulBeginCharInfo, tCharInfoLen);
+	if (aucBuffer == NULL) {
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tCharInfoLen);
+
+	tLen = (tCharInfoLen / 4 - 1) / 2;
+	aulCharPage = xcalloc(tLen, sizeof(ULONG));
+	for (iIndex = 0, tOffset = (tLen + 1) * 4;
+	     iIndex < (int)tLen;
+	     iIndex++, tOffset += 4) {
+		 aulCharPage[iIndex] = ulGetLong(tOffset, aucBuffer);
+		 NO_DBG_DEC(aulCharPage[iIndex]);
+	}
+	DBG_HEX(ulGetLong(0, aucBuffer));
+	aucBuffer = xfree(aucBuffer);
+	NO_DBG_PRINT_BLOCK(aucHeader, HEADER_SIZE);
+
+	for (iIndex = 0; iIndex < (int)tLen; iIndex++) {
+		fail(aulCharPage[iIndex] > ULONG_MAX / BIG_BLOCK_SIZE);
+		if (!bReadBuffer(pFile, pPPS->tWordDocument.ulSB,
+				aulBBD, tBBDLen, BIG_BLOCK_SIZE,
+				aucFpage,
+				aulCharPage[iIndex] * BIG_BLOCK_SIZE,
+				BIG_BLOCK_SIZE)) {
+			break;
+		}
+		NO_DBG_PRINT_BLOCK(aucFpage, BIG_BLOCK_SIZE);
+		iRun = (int)ucGetByte(0x1ff, aucFpage);
+		NO_DBG_DEC(iRun);
+		for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) {
+			ulCharPos = ulGetLong(iIndex2 * 4, aucFpage);
+			ulFileOffset = ulCharPos2FileOffset(ulCharPos);
+			iFodo = 2 * (int)ucGetByte(
+				(iRun + 1) * 4 + iIndex2, aucFpage);
+
+			iLen = (int)ucGetByte(iFodo, aucFpage);
+
+			usIstd = usGetIstd(ulFileOffset);
+			vFillFontFromStylesheet(usIstd, &tFont);
+			if (iFodo != 0) {
+				vGet8FontInfo(iFodo, usIstd,
+					aucFpage + 1, iLen - 1, &tFont);
+			}
+			tFont.ulFileOffset = ulFileOffset;
+			vAdd2FontInfoList(&tFont);
+
+			if (iFodo <= 0) {
+				continue;
+			}
+
+			(void)memset(&tPicture, 0, sizeof(tPicture));
+			if (bGet8PicInfo(iFodo, aucFpage + 1,
+						iLen - 1, &tPicture)) {
+				tPicture.ulFileOffset = ulFileOffset;
+				tPicture.ulFileOffsetPicture =
+					ulDataPos2FileOffset(
+						tPicture.ulPictureOffset);
+				vAdd2PictInfoList(&tPicture);
+			}
+		}
+	}
+	aulCharPage = xfree(aulCharPage);
+} /* end of vGet8ChrInfo */
diff --git a/properties.c b/properties.c
new file mode 100644
index 0000000..28087a4
--- /dev/null
+++ b/properties.c
@@ -0,0 +1,198 @@
+/*
+ * properties.c
+ * Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Read the properties information from a MS Word file
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "antiword.h"
+
+
+/*
+ * Build the lists with Property Information
+ */
+void
+vGetPropertyInfo(FILE *pFile, const pps_info_type *pPPS,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const ULONG *aulSBD, size_t tSBDLen,
+	const UCHAR *aucHeader, int iWordVersion)
+{
+	options_type	tOptions;
+
+	TRACE_MSG("vGetPropertyInfo");
+
+	fail(pFile == NULL);
+	fail(pPPS == NULL && iWordVersion >= 6);
+	fail(aulBBD == NULL && tBBDLen != 0);
+	fail(aulSBD == NULL && tSBDLen != 0);
+	fail(aucHeader == NULL);
+
+	/* Get the options */
+	vGetOptions(&tOptions);
+
+	/* Get the property information per Word version */
+	switch (iWordVersion) {
+	case 0:
+		vGet0DopInfo(pFile, aucHeader);
+		vGet0SepInfo(pFile, aucHeader);
+		vGet0PapInfo(pFile, aucHeader);
+		if (tOptions.eConversionType == conversion_draw ||
+		    tOptions.eConversionType == conversion_ps ||
+		    tOptions.eConversionType == conversion_xml ||
+		    tOptions.eConversionType == conversion_fmt_text ||
+		    tOptions.eConversionType == conversion_pdf) {
+			vGet0ChrInfo(pFile, aucHeader);
+		}
+		if (tOptions.eConversionType == conversion_draw ||
+		    tOptions.eConversionType == conversion_ps ||
+		    tOptions.eConversionType == conversion_pdf) {
+			vCreate0FontTable();
+		}
+		vSet0SummaryInfo(pFile, aucHeader);
+		break;
+	case 1:
+	case 2:
+		vGet2Stylesheet(pFile, iWordVersion, aucHeader);
+		vGet2DopInfo(pFile, aucHeader);
+		vGet2SepInfo(pFile, aucHeader);
+		vGet2PapInfo(pFile, aucHeader);
+		if (tOptions.eConversionType == conversion_ps ||
+		    tOptions.eConversionType == conversion_pdf) {
+			vGet2HdrFtrInfo(pFile, aucHeader);
+		}
+		if (tOptions.eConversionType == conversion_draw ||
+		    tOptions.eConversionType == conversion_ps ||
+		    tOptions.eConversionType == conversion_xml ||
+		    tOptions.eConversionType == conversion_fmt_text ||
+		    tOptions.eConversionType == conversion_pdf) {
+			vGet2ChrInfo(pFile, iWordVersion, aucHeader);
+		}
+		if (tOptions.eConversionType == conversion_draw ||
+		    tOptions.eConversionType == conversion_ps ||
+		    tOptions.eConversionType == conversion_pdf) {
+			vCreate2FontTable(pFile, iWordVersion, aucHeader);
+		}
+		vSet2SummaryInfo(pFile, iWordVersion, aucHeader);
+		break;
+	case 4:
+	case 5:
+		break;
+	case 6:
+	case 7:
+		vGet6Stylesheet(pFile, pPPS->tWordDocument.ulSB,
+			aulBBD, tBBDLen, aucHeader);
+		vGet6DopInfo(pFile, pPPS->tWordDocument.ulSB,
+			aulBBD, tBBDLen, aucHeader);
+		vGet6SepInfo(pFile, pPPS->tWordDocument.ulSB,
+			aulBBD, tBBDLen, aucHeader);
+		vGet6PapInfo(pFile, pPPS->tWordDocument.ulSB,
+			aulBBD, tBBDLen, aucHeader);
+		if (tOptions.eConversionType == conversion_ps ||
+		    tOptions.eConversionType == conversion_pdf) {
+			vGet6HdrFtrInfo(pFile, pPPS->tWordDocument.ulSB,
+				aulBBD, tBBDLen, aucHeader);
+		}
+		if (tOptions.eConversionType == conversion_draw ||
+		    tOptions.eConversionType == conversion_ps ||
+		    tOptions.eConversionType == conversion_xml ||
+		    tOptions.eConversionType == conversion_fmt_text ||
+		    tOptions.eConversionType == conversion_pdf) {
+			vGet6ChrInfo(pFile, pPPS->tWordDocument.ulSB,
+				aulBBD, tBBDLen, aucHeader);
+		}
+		if (tOptions.eConversionType == conversion_draw ||
+		    tOptions.eConversionType == conversion_ps ||
+		    tOptions.eConversionType == conversion_pdf) {
+			vCreate6FontTable(pFile, pPPS->tWordDocument.ulSB,
+				aulBBD, tBBDLen, aucHeader);
+		}
+		vSet6SummaryInfo(pFile, pPPS,
+			aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
+		break;
+	case 8:
+		vGet8LstInfo(pFile, pPPS,
+			aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
+		vGet8Stylesheet(pFile, pPPS,
+			aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
+		vGet8DopInfo(pFile, &pPPS->tTable,
+			aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
+		vGet8SepInfo(pFile, pPPS,
+			aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
+		vGet8PapInfo(pFile, pPPS,
+			aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
+		if (tOptions.eConversionType == conversion_ps ||
+		    tOptions.eConversionType == conversion_pdf) {
+			vGet8HdrFtrInfo(pFile, &pPPS->tTable,
+				aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
+		}
+		if (tOptions.eConversionType == conversion_draw ||
+		    tOptions.eConversionType == conversion_ps ||
+		    tOptions.eConversionType == conversion_xml ||
+		    tOptions.eConversionType == conversion_fmt_text ||
+		    tOptions.eConversionType == conversion_pdf) {
+			vGet8ChrInfo(pFile, pPPS,
+				aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
+		}
+		if (tOptions.eConversionType == conversion_draw ||
+		    tOptions.eConversionType == conversion_ps ||
+		    tOptions.eConversionType == conversion_pdf) {
+			vCreate8FontTable(pFile, pPPS,
+				aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
+		}
+		vSet8SummaryInfo(pFile, pPPS,
+			aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
+		break;
+	default:
+		DBG_DEC(iWordVersion);
+		DBG_FIXME();
+		werr(0, "Sorry, no property information");
+		break;
+	}
+
+	/* Temporarily: Correct the font table */
+	vCorrectFontTable(tOptions.eConversionType, tOptions.eEncoding);
+} /* end of vGetPropertyInfo */
+
+/*
+ * ePropMod2RowInfo - Turn the Property Modifier into row information
+ *
+ * Returns: the row information
+ */
+row_info_enum
+ePropMod2RowInfo(USHORT usPropMod, int iWordVersion)
+{
+	row_block_type	tRow;
+	const UCHAR	*aucPropMod;
+	int	iLen;
+
+	TRACE_MSG("ePropMod2RowInfo");
+
+	aucPropMod = aucReadPropModListItem(usPropMod);
+	if (aucPropMod == NULL) {
+		return found_nothing;
+	}
+	iLen = (int)usGetWord(0, aucPropMod);
+
+	switch (iWordVersion) {
+	case 0:
+		return found_nothing;
+	case 1:
+	case 2:
+		return eGet2RowInfo(0, aucPropMod + 2, iLen, &tRow);
+	case 4:
+	case 5:
+		return found_nothing;
+	case 6:
+	case 7:
+		return eGet6RowInfo(0, aucPropMod + 2, iLen, &tRow);
+	case 8:
+		return eGet8RowInfo(0, aucPropMod + 2, iLen, &tRow);
+	default:
+		DBG_DEC(iWordVersion);
+		DBG_FIXME();
+		return found_nothing;
+	}
+} /* end of ePropMod2RowInfo */
diff --git a/propmod.c b/propmod.c
new file mode 100644
index 0000000..7a3cdbb
--- /dev/null
+++ b/propmod.c
@@ -0,0 +1,110 @@
+/*
+ * propmod.c
+ * Copyright (C) 2001-2003 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Build, read and destroy a list (array) of Word property modifiers
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "antiword.h"
+
+#if defined(DEBUG)
+#define ELEMENTS_TO_ADD	 3
+#else
+#define ELEMENTS_TO_ADD	30
+#endif /* DEBUG */
+
+/* Variables needed to write the property modifier list */
+static UCHAR	**ppAnchor = NULL;
+static size_t	tNextFree = 0;
+static size_t	tMaxElements = 0;
+
+
+/*
+ * vDestroyPropModList - destroy the property modifier list
+ */
+void
+vDestroyPropModList(void)
+{
+	size_t	tIndex;
+
+	DBG_MSG("vDestroyPropModList");
+
+	/* Free all the elements of the list */
+	for (tIndex = 0; tIndex < tNextFree; tIndex++) {
+		ppAnchor[tIndex] = xfree(ppAnchor[tIndex]);
+	}
+	/* Free the list itself */
+	ppAnchor = xfree(ppAnchor);
+	/* Reset all control variables */
+	tNextFree = 0;
+	tMaxElements = 0;
+} /* end of vDestroyPropModList */
+
+/*
+ * vAdd2PropModList - add an element to the property modifier list
+ */
+void
+vAdd2PropModList(const UCHAR *aucPropMod)
+{
+	size_t	tSize, tLen;
+
+	fail(aucPropMod == NULL);
+
+	NO_DBG_MSG("vAdd2PropModList");
+
+	if (tNextFree >= tMaxElements) {
+		tMaxElements += ELEMENTS_TO_ADD;
+		tSize = tMaxElements * sizeof(UCHAR **);
+		ppAnchor = xrealloc(ppAnchor, tSize);
+	}
+	NO_DBG_DEC(tNextFree);
+
+	tLen = 2 + (size_t)usGetWord(0, aucPropMod);
+	NO_DBG_HEX(tLen);
+	NO_DBG_PRINT_BLOCK(pucPropMod, tLen);
+	ppAnchor[tNextFree] = xmalloc(tLen);
+	memcpy(ppAnchor[tNextFree], aucPropMod, tLen);
+	tNextFree++;
+} /* end of vAdd2PropModList */
+
+/*
+ * aucReadPropModListItem - get an item of the property modifier list
+ */
+const UCHAR *
+aucReadPropModListItem(USHORT usPropMod)
+{
+	static UCHAR	aucBuffer[4];
+	size_t	tIndex;
+
+	if (usPropMod == IGNORE_PROPMOD) {
+		/* This Properties Modifier must be ignored */
+		return NULL;
+	}
+
+	if (!odd(usPropMod)) {
+		/* Variant 1: The information is in the input ifself */
+		aucBuffer[0] = 2;
+		aucBuffer[1] = 0;
+		aucBuffer[2] = (UCHAR)((usPropMod & 0x00fe) >> 1);
+		aucBuffer[3] = (UCHAR)((usPropMod & 0xff00) >> 8);
+		return aucBuffer;
+	}
+
+	if (ppAnchor == NULL) {
+		/* No information available */
+		return NULL;
+	}
+
+	/* Variant 2: The input contains an index */
+	tIndex = (size_t)(usPropMod >> 1);
+	if (tIndex >= tNextFree) {
+		DBG_HEX(usPropMod);
+		DBG_DEC(tIndex);
+		DBG_DEC(tNextFree);
+		return NULL;
+	}
+	return ppAnchor[tIndex];
+} /* end of aucGetPropModListItem */
diff --git a/riscos.c b/riscos.c
new file mode 100644
index 0000000..78bd0fd
--- /dev/null
+++ b/riscos.c
@@ -0,0 +1,251 @@
+/*
+ * riscos.c
+ * Copyright (C) 2001,2002 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * RISC OS only functions
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include "DeskLib:Error.h"
+#include "DeskLib:SWI.h"
+#include "antiword.h"
+
+#if !defined(DrawFile_Render)
+#define DrawFile_Render		0x045540
+#endif /* !DrawFile_Render */
+#if !defined(JPEG_Info)
+#define JPEG_Info		0x049980
+#endif /* !JPEG_Info */
+
+/*
+ * werr - write an error message and exit if needed
+ */
+void
+werr(int iFatal, const char *szFormat, ...)
+{
+	va_list tArg;
+
+	va_start(tArg, szFormat);
+	Error_Report(iFatal, (char *)szFormat, tArg);
+	va_end(tArg);
+	switch (iFatal) {
+	case 0:		/* The message is just a warning, so no exit */
+		return;
+	case 1:		/* Fatal error with a standard exit */
+		exit(EXIT_FAILURE);
+	default:	/* Fatal error with a non-standard exit */
+		exit(iFatal);
+	}
+} /* end of werr */
+
+/*
+ * iGetFiletype
+ * This function will get the filetype of the given file.
+ * returns the filetype.
+ */
+int
+iGetFiletype(const char *szFilename)
+{
+	os_error	*e;
+	int		iType;
+
+	fail(szFilename == NULL || szFilename[0] == '\0');
+
+	e = SWI(2, 7, SWI_OS_File | XOS_Bit,
+		23, szFilename,
+		NULL, NULL, NULL, NULL, NULL, NULL, &iType);
+	if (e == NULL) {
+		return iType;
+	}
+	werr(0, "Get Filetype error %d: %s", e->errnum, e->errmess);
+	return -1;
+} /* end of iGetFiletype */
+
+/*
+ * vSetFiletype
+ * This procedure will set the filetype of the given file to the given
+ * type.
+ */
+void
+vSetFiletype(const char *szFilename, int iFiletype)
+{
+	os_error	*e;
+
+	fail(szFilename == NULL || szFilename[0] == '\0');
+
+	if (iFiletype < 0x000 || iFiletype > 0xfff) {
+		return;
+	}
+	e = SWI(3, 0, SWI_OS_File | XOS_Bit,
+		18, szFilename, iFiletype);
+	if (e != NULL) {
+		switch (e->errnum) {
+		case 0x000113:	/* ROM */
+		case 0x0104e1:	/* Read-only floppy DOSFS */
+		case 0x0108c9:	/* Read-only floppy ADFS */
+		case 0x013803:	/* Read-only ArcFS */
+		case 0x80344a:	/* CD-ROM */
+			break;
+		default:
+			werr(0, "Set Filetype error %d: %s",
+				e->errnum, e->errmess);
+			break;
+		}
+	}
+} /* end of vSetFileType */
+
+/*
+ * Check if the directory part of the given file exists, make the directory
+ * if it does not exist yet.
+ * Returns TRUE in case of success, otherwise FALSE.
+ */
+BOOL
+bMakeDirectory(const char *szFilename)
+{
+	os_error	*e;
+	char	*pcLastDot;
+	int	iObjectType;
+	char	szDirectory[PATH_MAX+1];
+
+	DBG_MSG("bMakeDirectory");
+	fail(szFilename == NULL || szFilename[0] == '\0');
+	DBG_MSG(szFilename);
+
+	if (strlen(szFilename) >= sizeof(szDirectory)) {
+		DBG_DEC(strlen(szFilename));
+		return FALSE;
+	}
+	strcpy(szDirectory, szFilename);
+	pcLastDot = strrchr(szDirectory, '.');
+	if (pcLastDot == NULL) {
+		/* No directory equals current directory */
+		DBG_MSG("No directory part given");
+		return TRUE;
+	}
+	*pcLastDot = '\0';
+	DBG_MSG(szDirectory);
+	/* Check if the name exists */
+	e = SWI(2, 1, SWI_OS_File | XOS_Bit,
+		17, szDirectory,
+		&iObjectType);
+	if (e != NULL) {
+		werr(0, "Directory check %d: %s", e->errnum, e->errmess);
+		return FALSE;
+	}
+	if (iObjectType == 2) {
+		/* The name exists and it is a directory */
+		DBG_MSG("The directory already exists");
+		return TRUE;
+	}
+	if (iObjectType != 0) {
+		/* The name exists and it is not a directory */
+		DBG_DEC(iObjectType);
+		return FALSE;
+	}
+	/* The name does not exist, make the directory */
+	e = SWI(5, 0, SWI_OS_File | XOS_Bit,
+		8, szDirectory, 0, 0, 0);
+	if (e != NULL) {
+		werr(0, "I can't make a directory %d: %s",
+			e->errnum, e->errmess);
+		return FALSE;
+	}
+	return TRUE;
+} /* end of bMakeDirectory */
+
+/*
+ * iReadCurrentAlphabetNumber
+ * This function reads the current Alphabet number.
+ * Returns the current Alphabet number when successful, otherwise -1
+ */
+int
+iReadCurrentAlphabetNumber(void)
+{
+	os_error	*e;
+	int		iAlphabetNumber;
+
+	e = SWI(2, 2, SWI_OS_Byte | XOS_Bit,
+		71, 127,
+		NULL, &iAlphabetNumber);
+	if (e == NULL) {
+		return iAlphabetNumber;
+	}
+	werr(0, "Read alphabet error %d: %s", e->errnum, e->errmess);
+	return -1;
+} /* end of iReadCurrentAlphabetNumber */
+
+/*
+ * iGetRiscOsVersion - get the RISC OS version number
+ *
+ * returns the RISC OS version * 100
+ */
+int
+iGetRiscOsVersion(void)
+{
+	os_error	*e;
+	int		iVersion;
+
+	e = SWI(3, 2, SWI_OS_Byte | XOS_Bit,
+		129, 0, 0xff,
+		NULL, &iVersion);
+	if (e != NULL) {
+		werr(0, "Read RISC OS version error %d: %s",
+			e->errnum, e->errmess);
+		return 0;
+	}
+	switch (iVersion) {
+	case 0xa0:	/* Arthur 1.20 */
+		return 120;
+	case 0xa1:	/* RISC OS 2.00 */
+		return 200;
+	case 0xa2:	/* RISC OS 2.01 */
+		return 201;
+	case 0xa3:	/* RISC OS 3.00 */
+		return 300;
+	case 0xa4:	/* RISC OS 3.1x */
+		return 310;
+	case 0xa5:	/* RISC OS 3.50 */
+		return 350;
+	case 0xa6:	/* RISC OS 3.60 */
+		return 360;
+	case 0xa7:	/* RISC OS 3.7x */
+		return 370;
+	case 0xa8:	/* RISC OS 4.0x */
+		return 400;
+	default:
+		if (iVersion >= 0xa9 && iVersion <= 0xaf) {
+			/* RISC OS 4.10 and up */
+			return 410;
+		}
+		/* Unknown version */
+		return 0;
+	}
+} /* end of iGetRiscOsVersion */
+
+#if defined(DEBUG)
+BOOL
+bGetJpegInfo(UCHAR *pucJpeg, size_t tJpegSize)
+{
+	os_error	*e;
+	int	iReg0, iReg4, iReg5;
+
+	e = SWI(3, 6, JPEG_Info | XOS_Bit,
+		0x00, pucJpeg, tJpegSize,
+		&iReg0, NULL, NULL, NULL, &iReg4, &iReg5);
+	if (e == NULL) {
+		if (iReg0 & BIT(2)) {
+			DBG_MSG("Pixel density is a simple ratio");
+		} else {
+			DBG_MSG("Pixel density is in dpi");
+		}
+		DBG_DEC(iReg4);
+		DBG_DEC(iReg5);
+		return TRUE;
+	}
+	werr(0, "JPEG Info error %d: %s", e->errnum, e->errmess);
+	return FALSE;
+} /* end of bGetJpegInfo */
+#endif /* DEBUG */
diff --git a/rowlist.c b/rowlist.c
new file mode 100644
index 0000000..a3dd2fb
--- /dev/null
+++ b/rowlist.c
@@ -0,0 +1,117 @@
+/*
+ * rowlist.c
+ * Copyright (C) 1998-2004 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Build, read and destroy a list of Word table-row information
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "antiword.h"
+
+/*
+ * Private structure to hide the way the information
+ * is stored from the rest of the program
+ */
+typedef struct row_desc_tag {
+	row_block_type		tInfo;
+	struct row_desc_tag	*pNext;
+} row_desc_type;
+
+/* Variables needed to write the Row Information List */
+static row_desc_type	*pAnchor = NULL;
+static row_desc_type	*pRowLast = NULL;
+/* Variable needed to read the Row Information List */
+static row_desc_type	*pRowCurrent = NULL;
+
+
+/*
+ * vDestroyRowInfoList - destroy the Row Information List
+ */
+void
+vDestroyRowInfoList(void)
+{
+	row_desc_type	*pCurr, *pNext;
+
+	DBG_MSG("vDestroyRowInfoList");
+
+	/* Free the Row Information List */
+	pCurr = pAnchor;
+	while (pCurr != NULL) {
+		pNext = pCurr->pNext;
+		pCurr = xfree(pCurr);
+		pCurr = pNext;
+	}
+	pAnchor = NULL;
+	/* Reset all control variables */
+	pRowLast = NULL;
+	pRowCurrent = NULL;
+} /* end of vDestroyRowInfoList */
+
+/*
+ * vAdd2RowInfoList - Add an element to the Row Information List
+ */
+void
+vAdd2RowInfoList(const row_block_type *pRowBlock)
+{
+	row_desc_type	*pListMember;
+	short		*psTmp;
+	int		iIndex;
+
+	fail(pRowBlock == NULL);
+
+	if (pRowBlock->ulFileOffsetStart == FC_INVALID ||
+	    pRowBlock->ulFileOffsetEnd == FC_INVALID ||
+	    pRowBlock->ulFileOffsetStart == pRowBlock->ulFileOffsetEnd) {
+		DBG_HEX_C(pRowBlock->ulFileOffsetStart != FC_INVALID,
+			pRowBlock->ulFileOffsetStart);
+		DBG_HEX_C(pRowBlock->ulFileOffsetEnd != FC_INVALID,
+			pRowBlock->ulFileOffsetEnd);
+		return;
+	}
+
+	NO_DBG_HEX(pRowBlock->ulFileOffsetStart);
+	NO_DBG_HEX(pRowBlock->ulFileOffsetEnd);
+	NO_DBG_DEC(pRowBlock->ucNumberOfColumns);
+
+	/* Create the new list member */
+	pListMember = xmalloc(sizeof(row_desc_type));
+	/* Fill the new list member */
+	pListMember->tInfo = *pRowBlock;
+	pListMember->pNext = NULL;
+	/* Correct the values where needed */
+	for (iIndex = 0, psTmp = pListMember->tInfo.asColumnWidth;
+	     iIndex < (int)pListMember->tInfo.ucNumberOfColumns;
+	     iIndex++, psTmp++) {
+		if (*psTmp < 0) {
+			*psTmp = 0;
+			DBG_MSG("The column width was negative");
+		}
+	}
+	/* Add the new member to the list */
+	if (pAnchor == NULL) {
+		pAnchor = pListMember;
+		pRowCurrent = pListMember;
+	} else {
+		fail(pRowLast == NULL);
+		pRowLast->pNext = pListMember;
+	}
+	pRowLast = pListMember;
+} /* end of vAdd2RowInfoList */
+
+/*
+ * Get the next item in the Row Information List
+ */
+const row_block_type *
+pGetNextRowInfoListItem(void)
+{
+	const row_block_type	*pItem;
+
+	if (pRowCurrent == NULL) {
+		return NULL;
+	}
+	pItem = &pRowCurrent->tInfo;
+	pRowCurrent = pRowCurrent->pNext;
+	return pItem;
+} /* end of pGetNextRowInfoListItem */
diff --git a/saveas.c b/saveas.c
new file mode 100644
index 0000000..678ff04
--- /dev/null
+++ b/saveas.c
@@ -0,0 +1,387 @@
+/*
+ * saveas.c
+ * Copyright (C) 1998-2001 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Functions to save the results as a textfile or a drawfile
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "DeskLib:Menu.h"
+#include "DeskLib:Save.h"
+#include "DeskLib:Template.h"
+#include "DeskLib:Window.h"
+#include "drawfile.h"
+#include "antiword.h"
+
+/* The window handle of the save window */
+static window_handle	tSaveWindow = 0;
+
+/* Xfer_send box fields */
+#define DRAG_SPRITE	3
+#define OK_BUTTON	0
+#define CANCEL_BUTTON	(-1)
+#define FILENAME_ICON	2
+
+
+/*
+ * saveas - a wrapper around Save_InitSaveWindowhandler
+ */
+static void
+saveas(int iFileType, char *szOutfile, size_t tEstSize,
+	save_filesaver save_function, void *pvReference)
+{
+	TRACE_MSG("saveas");
+
+	if (tSaveWindow == 0) {
+		tSaveWindow = Window_Create("xfer_send", template_TITLEMIN);
+	}
+	Icon_SetText(tSaveWindow, FILENAME_ICON, szOutfile);
+	Window_Show(tSaveWindow, open_UNDERPOINTER);
+	(void)Save_InitSaveWindowHandler(tSaveWindow, FALSE, TRUE, TRUE,
+		DRAG_SPRITE, OK_BUTTON, CANCEL_BUTTON, FILENAME_ICON,
+		save_function, NULL, NULL, tEstSize, iFileType, pvReference);
+} /* end of saveas */
+
+static BOOL
+bWrite2File(void *pvBytes, size_t tSize, FILE *pFile, const char *szFilename)
+{
+	if (fwrite(pvBytes, sizeof(char), tSize, pFile) != tSize) {
+		werr(0, "I can't write to '%s'", szFilename);
+		return FALSE;
+	}
+	return TRUE;
+} /* end of bWrite2File */
+
+/*
+ * bText2File - Save the generated draw file to a Text file
+ */
+static BOOL
+bText2File(char *szFilename, void *pvHandle)
+{
+	FILE	*pFile;
+	diagram_type	*pDiag;
+	drawfile_object	*pObj;
+	drawfile_text	*pText;
+	const char	*pcTmp;
+	int	iToGo, iX, iYtopPrev, iHeight, iLines;
+	BOOL	bFirst, bIndent, bSuccess;
+
+	TRACE_MSG("bText2File");
+
+	fail(szFilename == NULL || szFilename[0] == '\0');
+	fail(pvHandle == NULL);
+
+	DBG_MSG(szFilename);
+
+	pDiag = (diagram_type *)pvHandle;
+	pFile = fopen(szFilename, "w");
+	if (pFile == NULL) {
+		werr(0, "I can't open '%s' for writing", szFilename);
+		return FALSE;
+	}
+	bFirst = TRUE;
+	iYtopPrev = 0;
+	iHeight = (int)lWord2DrawUnits20(DEFAULT_FONT_SIZE);
+	bSuccess = TRUE;
+	fail(pDiag->tInfo.length < offsetof(drawfile_diagram, objects));
+	iToGo = pDiag->tInfo.length - offsetof(drawfile_diagram, objects);
+	DBG_DEC(iToGo);
+	pcTmp = (const char *)pDiag->tInfo.data +
+				offsetof(drawfile_diagram, objects);
+	while (iToGo > 0 && bSuccess) {
+		pObj = (drawfile_object *)pcTmp;
+		switch (pObj->type) {
+		case drawfile_TYPE_TEXT:
+			pText = &pObj->data.text;
+			/* Compute the number of lines */
+			iLines = (iYtopPrev - pText->bbox.max.y +
+					iHeight / 2) / iHeight;
+			DBG_DEC_C(iLines < 0, iYtopPrev);
+			DBG_DEC_C(iLines < 0, pText->bbox.max.y);
+			fail(iLines < 0);
+			bIndent = iLines > 0 || bFirst;
+			bFirst = FALSE;
+			/* Print the newlines */
+			while (iLines > 0 && bSuccess) {
+				bSuccess = bWrite2File("\n",
+					1, pFile, szFilename);
+				iLines--;
+			}
+			/* Print the indentation */
+			if (bIndent && bSuccess) {
+				for (iX = Drawfile_ScreenToDraw(8);
+				     iX <= pText->bbox.min.x && bSuccess;
+				     iX += Drawfile_ScreenToDraw(16)) {
+					bSuccess = bWrite2File(" ",
+						1, pFile, szFilename);
+				}
+			}
+			if (!bSuccess) {
+				break;
+			}
+			/* Print the text object */
+			bSuccess = bWrite2File(pText->text,
+				strlen(pText->text), pFile, szFilename);
+			/* Setup for the next object */
+			iYtopPrev = pText->bbox.max.y;
+			iHeight = pText->bbox.max.y - pText->bbox.min.y;
+			break;
+		case drawfile_TYPE_FONT_TABLE:
+		case drawfile_TYPE_PATH:
+		case drawfile_TYPE_SPRITE:
+		case drawfile_TYPE_JPEG:
+			/* These are not relevant in a textfile */
+			break;
+		default:
+			DBG_DEC(pObj->type);
+			bSuccess = FALSE;
+			break;
+		}
+		pcTmp += pObj->size;
+		iToGo -= pObj->size;
+	}
+	DBG_DEC_C(iToGo != 0, iToGo);
+	if (bSuccess) {
+		bSuccess = bWrite2File("\n", 1, pFile, szFilename);
+	}
+	(void)fclose(pFile);
+	if (bSuccess) {
+		vSetFiletype(szFilename, FILETYPE_TEXT);
+	} else {
+		(void)remove(szFilename);
+		werr(0, "Unable to save textfile '%s'", szFilename);
+	}
+	return bSuccess;
+} /* end of bText2File */
+
+/*
+ * bSaveTextfile - save the diagram as a text file
+ */
+BOOL
+bSaveTextfile(event_pollblock *pEvent, void *pvReference)
+{
+	diagram_type	*pDiag;
+	size_t	tRecLen, tNbrRecs, tEstSize;
+
+	TRACE_MSG("bSaveTextfile");
+
+	fail(pEvent == NULL);
+	fail(pvReference == NULL);
+
+	pDiag = (diagram_type *)pvReference;
+
+	switch (pEvent->type) {
+	case event_SEND:	/* From a menu */
+		fail(pEvent->data.message.header.action != message_MENUWARN);
+		if (menu_currentopen != pDiag->pSaveMenu ||
+		    pEvent->data.message.data.menuwarn.selection[0] !=
+							SAVEMENU_SAVETEXT) {
+			return FALSE;
+		}
+		break;
+	case event_KEY:		/* From a key short cut */
+		if (pEvent->data.key.caret.window != pDiag->tMainWindow) {
+			return FALSE;
+		}
+		break;
+	default:
+		DBG_DEC(pEvent->type);
+		return FALSE;
+	}
+
+	tRecLen = sizeof(drawfile_text) + DEFAULT_SCREEN_WIDTH * 2 / 3;
+	tNbrRecs = pDiag->tInfo.length / tRecLen + 1;
+	tEstSize = tNbrRecs * DEFAULT_SCREEN_WIDTH * 2 / 3;
+	DBG_DEC(tEstSize);
+
+	saveas(FILETYPE_TEXT, "WordText", tEstSize, bText2File, pDiag);
+	return TRUE;
+} /* end of bSaveTextfile */
+
+/*
+ * bDraw2File - Save the generated draw file to a Draw file
+ *
+ * Remark: This is not a simple copy action. The origin of the
+ * coordinates (0,0) must move from the top-left corner to the
+ * bottom-left corner.
+ */
+static BOOL
+bDraw2File(char *szFilename, void *pvHandle)
+{
+	FILE		*pFile;
+	diagram_type	*pDiagram;
+	wimp_box	*pBbox;
+	drawfile_object	*pObj;
+	drawfile_text	*pText;
+	drawfile_path	*pPath;
+	drawfile_sprite	*pSprite;
+	drawfile_jpeg	*pJpeg;
+	int	*piPath;
+	char	*pcTmp;
+	int	iYadd, iToGo, iSize;
+	BOOL	bSuccess;
+
+	TRACE_MSG("bDraw2File");
+
+	fail(szFilename == NULL || szFilename[0] == '\0');
+	fail(pvHandle == NULL);
+
+	NO_DBG_MSG(szFilename);
+
+	pDiagram = (diagram_type *)pvHandle;
+	pFile = fopen(szFilename, "wb");
+	if (pFile == NULL) {
+		werr(0, "I can't open '%s' for writing", szFilename);
+		return FALSE;
+	}
+	iToGo = pDiagram->tInfo.length;
+	DBG_DEC(iToGo);
+	pcTmp = pDiagram->tInfo.data;
+	bSuccess = bWrite2File(pcTmp,
+			offsetof(drawfile_diagram, bbox), pFile, szFilename);
+	if (bSuccess) {
+	  	pcTmp += offsetof(drawfile_diagram, bbox);
+		iToGo -= offsetof(drawfile_diagram, bbox);
+		pBbox = (wimp_box *)pcTmp;
+		iYadd = -pBbox->min.y;
+		pBbox->min.y += iYadd;
+		pBbox->max.y += iYadd;
+		bSuccess = bWrite2File(pcTmp,
+				sizeof(*pBbox), pFile, szFilename);
+		iToGo -= sizeof(*pBbox);
+		DBG_DEC(iToGo);
+		pcTmp += sizeof(*pBbox);
+	} else {
+		iYadd = 0;
+	}
+	while (iToGo > 0 && bSuccess) {
+		pObj = (drawfile_object *)pcTmp;
+		iSize = pObj->size;
+		switch (pObj->type) {
+		case drawfile_TYPE_FONT_TABLE:
+			bSuccess = bWrite2File(pcTmp,
+					iSize, pFile, szFilename);
+			pcTmp += iSize;
+			iToGo -= iSize;
+			break;
+		case drawfile_TYPE_TEXT:
+			pText = &pObj->data.text;
+			/* First correct the coordinates */
+			pText->bbox.min.y += iYadd;
+			pText->bbox.max.y += iYadd;
+			pText->base.y += iYadd;
+			/* Now write the information to file */
+			bSuccess = bWrite2File(pcTmp,
+					iSize, pFile, szFilename);
+			pcTmp += pObj->size;
+			iToGo -= pObj->size;
+			break;
+		case drawfile_TYPE_PATH:
+			pPath = &pObj->data.path;
+			/* First correct the coordinates */
+			pPath->bbox.min.y += iYadd;
+			pPath->bbox.max.y += iYadd;
+			/* Now write the information to file */
+			bSuccess = bWrite2File(pPath,
+				sizeof(*pPath), pFile, szFilename);
+			pcTmp += sizeof(*pPath);
+			iSize = pObj->size - sizeof(*pPath);
+			fail(iSize < 14 * sizeof(int));
+			/* Second correct the path coordinates */
+			piPath = xmalloc(iSize);
+			memcpy(piPath, pcTmp, iSize);
+			piPath[ 2] += iYadd;
+			piPath[ 5] += iYadd;
+			piPath[ 8] += iYadd;
+			piPath[11] += iYadd;
+			if (bSuccess) {
+				bSuccess = bWrite2File(piPath,
+					iSize, pFile, szFilename);
+				pcTmp += iSize;
+			}
+			piPath = xfree(piPath);
+			iToGo -= pObj->size;
+			break;
+		case drawfile_TYPE_SPRITE:
+			pSprite = &pObj->data.sprite;
+			/* First correct the coordinates */
+			pSprite->bbox.min.y += iYadd;
+			pSprite->bbox.max.y += iYadd;
+			/* Now write the information to file */
+			bSuccess = bWrite2File(pcTmp,
+					iSize, pFile, szFilename);
+			pcTmp += pObj->size;
+			iToGo -= pObj->size;
+			break;
+		case drawfile_TYPE_JPEG:
+			pJpeg = &pObj->data.jpeg;
+			/* First correct the coordinates */
+			pJpeg->bbox.min.y += iYadd;
+			pJpeg->bbox.max.y += iYadd;
+			pJpeg->trfm.entries[2][1] += iYadd;
+			/* Now write the information to file */
+			bSuccess = bWrite2File(pcTmp,
+					iSize, pFile, szFilename);
+			pcTmp += pObj->size;
+			iToGo -= pObj->size;
+			break;
+		default:
+			DBG_DEC(pObj->type);
+			bSuccess = FALSE;
+			break;
+		}
+	}
+	DBG_DEC_C(iToGo != 0, iToGo);
+	(void)fclose(pFile);
+	if (bSuccess) {
+		vSetFiletype(szFilename, FILETYPE_DRAW);
+	} else {
+		(void)remove(szFilename);
+		werr(0, "Unable to save drawfile '%s'", szFilename);
+	}
+	return bSuccess;
+} /* end of bDraw2File */
+
+/*
+ * bSaveDrawfile - save the diagram as a draw file
+ */
+BOOL
+bSaveDrawfile(event_pollblock *pEvent, void *pvReference)
+{
+	diagram_type	*pDiag;
+	size_t		tEstSize;
+
+	TRACE_MSG("bSaveDrawfile");
+
+	fail(pEvent == NULL);
+	fail(pvReference == NULL);
+
+	pDiag = (diagram_type *)pvReference;
+
+	switch (pEvent->type) {
+	case event_SEND:	/* From a menu */
+		fail(pEvent->data.message.header.action != message_MENUWARN);
+		if (menu_currentopen != pDiag->pSaveMenu ||
+		    pEvent->data.message.data.menuwarn.selection[0] !=
+							SAVEMENU_SAVEDRAW) {
+			return FALSE;
+		}
+		break;
+	case event_KEY:		/* From a key short cut */
+		if (pEvent->data.key.caret.window != pDiag->tMainWindow) {
+			return FALSE;
+		}
+		break;
+	default:
+		DBG_DEC(pEvent->type);
+		return FALSE;
+	}
+
+	tEstSize = pDiag->tInfo.length;
+	DBG_DEC(tEstSize);
+
+	saveas(FILETYPE_DRAW, "WordDraw", tEstSize, bDraw2File, pDiag);
+	return TRUE;
+} /* end of bSaveDrawfile */
diff --git a/sectlist.c b/sectlist.c
new file mode 100644
index 0000000..016d1b8
--- /dev/null
+++ b/sectlist.c
@@ -0,0 +1,165 @@
+/*
+ * sectlist.c
+ * Copyright (C) 2001-2004 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Build, read and destroy list(s) of Word section information
+ */
+
+#include <stddef.h>
+#include <string.h>
+#include "antiword.h"
+
+
+/*
+ * Private structure to hide the way the information
+ * is stored from the rest of the program
+ */
+typedef struct section_mem_tag {
+	section_block_type	tInfo;
+	ULONG			ulCharPos;
+	struct section_mem_tag	*pNext;
+} section_mem_type;
+
+/* Variables needed to write the Section Information List */
+static section_mem_type	*pAnchor = NULL;
+static section_mem_type	*pSectionLast = NULL;
+
+
+/*
+ * vDestroySectionInfoList - destroy the Section Information List
+ */
+void
+vDestroySectionInfoList(void)
+{
+	section_mem_type	*pCurr, *pNext;
+
+	DBG_MSG("vDestroySectionInfoList");
+
+	/* Free the Section Information List */
+	pCurr = pAnchor;
+	while (pCurr != NULL) {
+		pNext = pCurr->pNext;
+		pCurr = xfree(pCurr);
+		pCurr = pNext;
+	}
+	pAnchor = NULL;
+	/* Reset all control variables */
+	pSectionLast = NULL;
+} /* end of vDestroySectionInfoList */
+
+/*
+ * vAdd2SectionInfoList - Add an element to the Section Information List
+ */
+void
+vAdd2SectionInfoList(const section_block_type *pSection, ULONG ulCharPos)
+{
+	section_mem_type	*pListMember;
+
+	fail(pSection == NULL);
+
+	/* Create list member */
+	pListMember = xmalloc(sizeof(section_mem_type));
+	/* Fill the list member */
+	pListMember->tInfo = *pSection;
+	pListMember->ulCharPos = ulCharPos;
+	pListMember->pNext = NULL;
+	/* Add the new member to the list */
+	if (pAnchor == NULL) {
+		pAnchor = pListMember;
+	} else {
+		fail(pSectionLast == NULL);
+		pSectionLast->pNext = pListMember;
+	}
+	pSectionLast = pListMember;
+} /* vAdd2SectionInfoList */
+
+/*
+ * vGetDefaultSection - fill the section struct with default values
+ */
+void
+vGetDefaultSection(section_block_type *pSection)
+{
+	(void)memset(pSection, 0, sizeof(*pSection));
+	pSection->bNewPage = TRUE;
+} /* end of vGetDefaultSection */
+
+/*
+ * vDefault2SectionInfoList - Add a default to the Section Information List
+ */
+void
+vDefault2SectionInfoList(ULONG ulCharPos)
+{
+	section_block_type	tSection;
+
+	vGetDefaultSection(&tSection);
+	vAdd2SectionInfoList(&tSection, ulCharPos);
+} /* end of vDefault2SectionInfoList */
+
+/*
+ * pGetSectionInfo - get the section information
+ */
+const section_block_type *
+pGetSectionInfo(const section_block_type *pOld, ULONG ulCharPos)
+{
+	const section_mem_type	*pCurr;
+
+	if (pOld == NULL || ulCharPos == 0) {
+		if (pAnchor == NULL) {
+			/* There are no records, make one */
+			vDefault2SectionInfoList(0);
+			fail(pAnchor == NULL);
+		}
+		/* The first record */
+		NO_DBG_MSG("First record");
+		return &pAnchor->tInfo;
+	}
+
+	NO_DBG_HEX(ulCharPos);
+	for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
+		NO_DBG_HEX(pCurr->ulCharPos);
+		if (ulCharPos == pCurr->ulCharPos ||
+		    ulCharPos + 1 == pCurr->ulCharPos) {
+			NO_DBG_HEX(pCurr->ulCharPos);
+			return &pCurr->tInfo;
+		}
+	}
+	return pOld;
+} /* end of pGetSectionInfo */
+
+/*
+ * tGetNumberOfSections - get the number of sections
+ */
+size_t
+tGetNumberOfSections(void)
+{
+	const section_mem_type	*pCurr;
+	size_t	tCounter;
+
+	for (tCounter = 0, pCurr = pAnchor;
+	     pCurr != NULL;
+	     tCounter++, pCurr = pCurr->pNext)
+		;	/* Empty */
+	return tCounter;
+} /* end of tGetNumberOfSections */
+
+/*
+ * ucGetSepHdrFtrSpecification - get the Heder/footer specification
+ */
+UCHAR
+ucGetSepHdrFtrSpecification(size_t tSectionNumber)
+{
+	const section_mem_type	*pCurr;
+	size_t	tIndex;
+
+	for (tIndex = 0, pCurr = pAnchor;
+	     tIndex < tSectionNumber && pCurr != NULL;
+	     tIndex++, pCurr = pCurr->pNext)
+		;	/* Empty */
+	if (pCurr == NULL) {
+		DBG_DEC(tSectionNumber);
+		DBG_FIXME();
+		return 0x00;
+	}
+	return pCurr->tInfo.ucHdrFtrSpecification;
+} /* end of ucGetSepHdrFtrSpecification */
diff --git a/startup.c b/startup.c
new file mode 100644
index 0000000..7e1b6d7
--- /dev/null
+++ b/startup.c
@@ -0,0 +1,145 @@
+/*
+ * startup.c
+ * Copyright (C) 1998-2001 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Try to force a single startup of !Antiword
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "DeskLib:Error.h"
+#include "DeskLib:Event.h"
+#include "DeskLib:SWI.h"
+#include "antiword.h"
+
+
+#if !defined(TaskManager_EnumerateTasks)
+#define TaskManager_EnumerateTasks	0x042681
+#endif /* TaskManager_EnumerateTasks */
+
+/*
+ * bIsMatch - decide whether the two strings match
+ *
+ * like strcmp, but this one ignores case
+ */
+static BOOL
+bIsMatch(const char *szStr1, const char *szStr2)
+{
+	const char	*pcTmp1, *pcTmp2;
+
+	for (pcTmp1 = szStr1, pcTmp2 = szStr2;
+	     *pcTmp1 != '\0';
+	     pcTmp1++, pcTmp2++) {
+		if (toupper(*pcTmp1) != toupper(*pcTmp2)) {
+			return FALSE;
+		}
+	}
+	return *pcTmp2 == '\0';
+} /* end of bIsMatch */
+
+/*
+ * tGetTaskHandle - get the task handle of the given task
+ *
+ * returns the task handle when found, otherwise 0
+ */
+static task_handle
+tGetTaskHandle(const char *szTaskname)
+{
+	const char	*pcTmp;
+	int	iReg0, iIndex;
+	int	aiBuffer[4];
+	char	szTmp[21];
+
+	iReg0 = 0;
+	do {
+		/* Get info on the next task */
+		Error_CheckFatal(SWI(3, 1, TaskManager_EnumerateTasks | XOS_Bit,
+			iReg0, aiBuffer, sizeof(aiBuffer), &iReg0));
+		/* Copy the (control character terminated) task name */
+		for (iIndex = 0, pcTmp = (const char *)aiBuffer[1];
+		     iIndex < elementsof(szTmp);
+		     iIndex++, pcTmp++) {
+			if (iscntrl(*pcTmp)) {
+				szTmp[iIndex] = '\0';
+				break;
+			}
+			szTmp[iIndex] = *pcTmp;
+		}
+		szTmp[elementsof(szTmp) - 1] = '\0';
+		if (bIsMatch(szTmp, szTaskname)) {
+			/* Task found */
+			return (task_handle)aiBuffer[0];
+		}
+	} while (iReg0 >= 0);
+
+	/* Task not found */
+	return 0;
+} /* end of tGetTaskHandle */
+
+int
+main(int argc, char **argv)
+{
+	message_block	tMsg;
+	task_handle	tTaskHandle;
+	size_t	tArgLen;
+	int	aiMessages[] = {0};
+	char	szCommand[512];
+
+	Event_Initialise3("StartUp", 310, aiMessages);
+
+	if (argc > 1) {
+		tArgLen = strlen(argv[1]);
+	} else {
+		tArgLen = 0;
+	}
+	if (tArgLen >= sizeof(tMsg.data.dataload.filename)) {
+		werr(1, "Input filename too long");
+		return EXIT_FAILURE;
+	}
+
+	tTaskHandle = tGetTaskHandle("antiword");
+
+	if (tTaskHandle == 0) {
+		/* Antiword is not active */
+		strcpy(szCommand, "chain:<Antiword$Dir>.!Antiword");
+		if (argc > 1) {
+			strcat(szCommand, " ");
+			strcat(szCommand, argv[1]);
+		}
+#if defined(DEBUG)
+		strcat(szCommand, " ");
+		strcat(szCommand, "2><Antiword$Dir>.Debug");
+#endif /* DEBUG */
+		system(szCommand);
+		/* If we reach here something has gone wrong */
+		return EXIT_FAILURE;
+	}
+
+	/* Antiword is active */
+	if (argc > 1) {
+		/*
+		 * Send the argument to Antiword by imitating a
+		 * drag-and-drop to Antiword's iconbar icon
+		 */
+		memset(&tMsg, 0, sizeof(tMsg));
+		tMsg.header.size = ROUND4(offsetof(message_block, data) +
+					offsetof(message_dataload, filename) +
+					1 + tArgLen);
+		tMsg.header.yourref = 0;
+		tMsg.header.action = message_DATALOAD;
+		tMsg.data.dataload.window = window_ICONBAR;
+		tMsg.data.dataload.icon = -1;
+		tMsg.data.dataload.size = 0;
+		tMsg.data.dataload.filetype = FILETYPE_MSWORD;
+		strcpy(tMsg.data.dataload.filename, argv[1]);
+		Error_CheckFatal(Wimp_SendMessage(event_SEND,
+						&tMsg, tTaskHandle, 0));
+		return EXIT_SUCCESS;
+	} else {
+		/* Give an error message and return */
+		werr(1, "Antiword is already running");
+		return EXIT_FAILURE;
+	}
+} /* end of main */
diff --git a/stylelist.c b/stylelist.c
new file mode 100644
index 0000000..09b5ab5
--- /dev/null
+++ b/stylelist.c
@@ -0,0 +1,487 @@
+/*
+ * stylelist.c
+ * Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Build, read and destroy a list of Word style information
+ */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <ctype.h>
+#include "antiword.h"
+
+
+/*
+ * Private structure to hide the way the information
+ * is stored from the rest of the program
+ */
+typedef struct style_mem_tag {
+	style_block_type	tInfo;
+	ULONG			ulSequenceNumber;
+	struct style_mem_tag	*pNext;
+} style_mem_type;
+
+/* Variables needed to write the Style Information List */
+static style_mem_type	*pAnchor = NULL;
+static style_mem_type	*pStyleLast = NULL;
+/* The type of conversion */
+static conversion_type	eConversionType = conversion_unknown;
+/* The character set encoding */
+static encoding_type	eEncoding = encoding_neutral;
+/* Values for efficiency reasons */
+static const style_mem_type	*pMidPtr = NULL;
+static BOOL		bMoveMidPtr = FALSE;
+static BOOL		bInSequence = TRUE;
+
+
+/*
+ * vDestroyStyleInfoList - destroy the Style Information List
+ */
+void
+vDestroyStyleInfoList(void)
+{
+	style_mem_type	*pCurr, *pNext;
+
+	DBG_MSG("vDestroyStyleInfoList");
+
+	/* Free the Style Information List */
+	pCurr = pAnchor;
+	while (pCurr != NULL) {
+		pNext = pCurr->pNext;
+		pCurr = xfree(pCurr);
+		pCurr = pNext;
+	}
+	pAnchor = NULL;
+	/* Reset all control variables */
+	pStyleLast = NULL;
+	pMidPtr = NULL;
+	bMoveMidPtr = FALSE;
+	bInSequence = TRUE;
+} /* end of vDestroyStyleInfoList */
+
+/*
+ * vConvertListCharacter - convert the list character
+ */
+static void
+vConvertListCharacter(UCHAR ucNFC, USHORT usListChar, char *szListChar)
+{
+	options_type	tOptions;
+	size_t	tLen;
+
+	fail(szListChar == NULL);
+	fail(szListChar[0] != '\0');
+
+	if (usListChar < 0x80 && isprint((int)usListChar)) {
+		DBG_CHR_C(isalnum((int)usListChar), usListChar);
+		szListChar[0] = (char)usListChar;
+		szListChar[1] = '\0';
+		return;
+	}
+
+	if (ucNFC != LIST_SPECIAL &&
+	    ucNFC != LIST_SPECIAL2 &&
+	    ucNFC != LIST_BULLETS) {
+		szListChar[0] = '.';
+		szListChar[1] = '\0';
+		return;
+	}
+
+	if (eConversionType == conversion_unknown ||
+	    eEncoding == encoding_neutral) {
+		vGetOptions(&tOptions);
+		eConversionType = tOptions.eConversionType;
+		eEncoding = tOptions.eEncoding;
+	}
+
+	switch (usListChar) {
+	case 0x0000: case 0x00b7: case 0x00fe: case  0xf021: case 0xf043:
+	case 0xf06c: case 0xf093: case 0xf0b7:
+		usListChar = 0x2022;	/* BULLET */
+		break;
+	case 0x0096: case 0xf02d:
+		usListChar = 0x2013;	/* EN DASH */
+		break;
+	case 0x00a8:
+		usListChar = 0x2666;	/* BLACK DIAMOND SUIT */
+		break;
+	case 0x00de:
+		usListChar = 0x21d2;	/* RIGHTWARDS DOUBLE ARROW */
+		break;
+	case 0x00e0: case 0xf074:
+		usListChar = 0x25ca;	/* LOZENGE */
+		break;
+	case 0x00e1:
+		usListChar = 0x2329;	/* LEFT ANGLE BRACKET */
+		break;
+	case 0xf020:
+		usListChar = 0x0020;	/* SPACE */
+		break;
+	case 0xf041:
+		usListChar = 0x270c;	/* VICTORY HAND */
+		break;
+	case 0xf066:
+		usListChar = 0x03d5;	/* GREEK PHI SYMBOL */
+		break;
+	case 0xf06e:
+		usListChar = 0x25a0;	/* BLACK SQUARE */
+		break;
+	case 0xf06f: case 0xf070: case 0xf0a8:
+		usListChar = 0x25a1;	/* WHITE SQUARE */
+		break;
+	case 0xf071:
+		usListChar = 0x2751;	/* LOWER RIGHT SHADOWED WHITE SQUARE */
+		break;
+	case 0xf075: case 0xf077:
+		usListChar = 0x25c6;	/* BLACK DIAMOND */
+		break;
+	case 0xf076:
+		usListChar = 0x2756;	/* BLACK DIAMOND MINUS WHITE X */
+		break;
+	case 0xf0a7:
+		usListChar = 0x25aa;	/* BLACK SMALL SQUARE */
+		break;
+	case 0xf0d8:
+		usListChar = 0x27a2;	/* RIGHTWARDS ARROWHEAD */
+		break;
+	case 0xf0e5:
+		usListChar = 0x2199;	/* SOUTH WEST ARROW */
+		break;
+	case 0xf0f0:
+		usListChar = 0x21e8;	/* RIGHTWARDS WHITE ARROW */
+		break;
+	case 0xf0fc:
+		usListChar = 0x2713;	/* CHECK MARK */
+		break;
+	default:
+		if ((usListChar >= 0xe000 && usListChar < 0xf900) ||
+		    (usListChar < 0x80 && !isprint((int)usListChar))) {
+			/*
+			 * All remaining private area characters and all
+			 * remaining non-printable ASCII characters to their
+			 * default bullet character
+			 */
+			DBG_HEX(usListChar);
+			DBG_FIXME();
+			if (ucNFC == LIST_SPECIAL || ucNFC == LIST_SPECIAL2) {
+				usListChar = 0x2190;	/* LEFTWARDS ARROW */
+			} else {
+				usListChar = 0x2022;	/* BULLET */
+			}
+		}
+		break;
+	}
+
+	if (eEncoding == encoding_utf_8) {
+		tLen = tUcs2Utf8(usListChar, szListChar, 4);
+		szListChar[tLen] = '\0';
+	} else {
+		switch (usListChar) {
+		case 0x03d5: case 0x25a1: case 0x25c6: case 0x25ca:
+		case 0x2751:
+			szListChar[0] = 'o';
+			break;
+		case 0x2013: case 0x2500:
+			szListChar[0] = '-';
+			break;
+		case 0x2190: case 0x2199: case 0x2329:
+			szListChar[0] = '<';
+			break;
+		case 0x21d2:
+			szListChar[0] = '=';
+			break;
+		case 0x21e8: case 0x27a2:
+			szListChar[0] = '>';
+			break;
+		case 0x25a0: case 0x25aa:
+			szListChar[0] = '.';
+			break;
+		case 0x2666:
+			szListChar[0] = OUR_DIAMOND;
+			break;
+		case 0x270c:
+			szListChar[0] = 'x';
+			break;
+		case 0x2713:
+			szListChar[0] = 'V';
+			break;
+		case 0x2756:
+			szListChar[0] = '*';
+			break;
+		case 0x2022:
+		default:
+			vGetBulletValue(eConversionType, eEncoding,
+					szListChar, 2);
+			break;
+		}
+		tLen = 1;
+	}
+	szListChar[tLen] = '\0';
+} /* end of vConvertListCharacter */
+
+/*
+ * eGetNumType - get the level type from the given level number
+ *
+ * Returns the level type
+ */
+level_type_enum
+eGetNumType(UCHAR ucNumLevel)
+{
+	switch (ucNumLevel) {
+	case  1: case  2: case  3: case  4: case  5:
+	case  6: case  7: case  8: case  9:
+		return level_type_outline;
+	case 10:
+		return level_type_numbering;
+	case 11:
+		return level_type_sequence;
+	case 12:
+		return level_type_pause;
+	default:
+		return level_type_none;
+	}
+} /* end of eGetNumType */
+
+/*
+ * vCorrectStyleValues - correct style values that Antiword can't use
+ */
+void
+vCorrectStyleValues(style_block_type *pStyleBlock)
+{
+	if (pStyleBlock->usBeforeIndent > 0x7fff) {
+		pStyleBlock->usBeforeIndent = 0;
+	} else if (pStyleBlock->usBeforeIndent > 2160) {
+		/* 2160 twips = 1.5 inches or 38.1 mm */
+		DBG_DEC(pStyleBlock->usBeforeIndent);
+		pStyleBlock->usBeforeIndent = 2160;
+	}
+	if (pStyleBlock->usIstd >= 1 &&
+	    pStyleBlock->usIstd <= 9 &&
+	    pStyleBlock->usBeforeIndent < HEADING_GAP) {
+		NO_DBG_DEC(pStyleBlock->usBeforeIndent);
+		pStyleBlock->usBeforeIndent = HEADING_GAP;
+	}
+
+	if (pStyleBlock->usAfterIndent > 0x7fff) {
+		pStyleBlock->usAfterIndent = 0;
+	} else if (pStyleBlock->usAfterIndent > 2160) {
+		/* 2160 twips = 1.5 inches or 38.1 mm */
+		DBG_DEC(pStyleBlock->usAfterIndent);
+		pStyleBlock->usAfterIndent = 2160;
+	}
+	if (pStyleBlock->usIstd >= 1 &&
+	    pStyleBlock->usIstd <= 9 &&
+	    pStyleBlock->usAfterIndent < HEADING_GAP) {
+		NO_DBG_DEC(pStyleBlock->usAfterIndent);
+		pStyleBlock->usAfterIndent = HEADING_GAP;
+	}
+
+	if (pStyleBlock->sLeftIndent < 0) {
+		pStyleBlock->sLeftIndent = 0;
+	}
+	if (pStyleBlock->sRightIndent > 0) {
+		pStyleBlock->sRightIndent = 0;
+	}
+	vConvertListCharacter(pStyleBlock->ucNFC,
+			pStyleBlock->usListChar,
+			pStyleBlock->szListChar);
+} /* end of vCorrectStyleValues */
+
+/*
+ * vAdd2StyleInfoList - Add an element to the Style Information List
+ */
+void
+vAdd2StyleInfoList(const style_block_type *pStyleBlock)
+{
+	style_mem_type	*pListMember;
+
+	fail(pStyleBlock == NULL);
+
+	NO_DBG_MSG("bAdd2StyleInfoList");
+
+	if (pStyleBlock->ulFileOffset == FC_INVALID) {
+		NO_DBG_DEC(pStyleBlock->usIstd);
+		return;
+	}
+
+	NO_DBG_HEX(pStyleBlock->ulFileOffset);
+	NO_DBG_DEC_C(pStyleBlock->sLeftIndent != 0,
+					pStyleBlock->sLeftIndent);
+	NO_DBG_DEC_C(pStyleBlock->sRightIndent != 0,
+					pStyleBlock->sRightIndent);
+	NO_DBG_DEC_C(pStyleBlock->bNumPause, pStyleBlock->bNumPause);
+	NO_DBG_DEC_C(pStyleBlock->usIstd != 0, pStyleBlock->usIstd);
+	NO_DBG_DEC_C(pStyleBlock->usStartAt != 1, pStyleBlock->usStartAt);
+	NO_DBG_DEC_C(pStyleBlock->usAfterIndent != 0,
+					pStyleBlock->usAfterIndent);
+	NO_DBG_DEC_C(pStyleBlock->ucAlignment != 0, pStyleBlock->ucAlignment);
+	NO_DBG_DEC(pStyleBlock->ucNFC);
+	NO_DBG_HEX(pStyleBlock->usListChar);
+
+	if (pStyleLast != NULL &&
+	    pStyleLast->tInfo.ulFileOffset == pStyleBlock->ulFileOffset) {
+		/*
+		 * If two consecutive styles share the same
+		 * offset, remember only the last style
+		 */
+		fail(pStyleLast->pNext != NULL);
+		pStyleLast->tInfo = *pStyleBlock;
+		/* Correct the values where needed */
+		vCorrectStyleValues(&pStyleLast->tInfo);
+		return;
+	}
+
+	/* Create list member */
+	pListMember = xmalloc(sizeof(style_mem_type));
+	/* Fill the list member */
+	pListMember->tInfo = *pStyleBlock;
+	pListMember->pNext = NULL;
+	/* Add the sequence number */
+	pListMember->ulSequenceNumber =
+			ulGetSeqNumber(pListMember->tInfo.ulFileOffset);
+	/* Correct the values where needed */
+	vCorrectStyleValues(&pListMember->tInfo);
+	/* Add the new member to the list */
+	if (pAnchor == NULL) {
+		pAnchor = pListMember;
+		/* For efficiency */
+		pMidPtr = pAnchor;
+		bMoveMidPtr = FALSE;
+		bInSequence = TRUE;
+	} else {
+		fail(pStyleLast == NULL);
+		pStyleLast->pNext = pListMember;
+		/* For efficiency */
+		if (bMoveMidPtr) {
+			pMidPtr = pMidPtr->pNext;
+			bMoveMidPtr = FALSE;
+		} else {
+			bMoveMidPtr = TRUE;
+		}
+		if (bInSequence) {
+			bInSequence = pListMember->ulSequenceNumber >
+					pStyleLast->ulSequenceNumber;
+		}
+	}
+	pStyleLast = pListMember;
+} /* end of vAdd2StyleInfoList */
+
+/*
+ * Get the record that follows the given recored in the Style Information List
+ */
+const style_block_type *
+pGetNextStyleInfoListItem(const style_block_type *pCurr)
+{
+	const style_mem_type	*pRecord;
+	size_t	tOffset;
+
+	if (pCurr == NULL) {
+		if (pAnchor == NULL) {
+			/* There are no records */
+			return NULL;
+		}
+		/* The first record is the only one without a predecessor */
+		return &pAnchor->tInfo;
+	}
+	tOffset = offsetof(style_mem_type, tInfo);
+	/* Many casts to prevent alignment warnings */
+	pRecord = (style_mem_type *)(void *)((char *)pCurr - tOffset);
+	fail(pCurr != &pRecord->tInfo);
+	if (pRecord->pNext == NULL) {
+		/* The last record has no successor */
+		return NULL;
+	}
+	return &pRecord->pNext->tInfo;
+} /* end of pGetNextStyleInfoListItem */
+
+/*
+ * Get the next text style
+ */
+const style_block_type *
+pGetNextTextStyle(const style_block_type *pCurr)
+{
+	const style_block_type	*pRecord;
+
+	pRecord = pCurr;
+	do {
+		pRecord = pGetNextStyleInfoListItem(pRecord);
+	} while (pRecord != NULL &&
+		 (pRecord->eListID == hdrftr_list ||
+		  pRecord->eListID == macro_list ||
+		  pRecord->eListID == annotation_list));
+	return pRecord;
+} /* end of pGetNextTextStyle */
+
+/*
+ * usGetIstd - get the istd that belongs to the given file offset
+ */
+USHORT
+usGetIstd(ULONG ulFileOffset)
+{
+	const style_mem_type	*pCurr, *pBest, *pStart;
+	ULONG	ulSeq, ulBest;
+
+	ulSeq = ulGetSeqNumber(ulFileOffset);
+	if (ulSeq == FC_INVALID) {
+		return ISTD_NORMAL;
+	}
+	NO_DBG_HEX(ulFileOffset);
+	NO_DBG_DEC(ulSeq);
+
+	if (bInSequence &&
+	    pMidPtr != NULL &&
+	    ulSeq > pMidPtr->ulSequenceNumber) {
+		/* The istd is in the second half of the chained list */
+		pStart = pMidPtr;
+	} else {
+		pStart = pAnchor;
+	}
+
+	pBest = NULL;
+	ulBest = 0;
+	for (pCurr = pStart; pCurr != NULL; pCurr = pCurr->pNext) {
+		if (pCurr->ulSequenceNumber != FC_INVALID &&
+		    (pBest == NULL || pCurr->ulSequenceNumber > ulBest) &&
+		    pCurr->ulSequenceNumber <= ulSeq) {
+			pBest = pCurr;
+			ulBest = pCurr->ulSequenceNumber;
+		}
+		if (bInSequence && pCurr->ulSequenceNumber > ulSeq) {
+			break;
+		}
+	}
+	NO_DBG_DEC(ulBest);
+
+	if (pBest == NULL) {
+		return ISTD_NORMAL;
+	}
+
+	NO_DBG_DEC(pBest->tInfo.usIstd);
+	return pBest->tInfo.usIstd;
+} /* end of usGetIstd */
+
+/*
+ * bStyleImpliesList - does style info implies being part of a list
+ *
+ * Decide whether the style information implies that the given paragraph is
+ * part of a list
+ *
+ * Returns TRUE when the paragraph is part of a list, otherwise FALSE
+ */
+BOOL
+bStyleImpliesList(const style_block_type *pStyle, int iWordVersion)
+{
+	fail(pStyle == NULL);
+	fail(iWordVersion < 0);
+
+	if (pStyle->usIstd >= 1 && pStyle->usIstd <= 9) {
+		/* These are heading levels */
+		return FALSE;
+	}
+	if (iWordVersion < 8) {
+		/* Check for old style lists */
+		return pStyle->ucNumLevel != 0;
+	}
+	/* Check for new style lists */
+	return pStyle->usListIndex != 0;
+} /* end of bStyleImpliesList */
diff --git a/stylesheet.c b/stylesheet.c
new file mode 100644
index 0000000..0cb4cc3
--- /dev/null
+++ b/stylesheet.c
@@ -0,0 +1,838 @@
+/*
+ * stylesheet.c
+ * Copyright (C) 2001-2004 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Build, read and destroy a list of stylesheet information
+ *
+ */
+
+#include <string.h>
+#include "antiword.h"
+
+
+#define SGC_PAP		1
+#define SGC_CHP		2
+
+/* Variables needed to describe the stylesheet list */
+static style_block_type	*atStyleInfo = NULL;
+static font_block_type	*atFontInfo = NULL;
+static BOOL		*abFilled = NULL;
+static size_t		tStdCount = 0;
+
+
+/*
+ * vDestroyStylesheetList - destroy the stylesheet list
+ */
+void
+vDestroyStylesheetList(void)
+{
+	DBG_MSG("vDestroyStylesheetList");
+
+	tStdCount = 0;
+	atStyleInfo = xfree(atStyleInfo);
+	atFontInfo = xfree(atFontInfo);
+	abFilled = xfree(abFilled);
+} /* end of vDestroyStylesheetList */
+
+/*
+ * vGetDefaultStyle - fill the style struct with default values
+ */
+static void
+vGetDefaultStyle(style_block_type *pStyle)
+{
+	(void)memset(pStyle, 0, sizeof(*pStyle));
+	pStyle->usIstd = ISTD_INVALID;
+	pStyle->usIstdNext = ISTD_INVALID;
+	pStyle->usStartAt = 1;
+	pStyle->ucListLevel = 9;
+} /* end of vGetDefaultStyle */
+
+/*
+ * vGetDefaultFont - fill the font struct with default values
+ */
+static void
+vGetDefaultFont(font_block_type *pFont, USHORT usDefaultFontNumber)
+{
+	(void)memset(pFont, 0, sizeof(*pFont));
+	pFont->usFontSize = DEFAULT_FONT_SIZE;
+	if (usDefaultFontNumber <= (USHORT)UCHAR_MAX) {
+		pFont->ucFontNumber = (UCHAR)usDefaultFontNumber;
+	} else {
+		DBG_DEC(usDefaultFontNumber);
+		DBG_FIXME();
+		pFont->ucFontNumber = 0;
+	}
+} /* end of vGetDefaultFont */
+
+/*
+ * iGetStyleIndex - get the index of the record with the specified istd
+ *
+ * returns the index when found, otherwise -1
+ */
+static int
+iGetStyleIndex(USHORT usIstd)
+{
+	int	iIndex;
+
+	fail(abFilled == NULL);
+
+	if (usIstd == ISTD_INVALID || abFilled == NULL) {
+		return -1;
+	}
+
+	for (iIndex = 0; iIndex < (int)tStdCount; iIndex++) {
+		if (abFilled[iIndex] && atStyleInfo[iIndex].usIstd == usIstd) {
+			/* The record is filled and the istd matches */
+			return iIndex;
+		}
+	}
+	return -1;
+} /* end of iGetStyleIndex */
+
+/*
+ * Get a build-in style for Winword 1/2
+ */
+static void
+vGetBuildinStyle(UCHAR ucStc, style_block_type *pStyle)
+{
+	fail(pStyle == NULL);
+
+	/* Start with de defaults */
+	vGetDefaultStyle(pStyle);
+
+	/* Add the build-in style info */
+	switch (ucStc) {
+	case 246:
+	case 247:
+	case 248:
+	case 249:
+	case 250:
+	case 255:
+		pStyle->sLeftIndent = 720;
+		break;
+	case 251:
+	case 252:
+		pStyle->sLeftIndent = 360;
+		break;
+	case 253:
+		pStyle->usBeforeIndent = 120;
+		break;
+	case 254:
+		pStyle->usBeforeIndent = 240;
+		break;
+	default:
+		if (ucStc >= 233 && ucStc <= 239) {
+			pStyle->sLeftIndent = (239 - (short)ucStc) * 360;
+		}
+		if (ucStc >= 225 && ucStc <= 232) {
+			pStyle->sLeftIndent = (232 - (short)ucStc) * 720;
+			pStyle->sRightIndent = 720;
+		}
+		break;
+	}
+} /* end of vGetBuildinStyle */
+
+/*
+ * Get a build-in fontstyle for Winword 1/2
+ */
+static void
+vGetBuildinFont(UCHAR ucStc, font_block_type *pFont)
+{
+	fail(pFont == NULL);
+
+	/* Start with de defaults */
+	vGetDefaultFont(pFont, 0);
+
+	/* Add the build-in fontstyle info */
+	switch (ucStc) {
+	case 223:
+	case 244:
+		pFont->usFontSize = 16;
+		break;
+	case 246:
+	case 247:
+	case 248:
+		pFont->usFontStyle |= FONT_ITALIC;
+		break;
+	case 249:
+		pFont->usFontStyle |= FONT_UNDERLINE;
+		break;
+	case 250:
+		pFont->usFontStyle |= FONT_BOLD;
+		break;
+	case 251:
+		pFont->usFontStyle |= FONT_UNDERLINE;
+		pFont->usFontSize = 24;
+		break;
+	case 252:
+		pFont->usFontStyle |= FONT_BOLD;
+		pFont->usFontSize = 24;
+		break;
+	case 253:
+		pFont->ucFontNumber = 2;
+		pFont->usFontStyle |= FONT_BOLD;
+		pFont->usFontSize = 24;
+		break;
+	case 254:
+		pFont->ucFontNumber = 2;
+		pFont->usFontStyle |= (FONT_BOLD|FONT_UNDERLINE);
+		pFont->usFontSize = 24;
+		break;
+	default:
+		break;
+	}
+} /* end of vGetBuildinFont */
+
+/*
+ * Convert a stylecode (stc) as used by WinWord 1/2 into a styleindex (istd)
+ * as used by Word 6 and up
+ */
+USHORT
+usStc2istd(UCHAR ucStc)
+{
+	/* Old nil style to new nil style */
+	if (ucStc == 222) {
+		return STI_NIL;
+	}
+
+	/* Heading 1 through 9 must become istd 1 through 9 */
+	/* so 254 through 246 must become 1 through 9 and vice versa */
+	if ((ucStc >= 1 && ucStc <= 9) ||
+	    (ucStc >= 246 && ucStc <= 254)) {
+		return 255 - (USHORT)ucStc;
+	}
+	return (USHORT)ucStc;
+} /* end of usStd2istd */
+
+/*
+ * Build the lists with Stylesheet Information for WinWord 1/2 files
+ */
+void
+vGet2Stylesheet(FILE *pFile, int iWordVersion, const UCHAR *aucHeader)
+{
+	style_block_type	*pStyle;
+	font_block_type		*pFont;
+	UCHAR	*aucBuffer;
+	ULONG	ulBeginStshInfo;
+	size_t	tStshInfoLen, tName, tChpx, tPapx, tMaxIndex;
+	int	iStIndex, iChpxIndex, iPapxIndex, iSt, iChpx, iPapx;
+	int	iStd, iIndex, iBaseStyleIndex, iCounter;
+	USHORT	usBaseStyle;
+	UCHAR	ucStc, ucStcNext, ucStcBase;
+
+	fail(pFile == NULL || aucHeader == NULL);
+	fail(iWordVersion != 1 && iWordVersion != 2);
+
+	ulBeginStshInfo = ulGetLong(0x5e, aucHeader); /* fcStshf */
+	NO_DBG_HEX(ulBeginStshInfo);
+	tStshInfoLen = (size_t)usGetWord(0x62, aucHeader); /* cbStshf */
+	NO_DBG_DEC(tStshInfoLen);
+
+	aucBuffer = xmalloc(tStshInfoLen);
+	if (!bReadBytes(aucBuffer, tStshInfoLen, ulBeginStshInfo, pFile)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tStshInfoLen);
+
+	fail(2 > tStshInfoLen);
+	iStd = (int)usGetWord(0, aucBuffer);
+
+	fail(2 + 2 > tStshInfoLen);
+	tName = (size_t)usGetWord(2, aucBuffer);
+
+	fail(2 + tName + 2 > tStshInfoLen);
+	tChpx = (size_t)usGetWord(2 + tName, aucBuffer);
+
+	fail(2 + tName + tChpx + 2 > tStshInfoLen);
+	tPapx = (size_t)usGetWord(2 + tName + tChpx, aucBuffer);
+
+	fail(2 + tName + tChpx + tPapx + 2 > tStshInfoLen);
+	tStdCount = (size_t)usGetWord(2 + tName + tChpx + tPapx, aucBuffer);
+
+	NO_DBG_HEX(tStdCount);
+
+	atStyleInfo = xcalloc(tStdCount, sizeof(style_block_type));
+	atFontInfo = xcalloc(tStdCount, sizeof(font_block_type));
+	abFilled = xcalloc(tStdCount, sizeof(BOOL));
+
+	do {
+		iCounter = 0;
+		iStIndex = 2 + 2;
+		iChpxIndex = 2 + (int)tName + 2;
+		iPapxIndex = 2 + (int)tName + (int)tChpx + 2;
+		tMaxIndex = 2 + tName + tChpx + tPapx + 2;
+		/* Read the styles one-by-one */
+		for (iIndex = 0; iIndex < (int)tStdCount; iIndex++) {
+			pStyle = &atStyleInfo[iIndex];
+			pFont = &atFontInfo[iIndex];
+			iSt = (int)ucGetByte(iStIndex, aucBuffer);
+			iChpx = (int)ucGetByte(iChpxIndex, aucBuffer);
+			iPapx = (int)ucGetByte(iPapxIndex, aucBuffer);
+			NO_DBG_HEX(iSt);
+			NO_DBG_HEX(iChpx);
+			NO_DBG_HEX(iPapx);
+			if (iSt == 0xff || tMaxIndex + 1 >= tStshInfoLen) {
+				/* Undefined style or no information */
+				iStIndex++;
+				iChpxIndex++;
+				iPapxIndex++;
+				tMaxIndex += 2;
+				if (!abFilled[iIndex]) {
+					DBG_HEX_C(iChpx != 0xff, iChpx);
+					DBG_HEX_C(iPapx != 0xff, iPapx);
+					vGetDefaultStyle(pStyle);
+					vGetDefaultFont(pFont, 0);
+					abFilled[iIndex] = TRUE;
+				}
+				continue;
+			}
+
+			NO_DBG_STRN(aucBuffer + iStIndex + 1, iSt);
+			iStIndex += iSt + 1;
+
+			ucStcNext = ucGetByte(tMaxIndex, aucBuffer);
+			ucStcBase = ucGetByte(tMaxIndex + 1, aucBuffer);
+			ucStc = (UCHAR)((iIndex - iStd) & 0xff);
+			NO_DBG_DEC(ucStc);
+
+			if (iChpx == 0xff || iPapx == 0xff) {
+				/* Use a build-in style */
+				iChpxIndex++;
+				iPapxIndex++;
+				tMaxIndex += 2;
+				if (!abFilled[iIndex]) {
+					DBG_HEX_C(iChpx != 0xff, iChpx);
+					DBG_HEX_C(iPapx != 0xff, iPapx);
+					vGetBuildinStyle(ucStc, pStyle);
+					pStyle->usIstd = usStc2istd(ucStc);
+					pStyle->usIstdNext =
+							usStc2istd(ucStcNext);
+					vGetBuildinFont(ucStc, pFont);
+					abFilled[iIndex] = TRUE;
+				}
+				continue;
+			}
+
+			if (abFilled[iIndex]) {
+				/* This record has already been filled */
+				iChpxIndex += iChpx + 1;
+				iPapxIndex += iPapx + 1;
+				tMaxIndex += 2;
+				continue;
+			}
+
+			usBaseStyle = usStc2istd(ucStcBase);
+
+			if (usBaseStyle == STI_NIL) {
+				/* Based on the Nil style */
+				vGetDefaultStyle(pStyle);
+				vGetDefaultFont(pFont, 0);
+			} else {
+				iBaseStyleIndex = iGetStyleIndex(usBaseStyle);
+				NO_DBG_DEC(iBaseStyleIndex);
+				if (iBaseStyleIndex < 0) {
+					/* This style is not known yet */
+					iChpxIndex += iChpx + 1;
+					iPapxIndex += iPapx + 1;
+					tMaxIndex += 2;
+					continue;
+				}
+				fail(iBaseStyleIndex >= (int)tStdCount);
+				fail(!abFilled[iBaseStyleIndex]);
+				/* Based on the specified base style */
+				*pStyle = atStyleInfo[iBaseStyleIndex];
+				*pFont = atFontInfo[iBaseStyleIndex];
+			}
+			pStyle->usIstd = usStc2istd(ucStc);
+			pStyle->usIstdNext = usStc2istd(ucStcNext);
+
+			abFilled[iIndex] = TRUE;
+			iCounter++;
+
+			/* Add the changes if any */
+			switch (iChpx) {
+			case 0x00:
+			case 0xff:
+				iChpxIndex++;
+				break;
+			default:
+				NO_DBG_PRINT_BLOCK(aucBuffer + iChpxIndex + 1,
+						iChpx);
+				if (iWordVersion == 1) {
+					vGet1FontInfo(0,
+						aucBuffer + iChpxIndex + 1,
+						(size_t)iChpx, pFont);
+				} else {
+					vGet2FontInfo(0,
+						aucBuffer + iChpxIndex + 1,
+						(size_t)iChpx, pFont);
+				}
+				iChpxIndex += iChpx + 1;
+				break;
+			}
+
+			switch (iPapx) {
+			case 0x00:
+			case 0xff:
+				iPapxIndex++;
+				break;
+			default:
+				NO_DBG_PRINT_BLOCK(aucBuffer + iPapxIndex + 8,
+						iPapx - 7);
+				vGet2StyleInfo(0, aucBuffer + iPapxIndex + 8,
+						iPapx - 7, pStyle);
+				iPapxIndex += iPapx + 1;
+				break;
+			}
+			tMaxIndex += 2;
+
+		}
+		NO_DBG_DEC(iCounter);
+	} while (iCounter > 0);
+
+	/* Fill records that are still empty */
+	for (iIndex = 0; iIndex < (int)tStdCount; iIndex++) {
+		if (!abFilled[iIndex]) {
+			NO_DBG_DEC(iIndex);
+			vGetDefaultStyle(&atStyleInfo[iIndex]);
+			vGetDefaultFont(&atFontInfo[iIndex], 0);
+		}
+	}
+
+	/* Clean up before you leave */
+	abFilled = xfree(abFilled);
+	aucBuffer = xfree(aucBuffer);
+} /* end of vGet2Stylesheet */
+
+/*
+ * Build the lists with Stylesheet Information for Word 6/7 files
+ */
+void
+vGet6Stylesheet(FILE *pFile, ULONG ulStartBlock,
+	const ULONG *aulBBD, size_t tBBDLen, const UCHAR *aucHeader)
+{
+	style_block_type	*pStyle;
+	font_block_type		*pFont;
+	UCHAR	*aucBuffer;
+	ULONG	ulBeginStshInfo;
+	size_t	tStshInfoLen, tOffset, tStdLen, tStdBaseInFile;
+	size_t	tPos, tNameLen, tUpxLen;
+	int	iIndex, iBaseStyleIndex, iCounter;
+	USHORT	usTmp, usUpxCount, usStyleType, usBaseStyle;
+	USHORT	usFtcStandardChpStsh;
+
+	fail(pFile == NULL || aucHeader == NULL);
+	fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
+	fail(aulBBD == NULL);
+
+	ulBeginStshInfo = ulGetLong(0x60, aucHeader); /* fcStshf */
+	NO_DBG_HEX(ulBeginStshInfo);
+	tStshInfoLen = (size_t)ulGetLong(0x64, aucHeader); /* lcbStshf */
+	NO_DBG_DEC(tStshInfoLen);
+
+	aucBuffer = xmalloc(tStshInfoLen);
+	if (!bReadBuffer(pFile, ulStartBlock,
+			aulBBD, tBBDLen, BIG_BLOCK_SIZE,
+			aucBuffer, ulBeginStshInfo, tStshInfoLen)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tStshInfoLen);
+
+	tStdCount = (size_t)usGetWord(2, aucBuffer);
+	NO_DBG_DEC(tStdCount);
+	tStdBaseInFile = (size_t)usGetWord(4, aucBuffer);
+	usFtcStandardChpStsh = usGetWord(14, aucBuffer);
+	NO_DBG_DEC(usFtcStandardChpStsh);
+
+	atStyleInfo = xcalloc(tStdCount, sizeof(style_block_type));
+	atFontInfo = xcalloc(tStdCount, sizeof(font_block_type));
+	abFilled = xcalloc(tStdCount, sizeof(BOOL));
+
+	do {
+		iCounter = 0;
+		/* Read the styles one-by-one */
+		for (iIndex = 0, tOffset = 2 + (size_t)usGetWord(0, aucBuffer);
+		     iIndex < (int)tStdCount;
+		     iIndex++, tOffset += 2 + tStdLen) {
+			NO_DBG_DEC(tOffset);
+			tStdLen = (size_t)usGetWord(tOffset, aucBuffer);
+			NO_DBG_DEC(tStdLen);
+			if (abFilled[iIndex]) {
+				/* This record has already been filled */
+				continue;
+			}
+			pStyle = &atStyleInfo[iIndex];
+			pFont = &atFontInfo[iIndex];
+			if (tStdLen == 0) {
+				/* Empty record */
+				vGetDefaultStyle(pStyle);
+				vGetDefaultFont(pFont, usFtcStandardChpStsh);
+				abFilled[iIndex] = TRUE;
+				continue;
+			}
+			usTmp = usGetWord(tOffset + 4, aucBuffer);
+			usStyleType = usTmp % 16;
+			usBaseStyle = usTmp / 16;
+			NO_DBG_DEC(usStyleType);
+			NO_DBG_DEC(usBaseStyle);
+			if (usBaseStyle == STI_NIL || usBaseStyle == STI_USER) {
+				/* Based on the Nil style */
+				vGetDefaultStyle(pStyle);
+				vGetDefaultFont(pFont, usFtcStandardChpStsh);
+			} else {
+				iBaseStyleIndex = iGetStyleIndex(usBaseStyle);
+				NO_DBG_DEC(iBaseStyleIndex);
+				if (iBaseStyleIndex < 0) {
+					/* This base style is not known yet */
+					continue;
+				}
+				fail(iBaseStyleIndex >= (int)tStdCount);
+				fail(!abFilled[iBaseStyleIndex]);
+				/* Based on the specified base style */
+				*pStyle = atStyleInfo[iBaseStyleIndex];
+				pStyle->usIstd = ISTD_INVALID;
+				*pFont = atFontInfo[iBaseStyleIndex];
+			}
+			abFilled[iIndex] = TRUE;
+			iCounter++;
+			/* STD */
+			usTmp = usGetWord(tOffset + 6, aucBuffer);
+			usUpxCount = usTmp % 16;
+			pStyle->usIstdNext = usTmp / 16;;
+			NO_DBG_DEC(usUpxCount);
+			tPos = 2 + tStdBaseInFile;
+			NO_DBG_DEC(tPos);
+			tNameLen = (size_t)ucGetByte(tOffset + tPos, aucBuffer);
+			NO_DBG_DEC(tNameLen);
+			NO_DBG_STRN(aucBuffer + tOffset + tPos + 1, tNameLen);
+			tNameLen++;	/* Include the ASCII NULL character */
+			tPos += 1 + tNameLen;
+			if (odd(tPos)) {
+				tPos++;
+			}
+			NO_DBG_DEC(tPos);
+			if (tPos >= tStdLen) {
+				continue;
+			}
+			tUpxLen = (size_t)usGetWord(tOffset + tPos, aucBuffer);
+			NO_DBG_DEC(tUpxLen);
+			if (tPos + tUpxLen > tStdLen) {
+				/* UPX length too large to be a record */
+				DBG_DEC_C(tPos + tUpxLen > tStdLen,
+						tPos + tUpxLen);
+				continue;
+			}
+			if (usStyleType == SGC_PAP && usUpxCount >= 1) {
+				if (tUpxLen >= 2) {
+					NO_DBG_PRINT_BLOCK(
+						aucBuffer + tOffset + tPos + 2,
+						tUpxLen);
+					pStyle->usIstd = usGetWord(
+						tOffset + tPos + 2, aucBuffer);
+					NO_DBG_DEC(pStyle->usIstd);
+					NO_DBG_DEC(pStyle->usIstdNext);
+					vGet6StyleInfo(0,
+						aucBuffer + tOffset + tPos + 4,
+						tUpxLen - 2, pStyle);
+					NO_DBG_DEC(pStyle->sLeftIndent);
+					NO_DBG_DEC(pStyle->sRightIndent);
+					NO_DBG_HEX(pStyle->ucAlignment);
+				}
+				tPos += 2 + tUpxLen;
+				if (odd(tPos)) {
+					tPos++;
+				}
+				NO_DBG_DEC(tPos);
+				tUpxLen = (size_t)usGetWord(
+						tOffset + tPos, aucBuffer);
+				NO_DBG_DEC(tUpxLen);
+			}
+			if (tUpxLen == 0 || tPos + tUpxLen > tStdLen) {
+				/* Too small or too large to be a record */
+				DBG_DEC_C(tPos + tUpxLen > tStdLen,
+							tPos + tUpxLen);
+				continue;
+			}
+			if ((usStyleType == SGC_PAP && usUpxCount >= 2) ||
+			    (usStyleType == SGC_CHP && usUpxCount >= 1)) {
+				NO_DBG_PRINT_BLOCK(
+						aucBuffer + tOffset + tPos + 2,
+						tUpxLen);
+				vGet6FontInfo(0, ISTD_INVALID,
+						aucBuffer + tOffset + tPos + 2,
+						(int)tUpxLen, pFont);
+				NO_DBG_DEC(pFont->usFontSize);
+				NO_DBG_DEC(pFont->ucFontcolor);
+				NO_DBG_HEX(pFont->usFontStyle);
+			}
+		}
+		NO_DBG_DEC(iCounter);
+	} while (iCounter > 0);
+
+	/* Fill records that are still empty */
+	for (iIndex = 0; iIndex < (int)tStdCount; iIndex++) {
+		if (!abFilled[iIndex]) {
+			NO_DBG_DEC(iIndex);
+			vGetDefaultStyle(&atStyleInfo[iIndex]);
+			vGetDefaultFont(&atFontInfo[iIndex],
+					usFtcStandardChpStsh);
+		}
+	}
+
+	/* Clean up before you leave */
+	abFilled = xfree(abFilled);
+	aucBuffer = xfree(aucBuffer);
+} /* end of vGet6Stylesheet */
+
+/*
+ * Build the lists with Stylesheet Information for Word 8/9/10 files
+ */
+void
+vGet8Stylesheet(FILE *pFile, const pps_info_type *pPPS,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const ULONG *aulSBD, size_t tSBDLen,
+	const UCHAR *aucHeader)
+{
+	style_block_type	*pStyle;
+	font_block_type		*pFont;
+	const ULONG	*aulBlockDepot;
+	UCHAR	*aucBuffer;
+	ULONG	ulBeginStshInfo;
+	size_t	tStshInfoLen, tBlockDepotLen, tOffset, tStdLen, tStdBaseInFile;
+	size_t	tBlockSize, tPos, tNameLen, tUpxLen;
+	int	iIndex, iBaseStyleIndex, iCounter;
+	USHORT	usTmp, usUpxCount, usStyleType, usBaseStyle;
+	USHORT	usFtcStandardChpStsh;
+
+	fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
+	fail(aulBBD == NULL || aulSBD == NULL);
+
+	ulBeginStshInfo = ulGetLong(0xa2, aucHeader); /* fcStshf */
+	NO_DBG_HEX(ulBeginStshInfo);
+	tStshInfoLen = (size_t)ulGetLong(0xa6, aucHeader); /* lcbStshf */
+	NO_DBG_DEC(tStshInfoLen);
+
+	NO_DBG_DEC(pPPS->tTable.ulSB);
+	NO_DBG_HEX(pPPS->tTable.ulSize);
+	if (pPPS->tTable.ulSize == 0) {
+		DBG_MSG("No stylesheet information");
+		return;
+	}
+
+	if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
+		/* Use the Small Block Depot */
+		aulBlockDepot = aulSBD;
+		tBlockDepotLen = tSBDLen;
+		tBlockSize = SMALL_BLOCK_SIZE;
+	} else {
+		/* Use the Big Block Depot */
+		aulBlockDepot = aulBBD;
+		tBlockDepotLen = tBBDLen;
+		tBlockSize = BIG_BLOCK_SIZE;
+	}
+	aucBuffer = xmalloc(tStshInfoLen);
+	if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
+			aulBlockDepot, tBlockDepotLen, tBlockSize,
+			aucBuffer, ulBeginStshInfo, tStshInfoLen)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tStshInfoLen);
+
+	tStdCount = (size_t)usGetWord(2, aucBuffer);
+	NO_DBG_DEC(tStdCount);
+	tStdBaseInFile = (size_t)usGetWord(4, aucBuffer);
+	usFtcStandardChpStsh = usGetWord(14, aucBuffer);
+	NO_DBG_DEC(usFtcStandardChpStsh);
+
+	atStyleInfo = xcalloc(tStdCount, sizeof(style_block_type));
+	atFontInfo = xcalloc(tStdCount, sizeof(font_block_type));
+	abFilled = xcalloc(tStdCount, sizeof(BOOL));
+
+	do {
+		iCounter = 0;
+		/* Read the styles one-by-one */
+		for (iIndex = 0, tOffset = 2 + (size_t)usGetWord(0, aucBuffer);
+		     iIndex < (int)tStdCount;
+		     iIndex++, tOffset += 2 + tStdLen) {
+			NO_DBG_DEC(tOffset);
+			tStdLen = (size_t)usGetWord(tOffset, aucBuffer);
+			NO_DBG_DEC(tStdLen);
+			if (abFilled[iIndex]) {
+				/* This record has already been filled */
+				continue;
+			}
+			pStyle = &atStyleInfo[iIndex];
+			pFont = &atFontInfo[iIndex];
+			if (tStdLen == 0) {
+				/* Empty record */
+				vGetDefaultStyle(pStyle);
+				vGetDefaultFont(pFont, usFtcStandardChpStsh);
+				abFilled[iIndex] = TRUE;
+				continue;
+			}
+			usTmp = usGetWord(tOffset + 4, aucBuffer);
+			usStyleType = usTmp % 16;
+			usBaseStyle = usTmp / 16;
+			NO_DBG_DEC(usStyleType);
+			NO_DBG_DEC(usBaseStyle);
+			if (usBaseStyle == STI_NIL || usBaseStyle == STI_USER) {
+				/* Based on the Nil style */
+				vGetDefaultStyle(pStyle);
+				vGetDefaultFont(pFont, usFtcStandardChpStsh);
+			} else {
+				iBaseStyleIndex = iGetStyleIndex(usBaseStyle);
+				NO_DBG_DEC(iBaseStyleIndex);
+				if (iBaseStyleIndex < 0) {
+					/* This base style is not known yet */
+					continue;
+				}
+				fail(iBaseStyleIndex >= (int)tStdCount);
+				fail(!abFilled[iBaseStyleIndex]);
+				/* Based on the specified base style */
+				*pStyle = atStyleInfo[iBaseStyleIndex];
+				pStyle->usIstd = ISTD_INVALID;
+				*pFont = atFontInfo[iBaseStyleIndex];
+			}
+			abFilled[iIndex] = TRUE;
+			iCounter++;
+			/* STD */
+			usTmp = usGetWord(tOffset + 6, aucBuffer);
+			usUpxCount = usTmp % 16;
+			pStyle->usIstdNext = usTmp / 16;
+			NO_DBG_DEC(usUpxCount);
+			tPos = 2 + tStdBaseInFile;
+			NO_DBG_DEC(tPos);
+			tNameLen = (size_t)usGetWord(tOffset + tPos, aucBuffer);
+			NO_DBG_DEC(tNameLen);
+			tNameLen *= 2;	/* From Unicode characters to bytes */
+			NO_DBG_UNICODE_N(aucBuffer + tOffset + tPos + 2,
+					tNameLen);
+			tNameLen += 2;	/* Include the Unicode NULL character */
+			tPos += 2 + tNameLen;
+			if (odd(tPos)) {
+				tPos++;
+			}
+			NO_DBG_DEC(tPos);
+			if (tPos >= tStdLen) {
+				continue;
+			}
+			tUpxLen = (size_t)usGetWord(tOffset + tPos, aucBuffer);
+			NO_DBG_DEC(tUpxLen);
+			if (tPos + tUpxLen > tStdLen) {
+				/* UPX length too large to be a record */
+				DBG_DEC_C(tPos + tUpxLen > tStdLen,
+						tPos + tUpxLen);
+				continue;
+			}
+			if (usStyleType == SGC_PAP && usUpxCount >= 1) {
+				if (tUpxLen >= 2) {
+					NO_DBG_PRINT_BLOCK(
+						aucBuffer + tOffset + tPos + 2,
+						tUpxLen);
+					pStyle->usIstd = usGetWord(
+						tOffset + tPos + 2, aucBuffer);
+					NO_DBG_DEC(pStyle->usIstd);
+					NO_DBG_DEC(pStyle->usIstdNext);
+					vGet8StyleInfo(0,
+						aucBuffer + tOffset + tPos + 4,
+						tUpxLen - 2, pStyle);
+					NO_DBG_DEC(pStyle->sLeftIndent);
+					NO_DBG_DEC(pStyle->sRightIndent);
+					NO_DBG_HEX(pStyle->ucAlignment);
+				}
+				tPos += 2 + tUpxLen;
+				if (odd(tPos)) {
+					tPos++;
+				}
+				NO_DBG_DEC(tPos);
+				tUpxLen = (size_t)usGetWord(
+						tOffset + tPos, aucBuffer);
+				NO_DBG_DEC(tUpxLen);
+			}
+			if (tUpxLen == 0 || tPos + tUpxLen > tStdLen) {
+				/* Too small or too large to be a record */
+				DBG_DEC_C(tPos + tUpxLen > tStdLen,
+							tPos + tUpxLen);
+				continue;
+			}
+			if ((usStyleType == SGC_PAP && usUpxCount >= 2) ||
+			    (usStyleType == SGC_CHP && usUpxCount >= 1)) {
+				NO_DBG_PRINT_BLOCK(
+						aucBuffer + tOffset + tPos + 2,
+						tUpxLen);
+				vGet8FontInfo(0, ISTD_INVALID,
+						aucBuffer + tOffset + tPos + 2,
+						(int)tUpxLen, pFont);
+				NO_DBG_DEC(pFont->usFontSize);
+				NO_DBG_DEC(pFont->ucFontcolor);
+				NO_DBG_HEX(pFont->usFontStyle);
+			}
+		}
+		NO_DBG_DEC(iCounter);
+	} while (iCounter > 0);
+
+	/* Fill records that are still empty */
+	for (iIndex = 0; iIndex < (int)tStdCount; iIndex++) {
+		if (!abFilled[iIndex]) {
+			NO_DBG_DEC(iIndex);
+			vGetDefaultStyle(&atStyleInfo[iIndex]);
+			vGetDefaultFont(&atFontInfo[iIndex],
+					usFtcStandardChpStsh);
+		}
+	}
+
+	/* Clean up before you leave */
+	abFilled = xfree(abFilled);
+	aucBuffer = xfree(aucBuffer);
+} /* end of vGet8Stylesheet */
+
+/*
+ * vFillStyleFromStylesheet - fill a style struct with stylesheet info
+ */
+void
+vFillStyleFromStylesheet(USHORT usIstd, style_block_type *pStyle)
+{
+	int	iIndex;
+
+	fail(pStyle == NULL);
+
+	if (usIstd != ISTD_INVALID && usIstd != STI_NIL && usIstd != STI_USER) {
+		for (iIndex = 0; iIndex < (int)tStdCount; iIndex++) {
+			if (atStyleInfo[iIndex].usIstd == usIstd) {
+				/* Right index found; return style */
+				*pStyle = atStyleInfo[iIndex];
+				return;
+			}
+		}
+	}
+
+	vGetDefaultStyle(pStyle);
+	pStyle->usIstd = usIstd;
+} /* end of vFillStyleFromStylesheet */
+
+/*
+ * vFillFontFromStylesheet - fill a font struct with stylesheet info
+ */
+void
+vFillFontFromStylesheet(USHORT usIstd, font_block_type *pFont)
+{
+	int	iIndex;
+
+	fail(pFont == NULL);
+
+	if (usIstd != ISTD_INVALID && usIstd != STI_NIL && usIstd != STI_USER) {
+		for (iIndex = 0; iIndex < (int)tStdCount; iIndex++) {
+			if (atStyleInfo[iIndex].usIstd == usIstd) {
+				/* Right index found; return font */
+				*pFont = atFontInfo[iIndex];
+				return;
+			}
+		}
+	}
+
+	vGetDefaultFont(pFont, 0);
+} /* end of vFillFontFromStylesheet */
diff --git a/summary.c b/summary.c
new file mode 100644
index 0000000..d9ee687
--- /dev/null
+++ b/summary.c
@@ -0,0 +1,888 @@
+/*
+ * summary.c
+ * Copyright (C) 2002-2005 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Read the summary information of a Word document
+ */
+
+#include <time.h>
+#include <string.h>
+#include "antiword.h"
+
+#define P_HEADER_SZ		28
+#define P_SECTIONLIST_SZ	20
+#define P_LENGTH_SZ		 4
+#define P_SECTION_MAX_SZ	(2 * P_SECTIONLIST_SZ + P_LENGTH_SZ)
+#define P_SECTION_SZ(x)		((x) * P_SECTIONLIST_SZ + P_LENGTH_SZ)
+
+#define PID_TITLE		 2
+#define PID_SUBJECT		 3
+#define PID_AUTHOR		 4
+#define PID_CREATE_DTM		12
+#define PID_LASTSAVE_DTM	13
+#define PID_APPNAME		18
+
+#define PIDD_MANAGER		14
+#define PIDD_COMPANY		15
+
+#define VT_LPSTR		30
+#define VT_FILETIME		64
+
+#define TIME_OFFSET_HI		0x019db1de
+#define TIME_OFFSET_LO		0xd53e8000
+
+static char	*szTitle = NULL;
+static char	*szSubject = NULL;
+static char	*szAuthor = NULL;
+static time_t	tCreateDtm = (time_t)-1;
+static time_t	tLastSaveDtm= (time_t)-1;
+static char	*szAppName = NULL;
+static char	*szManager = NULL;
+static char	*szCompany = NULL;
+static USHORT	usLid = (USHORT)-1;
+
+
+/*
+ * vDestroySummaryInfo - destroy the summary information
+ */
+void
+vDestroySummaryInfo(void)
+{
+	TRACE_MSG("vDestroySummaryInfo");
+
+	szTitle = xfree(szTitle);
+	szSubject = xfree(szSubject);
+	szAuthor = xfree(szAuthor);
+	tCreateDtm = (time_t)-1;
+	tLastSaveDtm = (time_t)-1;
+	szAppName = xfree(szAppName);
+	szManager = xfree(szManager);
+	szCompany = xfree(szCompany);
+	usLid = (USHORT)-1;
+} /* end of vDestroySummaryInfo */
+
+/*
+ * tConvertDosDate - convert DOS date format
+ *
+ * returns Unix time_t or -1
+ */
+static time_t
+tConvertDosDate(const char *szDosDate)
+{
+	struct tm	tTime;
+	const char	*pcTmp;
+	time_t		tResult;
+
+	memset(&tTime, 0, sizeof(tTime));
+	pcTmp = szDosDate;
+	/* Get the month */
+	if (!isdigit(*pcTmp)) {
+		return (time_t)-1;
+	}
+	tTime.tm_mon = (int)(*pcTmp - '0');
+	pcTmp++;
+	if (isdigit(*pcTmp)) {
+		tTime.tm_mon *= 10;
+		tTime.tm_mon += (int)(*pcTmp - '0');
+		pcTmp++;
+	}
+	/* Get the first separater */
+	if (isalnum(*pcTmp)) {
+		return (time_t)-1;
+	}
+	pcTmp++;
+	/* Get the day */
+	if (!isdigit(*pcTmp)) {
+		return (time_t)-1;
+	}
+	tTime.tm_mday = (int)(*pcTmp - '0');
+	pcTmp++;
+	if (isdigit(*pcTmp)) {
+		tTime.tm_mday *= 10;
+		tTime.tm_mday += (int)(*pcTmp - '0');
+		pcTmp++;
+	}
+	/* Get the second separater */
+	if (isalnum(*pcTmp)) {
+		return (time_t)-1;
+	}
+	pcTmp++;
+	/* Get the year */
+	if (!isdigit(*pcTmp)) {
+		return (time_t)-1;
+	}
+	tTime.tm_year = (int)(*pcTmp - '0');
+	pcTmp++;
+	if (isdigit(*pcTmp)) {
+		tTime.tm_year *= 10;
+		tTime.tm_year += (int)(*pcTmp - '0');
+		pcTmp++;
+	}
+	/* Check the values */
+	if (tTime.tm_mon == 0 || tTime.tm_mday == 0 || tTime.tm_mday > 31) {
+		return (time_t)-1;
+	}
+	/* Correct the values */
+	tTime.tm_mon--;		/* From 01-12 to 00-11 */
+	if (tTime.tm_year < 80) {
+		tTime.tm_year += 100;	/* 00 means 2000 is 100 */
+	}
+	tTime.tm_isdst = -1;
+	tResult = mktime(&tTime);
+	NO_DBG_MSG(ctime(&tResult));
+	return tResult;
+} /* end of tConvertDosDate */
+
+/*
+ * szLpstr - get a zero terminate string property
+ */
+static char *
+szLpstr(ULONG ulOffset, const UCHAR *aucBuffer)
+{
+	char	*szStart, *szResult, *szTmp;
+	size_t	tSize;
+
+	tSize = (size_t)ulGetLong(ulOffset + 4, aucBuffer);
+	NO_DBG_DEC(tSize);
+	if (tSize == 0) {
+		return NULL;
+	}
+	/* Remove white space from the start of the string */
+	szStart = (char *)aucBuffer + ulOffset + 8;
+	NO_DBG_MSG(szStart);
+	fail(strlen(szStart) >= tSize);
+	while (isspace(*szStart)) {
+		szStart++;
+	}
+	if (szStart[0] == '\0') {
+		return NULL;
+	}
+	szResult = xstrdup(szStart);
+	/* Remove white space from the end of the string */
+	szTmp = szResult + strlen(szResult) - 1;
+	while (isspace(*szTmp)) {
+		*szTmp = '\0';
+		szTmp--;
+	}
+	NO_DBG_MSG(szResult);
+	return szResult;
+} /* end of szLpstr */
+
+/*
+ * tFiletime - get a filetime property
+ */
+static time_t
+tFiletime(ULONG ulOffset, const UCHAR *aucBuffer)
+{
+	double	dHi, dLo, dTmp;
+	ULONG	ulHi, ulLo;
+	time_t	tResult;
+
+	ulLo = ulGetLong(ulOffset + 4, aucBuffer);
+	ulHi = ulGetLong(ulOffset + 8, aucBuffer);
+	NO_DBG_HEX(ulHi);
+	NO_DBG_HEX(ulLo);
+
+	/* Move the starting point from 01 Jan 1601 to 01 Jan 1970 */
+	dHi = (double)ulHi - (double)TIME_OFFSET_HI;
+	dLo = (double)ulLo - (double)TIME_OFFSET_LO;
+	NO_DBG_FLT(dHi);
+	NO_DBG_FLT(dLo);
+
+	/* Combine the values and divide by 10^7 to get seconds */
+	dTmp  = dLo / 10000000.0;	/* 10^7 */
+	dTmp += dHi * 429.4967926;	/* 2^32 / 10^7 */
+	NO_DBG_FLT(dTmp);
+
+	/* Make a time_t */
+	if (dTmp - 0.5 < TIME_T_MIN || dTmp + 0.5 > TIME_T_MAX) {
+		return (time_t)-1;
+	}
+	tResult = dTmp < 0.0 ? (time_t)(dTmp - 0.5) : (time_t)(dTmp + 0.5);
+	NO_DBG_MSG(ctime(&tResult));
+	return tResult;
+} /* end of tFiletime */
+
+/*
+ * vAnalyseSummaryInfo - analyse the summary information
+ */
+static void
+vAnalyseSummaryInfo(const UCHAR *aucBuffer)
+{
+	ULONG	ulOffset;
+	size_t	tIndex, tCount, tPropID, tPropType;
+
+	tCount = (size_t)ulGetLong(4, aucBuffer);
+	DBG_DEC(tCount);
+	for (tIndex = 0; tIndex < tCount; tIndex++) {
+		tPropID = (size_t)ulGetLong(8 + tIndex * 8, aucBuffer);
+		ulOffset = ulGetLong(12 + tIndex * 8, aucBuffer);
+		NO_DBG_DEC(tPropID);
+		NO_DBG_HEX(ulOffset);
+		tPropType = (size_t)ulGetLong(ulOffset, aucBuffer);
+		NO_DBG_DEC(tPropType);
+		switch (tPropID) {
+		case PID_TITLE:
+			if (tPropType == VT_LPSTR && szTitle == NULL) {
+				szTitle = szLpstr(ulOffset, aucBuffer);
+			}
+			break;
+		case PID_SUBJECT:
+			if (tPropType == VT_LPSTR && szSubject == NULL) {
+				szSubject = szLpstr(ulOffset, aucBuffer);
+			}
+			break;
+		case PID_AUTHOR:
+			if (tPropType == VT_LPSTR && szAuthor == NULL) {
+				szAuthor = szLpstr(ulOffset, aucBuffer);
+			}
+			break;
+		case PID_CREATE_DTM:
+			if (tPropType == VT_FILETIME &&
+			    tCreateDtm == (time_t)-1) {
+				tCreateDtm = tFiletime(ulOffset, aucBuffer);
+			}
+			break;
+		case PID_LASTSAVE_DTM:
+			if (tPropType == VT_FILETIME &&
+			    tLastSaveDtm == (time_t)-1) {
+				tLastSaveDtm = tFiletime(ulOffset, aucBuffer);
+			}
+			break;
+		case PID_APPNAME:
+			if (tPropType == VT_LPSTR && szAppName == NULL) {
+				szAppName = szLpstr(ulOffset, aucBuffer);
+			}
+			break;
+		default:
+			break;
+		}
+	}
+} /* end of vAnalyseSummaryInfo */
+
+/*
+ * vAnalyseDocumentSummaryInfo - analyse the document summary information
+ */
+static void
+vAnalyseDocumentSummaryInfo(const UCHAR *aucBuffer)
+{
+	ULONG	ulOffset;
+	size_t	tIndex, tCount, tPropID, tPropType;
+
+	tCount = (size_t)ulGetLong(4, aucBuffer);
+	DBG_DEC(tCount);
+	for (tIndex = 0; tIndex < tCount; tIndex++) {
+		tPropID = (size_t)ulGetLong(8 + tIndex * 8, aucBuffer);
+		ulOffset = ulGetLong(12 + tIndex * 8, aucBuffer);
+		NO_DBG_DEC(tPropID);
+		NO_DBG_HEX(ulOffset);
+		tPropType = (size_t)ulGetLong(ulOffset, aucBuffer);
+		NO_DBG_DEC(tPropType);
+		switch (tPropID) {
+		case PIDD_MANAGER:
+			if (tPropType == VT_LPSTR && szManager == NULL) {
+				szManager = szLpstr(ulOffset, aucBuffer);
+			}
+			break;
+		case PIDD_COMPANY:
+			if (tPropType == VT_LPSTR && szCompany == NULL) {
+				szCompany = szLpstr(ulOffset, aucBuffer);
+			}
+			break;
+		default:
+			break;
+		}
+	}
+} /* end of vAnalyseDocumentSummaryInfo */
+
+/*
+ * pucAnalyseSummaryInfoHeader-
+ */
+static UCHAR *
+pucAnalyseSummaryInfoHeader(FILE *pFile,
+	ULONG ulStartBlock, ULONG ulSize,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const ULONG *aulSBD, size_t tSBDLen)
+{
+	const ULONG	*aulBlockDepot;
+	UCHAR	*aucBuffer;
+	size_t	tBlockDepotLen, tBlockSize, tSectionCount, tLength;
+	ULONG	ulTmp, ulOffset;
+	USHORT	usLittleEndian, usEmpty, usOS, usVersion;
+	UCHAR	aucHdr[P_HEADER_SZ], aucSecLst[P_SECTION_MAX_SZ];
+
+	if (ulSize < MIN_SIZE_FOR_BBD_USE) {
+		/* Use the Small Block Depot */
+		aulBlockDepot = aulSBD;
+		tBlockDepotLen = tSBDLen;
+		tBlockSize = SMALL_BLOCK_SIZE;
+	} else {
+		/* Use the Big Block Depot */
+		aulBlockDepot = aulBBD;
+		tBlockDepotLen = tBBDLen;
+		tBlockSize = BIG_BLOCK_SIZE;
+	}
+
+	if (tBlockDepotLen == 0) {
+		DBG_MSG("The Block Depot length is zero");
+		return NULL;
+	}
+
+	/* Read the Summery Information header */
+	if (!bReadBuffer(pFile, ulStartBlock,
+			aulBlockDepot, tBlockDepotLen, tBlockSize,
+			aucHdr, 0, P_HEADER_SZ)) {
+		return NULL;
+	}
+	NO_DBG_PRINT_BLOCK(aucHdr, P_HEADER_SZ);
+
+	/* Analyse the Summery Information header */
+	usLittleEndian =  usGetWord(0, aucHdr);
+	if (usLittleEndian != 0xfffe) {
+		DBG_HEX(usLittleEndian);
+		DBG_MSG_C(usLittleEndian == 0xfeff, "Big endian");
+		return NULL;
+	}
+	usEmpty =  usGetWord(2, aucHdr);
+	if (usEmpty != 0x0000) {
+		DBG_DEC(usEmpty);
+		return NULL;
+	}
+	ulTmp = ulGetLong(4, aucHdr);
+	DBG_HEX(ulTmp);
+	usOS = (USHORT)(ulTmp >> 16);
+	usVersion = (USHORT)(ulTmp & 0xffff);
+	switch (usOS) {
+	case 0:
+		DBG_MSG("Win16");
+		DBG_HEX(usVersion);
+		break;
+	case 1:
+		DBG_MSG("MacOS");
+		DBG_HEX(usVersion);
+		break;
+	case 2:
+		DBG_MSG("Win32");
+		DBG_HEX(usVersion);
+		break;
+	default:
+		DBG_DEC(usOS);
+		DBG_HEX(usVersion);
+		break;
+	}
+	tSectionCount = (size_t)ulGetLong(24, aucHdr);
+	DBG_DEC_C(tSectionCount != 1 && tSectionCount != 2, tSectionCount);
+	if (tSectionCount != 1 && tSectionCount != 2) {
+		return NULL;
+	}
+
+	/* Read the Summery Information Section Lists */
+	if (!bReadBuffer(pFile, ulStartBlock,
+			aulBlockDepot, tBlockDepotLen, tBlockSize,
+			aucSecLst, P_HEADER_SZ, P_SECTION_SZ(tSectionCount))) {
+		return NULL;
+	}
+	NO_DBG_PRINT_BLOCK(aucSecLst, P_SECTION_SZ(tSectionCount));
+
+	ulTmp = ulGetLong(0, aucSecLst);
+	DBG_HEX(ulTmp);
+	ulTmp = ulGetLong(4, aucSecLst);
+	DBG_HEX(ulTmp);
+	ulTmp = ulGetLong(8, aucSecLst);
+	DBG_HEX(ulTmp);
+	ulTmp = ulGetLong(12, aucSecLst);
+	DBG_HEX(ulTmp);
+	ulOffset = ulGetLong(16, aucSecLst);
+	DBG_DEC_C(ulOffset != P_HEADER_SZ + P_SECTIONLIST_SZ &&
+		ulOffset != P_HEADER_SZ + 2 * P_SECTIONLIST_SZ,
+		ulOffset);
+	fail(ulOffset != P_HEADER_SZ + P_SECTIONLIST_SZ &&
+		ulOffset != P_HEADER_SZ + 2 * P_SECTIONLIST_SZ);
+	tLength =
+		(size_t)ulGetLong(tSectionCount * P_SECTIONLIST_SZ, aucSecLst);
+	NO_DBG_HEX(tLength);
+	fail(ulOffset + tLength > ulSize);
+
+	/* Read the Summery Information */
+	aucBuffer = xmalloc(tLength);
+	if (!bReadBuffer(pFile, ulStartBlock,
+			aulBlockDepot, tBlockDepotLen, tBlockSize,
+			aucBuffer, ulOffset, tLength)) {
+		aucBuffer = xfree(aucBuffer);
+		return NULL;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tLength);
+	return aucBuffer;
+} /* end of pucAnalyseSummaryInfoHeader */
+
+/*
+ * vSet0SummaryInfo - set summary information from a Word for DOS file
+ */
+void
+vSet0SummaryInfo(FILE *pFile, const UCHAR *aucHeader)
+{
+	UCHAR	*aucBuffer;
+	ULONG	ulBeginSumdInfo, ulBeginNextBlock;
+	size_t	tLen;
+	USHORT	usCodepage, usOffset;
+
+	TRACE_MSG("vSet0SummaryInfo");
+
+	fail(pFile == NULL || aucHeader == NULL);
+
+	/* First check the header */
+	usCodepage = usGetWord(0x7e, aucHeader);
+	DBG_DEC(usCodepage);
+	switch (usCodepage) {
+	case 850: usLid = 0x0809; break; /* Latin1 -> British English */
+	case 862: usLid = 0x040d; break; /* Hebrew */
+	case 866: usLid = 0x0419; break; /* Russian */
+	case 0:
+	case 437:
+	default: usLid = 0x0409; break; /* ASCII -> American English */
+	}
+
+	/* Second check the summary information block */
+	ulBeginSumdInfo = 128 * (ULONG)usGetWord(0x1c, aucHeader);
+	DBG_HEX(ulBeginSumdInfo);
+	ulBeginNextBlock = 128 * (ULONG)usGetWord(0x6a, aucHeader);
+	DBG_HEX(ulBeginNextBlock);
+
+	if (ulBeginSumdInfo >= ulBeginNextBlock || ulBeginNextBlock == 0) {
+		/* There is no summary information block */
+		return;
+	}
+	tLen = (size_t)(ulBeginNextBlock - ulBeginSumdInfo);
+	aucBuffer = xmalloc(tLen);
+	/* Read the summary information block */
+	if (!bReadBytes(aucBuffer, tLen, ulBeginSumdInfo, pFile)) {
+		return;
+	}
+	usOffset = usGetWord(0, aucBuffer);
+	if (aucBuffer[usOffset] != 0) {
+		NO_DBG_MSG(aucBuffer + usOffset);
+		szTitle = xstrdup((char *)aucBuffer + usOffset);
+	}
+	usOffset = usGetWord(2, aucBuffer);
+	if (aucBuffer[usOffset] != 0) {
+		NO_DBG_MSG(aucBuffer + usOffset);
+		szAuthor = xstrdup((char *)aucBuffer + usOffset);
+	}
+	usOffset = usGetWord(12, aucBuffer);
+	if (aucBuffer[usOffset] != 0) {
+		NO_DBG_STRN(aucBuffer + usOffset, 8);
+		tLastSaveDtm = tConvertDosDate((char *)aucBuffer + usOffset);
+	}
+	usOffset = usGetWord(14, aucBuffer);
+	if (aucBuffer[usOffset] != 0) {
+		NO_DBG_STRN(aucBuffer + usOffset, 8);
+		tCreateDtm = tConvertDosDate((char *)aucBuffer + usOffset);
+	}
+	aucBuffer = xfree(aucBuffer);
+} /* end of vSet0SummaryInfo */
+
+/*
+ * vSet2SummaryInfo - set summary information from a WinWord 1/2 file
+ */
+void
+vSet2SummaryInfo(FILE *pFile, int iWordVersion, const UCHAR *aucHeader)
+{
+	UCHAR	*aucBuffer;
+	ULONG	ulBeginSumdInfo, ulBeginDocpInfo, ulTmp;
+	size_t	tSumdInfoLen, tDocpInfoLen, tLen, tCounter, tStart;
+
+	TRACE_MSG("vSet2SummaryInfo");
+
+	fail(pFile == NULL || aucHeader == NULL);
+	fail(iWordVersion != 1 && iWordVersion != 2);
+
+	/* First check the header */
+	usLid = usGetWord(0x06, aucHeader); /* Language IDentification */
+	DBG_HEX(usLid);
+	if (usLid < 999 && iWordVersion == 1) {
+		switch (usLid) {
+		case   1: usLid = 0x0409; break;	/* American English */
+		case   2: usLid = 0x0c0c; break;	/* Canadian French */
+		case  31: usLid = 0x0413; break;	/* Dutch */
+		case  33: usLid = 0x040c; break;	/* French */
+		case  34: usLid = 0x040a; break;	/* Spanish */
+		case  36: usLid = 0x040e; break;	/* Hungarian */
+		case  39: usLid = 0x0410; break;	/* Italian */
+		case  44: usLid = 0x0809; break;	/* British English */
+		case  45: usLid = 0x0406; break;	/* Danish */
+		case  46: usLid = 0x041f; break;	/* Swedish */
+		case  47: usLid = 0x0414; break;	/* Norwegian */
+		case  48: usLid = 0x0415; break;	/* Polish */
+		case  49: usLid = 0x0407; break;	/* German */
+		case 351: usLid = 0x0816; break;	/* Portuguese */
+		case 358: usLid = 0x040b; break;	/* Finnish */
+		default:
+			DBG_DEC(usLid);
+			DBG_FIXME();
+			usLid = 0x0409;		/* American English */
+			break;
+		}
+	}
+
+	if (iWordVersion != 2) {
+		/* Unknown where to find the associated strings */
+		return;
+	}
+
+	/* Second check the associated strings */
+	ulBeginSumdInfo = ulGetLong(0x118, aucHeader); /* fcSttbfAssoc */
+	DBG_HEX(ulBeginSumdInfo);
+	tSumdInfoLen = (size_t)usGetWord(0x11c, aucHeader); /* cbSttbfAssoc */
+	DBG_DEC(tSumdInfoLen);
+
+	if (tSumdInfoLen == 0) {
+		/* There is no summary information */
+		return;
+	}
+
+	aucBuffer = xmalloc(tSumdInfoLen);
+	if (!bReadBytes(aucBuffer, tSumdInfoLen, ulBeginSumdInfo, pFile)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+	NO_DBG_PRINT_BLOCK(aucBuffer, tSumdInfoLen);
+	tLen = (size_t)ucGetByte(0, aucBuffer);
+	DBG_DEC_C(tSumdInfoLen != tLen, tSumdInfoLen);
+	DBG_DEC_C(tSumdInfoLen != tLen, tLen);
+	tStart = 1;
+	for (tCounter = 0; tCounter < 17; tCounter++) {
+		if (tStart >= tSumdInfoLen) {
+			break;
+		}
+		tLen = (size_t)ucGetByte(tStart, aucBuffer);
+		if (tLen != 0) {
+			NO_DBG_DEC(tCounter);
+			NO_DBG_STRN(aucBuffer + tStart + 1, tLen);
+			switch (tCounter) {
+			case 3:
+				szTitle = xmalloc(tLen + 1);
+				strncpy(szTitle,
+					(char *)aucBuffer + tStart + 1, tLen);
+				szTitle[tLen] = '\0';
+				break;
+			case 4:
+				szSubject = xmalloc(tLen + 1);
+				strncpy(szSubject,
+					(char *)aucBuffer + tStart + 1, tLen);
+				szSubject[tLen] = '\0';
+				break;
+			case 7:
+				szAuthor = xmalloc(tLen + 1);
+				strncpy(szAuthor,
+					(char *)aucBuffer + tStart + 1, tLen);
+				szAuthor[tLen] = '\0';
+				break;
+			default:
+				break;
+			}
+		}
+		tStart += tLen + 1;
+	}
+	aucBuffer = xfree(aucBuffer);
+
+	/* Third check the document properties */
+	ulBeginDocpInfo = ulGetLong(0x112, aucHeader); /* fcDop */
+	DBG_HEX(ulBeginDocpInfo);
+	tDocpInfoLen = (size_t)usGetWord(0x116, aucHeader); /* cbDop */
+	DBG_DEC(tDocpInfoLen);
+	if (tDocpInfoLen < 12) {
+		return;
+	}
+
+	aucBuffer = xmalloc(tDocpInfoLen);
+	if (!bReadBytes(aucBuffer, tDocpInfoLen, ulBeginDocpInfo, pFile)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+        ulTmp = ulGetLong(0x14, aucBuffer); /* dttmCreated */
+	tCreateDtm = tConvertDTTM(ulTmp);
+        ulTmp = ulGetLong(0x18, aucBuffer); /* dttmRevised */
+	tLastSaveDtm = tConvertDTTM(ulTmp);
+	aucBuffer = xfree(aucBuffer);
+} /* end of vSet2SummaryInfo */
+
+/*
+ * vSetSummaryInfoOLE - set summary information from a Word 6+ file
+ */
+static void
+vSetSummaryInfoOLE(FILE *pFile, const pps_info_type *pPPS,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const ULONG *aulSBD, size_t tSBDLen)
+{
+	UCHAR	*pucBuffer;
+
+	fail(pFile == NULL || pPPS == NULL);
+	fail(aulBBD == NULL || aulSBD == NULL);
+
+	/* Summary Information */
+	pucBuffer = pucAnalyseSummaryInfoHeader(pFile,
+		pPPS->tSummaryInfo.ulSB, pPPS->tSummaryInfo.ulSize,
+		aulBBD, tBBDLen, aulSBD, tSBDLen);
+	if (pucBuffer != NULL) {
+		vAnalyseSummaryInfo(pucBuffer);
+		pucBuffer = xfree(pucBuffer);
+	}
+
+	/* Document Summary Information */
+	pucBuffer = pucAnalyseSummaryInfoHeader(pFile,
+		pPPS->tDocSummaryInfo.ulSB, pPPS->tDocSummaryInfo.ulSize,
+		aulBBD, tBBDLen, aulSBD, tSBDLen);
+	if (pucBuffer != NULL) {
+		vAnalyseDocumentSummaryInfo(pucBuffer);
+		pucBuffer = xfree(pucBuffer);
+	}
+} /* end of vSetSummaryInfoOLE */
+
+/*
+ * vSet6SummaryInfo - set summary information from a Word 6/7 file
+ */
+void
+vSet6SummaryInfo(FILE *pFile, const pps_info_type *pPPS,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const ULONG *aulSBD, size_t tSBDLen,
+	const UCHAR *aucHeader)
+{
+	TRACE_MSG("vSet6SummaryInfo");
+
+	/* Header Information */
+	usLid = usGetWord(0x06, aucHeader); /* Language IDentification */
+	DBG_HEX(usLid);
+
+	/* Summery Information */
+	vSetSummaryInfoOLE(pFile, pPPS, aulBBD, tBBDLen, aulSBD, tSBDLen);
+} /* end of vSet6SummaryInfo */
+
+/*
+ * vSet8SummaryInfo - set summary information a Word 8/9/10 file
+ */
+void
+vSet8SummaryInfo(FILE *pFile, const pps_info_type *pPPS,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const ULONG *aulSBD, size_t tSBDLen,
+	const UCHAR *aucHeader)
+{
+	USHORT	usTmp;
+
+	TRACE_MSG("vSet8SummaryInfo");
+
+	/* Header Information */
+	usTmp = usGetWord(0x0a, aucHeader);
+	if (usTmp & BIT(14)) {
+		/* Language IDentification Far East */
+		usLid = usGetWord(0x3c, aucHeader);
+	} else {
+		/* Language IDentification */
+		usLid = usGetWord(0x06, aucHeader);
+	}
+	DBG_HEX(usLid);
+
+	/* Summery Information */
+	vSetSummaryInfoOLE(pFile, pPPS, aulBBD, tBBDLen, aulSBD, tSBDLen);
+} /* end of vSet8SummaryInfo */
+
+/*
+ * szGetTitle - get the title field
+ */
+const char *
+szGetTitle(void)
+{
+	return szTitle;
+} /* end of szGetTitle */
+
+/*
+ * szGetSubject - get the subject field
+ */
+const char *
+szGetSubject(void)
+{
+	return szSubject;
+} /* end of szGetSubject */
+
+/*
+ * szGetAuthor - get the author field
+ */
+const char *
+szGetAuthor(void)
+{
+	return szAuthor;
+} /* end of szGetAuthor */
+
+/*
+ * szGetLastSaveDtm - get the last save date field
+ */
+const char *
+szGetLastSaveDtm(void)
+{
+	static char	szTime[12];
+	struct tm	*pTime;
+
+	if (tLastSaveDtm == (time_t)-1) {
+		return NULL;
+	}
+	pTime = localtime(&tLastSaveDtm);
+	if (pTime == NULL) {
+		return NULL;
+	}
+	sprintf(szTime, "%04d-%02d-%02d",
+		pTime->tm_year + 1900, pTime->tm_mon + 1, pTime->tm_mday);
+	return szTime;
+} /* end of szGetLastSaveDtm */
+
+/*
+ * szGetModDate - get the last save date field
+ */
+const char *
+szGetModDate(void)
+{
+	static char	szTime[20];
+	struct tm	*pTime;
+
+	if (tLastSaveDtm == (time_t)-1) {
+		return NULL;
+	}
+	pTime = localtime(&tLastSaveDtm);
+	if (pTime == NULL) {
+		return NULL;
+	}
+	sprintf(szTime, "D:%04d%02d%02d%02d%02d",
+		pTime->tm_year + 1900, pTime->tm_mon + 1, pTime->tm_mday,
+		pTime->tm_hour, pTime->tm_min);
+	return szTime;
+} /* end of szGetModDate */
+
+/*
+ * szGetCreationDate - get the last save date field
+ */
+const char *
+szGetCreationDate(void)
+{
+	static char	szTime[20];
+	struct tm	*pTime;
+
+	if (tCreateDtm == (time_t)-1) {
+		return NULL;
+	}
+	pTime = localtime(&tCreateDtm);
+	if (pTime == NULL) {
+		return NULL;
+	}
+	sprintf(szTime, "D:%04d%02d%02d%02d%02d",
+		pTime->tm_year + 1900, pTime->tm_mon + 1, pTime->tm_mday,
+		pTime->tm_hour, pTime->tm_min);
+	return szTime;
+} /* end of szGetCreationDate */
+
+/*
+ * szGetCompany - get the company field
+ */
+const char *
+szGetCompany(void)
+{
+	return szCompany;
+} /* end of szGetCompany */
+
+/*
+ * szGetLanguage - get de language field
+ */
+const char *
+szGetLanguage(void)
+{
+	if (usLid == (USHORT)-1) {
+		/* No Language IDentification */
+		return NULL;
+	}
+	if (usLid < 999) {
+		/* This is a Locale, not a Language IDentification */
+		DBG_DEC(usLid);
+		return NULL;
+	}
+
+	/* Exceptions to the general rule */
+	switch (usLid) {
+	case 0x0404: return "zh_TW"; /* Traditional Chinese */
+	case 0x0804: return "zh_CN"; /* Simplified Chinese */
+	case 0x0c04: return "zh_HK"; /* Hong Kong Chinese */
+	case 0x1004: return "zh_SG"; /* Singapore Chinese */
+	case 0x0807: return "de_CH"; /* Swiss German */
+	case 0x0409: return "en_US"; /* American English */
+	case 0x0809: return "en_GB"; /* British English */
+	case 0x0c09: return "en_AU"; /* Australian English */
+	case 0x080a: return "es_MX"; /* Mexican Spanish */
+	case 0x080c: return "fr_BE"; /* Belgian French */
+	case 0x0c0c: return "fr_CA"; /* Canadian French */
+	case 0x100c: return "fr_CH"; /* Swiss French */
+	case 0x0810: return "it_CH"; /* Swiss Italian */
+	case 0x0813: return "nl_BE"; /* Belgian Dutch */
+	case 0x0416: return "pt_BR"; /* Brazilian Portuguese */
+	case 0x081a:
+	case 0x0c1a: return "sr";    /* Serbian */
+	case 0x081d: return "sv_FI"; /* Finland Swedish */
+	default:
+		break;
+	}
+
+	/* The general rule */
+	switch (usLid & 0x00ff) {
+	case 0x01: return "ar";	/* Arabic */
+	case 0x02: return "bg";	/* Bulgarian */
+	case 0x03: return "ca";	/* Catalan */
+	case 0x04: return "zh";	/* Chinese */
+	case 0x05: return "cs";	/* Czech */
+	case 0x06: return "da";	/* Danish */
+	case 0x07: return "de";	/* German */
+	case 0x08: return "el";	/* Greek */
+	case 0x09: return "en";	/* English */
+	case 0x0a: return "es";	/* Spanish */
+	case 0x0b: return "fi";	/* Finnish */
+	case 0x0c: return "fr";	/* French */
+	case 0x0d: return "he";	/* Hebrew */
+	case 0x0e: return "hu";	/* Hungarian */
+	case 0x0f: return "is";	/* Icelandic */
+	case 0x10: return "it";	/* Italian */
+	case 0x11: return "ja";	/* Japanese */
+	case 0x12: return "ko";	/* Korean */
+	case 0x13: return "nl";	/* Dutch */
+	case 0x14: return "no";	/* Norwegian */
+	case 0x15: return "pl";	/* Polish */
+	case 0x16: return "pt";	/* Portuguese */
+	case 0x17: return "rm";	/* Rhaeto-Romance */
+	case 0x18: return "ro";	/* Romanian */
+	case 0x19: return "ru";	/* Russian */
+	case 0x1a: return "hr";	/* Croatian */
+	case 0x1b: return "sk";	/* Slovak */
+	case 0x1c: return "sq";	/* Albanian */
+	case 0x1d: return "sv";	/* Swedish */
+	case 0x1e: return "th";	/* Thai */
+	case 0x1f: return "tr";	/* Turkish */
+	case 0x20: return "ur";	/* Urdu */
+	case 0x21: return "id";	/* Indonesian */
+	case 0x22: return "uk";	/* Ukrainian */
+	case 0x23: return "be";	/* Belarusian */
+	case 0x24: return "sl";	/* Slovenian */
+	case 0x25: return "et";	/* Estonian */
+	case 0x26: return "lv";	/* Latvian */
+	case 0x27: return "lt";	/* Lithuanian */
+	case 0x29: return "fa";	/* Farsi */
+	case 0x2a: return "vi";	/* Viet Nam */
+	case 0x2b: return "hy";	/* Armenian */
+	case 0x2c: return "az";	/* Azeri */
+	case 0x2d: return "eu";	/* Basque */
+	case 0x2f: return "mk";	/* Macedonian */
+	case 0x36: return "af";	/* Afrikaans */
+	case 0x37: return "ka";	/* Georgian */
+	case 0x38: return "fo";	/* Faeroese */
+	case 0x39: return "hi";	/* Hindi */
+	case 0x3e: return "ms";	/* Malay */
+	case 0x3f: return "kk";	/* Kazakh */
+	default:
+		DBG_HEX(usLid);
+		DBG_FIXME();
+		return NULL;
+	}
+} /* end of szGetLanguage */
diff --git a/tabstop.c b/tabstop.c
new file mode 100644
index 0000000..604d949
--- /dev/null
+++ b/tabstop.c
@@ -0,0 +1,212 @@
+/*
+ * tabstops.c
+ * Copyright (C) 1999-2004 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Read the tab stop information from a MS Word file
+ */
+
+#include <stdio.h>
+#include "antiword.h"
+
+#define HALF_INCH	36000L	/* In millipoints */
+
+static long	lDefaultTabWidth = HALF_INCH;
+
+
+/*
+ * vSet0DefaultTabWidth -
+ */
+static void
+vSet0DefaultTabWidth(const UCHAR *aucHeader)
+{
+	USHORT	usTmp;
+
+	fail(aucHeader == NULL);
+
+	usTmp = usGetWord(0x70, aucHeader); /* dxaTab */
+	DBG_DEC(usTmp);
+	lDefaultTabWidth = usTmp == 0 ? HALF_INCH : lTwips2MilliPoints(usTmp);
+	DBG_DEC(lDefaultTabWidth);
+} /* end of vSet0DefaultTabWidth */
+
+/*
+ * vSet2DefaultTabWidth -
+ */
+static void
+vSet2DefaultTabWidth(FILE *pFile, const UCHAR *aucHeader)
+{
+	UCHAR	*aucBuffer;
+	ULONG	ulBeginDocpInfo;
+	size_t	tDocpInfoLen;
+	USHORT	usTmp;
+
+	fail(pFile == NULL || aucHeader == NULL);
+
+	ulBeginDocpInfo = ulGetLong(0x112, aucHeader); /* fcDop */
+	DBG_HEX(ulBeginDocpInfo);
+	tDocpInfoLen = (size_t)usGetWord(0x116, aucHeader); /* cbDop */
+	DBG_DEC(tDocpInfoLen);
+	if (tDocpInfoLen < 12) {
+		DBG_MSG("No TAB information");
+		return;
+	}
+
+	aucBuffer = xmalloc(tDocpInfoLen);
+	if (!bReadBytes(aucBuffer, tDocpInfoLen, ulBeginDocpInfo, pFile)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+	usTmp = usGetWord(0x0a, aucBuffer); /* dxaTab */
+	lDefaultTabWidth = usTmp == 0 ? HALF_INCH : lTwips2MilliPoints(usTmp);
+	DBG_DEC(lDefaultTabWidth);
+	aucBuffer = xfree(aucBuffer);
+} /* end of vSet2DefaultTabWidth */
+
+/*
+ * vSet6DefaultTabWidth -
+ */
+static void
+vSet6DefaultTabWidth(FILE *pFile, ULONG ulStartBlock,
+	const ULONG *aulBBD, size_t tBBDLen, const UCHAR *aucHeader)
+{
+	UCHAR	*aucBuffer;
+	ULONG	ulBeginDocpInfo;
+	size_t	tDocpInfoLen;
+	USHORT	usTmp;
+
+	ulBeginDocpInfo = ulGetLong(0x150, aucHeader); /* fcDop */
+	DBG_HEX(ulBeginDocpInfo);
+	tDocpInfoLen = (size_t)ulGetLong(0x154, aucHeader); /* lcbDop */
+	DBG_DEC(tDocpInfoLen);
+	if (tDocpInfoLen < 12) {
+		DBG_MSG("No TAB information");
+		return;
+	}
+
+	aucBuffer = xmalloc(tDocpInfoLen);
+	if (!bReadBuffer(pFile, ulStartBlock,
+			aulBBD, tBBDLen, BIG_BLOCK_SIZE,
+			aucBuffer, ulBeginDocpInfo, tDocpInfoLen)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+	usTmp = usGetWord(0x0a, aucBuffer); /* dxaTab */
+	lDefaultTabWidth = usTmp == 0 ? HALF_INCH : lTwips2MilliPoints(usTmp);
+	DBG_DEC(lDefaultTabWidth);
+	aucBuffer = xfree(aucBuffer);
+} /* end of vSet6DefaultTabWidth */
+
+/*
+ * vSet8DefaultTabWidth -
+ */
+static void
+vSet8DefaultTabWidth(FILE *pFile, const pps_info_type *pPPS,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const ULONG *aulSBD, size_t tSBDLen,
+	const UCHAR *aucHeader)
+{
+        const ULONG	*aulBlockDepot;
+	UCHAR	*aucBuffer;
+	ULONG	ulBeginDocpInfo;
+	size_t	tDocpInfoLen, tBlockDepotLen, tBlockSize;
+	USHORT	usTmp;
+
+	ulBeginDocpInfo = ulGetLong(0x192, aucHeader); /* fcDop */
+	DBG_HEX(ulBeginDocpInfo);
+	tDocpInfoLen = (size_t)ulGetLong(0x196, aucHeader); /* lcbDop */
+	DBG_DEC(tDocpInfoLen);
+	if (tDocpInfoLen < 12) {
+		DBG_MSG("No TAB information");
+		return;
+	}
+
+	DBG_DEC(pPPS->tTable.ulSB);
+	DBG_HEX(pPPS->tTable.ulSize);
+	if (pPPS->tTable.ulSize == 0) {
+		DBG_MSG("No TAB information");
+		return;
+	}
+
+	if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
+		/* Use the Small Block Depot */
+		aulBlockDepot = aulSBD;
+		tBlockDepotLen = tSBDLen;
+		tBlockSize = SMALL_BLOCK_SIZE;
+	} else {
+		/* Use the Big Block Depot */
+		aulBlockDepot = aulBBD;
+		tBlockDepotLen = tBBDLen;
+		tBlockSize = BIG_BLOCK_SIZE;
+	}
+	aucBuffer = xmalloc(tDocpInfoLen);
+	if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
+			aulBlockDepot, tBlockDepotLen, tBlockSize,
+			aucBuffer, ulBeginDocpInfo, tDocpInfoLen)) {
+		aucBuffer = xfree(aucBuffer);
+		return;
+	}
+	usTmp = usGetWord(0x0a, aucBuffer); /* dxaTab */
+	lDefaultTabWidth = usTmp == 0 ? HALF_INCH : lTwips2MilliPoints(usTmp);
+	DBG_DEC(lDefaultTabWidth);
+	aucBuffer = xfree(aucBuffer);
+} /* end of vSet8DefaultTabWidth */
+
+/*
+ * vSetDefaultTabWidth -
+ */
+void
+vSetDefaultTabWidth(FILE *pFile, const pps_info_type *pPPS,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const ULONG *aulSBD, size_t tSBDLen,
+	const UCHAR *aucHeader, int iWordVersion)
+{
+	fail(pFile == NULL && iWordVersion >= 1);
+	fail(pPPS == NULL && iWordVersion >= 6);
+	fail(aulBBD == NULL && tBBDLen != 0);
+	fail(aulSBD == NULL && tSBDLen != 0);
+	fail(aucHeader == NULL);
+
+	/* Reset to the default default value */
+	lDefaultTabWidth = HALF_INCH;
+
+	switch (iWordVersion) {
+	case 0:
+		vSet0DefaultTabWidth(aucHeader);
+		break;
+	case 1:
+	case 2:
+		vSet2DefaultTabWidth(pFile, aucHeader);
+		break;
+	case 4:
+	case 5:
+		break;
+	case 6:
+	case 7:
+		vSet6DefaultTabWidth(pFile, pPPS->tWordDocument.ulSB,
+				aulBBD, tBBDLen, aucHeader);
+		break;
+	case 8:
+		vSet8DefaultTabWidth(pFile, pPPS,
+				aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
+		break;
+	default:
+		werr(0, "Sorry, no TAB information");
+		break;
+	}
+} /* end of vSetDefaultTabWidth */
+
+#if 0
+/*
+ * lGetDefaultTabWidth - Get the default tabwidth in millipoints
+ */
+long
+lGetDefaultTabWidth(void)
+{
+	if (lDefaultTabWidth <= 0) {
+		DBG_DEC(lDefaultTabWidth);
+		return lTwips2MilliPoints(1);
+	}
+	return lDefaultTabWidth;
+} /* end of lGetDefaultTabWidth */
+#endif
diff --git a/text.c b/text.c
new file mode 100644
index 0000000..bd3dc92
--- /dev/null
+++ b/text.c
@@ -0,0 +1,182 @@
+/*
+ * text.c
+ * Copyright (C) 1999-2004 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Functions to deal with the Text format
+ *
+ */
+
+#include <string.h>
+#include "antiword.h"
+
+/* The character set */
+static encoding_type	eEncoding = encoding_neutral;
+/* Current vertical position information */
+static long		lYtopCurr = 0;
+/* Local representation of the non-breaking space */
+static UCHAR		ucNbsp = 0;
+
+
+/*
+ * vPrologueTXT - set options and perform the Text initialization
+ */
+void
+vPrologueTXT(diagram_type *pDiag, const options_type *pOptions)
+{
+	fail(pDiag == NULL);
+	fail(pOptions == NULL);
+
+	eEncoding = pOptions->eEncoding;
+	pDiag->lXleft = 0;
+	pDiag->lYtop = 0;
+	lYtopCurr = 0;
+} /* end of vPrologueTXT */
+
+/*
+ * vEpilogueTXT - clean up after everything is done
+ */
+void
+vEpilogueTXT(FILE *pOutFile)
+{
+	fail(pOutFile == NULL);
+
+	fprintf(pOutFile, "\n");
+} /* end of vEpilogueTXT */
+
+/*
+ * vPrintTXT - print a Text string
+ */
+static void
+vPrintTXT(FILE *pFile, const char *szString, size_t tStringLength)
+{
+	const UCHAR	*ucBytes;
+	size_t		tCount;
+
+	fail(szString == NULL);
+
+	if (szString == NULL || szString[0] == '\0' || tStringLength == 0) {
+		return;
+	}
+
+	if (eEncoding == encoding_utf_8) {
+		fprintf(pFile, "%.*s", (int)tStringLength, szString);
+		return;
+	}
+
+	if (ucNbsp == 0) {
+		ucNbsp = ucGetNbspCharacter();
+		DBG_HEX_C(ucNbsp != 0xa0, ucNbsp);
+	}
+
+	ucBytes = (UCHAR *)szString;
+	for (tCount = 0; tCount < tStringLength ; tCount++) {
+		if (ucBytes[tCount] == ucNbsp) {
+			(void)putc(' ', pFile);
+		} else {
+			(void)putc(szString[tCount], pFile);
+		}
+	}
+} /* end of vPrintTXT */
+
+/*
+ * vMoveTo - move to the given X,Y coordinates
+ *
+ * Move the current position of the given diagram to its X,Y coordinates,
+ * start on a new page if needed
+ */
+static void
+vMoveTo(diagram_type *pDiag)
+{
+	int	iCount, iNbr;
+
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+
+	if (pDiag->lYtop != lYtopCurr) {
+		iNbr = iDrawUnits2Char(pDiag->lXleft);
+		for (iCount = 0; iCount < iNbr; iCount++) {
+			(void)putc(FILLER_CHAR, pDiag->pOutFile);
+		}
+		lYtopCurr = pDiag->lYtop;
+	}
+} /* end of vMoveTo */
+
+/*
+ * vMove2NextLineTXT - move to the next line
+ */
+void
+vMove2NextLineTXT(diagram_type *pDiag)
+{
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+
+	pDiag->lYtop++;
+	(void)fprintf(pDiag->pOutFile, "\n");
+} /* end of vMove2NextLineTXT */
+
+/*
+ * vSubstringTXT - print a sub string
+ */
+void
+vSubstringTXT(diagram_type *pDiag,
+	const char *szString, size_t tStringLength, long lStringWidth)
+{
+	fail(pDiag == NULL || szString == NULL);
+	fail(pDiag->pOutFile == NULL);
+	fail(pDiag->lXleft < 0);
+	fail(tStringLength != strlen(szString));
+
+	if (szString[0] == '\0' || tStringLength == 0) {
+		return;
+	}
+
+	vMoveTo(pDiag);
+	vPrintTXT(pDiag->pOutFile, szString, tStringLength);
+	pDiag->lXleft += lStringWidth;
+} /* end of vSubstringTXT */
+
+/*
+ * Create an start of paragraph by moving the y-top mark
+ */
+void
+vStartOfParagraphTXT(diagram_type *pDiag, long lBeforeIndentation)
+{
+	fail(pDiag == NULL);
+	fail(lBeforeIndentation < 0);
+
+	if (lBeforeIndentation >= lTwips2MilliPoints(HEADING_GAP)) {
+		/* A large gap is replaced by an empty line */
+		vMove2NextLineTXT(pDiag);
+	}
+} /* end of vStartOfParagraphTXT */
+
+/*
+ * Create an end of paragraph by moving the y-top mark
+ */
+void
+vEndOfParagraphTXT(diagram_type *pDiag, long lAfterIndentation)
+{
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+	fail(lAfterIndentation < 0);
+
+	if (pDiag->lXleft > 0) {
+		/* To the start of the line */
+		vMove2NextLineTXT(pDiag);
+	}
+
+	if (lAfterIndentation >= lTwips2MilliPoints(HEADING_GAP)) {
+		/* A large gap is replaced by an empty line */
+		vMove2NextLineTXT(pDiag);
+	}
+} /* end of vEndOfParagraphTXT */
+
+/*
+ * Create an end of page
+ */
+void
+vEndOfPageTXT(diagram_type *pDiag, long lAfterIndentation)
+{
+	vEndOfParagraphTXT(pDiag, lAfterIndentation);
+} /* end of vEndOfPageTXT */
diff --git a/unix.c b/unix.c
new file mode 100644
index 0000000..3da3964
--- /dev/null
+++ b/unix.c
@@ -0,0 +1,45 @@
+/*
+ * unix.c
+ * Copyright (C) 1998-2000 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Unix approximations of RISC-OS functions
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include "antiword.h"
+
+
+/*
+ * werr - write an error message and exit if needed
+ */
+void
+werr(int iFatal, const char *szFormat, ...)
+{
+	va_list tArg;
+
+	va_start(tArg, szFormat);
+	(void)vfprintf(stderr, szFormat, tArg);
+	va_end(tArg);
+	fprintf(stderr, "\n");
+	switch (iFatal) {
+	case 0:		/* The message is just a warning, so no exit */
+		return;
+	case 1:		/* Fatal error with a standard exit */
+		exit(EXIT_FAILURE);
+	default:	/* Fatal error with a non-standard exit */
+		exit(iFatal);
+	}
+} /* end of werr */
+
+void
+Hourglass_On(void)
+{
+} /* end of Hourglass_On */
+
+void
+Hourglass_Off(void)
+{
+} /* end of Hourglass_Off */
diff --git a/utf8.c b/utf8.c
new file mode 100644
index 0000000..2cc2191
--- /dev/null
+++ b/utf8.c
@@ -0,0 +1,260 @@
+/*
+ * utf8.c
+ * Copyright (C) 2001-2004 A.J. van Os; Released under GPL
+ *
+ *====================================================================
+ * This part of the software is based on:
+ * An implementation of wcwidth() as defined in
+ * "The Single UNIX Specification, Version 2, The Open Group, 1997"
+ * <http://www.UNIX-systems.org/online.html>
+ * Markus Kuhn -- 2001-01-12 -- public domain
+ *====================================================================
+ * The credit should go to him, but all the bugs are mine.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "antiword.h"
+
+struct interval {
+	USHORT	first;
+	USHORT	last;
+};
+/* Sorted list of non-overlapping intervals of non-spacing characters */
+static const struct interval combining[] = {
+	{ 0x0300, 0x034E }, { 0x0360, 0x0362 }, { 0x0483, 0x0486 },
+	{ 0x0488, 0x0489 }, { 0x0591, 0x05A1 }, { 0x05A3, 0x05B9 },
+	{ 0x05BB, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
+	{ 0x05C4, 0x05C4 }, { 0x064B, 0x0655 }, { 0x0670, 0x0670 },
+	{ 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED },
+	{ 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A },
+	{ 0x07A6, 0x07B0 }, { 0x0901, 0x0902 }, { 0x093C, 0x093C },
+	{ 0x0941, 0x0948 }, { 0x094D, 0x094D }, { 0x0951, 0x0954 },
+	{ 0x0962, 0x0963 }, { 0x0981, 0x0981 }, { 0x09BC, 0x09BC },
+	{ 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD }, { 0x09E2, 0x09E3 },
+	{ 0x0A02, 0x0A02 }, { 0x0A3C, 0x0A3C }, { 0x0A41, 0x0A42 },
+	{ 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D }, { 0x0A70, 0x0A71 },
+	{ 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC }, { 0x0AC1, 0x0AC5 },
+	{ 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD }, { 0x0B01, 0x0B01 },
+	{ 0x0B3C, 0x0B3C }, { 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 },
+	{ 0x0B4D, 0x0B4D }, { 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 },
+	{ 0x0BC0, 0x0BC0 }, { 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 },
+	{ 0x0C46, 0x0C48 }, { 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 },
+	{ 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD },
+	{ 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D }, { 0x0DCA, 0x0DCA },
+	{ 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 }, { 0x0E31, 0x0E31 },
+	{ 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E }, { 0x0EB1, 0x0EB1 },
+	{ 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC }, { 0x0EC8, 0x0ECD },
+	{ 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 }, { 0x0F37, 0x0F37 },
+	{ 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E }, { 0x0F80, 0x0F84 },
+	{ 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 }, { 0x0F99, 0x0FBC },
+	{ 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 }, { 0x1032, 0x1032 },
+	{ 0x1036, 0x1037 }, { 0x1039, 0x1039 }, { 0x1058, 0x1059 },
+	{ 0x1160, 0x11FF }, { 0x17B7, 0x17BD }, { 0x17C6, 0x17C6 },
+	{ 0x17C9, 0x17D3 }, { 0x180B, 0x180E }, { 0x18A9, 0x18A9 },
+	{ 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x206A, 0x206F },
+	{ 0x20D0, 0x20E3 }, { 0x302A, 0x302F }, { 0x3099, 0x309A },
+	{ 0xFB1E, 0xFB1E }, { 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF },
+	{ 0xFFF9, 0xFFFB }
+};
+
+/* Auxiliary function for binary search in interval table */
+static BOOL
+bIsZeroWidthChar(ULONG ucs)
+{
+	int low = 0;
+	int high = elementsof(combining) - 1;
+	int mid;
+
+	if (ucs < (ULONG)combining[low].first ||
+	    ucs > (ULONG)combining[high].last) {
+		return FALSE;
+	}
+
+	while (high >= low) {
+		mid = (low + high) / 2;
+		if (ucs > (ULONG)combining[mid].last) {
+			low = mid + 1;
+		} else if (ucs < (ULONG)combining[mid].first) {
+			high = mid - 1;
+		} else {
+			return TRUE;
+		}
+	}
+	return FALSE;
+} /* end of bIsZeroWidthChar */
+
+/* The following functions define the column width of an ISO 10646
+ * character as follows:
+ *
+ *    - The null character (U+0000) has a column width of 0.
+ *
+ *    - Other C0/C1 control characters and DEL will lead to a return
+ *      value of -1.
+ *
+ *    - Non-spacing and enclosing combining characters (general
+ *      category code Mn or Me in the Unicode database) have a
+ *      column width of 0.
+ *
+ *    - Other format characters (general category code Cf in the Unicode
+ *      database) and ZERO WIDTH SPACE (U+200B) have a column width of 0.
+ *
+ *    - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
+ *      have a column width of 0.
+ *
+ *    - Spacing characters in the East Asian Wide (W) or East Asian
+ *      FullWidth (F) category as defined in Unicode Technical
+ *      Report #11 have a column width of 2.
+ *
+ *    - All remaining characters (including all printable
+ *      ISO 8859-1 and WGL4 characters, Unicode control characters,
+ *      etc.) have a column width of 1.
+ *
+ * This implementation assumes that all characters are encoded
+ * in ISO 10646.
+ *
+ * This function is not named wcwidth() to prevent name clashes
+ */
+static int
+iWcWidth(ULONG ucs)
+{
+	/* Test for 8-bit control characters */
+	if (ucs == 0) {
+		return 0;
+	}
+	if (ucs < 0x20 || (ucs >= 0x7f && ucs < 0xa0)) {
+		NO_DBG_HEX(ucs);
+		return -1;
+	}
+
+	/* Binary search in table of non-spacing characters */
+	if (bIsZeroWidthChar(ucs)) {
+		return 0;
+	}
+
+	/* Ucs is not a combining or C0/C1 control character */
+
+	return 1 +
+	(ucs >= 0x1100 &&
+	 (ucs <= 0x115f ||                    /* Hangul Jamo init. consonants */
+	  (ucs >= 0x2e80 && ucs <= 0xa4cf && (ucs & ~0x0011) != 0x300a &&
+	   ucs != 0x303f) ||                  /* CJK ... Yi */
+	  (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
+	  (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
+	  (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
+	  (ucs >= 0xff00 && ucs <= 0xff5f) || /* Fullwidth Forms */
+	  (ucs >= 0xffe0 && ucs <= 0xffe6) ||
+	  (ucs >= 0x20000 && ucs <= 0x2ffff)));
+} /* end of iWcWidth */
+
+/*
+ * utf8_to_ucs - convert from UTF-8 to UCS
+ *
+ * Returns the UCS character,
+ * Fills in the number of bytes in the UTF-8 character
+ */
+static ULONG
+utf8_to_ucs(const char *p, int iStrLen, int *piUtfLen)
+{
+	ULONG	ulUcs;
+	int	iIndex, iCharLen;
+
+	fail(p == NULL || piUtfLen == NULL);
+	fail(iStrLen < 1);
+
+	ulUcs = (ULONG)(UCHAR)p[0];
+
+	if (ulUcs < 0x80) {
+		*piUtfLen = 1;
+		return ulUcs;
+	}
+
+	if (ulUcs < 0xe0){
+		iCharLen = 2;
+		ulUcs &= 0x1f;
+	} else if (ulUcs < 0xf0){
+		iCharLen = 3;
+		ulUcs &= 0x0f;
+	} else if (ulUcs < 0xf8){
+		iCharLen = 4;
+		ulUcs &= 0x07;
+	} else if (ulUcs < 0xfc){
+		iCharLen = 5;
+		ulUcs &= 0x03;
+	} else {
+		iCharLen = 6;
+		ulUcs &= 0x01;
+	}
+	for (iIndex = 1; iIndex < iCharLen; iIndex++) {
+		ulUcs <<= 6;
+		if (iIndex < iStrLen) {
+			ulUcs |= (ULONG)(UCHAR)p[iIndex] & 0x3f;
+		}
+	}
+	*piUtfLen = iCharLen;
+	return ulUcs;
+} /* end of utf8_to_ucs */
+
+/*
+ * utf8_strwidth - compute the string width of an UTF-8 string
+ *
+ * Returns the string width in columns
+ */
+long
+utf8_strwidth(const char *pcString, size_t tNumchars)
+{
+	ULONG	ulUcs;
+	long	lTotal;
+	int	iToGo, iWidth, iUtflen;
+
+	fail(pcString == NULL || tNumchars > (size_t)INT_MAX);
+
+	lTotal = 0;
+	iToGo = (int)tNumchars;
+
+	while (iToGo > 0 && *pcString != '\0') {
+		ulUcs = utf8_to_ucs(pcString, iToGo, &iUtflen);
+		iWidth = iWcWidth(ulUcs);
+		if (iWidth > 0) {
+			lTotal += iWidth;
+		}
+		pcString += iUtflen;
+		iToGo -= iUtflen;
+	}
+	NO_DBG_DEC(lTotal);
+	return lTotal;
+} /* end of utf8_strwidth */
+
+/*
+ * utf8_chrlength - get the number of bytes in an UTF-8 character
+ *
+ * Returns the number of bytes
+ */
+int
+utf8_chrlength(const char *p)
+{
+	int	iUtflen;
+
+	fail(p == NULL);
+
+	iUtflen = -1;		/* Just to make sure */
+	(void)utf8_to_ucs(p, INT_MAX, &iUtflen);
+	NO_DBG_DEC(iUtflen);
+	return iUtflen;
+} /* end of utf8_chrlength */
+
+/*
+ * is_locale_utf8 - return TRUE if the locale is UTF-8
+ */
+BOOL
+is_locale_utf8(void)
+{
+	char	szCodeset[20];
+
+	szCodeset[0] = '\0';
+	if (!bGetNormalizedCodeset(szCodeset, sizeof(szCodeset), NULL)) {
+		return FALSE;
+	}
+	DBG_MSG(szCodeset);
+	return STREQ(szCodeset, "utf8");
+} /* end of is_locale_utf8 */
diff --git a/version.h b/version.h
new file mode 100644
index 0000000..01ed709
--- /dev/null
+++ b/version.h
@@ -0,0 +1,37 @@
+/*
+ * version.h
+ * Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Version and release information
+ */
+
+#if !defined(__version_h)
+#define __version_h 1
+
+/* Strings for the info box */
+#define PURPOSESTRING	"Display MS-Word files"
+
+#if defined(__riscos)
+#define AUTHORSTRING	"� 1998-2005 Adri van Os"
+#else
+#define AUTHORSTRING	"(C) 1998-2005 Adri van Os"
+#endif /* __riscos */
+
+#define VERSIONSTRING	"0.37  (21 Oct 2005)"
+
+#if defined(__dos)
+#if defined(__DJGPP__)
+#define VERSIONSTRING2	" # 32-bit Protected Mode"
+#else
+#define VERSIONSTRING2	" # 16-bit Real Mode"
+#endif /* __DJGPP__ */
+#endif /* __dos */
+
+#if defined(DEBUG)
+#define STATUSSTRING	"DEBUG version"
+#else
+#define STATUSSTRING	"GNU General Public License"
+#endif /* DEBUG */
+
+#endif /* __version_h */
diff --git a/word2text.c b/word2text.c
new file mode 100644
index 0000000..62b8964
--- /dev/null
+++ b/word2text.c
@@ -0,0 +1,1505 @@
+/*
+ * word2text.c
+ * Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * MS Word to "text" functions
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#if defined(__riscos)
+#include "DeskLib:Hourglass.h"
+#include "drawfile.h"
+#endif /* __riscos */
+#include "antiword.h"
+
+
+#define INITIAL_SIZE		40
+#define EXTENTION_SIZE		20
+
+
+/* Macros to make sure all such statements will be identical */
+#define OUTPUT_LINE()		\
+	do {\
+		vAlign2Window(pDiag, pAnchor, lWidthMax, ucAlignment);\
+		TRACE_MSG("after vAlign2Window");\
+		pAnchor = pStartNewOutput(pAnchor, NULL);\
+		pOutput = pAnchor;\
+	} while(0)
+
+#define RESET_LINE()		\
+	do {\
+		pAnchor = pStartNewOutput(pAnchor, NULL);\
+		pOutput = pAnchor;\
+	} while(0)
+
+#if defined(__riscos)
+/* Length of the document in characters */
+static ULONG	ulDocumentLength;
+/* Number of characters processed so far */
+static ULONG	ulCharCounter;
+static int	iCurrPct, iPrevPct;
+#endif /* __riscos */
+/* The document is in the format belonging to this version of Word */
+static int	iWordVersion = -1;
+/* Special treatment for files from Word 4/5/6 on an Apple Macintosh */
+static BOOL	bOldMacFile = FALSE;
+/* Section Information */
+static const section_block_type	*pSection = NULL;
+static const section_block_type	*pSectionNext = NULL;
+/* All the (command line) options */
+static options_type	tOptions;
+/* Needed for reading a complete table row */
+static const row_block_type	*pRowInfo = NULL;
+static BOOL	bStartRow = FALSE;
+static BOOL	bEndRowNorm = FALSE;
+static BOOL	bEndRowFast = FALSE;
+static BOOL	bIsTableRow = FALSE;
+/* Index of the next style and font information */
+static USHORT	usIstdNext = ISTD_NORMAL;
+/* Needed for finding the start of a style */
+static const style_block_type	*pStyleInfo = NULL;
+static style_block_type		tStyleNext;
+static BOOL	bStartStyle = FALSE;
+static BOOL	bStartStyleNext = FALSE;
+/* Needed for finding the start of a font */
+static const font_block_type	*pFontInfo = NULL;
+static font_block_type		tFontNext;
+static BOOL	bStartFont = FALSE;
+static BOOL	bStartFontNext = FALSE;
+/* Needed for finding an image */
+static ULONG	ulFileOffsetImage = FC_INVALID;
+
+
+/*
+ * vUpdateCounters - Update the counters for the hourglass
+ */
+static void
+vUpdateCounters(void)
+{
+#if defined(__riscos)
+	ulCharCounter++;
+	iCurrPct = (int)((ulCharCounter * 100) / ulDocumentLength);
+	if (iCurrPct != iPrevPct) {
+		Hourglass_Percentage(iCurrPct);
+		iPrevPct = iCurrPct;
+	}
+#endif /* __riscos */
+} /* end of vUpdateCounters */
+
+/*
+ * bOutputContainsText - see if the output contains more than white space
+ */
+BOOL
+bOutputContainsText(const output_type *pAnchor)
+{
+	const output_type	*pCurr;
+	size_t	tIndex;
+
+	fail(pAnchor == NULL);
+
+	for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
+		fail(pCurr->lStringWidth < 0);
+		for (tIndex = 0; tIndex < pCurr->tNextFree; tIndex++) {
+			if (isspace((int)(UCHAR)pCurr->szStorage[tIndex])) {
+				continue;
+			}
+#if defined(DEBUG)
+			if (pCurr->szStorage[tIndex] == FILLER_CHAR) {
+				continue;
+			}
+#endif /* DEBUG */
+			return TRUE;
+		}
+	}
+	return FALSE;
+} /* end of bOutputContainsText */
+
+/*
+ * lTotalStringWidth - compute the total width of the output string
+ */
+static long
+lTotalStringWidth(const output_type *pAnchor)
+{
+	const output_type	*pCurr;
+	long		lTotal;
+
+	lTotal = 0;
+	for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
+		DBG_DEC_C(pCurr->lStringWidth < 0, pCurr->lStringWidth);
+		fail(pCurr->lStringWidth < 0);
+		lTotal += pCurr->lStringWidth;
+	}
+	return lTotal;
+} /* end of lTotalStringWidth */
+
+/*
+ * vStoreByte - store one byte
+ */
+static void
+vStoreByte(UCHAR ucChar, output_type *pOutput)
+{
+	fail(pOutput == NULL);
+
+	if (ucChar == 0) {
+		pOutput->szStorage[pOutput->tNextFree] = '\0';
+		return;
+	}
+
+	while (pOutput->tNextFree + 2 > pOutput->tStorageSize) {
+		pOutput->tStorageSize += EXTENTION_SIZE;
+		pOutput->szStorage = xrealloc(pOutput->szStorage,
+					pOutput->tStorageSize);
+	}
+	pOutput->szStorage[pOutput->tNextFree] = (char)ucChar;
+	pOutput->szStorage[pOutput->tNextFree + 1] = '\0';
+	pOutput->tNextFree++;
+} /* end of vStoreByte */
+
+/*
+ * vStoreChar - store a character as one or more bytes
+ */
+static void
+vStoreChar(ULONG ulChar, BOOL bChangeAllowed, output_type *pOutput)
+{
+	char	szResult[4];
+	size_t	tIndex, tLen;
+
+	fail(pOutput == NULL);
+
+	if (tOptions.eEncoding == encoding_utf_8 && bChangeAllowed) {
+		DBG_HEX_C(ulChar > 0xffff, ulChar);
+		fail(ulChar > 0xffff);
+		tLen = tUcs2Utf8(ulChar, szResult, sizeof(szResult));
+		for (tIndex = 0; tIndex < tLen; tIndex++) {
+			vStoreByte((UCHAR)szResult[tIndex], pOutput);
+		}
+	} else {
+		DBG_HEX_C(ulChar > 0xff, ulChar);
+		fail(ulChar > 0xff);
+		vStoreByte((UCHAR)ulChar, pOutput);
+		tLen = 1;
+	}
+	pOutput->lStringWidth += lComputeStringWidth(
+				pOutput->szStorage + pOutput->tNextFree - tLen,
+				tLen,
+				pOutput->tFontRef,
+				pOutput->usFontSize);
+} /* end of vStoreChar */
+
+/*
+ * vStoreCharacter - store one character
+ */
+static void
+vStoreCharacter(ULONG ulChar, output_type *pOutput)
+{
+	vStoreChar(ulChar, TRUE, pOutput);
+} /* end of vStoreCharacter */
+
+/*
+ * vStoreString - store a string
+ */
+static void
+vStoreString(const char *szString, size_t tStringLength, output_type *pOutput)
+{
+	size_t	tIndex;
+
+	fail(szString == NULL || pOutput == NULL);
+
+	for (tIndex = 0; tIndex < tStringLength; tIndex++) {
+		vStoreCharacter((ULONG)(UCHAR)szString[tIndex], pOutput);
+	}
+} /* end of vStoreString */
+
+/*
+ * vStoreNumberAsDecimal - store a number as a decimal number
+ */
+static void
+vStoreNumberAsDecimal(UINT uiNumber, output_type *pOutput)
+{
+	size_t	tLen;
+	char	szString[3 * sizeof(UINT) + 1];
+
+	fail(uiNumber == 0);
+	fail(pOutput == NULL);
+
+	tLen = (size_t)sprintf(szString, "%u", uiNumber);
+	vStoreString(szString, tLen, pOutput);
+} /* end of vStoreNumberAsDecimal */
+
+/*
+ * vStoreNumberAsRoman - store a number as a roman numerical
+ */
+static void
+vStoreNumberAsRoman(UINT uiNumber, output_type *pOutput)
+{
+	size_t	tLen;
+	char	szString[15];
+
+	fail(uiNumber == 0);
+	fail(pOutput == NULL);
+
+	tLen = tNumber2Roman(uiNumber, FALSE, szString);
+	vStoreString(szString, tLen, pOutput);
+} /* end of vStoreNumberAsRoman */
+
+/*
+ * vStoreStyle - store a style
+ */
+static void
+vStoreStyle(diagram_type *pDiag, output_type *pOutput,
+	const style_block_type *pStyle)
+{
+	size_t	tLen;
+	char	szString[120];
+
+	fail(pDiag == NULL);
+	fail(pOutput == NULL);
+	fail(pStyle == NULL);
+
+	if (tOptions.eConversionType == conversion_xml) {
+		vSetHeaders(pDiag, pStyle->usIstd);
+	} else {
+		tLen = tStyle2Window(szString, sizeof(szString),
+					pStyle, pSection);
+		vStoreString(szString, tLen, pOutput);
+	}
+} /* end of vStoreStyle */
+
+/*
+ * vPutIndentation - output the specified amount of indentation
+ */
+static void
+vPutIndentation(diagram_type *pDiag, output_type *pOutput,
+	BOOL bNoMarks, BOOL bFirstLine,
+	UINT uiListNumber, UCHAR ucNFC, const char *szListChar,
+	long lLeftIndentation, long lLeftIndentation1)
+{
+	long	lWidth;
+	size_t	tIndex, tNextFree;
+	char	szLine[30];
+
+	fail(pDiag == NULL);
+	fail(pOutput == NULL);
+	fail(szListChar == NULL);
+	fail(lLeftIndentation < 0);
+
+	if (tOptions.eConversionType == conversion_xml) {
+		/* XML does its own indentation at rendering time */
+		return;
+	}
+
+	if (bNoMarks) {
+		if (bFirstLine) {
+			lLeftIndentation += lLeftIndentation1;
+		}
+		if (lLeftIndentation < 0) {
+			lLeftIndentation = 0;
+		}
+		vSetLeftIndentation(pDiag, lLeftIndentation);
+		return;
+	}
+	if (lLeftIndentation <= 0) {
+		DBG_HEX_C(ucNFC != 0x00, ucNFC);
+		vSetLeftIndentation(pDiag, 0);
+		return;
+	}
+
+#if defined(DEBUG)
+	if (tOptions.eEncoding == encoding_utf_8) {
+		fail(strlen(szListChar) > 3);
+	} else {
+		DBG_HEX_C(iscntrl((int)szListChar[0]), szListChar[0]);
+		fail(iscntrl((int)szListChar[0]));
+		fail(szListChar[1] != '\0');
+	}
+#endif /* DEBUG */
+
+	switch (ucNFC) {
+	case LIST_ARABIC_NUM:
+	case LIST_NUMBER_TXT:
+		tNextFree = (size_t)sprintf(szLine, "%u", uiListNumber);
+		break;
+	case LIST_UPPER_ROMAN:
+	case LIST_LOWER_ROMAN:
+		tNextFree = tNumber2Roman(uiListNumber,
+				ucNFC == LIST_UPPER_ROMAN, szLine);
+		break;
+	case LIST_UPPER_ALPHA:
+	case LIST_LOWER_ALPHA:
+		tNextFree = tNumber2Alpha(uiListNumber,
+				ucNFC == LIST_UPPER_ALPHA, szLine);
+		break;
+	case LIST_ORDINAL_NUM:
+	case LIST_ORDINAL_TXT:
+		if (uiListNumber % 10 == 1 && uiListNumber != 11) {
+			tNextFree =
+				(size_t)sprintf(szLine, "%ust", uiListNumber);
+		} else if (uiListNumber % 10 == 2 && uiListNumber != 12) {
+			tNextFree =
+				(size_t)sprintf(szLine, "%und", uiListNumber);
+		} else if (uiListNumber % 10 == 3 && uiListNumber != 13) {
+			tNextFree =
+				(size_t)sprintf(szLine, "%urd", uiListNumber);
+		} else {
+			tNextFree =
+				(size_t)sprintf(szLine, "%uth", uiListNumber);
+		}
+		break;
+	case LIST_OUTLINE_NUM:
+		tNextFree = (size_t)sprintf(szLine, "%02u", uiListNumber);
+		break;
+	case LIST_SPECIAL:
+	case LIST_SPECIAL2:
+	case LIST_BULLETS:
+		tNextFree = 0;
+		break;
+	default:
+		DBG_HEX(ucNFC);
+		DBG_FIXME();
+		tNextFree = (size_t)sprintf(szLine, "%u", uiListNumber);
+		break;
+	}
+	tNextFree += (size_t)sprintf(szLine + tNextFree, "%.3s", szListChar);
+	szLine[tNextFree++] = ' ';
+	szLine[tNextFree] = '\0';
+	lWidth = lComputeStringWidth(szLine, tNextFree,
+				pOutput->tFontRef, pOutput->usFontSize);
+	lLeftIndentation -= lWidth;
+	if (lLeftIndentation < 0) {
+		lLeftIndentation = 0;
+	}
+	vSetLeftIndentation(pDiag, lLeftIndentation);
+	for (tIndex = 0; tIndex < tNextFree; tIndex++) {
+		vStoreChar((ULONG)(UCHAR)szLine[tIndex], FALSE, pOutput);
+	}
+} /* end of vPutIndentation */
+
+/*
+ * vPutSeparatorLine - output a separator line
+ *
+ * A separator line is a horizontal line two inches long.
+ * Two inches equals 144000 millipoints.
+ */
+static void
+vPutSeparatorLine(output_type *pOutput)
+{
+	long	lCharWidth;
+	int	iCounter, iChars;
+	char	szOne[2];
+
+	fail(pOutput == NULL);
+
+	szOne[0] = OUR_EM_DASH;
+	szOne[1] = '\0';
+	lCharWidth = lComputeStringWidth(szOne, 1,
+				pOutput->tFontRef, pOutput->usFontSize);
+	NO_DBG_DEC(lCharWidth);
+	iChars = (int)((144000 + lCharWidth / 2) / lCharWidth);
+	NO_DBG_DEC(iChars);
+	for (iCounter = 0; iCounter < iChars; iCounter++) {
+		vStoreCharacter((ULONG)(UCHAR)OUR_EM_DASH, pOutput);
+	}
+} /* end of vPutSeparatorLine */
+
+/*
+ * pStartNextOutput - start the next output record
+ *
+ * returns a pointer to the next record
+ */
+static output_type *
+pStartNextOutput(output_type *pCurrent)
+{
+	output_type	*pNew;
+
+	TRACE_MSG("pStartNextOutput");
+
+	if (pCurrent->tNextFree == 0) {
+		/* The current record is empty, re-use */
+		fail(pCurrent->szStorage[0] != '\0');
+		fail(pCurrent->lStringWidth != 0);
+		return pCurrent;
+	}
+	/* The current record is in use, make a new one */
+	pNew = xmalloc(sizeof(*pNew));
+	pCurrent->pNext = pNew;
+	pNew->tStorageSize = INITIAL_SIZE;
+	pNew->szStorage = xmalloc(pNew->tStorageSize);
+	pNew->szStorage[0] = '\0';
+	pNew->tNextFree = 0;
+	pNew->lStringWidth = 0;
+	pNew->ucFontColor = FONT_COLOR_DEFAULT;
+	pNew->usFontStyle = FONT_REGULAR;
+	pNew->tFontRef = (drawfile_fontref)0;
+	pNew->usFontSize = DEFAULT_FONT_SIZE;
+	pNew->pPrev = pCurrent;
+	pNew->pNext = NULL;
+	return pNew;
+} /* end of pStartNextOutput */
+
+/*
+ * pStartNewOutput
+ */
+static output_type *
+pStartNewOutput(output_type *pAnchor, output_type *pLeftOver)
+{
+	output_type	*pCurr, *pNext;
+	USHORT		usFontStyle, usFontSize;
+	drawfile_fontref	tFontRef;
+	UCHAR		ucFontColor;
+
+	TRACE_MSG("pStartNewOutput");
+
+	ucFontColor = FONT_COLOR_DEFAULT;
+	usFontStyle = FONT_REGULAR;
+	tFontRef = (drawfile_fontref)0;
+	usFontSize = DEFAULT_FONT_SIZE;
+	/* Free the old output space */
+	pCurr = pAnchor;
+	while (pCurr != NULL) {
+		TRACE_MSG("Free the old output space");
+		pNext = pCurr->pNext;
+		pCurr->szStorage = xfree(pCurr->szStorage);
+		if (pCurr->pNext == NULL) {
+			ucFontColor = pCurr->ucFontColor;
+			usFontStyle = pCurr->usFontStyle;
+			tFontRef = pCurr->tFontRef;
+			usFontSize = pCurr->usFontSize;
+		}
+		pCurr = xfree(pCurr);
+		pCurr = pNext;
+	}
+	if (pLeftOver == NULL) {
+		/* Create new output space */
+		TRACE_MSG("Create new output space");
+		pLeftOver = xmalloc(sizeof(*pLeftOver));
+		pLeftOver->tStorageSize = INITIAL_SIZE;
+		NO_DBG_DEC(pLeftOver->tStorageSize);
+		TRACE_MSG("before 2nd xmalloc");
+		pLeftOver->szStorage = xmalloc(pLeftOver->tStorageSize);
+		TRACE_MSG("after 2nd xmalloc");
+		pLeftOver->szStorage[0] = '\0';
+		pLeftOver->tNextFree = 0;
+		pLeftOver->lStringWidth = 0;
+		pLeftOver->ucFontColor = ucFontColor;
+		pLeftOver->usFontStyle = usFontStyle;
+		pLeftOver->tFontRef = tFontRef;
+		pLeftOver->usFontSize = usFontSize;
+		pLeftOver->pPrev = NULL;
+		pLeftOver->pNext = NULL;
+	}
+	fail(!bCheckDoubleLinkedList(pLeftOver));
+	return pLeftOver;
+} /* end of pStartNewOutput */
+
+/*
+ * ulGetChar - get the next character from the specified list
+ *
+ * returns the next character of EOF
+ */
+static ULONG
+ulGetChar(FILE *pFile, list_id_enum eListID)
+{
+	const font_block_type	*pCurr;
+	ULONG		ulChar, ulFileOffset, ulCharPos;
+	row_info_enum	eRowInfo;
+	USHORT		usChar, usPropMod;
+	BOOL		bSkip;
+
+	fail(pFile == NULL);
+
+	pCurr = pFontInfo;
+	bSkip = FALSE;
+	for (;;) {
+		usChar = usNextChar(pFile, eListID,
+				&ulFileOffset, &ulCharPos, &usPropMod);
+		if (usChar == (USHORT)EOF) {
+			return (ULONG)EOF;
+		}
+
+		vUpdateCounters();
+
+		eRowInfo = ePropMod2RowInfo(usPropMod, iWordVersion);
+		if (!bStartRow) {
+#if 0
+			bStartRow = eRowInfo == found_a_cell ||
+				(pRowInfo != NULL &&
+				 ulFileOffset == pRowInfo->ulFileOffsetStart &&
+				 eRowInfo != found_not_a_cell);
+#else
+			bStartRow = pRowInfo != NULL &&
+				ulFileOffset == pRowInfo->ulFileOffsetStart;
+#endif
+			NO_DBG_HEX_C(bStartRow, pRowInfo->ulFileOffsetStart);
+		}
+		if (!bEndRowNorm) {
+#if 0
+			bEndRow = eRowInfo == found_end_of_row ||
+				(pRowInfo != NULL &&
+				 ulFileOffset == pRowInfo->ulFileOffsetEnd &&
+				 eRowInfo != found_not_end_of_row);
+#else
+			bEndRowNorm = pRowInfo != NULL &&
+				ulFileOffset == pRowInfo->ulFileOffsetEnd;
+#endif
+			NO_DBG_HEX_C(bEndRowNorm, pRowInfo->ulFileOffsetEnd);
+		}
+		if (!bEndRowFast) {
+			bEndRowFast = eRowInfo == found_end_of_row;
+			NO_DBG_HEX_C(bEndRowFast, pRowInfo->ulFileOffsetEnd);
+		}
+
+		if (!bStartStyle) {
+			bStartStyle = pStyleInfo != NULL &&
+				ulFileOffset == pStyleInfo->ulFileOffset;
+			NO_DBG_HEX_C(bStartStyle, ulFileOffset);
+		}
+		if (pCurr != NULL && ulFileOffset == pCurr->ulFileOffset) {
+			bStartFont = TRUE;
+			NO_DBG_HEX(ulFileOffset);
+			pFontInfo = pCurr;
+			pCurr = pGetNextFontInfoListItem(pCurr);
+		}
+
+		/* Skip embedded characters */
+		if (usChar == START_EMBEDDED) {
+			bSkip = TRUE;
+			continue;
+		}
+		if (usChar == END_IGNORE || usChar == END_EMBEDDED) {
+			bSkip = FALSE;
+			continue;
+		}
+		if (bSkip) {
+			continue;
+		}
+		ulChar = ulTranslateCharacters(usChar,
+					ulFileOffset,
+					iWordVersion,
+					tOptions.eConversionType,
+					tOptions.eEncoding,
+					bOldMacFile);
+		if (ulChar == IGNORE_CHARACTER) {
+			continue;
+		}
+		if (ulChar == PICTURE) {
+			ulFileOffsetImage = ulGetPictInfoListItem(ulFileOffset);
+		} else {
+			ulFileOffsetImage = FC_INVALID;
+		}
+		if (ulChar == PAR_END) {
+			/* End of paragraph seen, prepare for the next */
+			vFillStyleFromStylesheet(usIstdNext, &tStyleNext);
+			vCorrectStyleValues(&tStyleNext);
+			bStartStyleNext = TRUE;
+			vFillFontFromStylesheet(usIstdNext, &tFontNext);
+			vCorrectFontValues(&tFontNext);
+			bStartFontNext = TRUE;
+		}
+		if (ulChar == PAGE_BREAK) {
+			/* Might be the start of a new section */
+			pSectionNext = pGetSectionInfo(pSection, ulCharPos);
+		}
+		return ulChar;
+	}
+} /* end of ulGetChar */
+
+/*
+ * lGetWidthMax - get the maximum line width from the paragraph break value
+ *
+ * Returns the maximum line width in millipoints
+ */
+static long
+lGetWidthMax(int iParagraphBreak)
+{
+	fail(iParagraphBreak < 0);
+
+	if (iParagraphBreak == 0) {
+		return LONG_MAX;
+	}
+	if (iParagraphBreak < MIN_SCREEN_WIDTH) {
+		return lChar2MilliPoints(MIN_SCREEN_WIDTH);
+	}
+	if (iParagraphBreak > MAX_SCREEN_WIDTH) {
+		return lChar2MilliPoints(MAX_SCREEN_WIDTH);
+	}
+	return lChar2MilliPoints(iParagraphBreak);
+} /* end of lGetWidthMax */
+
+/*
+ * bWordDecryptor - turn Word to something more useful
+ *
+ * returns TRUE when succesful, otherwise FALSE
+ */
+BOOL
+bWordDecryptor(FILE *pFile, long lFilesize, diagram_type *pDiag)
+{
+	imagedata_type	tImage;
+	const style_block_type	*pStyleTmp;
+	const font_block_type	*pFontTmp;
+	const char	*szListChar;
+	output_type	*pAnchor, *pOutput, *pLeftOver;
+	ULONG	ulChar;
+	long	lBeforeIndentation, lAfterIndentation;
+	long	lLeftIndentation, lLeftIndentation1, lRightIndentation;
+	long	lWidthCurr, lWidthMax, lDefaultTabWidth, lHalfSpaceWidth, lTmp;
+	list_id_enum 	eListID;
+	image_info_enum	eRes;
+	UINT	uiFootnoteNumber, uiEndnoteNumber, uiTmp;
+	int	iListSeqNumber;
+	BOOL	bWasTableRow, bTableFontClosed, bWasEndOfParagraph;
+	BOOL	bInList, bWasInList, bNoMarks, bFirstLine;
+	BOOL	bAllCapitals, bHiddenText, bMarkDelText, bSuccess;
+	USHORT	usListNumber;
+	USHORT	usFontStyle, usFontStyleMinimal, usFontSize, usTmp;
+	UCHAR	ucFontNumber, ucFontColor;
+	UCHAR	ucNFC, ucAlignment;
+
+	fail(pFile == NULL || lFilesize <= 0 || pDiag == NULL);
+
+	TRACE_MSG("bWordDecryptor");
+
+	iWordVersion = iInitDocument(pFile, lFilesize);
+	if (iWordVersion < 0) {
+		DBG_DEC(iWordVersion);
+		return FALSE;
+	}
+
+	vGetOptions(&tOptions);
+	bOldMacFile = bIsOldMacFile();
+	vPrepareHdrFtrText(pFile);
+	vPrepareFootnoteText(pFile);
+
+	vPrologue2(pDiag, iWordVersion);
+
+	/* Initialisation */
+#if defined(__riscos)
+	ulCharCounter = 0;
+	iCurrPct = 0;
+	iPrevPct = -1;
+	ulDocumentLength = ulGetDocumentLength();
+#endif /* __riscos */
+	pSection = pGetSectionInfo(NULL, 0);
+	pSectionNext = pSection;
+	lDefaultTabWidth = lGetDefaultTabWidth();
+	DBG_DEC_C(lDefaultTabWidth != 36000, lDefaultTabWidth);
+	pRowInfo = pGetNextRowInfoListItem();
+	DBG_HEX_C(pRowInfo != NULL, pRowInfo->ulFileOffsetStart);
+	DBG_HEX_C(pRowInfo != NULL, pRowInfo->ulFileOffsetEnd);
+	DBG_MSG_C(pRowInfo == NULL, "No rows at all");
+	bStartRow = FALSE;
+	bEndRowNorm = FALSE;
+	bEndRowFast = FALSE;
+	bIsTableRow = FALSE;
+	bWasTableRow = FALSE;
+	vResetStyles();
+	pStyleInfo = pGetNextTextStyle(NULL);
+	bStartStyle = FALSE;
+	bInList = FALSE;
+	bWasInList = FALSE;
+	iListSeqNumber = 0;
+	usIstdNext = ISTD_NORMAL;
+	pAnchor = NULL;
+	pFontInfo = pGetNextFontInfoListItem(NULL);
+	DBG_HEX_C(pFontInfo != NULL, pFontInfo->ulFileOffset);
+	DBG_MSG_C(pFontInfo == NULL, "No fonts at all");
+	bStartFont = FALSE;
+	ucFontNumber = 0;
+	usFontStyleMinimal = FONT_REGULAR;
+	usFontStyle = FONT_REGULAR;
+	usFontSize = DEFAULT_FONT_SIZE;
+	ucFontColor = FONT_COLOR_DEFAULT;
+	pAnchor = pStartNewOutput(pAnchor, NULL);
+	pOutput = pAnchor;
+	pOutput->ucFontColor = ucFontColor;
+	pOutput->usFontStyle = usFontStyle;
+	pOutput->tFontRef = tOpenFont(ucFontNumber, usFontStyle, usFontSize);
+	pOutput->usFontSize = usFontSize;
+	bTableFontClosed = TRUE;
+	lBeforeIndentation = 0;
+	lAfterIndentation = 0;
+	lLeftIndentation = 0;
+	lLeftIndentation1 = 0;
+	lRightIndentation = 0;
+	bWasEndOfParagraph = TRUE;
+	bNoMarks = TRUE;
+	bFirstLine = TRUE;
+	ucNFC = LIST_BULLETS;
+	if (pStyleInfo != NULL) {
+		szListChar = pStyleInfo->szListChar;
+		pStyleTmp = pStyleInfo;
+	} else {
+		if (tStyleNext.szListChar[0] == '\0') {
+			vGetBulletValue(tOptions.eConversionType,
+				tOptions.eEncoding, tStyleNext.szListChar, 4);
+		}
+		szListChar = tStyleNext.szListChar;
+		pStyleTmp = &tStyleNext;
+	}
+	usListNumber = 0;
+	ucAlignment = ALIGNMENT_LEFT;
+	bAllCapitals = FALSE;
+	bHiddenText = FALSE;
+	bMarkDelText = FALSE;
+	lWidthMax = lGetWidthMax(tOptions.iParagraphBreak);
+	NO_DBG_DEC(lWidthMax);
+
+	Hourglass_On();
+
+	uiFootnoteNumber = 0;
+	uiEndnoteNumber = 0;
+	eListID = text_list;
+	for(;;) {
+		ulChar = ulGetChar(pFile, eListID);
+		if (ulChar == (ULONG)EOF) {
+			if (bOutputContainsText(pAnchor)) {
+				OUTPUT_LINE();
+			} else {
+				RESET_LINE();
+			}
+			switch (eListID) {
+			case text_list:
+				if (tOptions.eConversionType !=
+							conversion_xml) {
+					eListID = footnote_list;
+					if (uiFootnoteNumber != 0) {
+						vPutSeparatorLine(pAnchor);
+						OUTPUT_LINE();
+						uiFootnoteNumber = 0;
+					}
+					break;
+				}
+				/* No break or return */
+			case footnote_list:
+				eListID = endnote_list;
+				if (uiEndnoteNumber != 0) {
+					vPutSeparatorLine(pAnchor);
+					OUTPUT_LINE();
+					uiEndnoteNumber = 0;
+				}
+				break;
+			case endnote_list:
+				eListID = textbox_list;
+				if (bExistsTextBox()) {
+					vPutSeparatorLine(pAnchor);
+					OUTPUT_LINE();
+				}
+				break;
+			case textbox_list:
+				eListID = hdrtextbox_list;
+				if (bExistsHdrTextBox()) {
+					vPutSeparatorLine(pAnchor);
+					OUTPUT_LINE();
+				}
+				break;
+			case hdrtextbox_list:
+			default:
+				eListID = end_of_lists;
+				break;
+			}
+			if (eListID == end_of_lists) {
+				break;
+			}
+			continue;
+		}
+
+		if (ulChar == UNKNOWN_NOTE_CHAR) {
+			switch (eListID) {
+			case footnote_list:
+				ulChar = FOOTNOTE_CHAR;
+				break;
+			case endnote_list:
+				ulChar = ENDNOTE_CHAR;
+				break;
+			default:
+				break;
+			}
+		}
+
+		if (bStartRow) {
+			/* Begin of a tablerow found */
+			if (bOutputContainsText(pAnchor)) {
+				OUTPUT_LINE();
+			} else {
+				RESET_LINE();
+			}
+			fail(pAnchor != pOutput);
+			if (bTableFontClosed) {
+				/* Start special table font */
+				vCloseFont();
+				/*
+				 * Compensate for the fact that Word uses
+				 * proportional fonts for its tables and we
+				 * only one fixed-width font
+				 */
+				uiTmp = ((UINT)usFontSize * 5 + 3) / 6;
+				if (uiTmp < MIN_TABLEFONT_SIZE) {
+					uiTmp = MIN_TABLEFONT_SIZE;
+				} else if (uiTmp > MAX_TABLEFONT_SIZE) {
+					uiTmp = MAX_TABLEFONT_SIZE;
+				}
+				pOutput->usFontSize = (USHORT)uiTmp;
+				pOutput->tFontRef =
+					tOpenTableFont(pOutput->usFontSize);
+				pOutput->usFontStyle = FONT_REGULAR;
+				pOutput->ucFontColor = FONT_COLOR_BLACK;
+				bTableFontClosed = FALSE;
+			}
+			bIsTableRow = TRUE;
+			bStartRow = FALSE;
+		}
+
+		if (bWasTableRow &&
+		    !bIsTableRow &&
+		    ulChar != PAR_END &&
+		    ulChar != HARD_RETURN &&
+		    ulChar != PAGE_BREAK &&
+		    ulChar != COLUMN_FEED) {
+			/*
+			 * The end of a table should be followed by an
+			 * empty line, like the end of a paragraph
+			 */
+			OUTPUT_LINE();
+			vEndOfParagraph(pDiag,
+					pOutput->tFontRef,
+					pOutput->usFontSize,
+					(long)pOutput->usFontSize * 600);
+		}
+
+		switch (ulChar) {
+		case PAGE_BREAK:
+		case COLUMN_FEED:
+			if (bIsTableRow) {
+				/* Ignore when in a table */
+				break;
+			}
+			if (bOutputContainsText(pAnchor)) {
+				OUTPUT_LINE();
+			} else {
+				RESET_LINE();
+			}
+			if (ulChar == PAGE_BREAK) {
+				vEndOfPage(pDiag, lAfterIndentation,
+						pSection != pSectionNext);
+			} else {
+				vEndOfParagraph(pDiag,
+					pOutput->tFontRef,
+					pOutput->usFontSize,
+					lAfterIndentation);
+			}
+			break;
+		default:
+			break;
+		}
+
+		if (bStartFont || (bStartFontNext && ulChar != PAR_END)) {
+			/* Begin of a font found */
+			if (bStartFont) {
+				/* bStartFont takes priority */
+				fail(pFontInfo == NULL);
+				pFontTmp = pFontInfo;
+			} else {
+				pFontTmp = &tFontNext;
+			}
+			bAllCapitals = bIsCapitals(pFontTmp->usFontStyle);
+			bHiddenText = bIsHidden(pFontTmp->usFontStyle);
+			bMarkDelText = bIsMarkDel(pFontTmp->usFontStyle);
+			usTmp = pFontTmp->usFontStyle &
+				(FONT_BOLD|FONT_ITALIC|FONT_UNDERLINE|
+				 FONT_STRIKE|FONT_MARKDEL|
+				 FONT_SUPERSCRIPT|FONT_SUBSCRIPT);
+			if (!bIsTableRow &&
+			    (usFontSize != pFontTmp->usFontSize ||
+			     ucFontNumber != pFontTmp->ucFontNumber ||
+			     usFontStyleMinimal != usTmp ||
+			     ucFontColor != pFontTmp->ucFontColor)) {
+				pOutput = pStartNextOutput(pOutput);
+				vCloseFont();
+				pOutput->ucFontColor = pFontTmp->ucFontColor;
+				pOutput->usFontStyle = pFontTmp->usFontStyle;
+				pOutput->usFontSize = pFontTmp->usFontSize;
+				pOutput->tFontRef = tOpenFont(
+						pFontTmp->ucFontNumber,
+						pFontTmp->usFontStyle,
+						pFontTmp->usFontSize);
+				fail(!bCheckDoubleLinkedList(pAnchor));
+			}
+			ucFontNumber = pFontTmp->ucFontNumber;
+			usFontSize = pFontTmp->usFontSize;
+			ucFontColor = pFontTmp->ucFontColor;
+			usFontStyle = pFontTmp->usFontStyle;
+			usFontStyleMinimal = usTmp;
+			if (bStartFont) {
+				/* Get the next font info */
+				pFontInfo = pGetNextFontInfoListItem(pFontInfo);
+				NO_DBG_HEX_C(pFontInfo != NULL,
+						pFontInfo->ulFileOffset);
+				DBG_MSG_C(pFontInfo == NULL, "No more fonts");
+			}
+			bStartFont = FALSE;
+			bStartFontNext = FALSE;
+		}
+
+		if (bStartStyle || (bStartStyleNext && ulChar != PAR_END)) {
+			bFirstLine = TRUE;
+			/* Begin of a style found */
+			if (bStartStyle) {
+				/* bStartStyle takes priority */
+				fail(pStyleInfo == NULL);
+				pStyleTmp = pStyleInfo;
+			} else {
+				pStyleTmp = &tStyleNext;
+			}
+			if (!bIsTableRow) {
+				vStoreStyle(pDiag, pOutput, pStyleTmp);
+			}
+			usIstdNext = pStyleTmp->usIstdNext;
+			lBeforeIndentation =
+				lTwips2MilliPoints(pStyleTmp->usBeforeIndent);
+			lAfterIndentation =
+				lTwips2MilliPoints(pStyleTmp->usAfterIndent);
+			lLeftIndentation =
+				lTwips2MilliPoints(pStyleTmp->sLeftIndent);
+			lLeftIndentation1 =
+				lTwips2MilliPoints(pStyleTmp->sLeftIndent1);
+			lRightIndentation =
+				lTwips2MilliPoints(pStyleTmp->sRightIndent);
+			bInList = bStyleImpliesList(pStyleTmp, iWordVersion);
+			bNoMarks = !bInList || pStyleTmp->bNumPause;
+			ucNFC = pStyleTmp->ucNFC;
+			szListChar = pStyleTmp->szListChar;
+			ucAlignment = pStyleTmp->ucAlignment;
+			if (bInList && !bWasInList) {
+				/* Start of a list */
+				iListSeqNumber++;
+				vStartOfList(pDiag, ucNFC,
+						bWasTableRow && !bIsTableRow);
+			}
+			if (!bInList && bWasInList) {
+				/* End of a list */
+				vEndOfList(pDiag);
+			}
+			bWasInList = bInList;
+			if (bStartStyle) {
+				pStyleInfo = pGetNextTextStyle(pStyleInfo);
+				NO_DBG_HEX_C(pStyleInfo != NULL,
+						pStyleInfo->ulFileOffset);
+				DBG_MSG_C(pStyleInfo == NULL,
+						"No more styles");
+			}
+			bStartStyle = FALSE;
+			bStartStyleNext = FALSE;
+		}
+
+		if (bWasEndOfParagraph) {
+			vStartOfParagraph1(pDiag, lBeforeIndentation);
+		}
+
+		if (!bIsTableRow &&
+		    lTotalStringWidth(pAnchor) == 0) {
+			if (!bNoMarks) {
+				usListNumber = usGetListValue(iListSeqNumber,
+							iWordVersion,
+							pStyleTmp);
+			}
+			if (bInList && bFirstLine) {
+				vStartOfListItem(pDiag, bNoMarks);
+			}
+			vPutIndentation(pDiag, pAnchor, bNoMarks, bFirstLine,
+					usListNumber, ucNFC, szListChar,
+					lLeftIndentation, lLeftIndentation1);
+			bFirstLine = FALSE;
+			/* One number or mark per paragraph will do */
+			bNoMarks = TRUE;
+		}
+
+		if (bWasEndOfParagraph) {
+			vStartOfParagraph2(pDiag);
+			bWasEndOfParagraph = FALSE;
+		}
+
+		switch (ulChar) {
+		case PICTURE:
+			(void)memset(&tImage, 0, sizeof(tImage));
+			eRes = eExamineImage(pFile, ulFileOffsetImage, &tImage);
+			switch (eRes) {
+			case image_no_information:
+				bSuccess = FALSE;
+				break;
+			case image_minimal_information:
+			case image_full_information:
+#if 0
+				if (bOutputContainsText(pAnchor)) {
+					OUTPUT_LINE();
+				} else {
+					RESET_LINE();
+				}
+#endif
+				bSuccess = bTranslateImage(pDiag, pFile,
+					eRes == image_minimal_information,
+					ulFileOffsetImage, &tImage);
+				break;
+			default:
+				DBG_DEC(eRes);
+				bSuccess = FALSE;
+				break;
+			}
+			if (!bSuccess) {
+				vStoreString("[pic]", 5, pOutput);
+			}
+			break;
+		case FOOTNOTE_CHAR:
+			uiFootnoteNumber++;
+			if (tOptions.eConversionType == conversion_xml) {
+				vStoreCharacter((ULONG)FOOTNOTE_OR_ENDNOTE,
+								pOutput);
+				break;
+			}
+			vStoreCharacter((ULONG)'[', pOutput);
+			vStoreNumberAsDecimal(uiFootnoteNumber, pOutput);
+			vStoreCharacter((ULONG)']', pOutput);
+			break;
+		case ENDNOTE_CHAR:
+			uiEndnoteNumber++;
+			vStoreCharacter((ULONG)'[', pOutput);
+			vStoreNumberAsRoman(uiEndnoteNumber, pOutput);
+			vStoreCharacter((ULONG)']', pOutput);
+			break;
+		case UNKNOWN_NOTE_CHAR:
+			vStoreString("[?]", 3, pOutput);
+			break;
+		case PAR_END:
+			if (bIsTableRow) {
+				vStoreCharacter((ULONG)'\n', pOutput);
+				break;
+			}
+			if (bOutputContainsText(pAnchor)) {
+				OUTPUT_LINE();
+			} else {
+				vMove2NextLine(pDiag,
+					pOutput->tFontRef, pOutput->usFontSize);
+				RESET_LINE();
+			}
+			vEndOfParagraph(pDiag,
+					pOutput->tFontRef,
+					pOutput->usFontSize,
+					lAfterIndentation);
+			bWasEndOfParagraph = TRUE;
+			break;
+		case HARD_RETURN:
+			if (bIsTableRow) {
+				vStoreCharacter((ULONG)'\n', pOutput);
+				break;
+			}
+			if (bOutputContainsText(pAnchor)) {
+				OUTPUT_LINE();
+			} else {
+				vMove2NextLine(pDiag,
+					pOutput->tFontRef, pOutput->usFontSize);
+				RESET_LINE();
+			}
+			break;
+		case PAGE_BREAK:
+		case COLUMN_FEED:
+			pSection = pSectionNext;
+			break;
+		case TABLE_SEPARATOR:
+			if (bIsTableRow) {
+				vStoreCharacter(ulChar, pOutput);
+				break;
+			}
+			vStoreCharacter((ULONG)' ', pOutput);
+			vStoreCharacter((ULONG)TABLE_SEPARATOR_CHAR, pOutput);
+			break;
+		case TAB:
+			if (bIsTableRow ||
+			    tOptions.eConversionType == conversion_xml) {
+				vStoreCharacter((ULONG)' ', pOutput);
+				break;
+			}
+			if (tOptions.iParagraphBreak == 0 &&
+			    (tOptions.eConversionType == conversion_text ||
+			     tOptions.eConversionType == conversion_fmt_text)) {
+				/* No logical lines, so no tab expansion */
+				vStoreCharacter(TAB, pOutput);
+				break;
+			}
+			lHalfSpaceWidth = (lComputeSpaceWidth(
+					pOutput->tFontRef,
+					pOutput->usFontSize) + 1) / 2;
+			lTmp = lTotalStringWidth(pAnchor);
+			lTmp += lDrawUnits2MilliPoints(pDiag->lXleft);
+			lTmp /= lDefaultTabWidth;
+			do {
+				vStoreCharacter((ULONG)FILLER_CHAR, pOutput);
+				lWidthCurr = lTotalStringWidth(pAnchor);
+				lWidthCurr +=
+					lDrawUnits2MilliPoints(pDiag->lXleft);
+			} while (lTmp == lWidthCurr / lDefaultTabWidth &&
+				 lWidthCurr < lWidthMax + lRightIndentation);
+			break;
+		default:
+			if (bHiddenText && tOptions.bHideHiddenText) {
+				continue;
+			}
+			if (bMarkDelText && tOptions.bRemoveRemovedText) {
+				continue;
+			}
+			if (ulChar == UNICODE_ELLIPSIS &&
+			    tOptions.eEncoding != encoding_utf_8) {
+				vStoreString("...", 3, pOutput);
+			} else {
+				if (bAllCapitals) {
+					ulChar = ulToUpper(ulChar);
+				}
+				vStoreCharacter(ulChar, pOutput);
+			}
+			break;
+		}
+
+		if (bWasTableRow && !bIsTableRow) {
+			/* End of a table */
+			vEndOfTable(pDiag);
+			/* Resume normal font */
+			NO_DBG_MSG("End of table font");
+			vCloseFont();
+			bTableFontClosed = TRUE;
+			pOutput->ucFontColor = ucFontColor;
+			pOutput->usFontStyle = usFontStyle;
+			pOutput->usFontSize = usFontSize;
+			pOutput->tFontRef = tOpenFont(
+					ucFontNumber, usFontStyle, usFontSize);
+		}
+		bWasTableRow = bIsTableRow;
+
+		if (bIsTableRow) {
+			fail(pAnchor != pOutput);
+			if (!bEndRowNorm && !bEndRowFast) {
+				continue;
+			}
+			/* End of a table row */
+			if (bEndRowNorm) {
+				fail(pRowInfo == NULL);
+				vTableRow2Window(pDiag, pAnchor, pRowInfo,
+						tOptions.eConversionType,
+						tOptions.iParagraphBreak);
+			} else {
+				fail(!bEndRowFast);
+			}
+			/* Reset */
+			pAnchor = pStartNewOutput(pAnchor, NULL);
+			pOutput = pAnchor;
+			if (bEndRowNorm) {
+				pRowInfo = pGetNextRowInfoListItem();
+			}
+			bIsTableRow = FALSE;
+			bEndRowNorm = FALSE;
+			bEndRowFast = FALSE;
+			NO_DBG_HEX_C(pRowInfo != NULL,
+						pRowInfo->ulFileOffsetStart);
+			NO_DBG_HEX_C(pRowInfo != NULL,
+						pRowInfo->ulFileOffsetEnd);
+			continue;
+		}
+		lWidthCurr = lTotalStringWidth(pAnchor);
+		lWidthCurr += lDrawUnits2MilliPoints(pDiag->lXleft);
+		if (lWidthCurr < lWidthMax + lRightIndentation) {
+			continue;
+		}
+		pLeftOver = pSplitList(pAnchor);
+		vJustify2Window(pDiag, pAnchor,
+				lWidthMax, lRightIndentation, ucAlignment);
+		pAnchor = pStartNewOutput(pAnchor, pLeftOver);
+		for (pOutput = pAnchor;
+		     pOutput->pNext != NULL;
+		     pOutput = pOutput->pNext)
+			;	/* EMPTY */
+		fail(pOutput == NULL);
+		if (lTotalStringWidth(pAnchor) > 0) {
+			vSetLeftIndentation(pDiag, lLeftIndentation);
+		}
+	}
+
+	pAnchor = pStartNewOutput(pAnchor, NULL);
+	pAnchor->szStorage = xfree(pAnchor->szStorage);
+	pAnchor = xfree(pAnchor);
+	vCloseFont();
+	vFreeDocument();
+	Hourglass_Off();
+	return TRUE;
+} /* end of bWordDecryptor */
+
+/*
+ * lLastStringWidth - compute the width of the last part of the output string
+ */
+static long
+lLastStringWidth(const output_type *pAnchor)
+{
+	const output_type	*pCurr, *pStart;
+
+	pStart = NULL;
+	for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
+		if (pCurr->tNextFree == 1 &&
+		    (pCurr->szStorage[0] == PAR_END ||
+		     pCurr->szStorage[0] == HARD_RETURN)) {
+			/* Found a separator. Start after the separator */
+			pStart = pCurr->pNext;
+		}
+	}
+	if (pStart == NULL) {
+		/* No separators. Use the whole output string */
+		pStart = pAnchor;
+	}
+	return lTotalStringWidth(pStart);
+} /* end of lLastStringWidth */
+
+/*
+ * pHdrFtrDecryptor - turn a header/footer list element to something useful
+ */
+output_type *
+pHdrFtrDecryptor(FILE *pFile, ULONG ulCharPosStart, ULONG ulCharPosNext)
+{
+	output_type	*pAnchor, *pOutput, *pLeftOver;
+	ULONG	ulChar, ulFileOffset, ulCharPos;
+	long	lWidthCurr, lWidthMax;
+	long	lRightIndentation;
+	USHORT	usChar;
+	UCHAR	ucAlignment;
+	BOOL	bSkip;
+
+	fail(iWordVersion < 0);
+	fail(tOptions.eConversionType == conversion_unknown);
+	fail(tOptions.eEncoding == 0);
+
+	if (ulCharPosStart == ulCharPosNext) {
+		/* There are no bytes to decrypt */
+		return NULL;
+	}
+
+	lRightIndentation = 0;
+	ucAlignment = ALIGNMENT_LEFT;
+	bSkip = FALSE;
+	lWidthMax = lGetWidthMax(tOptions.iParagraphBreak);
+	pAnchor = pStartNewOutput(NULL, NULL);
+	pOutput = pAnchor;
+	pOutput->tFontRef = tOpenFont(0, FONT_REGULAR, DEFAULT_FONT_SIZE);
+	usChar = usToHdrFtrPosition(pFile, ulCharPosStart);
+	ulCharPos = ulCharPosStart;
+	ulFileOffset = ulCharPos2FileOffset(ulCharPos);
+	while (usChar != (USHORT)EOF && ulCharPos != ulCharPosNext) {
+		/* Skip embedded characters */
+		if (usChar == START_EMBEDDED) {
+			bSkip = TRUE;
+		} else if (usChar == END_IGNORE || usChar == END_EMBEDDED) {
+			bSkip = FALSE;
+		}
+		/* Translate character */
+		if (bSkip || usChar == END_IGNORE || usChar == END_EMBEDDED) {
+			ulChar = IGNORE_CHARACTER;
+		} else {
+			ulChar = ulTranslateCharacters(usChar,
+					ulFileOffset,
+					iWordVersion,
+					tOptions.eConversionType,
+					tOptions.eEncoding,
+					bOldMacFile);
+		}
+		/* Process character */
+		if (ulChar != IGNORE_CHARACTER) {
+			switch (ulChar) {
+			case PICTURE:
+				vStoreString("[pic]", 5, pOutput);
+				break;
+			case PAR_END:
+			case HARD_RETURN:
+			case PAGE_BREAK:
+			case COLUMN_FEED:
+				/* To the next substring */
+				pOutput = pStartNextOutput(pOutput);
+				vCloseFont();
+				pOutput->tFontRef = tOpenFont(0,
+					FONT_REGULAR, DEFAULT_FONT_SIZE);
+				/* A substring with just one character */
+				if (ulChar == HARD_RETURN) {
+					vStoreCharacter(HARD_RETURN, pOutput);
+				} else {
+					vStoreCharacter(PAR_END, pOutput);
+				}
+				/* To the next substring */
+				pOutput = pStartNextOutput(pOutput);
+				vCloseFont();
+				pOutput->tFontRef = tOpenFont(0,
+					FONT_REGULAR, DEFAULT_FONT_SIZE);
+				fail(!bCheckDoubleLinkedList(pAnchor));
+				break;
+			case TABLE_SEPARATOR:
+				vStoreCharacter((ULONG)' ', pOutput);
+				vStoreCharacter((ULONG)TABLE_SEPARATOR_CHAR,
+							pOutput);
+				break;
+			case TAB:
+				vStoreCharacter((ULONG)FILLER_CHAR, pOutput);
+				break;
+			default:
+				vStoreCharacter(ulChar, pOutput);
+				break;
+			}
+		}
+		lWidthCurr = lLastStringWidth(pAnchor);
+		if (lWidthCurr >= lWidthMax + lRightIndentation) {
+			pLeftOver = pSplitList(pAnchor);
+			for (pOutput = pAnchor;
+			     pOutput->pNext != NULL;
+			     pOutput = pOutput->pNext)
+				;	/* EMPTY */
+			fail(pOutput == NULL);
+			/* To the next substring */
+			pOutput = pStartNextOutput(pOutput);
+			/* A substring with just one HARD_RETURN */
+			vStoreCharacter(HARD_RETURN, pOutput);
+			/* Put the leftover piece(s) at the end */
+			pOutput->pNext = pLeftOver;
+			if (pLeftOver != NULL) {
+				pLeftOver->pPrev = pOutput;
+			}
+			fail(!bCheckDoubleLinkedList(pAnchor));
+			for (pOutput = pAnchor;
+			     pOutput->pNext != NULL;
+			     pOutput = pOutput->pNext)
+				;	/* EMPTY */
+			fail(pOutput == NULL);
+		}
+		usChar = usNextChar(pFile, hdrftr_list,
+					&ulFileOffset, &ulCharPos, NULL);
+	}
+	vCloseFont();
+	if (bOutputContainsText(pAnchor)) {
+		return pAnchor;
+	}
+	pAnchor = pStartNewOutput(pAnchor, NULL);
+	pAnchor->szStorage = xfree(pAnchor->szStorage);
+	pAnchor = xfree(pAnchor);
+	return NULL;
+} /* end of pHdrFtrDecryptor */
+
+/*
+ * pFootnoteDecryptor - turn a footnote text list element into text
+ */
+char *
+szFootnoteDecryptor(FILE *pFile, ULONG ulCharPosStart, ULONG ulCharPosNext)
+{
+	char	*szText;
+	ULONG	ulChar, ulFileOffset, ulCharPos;
+	USHORT	usChar;
+	size_t	tLen, tIndex, tNextFree, tStorageSize;
+	char	szResult[6];
+	BOOL	bSkip;
+
+	fail(iWordVersion < 0);
+	fail(tOptions.eConversionType == conversion_unknown);
+	fail(tOptions.eEncoding == 0);
+
+	if (ulCharPosStart == ulCharPosNext) {
+		/* There are no bytes to decrypt */
+		return NULL;
+	}
+
+	if (tOptions.eConversionType != conversion_xml) {
+		/* Only implemented for XML output */
+		return NULL;
+	}
+
+	bSkip = FALSE;
+
+	/* Initialise the text buffer */
+	tStorageSize = INITIAL_SIZE;
+	szText = xmalloc(tStorageSize);
+	tNextFree = 0;
+	szText[tNextFree] = '\0';
+
+	/* Goto the start */
+	usChar = usToFootnotePosition(pFile, ulCharPosStart);
+	ulCharPos = ulCharPosStart;
+	ulFileOffset = ulCharPos2FileOffset(ulCharPos);
+	/* Skip the unwanted starting characters */
+	while (usChar != (USHORT)EOF && ulCharPos != ulCharPosNext &&
+	       (usChar == FOOTNOTE_OR_ENDNOTE ||
+		usChar == PAR_END ||
+		usChar == TAB ||
+		usChar == (USHORT)' ')) {
+		usChar = usNextChar(pFile, footnote_list,
+					&ulFileOffset, &ulCharPos, NULL);
+	}
+	/* Process the footnote text */
+	while (usChar != (USHORT)EOF && ulCharPos != ulCharPosNext) {
+		/* Skip embedded characters */
+		if (usChar == START_EMBEDDED) {
+			bSkip = TRUE;
+		} else if (usChar == END_IGNORE || usChar == END_EMBEDDED) {
+			bSkip = FALSE;
+		}
+		/* Translate character */
+		if (bSkip ||
+		    usChar == END_IGNORE ||
+		    usChar == END_EMBEDDED ||
+		    usChar == FOOTNOTE_OR_ENDNOTE) {
+			ulChar = IGNORE_CHARACTER;
+		} else {
+			ulChar = ulTranslateCharacters(usChar,
+					ulFileOffset,
+					iWordVersion,
+					tOptions.eConversionType,
+					tOptions.eEncoding,
+					bOldMacFile);
+		}
+		/* Process character */
+		if (ulChar == PICTURE) {
+			tLen = 5;
+			strcpy(szResult, "[pic]");
+		} else if (ulChar == IGNORE_CHARACTER) {
+			tLen = 0;
+			szResult[0] = '\0';
+		} else {
+			switch (ulChar) {
+			case PAR_END:
+			case HARD_RETURN:
+			case PAGE_BREAK:
+			case COLUMN_FEED:
+				ulChar = (ULONG)PAR_END;
+				break;
+			case TAB:
+				ulChar = (ULONG)' ';
+				break;
+			default:
+				break;
+			}
+			tLen = tUcs2Utf8(ulChar, szResult, sizeof(szResult));
+		}
+		/* Add the results to the text */
+		if (tNextFree + tLen + 1 > tStorageSize) {
+			tStorageSize += EXTENTION_SIZE;
+			szText = xrealloc(szText, tStorageSize);
+		}
+		for (tIndex = 0; tIndex < tLen; tIndex++) {
+			szText[tNextFree++] = szResult[tIndex];
+		}
+		szText[tNextFree] = '\0';
+		/* Next character */
+		usChar = usNextChar(pFile, footnote_list,
+					&ulFileOffset, &ulCharPos, NULL);
+	}
+	/* Remove redundant spaces */
+	while (tNextFree != 0 && szText[tNextFree - 1] == ' ') {
+		szText[tNextFree - 1] = '\0';
+		tNextFree--;
+	}
+	if (tNextFree == 0) {
+		/* No text */
+		szText = xfree(szText);
+		return NULL;
+	}
+	return szText;
+} /* end of szFootnoteDecryptor */
diff --git a/wordconst.h b/wordconst.h
new file mode 100644
index 0000000..739f11b
--- /dev/null
+++ b/wordconst.h
@@ -0,0 +1,321 @@
+/*
+ * wordconst.h
+ * Copyright (C) 1998-2004 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Constants and macros for the interpretation of MS Word files
+ */
+
+#if !defined(__wordconst_h)
+#define __wordconst_h 1
+
+/*
+ * A bit odd definition of the type Boolean, but RISC OS insists
+ * on this and Linux/Unix doesn't mind.
+ */
+#if !defined(BOOL)
+#define BOOL int
+#define TRUE 1
+#define FALSE 0
+#endif /* !BOOL */
+
+/* Block sizes */
+#define HEADER_SIZE			768
+#define BIG_BLOCK_SIZE			512
+#define PROPERTY_SET_STORAGE_SIZE	128
+#define SMALL_BLOCK_SIZE		 64
+/* Switch size of Depot use */
+#define MIN_SIZE_FOR_BBD_USE		0x1000
+/* Table sizes */
+#define TABLE_COLUMN_MAX		 31
+/* Maximum number of tabs positions in a paragraph */
+#define NUMBER_OF_TABS_MAX		 64
+/* Font sizes (in half-points) */
+#define MIN_FONT_SIZE			  8
+#define DEFAULT_FONT_SIZE		 20
+#define MAX_FONT_SIZE			240
+#define MIN_TABLEFONT_SIZE		 16
+#define MAX_TABLEFONT_SIZE		 20
+/* Font styles */
+#define FONT_REGULAR			0x0000
+#define FONT_BOLD			0x0001
+#define FONT_ITALIC			0x0002
+#define FONT_UNDERLINE			0x0004
+#define FONT_CAPITALS			0x0008
+#define FONT_SMALL_CAPITALS		0x0010
+#define FONT_STRIKE			0x0020
+#define FONT_HIDDEN			0x0040
+#define FONT_MARKDEL			0x0080
+#define FONT_SUPERSCRIPT		0x0100
+#define FONT_SUBSCRIPT			0x0200
+/* Font colors */
+#define FONT_COLOR_DEFAULT		 0
+#define FONT_COLOR_BLACK		 1
+#define FONT_COLOR_BLUE			 2
+#define FONT_COLOR_CYAN			 3
+#define FONT_COLOR_GREEN		 4
+#define FONT_COLOR_MAGENTA		 5
+#define FONT_COLOR_RED			 6
+#define FONT_COLOR_YELLOW		 7
+#define FONT_COLOR_WHITE		 8
+/* Special block numbers */
+#define END_OF_CHAIN			0xfffffffeUL
+#define UNUSED_BLOCK			0xffffffffUL
+/* Blocksize (512 bytes) and maximum filesize (4 GB) gives 0..7fffff */
+#define MAX_BLOCKNUMBER			0x007fffffUL
+/* Invalid character position */
+#define CP_INVALID			0xffffffffUL
+/* Invalid file offset */
+#define FC_INVALID			0xffffffffUL
+/* Special istd values */
+#define ISTD_INVALID			USHRT_MAX
+#define ISTD_NORMAL			0
+/* Properties modifier without value */
+#define IGNORE_PROPMOD			0
+/* Types of lists */
+#define LIST_ARABIC_NUM			0x00
+#define LIST_UPPER_ROMAN		0x01
+#define LIST_LOWER_ROMAN		0x02
+#define LIST_UPPER_ALPHA		0x03
+#define LIST_LOWER_ALPHA		0x04
+#define LIST_ORDINAL_NUM		0x05
+#define LIST_NUMBER_TXT			0x06
+#define LIST_ORDINAL_TXT		0x07
+#define LIST_OUTLINE_NUM		0x16
+#define LIST_SPECIAL			0x17
+#define LIST_SPECIAL2			0x19
+#define LIST_BULLETS			0xff
+/* Types of paragraph alignment */
+#define ALIGNMENT_LEFT			0x00
+#define ALIGNMENT_CENTER		0x01
+#define ALIGNMENT_RIGHT			0x02
+#define ALIGNMENT_JUSTIFY		0x03
+/* Minimum vertical space before and after a heading line */
+#define HEADING_GAP			120	/* twips */
+/* Style identifier */
+#define STI_USER			0xffe
+#define STI_NIL				0xfff
+/* Table border style codes */
+#define TABLE_BORDER_TOP		0x01
+#define TABLE_BORDER_LEFT		0x02
+#define TABLE_BORDER_BOTTOM		0x04
+#define TABLE_BORDER_RIGHT		0x08
+
+/* Macros */
+	/* Get macros */
+#define ucGetByte(i,a)		((unsigned char)(a[i]))
+#define usGetWord(i,a)		((unsigned short)\
+					((unsigned int)(a[(i)+1])<<8|\
+					 (unsigned int)(a[i])))
+#define ulGetLong(i,a)		((unsigned long)(a[i])|\
+					(unsigned long)(a[(i)+1])<<8|\
+					(unsigned long)(a[(i)+2])<<16|\
+					(unsigned long)(a[(i)+3])<<24)
+#define usGetWordBE(i,a)	((unsigned short)\
+					((unsigned int)(a[i])<<8|\
+					 (unsigned int)(a[(i)+1])))
+#define ulGetLongBE(i,a)	((unsigned long)(a[(i)+3])|\
+					(unsigned long)(a[(i)+2])<<8|\
+					(unsigned long)(a[(i)+1])<<16|\
+					(unsigned long)(a[i])<<24)
+	/* Font style macros */
+#define bIsBold(x)		(((x) & FONT_BOLD) == FONT_BOLD)
+#define bIsItalic(x)		(((x) & FONT_ITALIC) == FONT_ITALIC)
+#define bIsUnderline(x)		(((x) & FONT_UNDERLINE) == FONT_UNDERLINE)
+#define bIsCapitals(x)		(((x) & FONT_CAPITALS) == FONT_CAPITALS)
+#define bIsSmallCapitals(x)	(((x) & FONT_SMALL_CAPITALS) == FONT_SMALL_CAPITALS)
+#define bIsStrike(x)		(((x) & FONT_STRIKE) == FONT_STRIKE)
+#define bIsHidden(x)		(((x) & FONT_HIDDEN) == FONT_HIDDEN)
+#define bIsMarkDel(x)		(((x) & FONT_MARKDEL) == FONT_MARKDEL)
+#define bIsSuperscript(x)	(((x) & FONT_SUPERSCRIPT) == FONT_SUPERSCRIPT)
+#define bIsSubscript(x)		(((x) & FONT_SUBSCRIPT) == FONT_SUBSCRIPT)
+	/* Table border style code macros */
+#define bIsTableBorderTop(x)	(((x) & TABLE_BORDER_TOP) == TABLE_BORDER_TOP)
+#define bIsTableBorderLeft(x)	(((x) & TABLE_BORDER_LEFT) == TABLE_BORDER_LEFT)
+#define bIsTableBorderBottom(x)	(((x) & TABLE_BORDER_BOTTOM) == TABLE_BORDER_BOTTOM)
+#define bIsTableBorderRight(x)	(((x) & TABLE_BORDER_RIGHT) == TABLE_BORDER_RIGHT)
+	/* Computation macros */
+#if defined(__riscos)
+/* From Words half-points to draw units (plus a percentage) */
+#define lWord2DrawUnits00(x)	((long)(x) * 320)
+#define lWord2DrawUnits20(x)	((long)(x) * 384)
+#define lToBaseLine(x)		((long)(x) *  45)
+#endif /* __riscos */
+/* From twips (1/20 of a point) to millipoints */
+#define lTwips2MilliPoints(x)	((long)(x) * 50)
+/* From twips (1/20 of a point) to points */
+#define dTwips2Points(x)	((double)(x) / 20.0)
+/* From default characters (16 OS units wide) to millipoints */
+#define lChar2MilliPoints(x)	((long)(x) * 6400)
+#define iMilliPoints2Char(x)	(int)(((long)(x) + 3200) / 6400)
+#define iDrawUnits2Char(x)	(int)(((long)(x) + 2048) / 4096)
+/* From draw units (1/180*256 inch) to millipoints (1/72*1000 inch) */
+#define lDrawUnits2MilliPoints(x)	(((long)(x) * 25 +  8) / 16)
+#define lMilliPoints2DrawUnits(x)	(((long)(x) * 16 + 12) / 25)
+#define lPoints2DrawUnits(x)		((long)(x) * 640)
+#define dDrawUnits2Points(x)		((double)(x) / 640.0)
+
+/* Special characters */
+#define IGNORE_CHARACTER	0x00	/* ^@ */
+#define PICTURE			0x01	/* ^A */
+#define FOOTNOTE_OR_ENDNOTE	0x02	/* ^B */
+#define FOOTNOTE_SEPARATOR	0x03	/* ^C */
+#define FOOTNOTE_CONTINUATION	0x04	/* ^D */
+#define ANNOTATION		0x05	/* ^E */
+#define TABLE_SEPARATOR		0x07	/* ^G */
+#define FRAME			0x08	/* ^H */
+#define TAB			0x09	/* ^I */
+/* End of line characters */
+#define LINE_FEED		0x0a	/* ^J */
+#define HARD_RETURN		0x0b	/* ^K */
+#define PAGE_BREAK		0x0c	/* ^L */
+#define PAR_END			0x0d	/* ^M */
+#define COLUMN_FEED		0x0e	/* ^N */
+/* Embedded stuff */
+#define START_EMBEDDED		0x13	/* ^S */
+#define END_IGNORE		0x14	/* ^T */
+#define END_EMBEDDED		0x15	/* ^U */
+/* Special characters */
+#if defined(DEBUG)
+#define FILLER_CHAR		'~'
+#else
+#define FILLER_CHAR		' '
+#endif /* DEBUG */
+#define TABLE_SEPARATOR_CHAR	'|'
+/* Pseudo characters. These must be outside the Unicode range */
+#define FOOTNOTE_CHAR		((unsigned long)0xffff + 1)
+#define ENDNOTE_CHAR		((unsigned long)0xffff + 2)
+#define UNKNOWN_NOTE_CHAR	((unsigned long)0xffff + 3)
+
+/* Charactercodes as used by Word */
+#define WORD_UNBREAKABLE_JOIN		0x1e
+#define WORD_SOFT_HYPHEN		0x1f
+
+/* Unicode characters */
+#define UNICODE_DOUBLE_LEFT_ANGLE_QMARK	0x00ab
+#define UNICODE_MIDDLE_DOT		0x00b7
+#define UNICODE_DOUBLE_RIGHT_ANGLE_QMARK	0x00bb
+#define UNICODE_CAPITAL_D_WITH_STROKE	0x0110
+#define UNICODE_SMALL_D_WITH_STROKE	0x0111
+#define UNICODE_CAPITAL_LIGATURE_OE	0x0152
+#define UNICODE_SMALL_LIGATURE_OE	0x0153
+#define UNICODE_SMALL_F_HOOK		0x0192
+#define UNICODE_GREEK_CAPITAL_CHI	0x03a7
+#define UNICODE_GREEK_SMALL_UPSILON	0x03c5
+#define UNICODE_MODIFIER_CIRCUMFLEX	0x02c6
+#define UNICODE_SMALL_TILDE		0x02dc
+#define UNICODE_SMALL_LETTER_OMEGA	0x03c9
+#define UNICODE_EN_QUAD			0x2000
+#define UNICODE_EM_QUAD			0x2001
+#define UNICODE_EN_SPACE		0x2002
+#define UNICODE_EM_SPACE		0x2003
+#define UNICODE_THREE_PER_EM_SPACE	0x2004
+#define UNICODE_FOUR_PER_EM_SPACE	0x2005
+#define UNICODE_SIX_PER_EM_SPACE	0x2006
+#define UNICODE_FIGURE_SPACE		0x2007
+#define UNICODE_PUNCTUATION_SPACE	0x2008
+#define UNICODE_THIN_SPACE		0x2009
+#define UNICODE_HAIR_SPACE		0x200a
+#define UNICODE_ZERO_WIDTH_SPACE	0x200b
+#define UNICODE_ZERO_WIDTH_NON_JOINER	0x200c
+#define UNICODE_ZERO_WIDTH_JOINER	0x200d
+#define UNICODE_LEFT_TO_RIGHT_MARK	0x200e
+#define UNICODE_RIGHT_TO_LEFT_MARK	0x200f
+#define UNICODE_HYPHEN			0x2010
+#define UNICODE_NON_BREAKING_HYPHEN	0x2011
+#define UNICODE_FIGURE_DASH		0x2012
+#define UNICODE_EN_DASH			0x2013
+#define UNICODE_EM_DASH			0x2014
+#define UNICODE_HORIZONTAL_BAR		0x2015
+#define UNICODE_DOUBLE_VERTICAL_LINE	0x2016
+#define UNICODE_DOUBLE_LOW_LINE		0x2017
+#define UNICODE_LEFT_SINGLE_QMARK	0x2018
+#define UNICODE_RIGHT_SINGLE_QMARK	0x2019
+#define UNICODE_SINGLE_LOW_9_QMARK	0x201a
+#define UNICODE_SINGLE_HIGH_REV_9_QMARK	0x201b
+#define UNICODE_LEFT_DOUBLE_QMARK	0x201c
+#define UNICODE_RIGHT_DOUBLE_QMARK	0x201d
+#define UNICODE_DOUBLE_LOW_9_QMARK	0x201e
+#define UNICODE_DOUBLE_HIGH_REV_9_QMARK	0x201f
+#define UNICODE_DAGGER			0x2020
+#define UNICODE_DOUBLE_DAGGER		0x2021
+#define UNICODE_BULLET			0x2022
+#define UNICODE_TRIANGULAR_BULLET	0x2023
+#define UNICODE_ONE_DOT_LEADER		0x2024
+#define UNICODE_TWO_DOT_LEADER		0x2025
+#define UNICODE_ELLIPSIS		0x2026
+#define UNICODE_HYPHENATION_POINT	0x2027
+#define UNICODE_LEFT_TO_RIGHT_EMBEDDING	0x202a
+#define UNICODE_RIGHT_TO_LEFT_EMBEDDING	0x202b
+#define UNICODE_POP_DIRECTIONAL_FORMATTING	0x202c
+#define UNICODE_LEFT_TO_RIGHT_OVERRIDE	0x202d
+#define UNICODE_RIGHT_TO_LEFT_OVERRIDE	0x202e
+#define UNICODE_NARROW_NO_BREAK_SPACE	0x202f
+#define UNICODE_PER_MILLE_SIGN		0x2030
+#define UNICODE_PRIME			0x2032
+#define UNICODE_DOUBLE_PRIME		0x2033
+#define UNICODE_SINGLE_LEFT_ANGLE_QMARK	0x2039
+#define UNICODE_SINGLE_RIGHT_ANGLE_QMARK	0x203a
+#define UNICODE_UNDERTIE		0x203f
+#define UNICODE_FRACTION_SLASH		0x2044
+#define UNICODE_EURO_SIGN		0x20ac
+#define UNICODE_CIRCLE			0x20dd
+#define UNICODE_SQUARE			0x20de
+#define UNICODE_DIAMOND			0x20df
+#define UNICODE_NUMERO_SIGN		0x2116
+#define UNICODE_TRADEMARK_SIGN		0x2122
+#define UNICODE_KELVIN_SIGN		0x212a
+#define UNICODE_LEFTWARDS_ARROW		0x2190
+#define UNICODE_UPWARDS_ARROW		0x2191
+#define UNICODE_RIGHTWARDS_ARROW	0x2192
+#define UNICODE_DOWNWARDS_ARROW		0x2193
+#define UNICODE_N_ARY_SUMMATION		0x2211
+#define UNICODE_MINUS_SIGN		0x2212
+#define UNICODE_DIVISION_SLASH		0x2215
+#define UNICODE_ASTERISK_OPERATOR	0x2217
+#define UNICODE_BULLET_OPERATOR		0x2219
+#define UNICODE_RATIO			0x2236
+#define UNICODE_TILDE_OPERATOR		0x223c
+#define UNICODE_BD_LIGHT_HORIZONTAL	0x2500
+#define UNICODE_BD_LIGHT_VERTICAL	0x2502
+#define UNICODE_BD_LIGHT_DOWN_RIGHT	0x250c
+#define UNICODE_BD_LIGHT_DOWN_AND_LEFT	0x2510
+#define UNICODE_BD_LIGHT_UP_AND_RIGHT	0x2514
+#define UNICODE_BD_LIGHT_UP_AND_LEFT	0x2518
+#define UNICODE_BD_LIGHT_VERTICAL_AND_RIGHT	0x251c
+#define UNICODE_BD_LIGHT_VERTICAL_AND_LEFT	0x2524
+#define UNICODE_BD_LIGHT_DOWN_AND_HORIZONTAL	0x252c
+#define UNICODE_BD_LIGHT_UP_AND_HORIZONTAL	0x2534
+#define UNICODE_BD_LIGHT_VERTICAL_AND_HORIZONTAL	0x253c
+#define UNICODE_BD_DOUBLE_HORIZONTAL	0x2550
+#define UNICODE_BD_DOUBLE_VERTICAL	0x2551
+#define UNICODE_BD_DOUBLE_DOWN_AND_RIGHT	0x2554
+#define UNICODE_BD_DOUBLE_DOWN_AND_LEFT	0x2557
+#define UNICODE_BD_DOUBLE_UP_AND_RIGHT	0x255a
+#define UNICODE_BD_DOUBLE_UP_AND_LEFT	0x255d
+#define UNICODE_BD_DOUBLE_VERTICAL_AND_RIGHT	0x2560
+#define UNICODE_BD_DOUBLE_VERTICAL_AND_LEFT	0x2563
+#define UNICODE_BD_DOUBLE_DOWN_AND_HORIZONTAL	0x2566
+#define UNICODE_BD_DOUBLE_UP_AND_HORIZONTAL	0x2569
+#define UNICODE_BD_DOUBLE_VERTICAL_AND_HORIZONTAL	0x256c
+#define UNICODE_LIGHT_SHADE		0x2591
+#define UNICODE_MEDIUM_SHADE		0x2592
+#define UNICODE_DARK_SHADE		0x2593
+#define UNICODE_BLACK_SQUARE		0x25a0
+#define UNICODE_BLACK_CLUB_SUIT		0x2663
+#define UNICODE_SMALL_LIGATURE_FI	0xfb01
+#define UNICODE_SMALL_LIGATURE_FL	0xfb02
+#define UNICODE_ZERO_WIDTH_NO_BREAK_SPACE	0xfeff
+
+#if defined(__riscos)
+#define OUR_ELLIPSIS			0x8c
+#define OUR_EM_DASH			0x98
+#define OUR_UNBREAKABLE_JOIN		0x99
+#else
+#define OUR_ELLIPSIS			'.'
+#define OUR_EM_DASH			'-'
+#define OUR_UNBREAKABLE_JOIN		'-'
+#endif /* __riscos */
+#define OUR_DIAMOND			'-'
+
+#endif /* __wordconst_h */
diff --git a/worddos.c b/worddos.c
new file mode 100644
index 0000000..c0e0142
--- /dev/null
+++ b/worddos.c
@@ -0,0 +1,110 @@
+/*
+ * worddos.c
+ * Copyright (C) 2002-2005 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Deal with the DOS internals of a MS Word file
+ */
+
+#include "antiword.h"
+
+
+/*
+ * bGetDocumentText - make a list of the text blocks of a Word document
+ *
+ * Return TRUE when succesful, otherwise FALSE
+ */
+static BOOL
+bGetDocumentText(FILE *pFile, long lFilesize, const UCHAR *aucHeader)
+{
+	text_block_type	tTextBlock;
+	ULONG	ulTextLen;
+	BOOL	bFastSaved;
+	UCHAR	ucDocStatus, ucVersion;
+
+	fail(pFile == NULL);
+	fail(lFilesize < 128);
+	fail(aucHeader == NULL);
+
+	/* Get the status flags from the header */
+	ucDocStatus = ucGetByte(0x75, aucHeader);
+	DBG_HEX(ucDocStatus);
+	bFastSaved = (ucDocStatus & BIT(1)) != 0;
+	DBG_MSG_C(bFastSaved, "This document is Fast Saved");
+	ucVersion = ucGetByte(0x74, aucHeader);
+	DBG_DEC(ucVersion);
+	DBG_MSG_C(ucVersion == 0, "Written by Word 4.0 or earlier");
+	DBG_MSG_C(ucVersion == 3, "Word 5.0 format, but not written by Word");
+	DBG_MSG_C(ucVersion == 4, "Written by Word 5.x");
+	if (bFastSaved) {
+		werr(0, "Word for DOS: autosave documents are not supported");
+		return FALSE;
+	}
+
+	/* Get length information */
+	ulTextLen = ulGetLong(0x0e, aucHeader);
+	DBG_HEX(ulTextLen);
+	ulTextLen -= 128;
+	DBG_DEC(ulTextLen);
+	tTextBlock.ulFileOffset = 128;
+	tTextBlock.ulCharPos = 128;
+	tTextBlock.ulLength = ulTextLen;
+	tTextBlock.bUsesUnicode = FALSE;
+	tTextBlock.usPropMod = IGNORE_PROPMOD;
+	if (!bAdd2TextBlockList(&tTextBlock)) {
+		DBG_HEX(tTextBlock.ulFileOffset);
+		DBG_HEX(tTextBlock.ulCharPos);
+		DBG_DEC(tTextBlock.ulLength);
+		DBG_DEC(tTextBlock.bUsesUnicode);
+		DBG_DEC(tTextBlock.usPropMod);
+		return FALSE;
+	}
+	return TRUE;
+} /* end of bGetDocumentText */
+
+/*
+ * iInitDocumentDOS - initialize an DOS document
+ *
+ * Returns the version of Word that made the document or -1
+ */
+int
+iInitDocumentDOS(FILE *pFile, long lFilesize)
+{
+	int	iWordVersion;
+	BOOL	bSuccess;
+	USHORT	usIdent;
+	UCHAR	aucHeader[128];
+
+	fail(pFile == NULL);
+
+	if (lFilesize < 128) {
+		return -1;
+	}
+
+	/* Read the headerblock */
+	if (!bReadBytes(aucHeader, 128, 0x00, pFile)) {
+		return -1;
+	}
+	/* Get the "magic number" from the header */
+	usIdent = usGetWord(0x00, aucHeader);
+	DBG_HEX(usIdent);
+	fail(usIdent != 0xbe31);	/* Word for DOS */
+	iWordVersion = iGetVersionNumber(aucHeader);
+	if (iWordVersion != 0) {
+		werr(0, "This file is not from 'Word for DOS'.");
+		return -1;
+	}
+	bSuccess = bGetDocumentText(pFile, lFilesize, aucHeader);
+	if (bSuccess) {
+		vGetPropertyInfo(pFile, NULL,
+				NULL, 0, NULL, 0,
+				aucHeader, iWordVersion);
+		vSetDefaultTabWidth(pFile, NULL,
+				NULL, 0, NULL, 0,
+				aucHeader, iWordVersion);
+		vGetNotesInfo(pFile, NULL,
+				NULL, 0, NULL, 0,
+				aucHeader, iWordVersion);
+	}
+	return bSuccess ? iWordVersion : -1;
+} /* end of iInitDocumentDOS */
diff --git a/wordlib.c b/wordlib.c
new file mode 100644
index 0000000..d8471d6
--- /dev/null
+++ b/wordlib.c
@@ -0,0 +1,359 @@
+/*
+ * wordlib.c
+ * Copyright (C) 1998-2004 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Deal with the internals of a MS Word file
+ */
+
+#include "antiword.h"
+
+static BOOL	bOldMacFile = FALSE;
+
+
+/*
+ * Common part of the file checking functions
+ */
+static BOOL
+bCheckBytes(FILE *pFile, const UCHAR *aucBytes, size_t tBytes)
+{
+	int	iIndex, iChar;
+
+	fail(pFile == NULL || aucBytes == NULL || tBytes == 0);
+
+	rewind(pFile);
+
+	for (iIndex = 0; iIndex < (int)tBytes; iIndex++) {
+		iChar = getc(pFile);
+		if (iChar == EOF || iChar != (int)aucBytes[iIndex]) {
+			NO_DBG_HEX(iChar);
+			NO_DBG_HEX(aucBytes[iIndex]);
+			return FALSE;
+		}
+	}
+	return TRUE;
+} /* end of bCheckBytes */
+
+/*
+ * This function checks whether the given file is or is not a "Word for DOS"
+ * document
+ */
+BOOL
+bIsWordForDosFile(FILE *pFile, long lFilesize)
+{
+	static UCHAR	aucBytes[] =
+		{ 0x31, 0xbe, 0x00, 0x00, 0x00, 0xab };	/* Word for DOS */
+
+	DBG_MSG("bIsWordForDosFile");
+
+	if (pFile == NULL || lFilesize < 0) {
+		DBG_MSG("No proper file given");
+		return FALSE;
+	}
+	if (lFilesize < 128) {
+		DBG_MSG("File too small to be a Word document");
+		return FALSE;
+	}
+	return bCheckBytes(pFile, aucBytes, elementsof(aucBytes));
+} /* end of bIsWordForDosFile */
+
+/*
+ * This function checks whether the given file is or is not a file with an
+ * OLE envelope (That is a document made by Word 6 or later)
+ */
+static BOOL
+bIsWordFileWithOLE(FILE *pFile, long lFilesize)
+{
+	static UCHAR	aucBytes[] =
+		{ 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 };
+	int	iTailLen;
+
+	if (pFile == NULL || lFilesize < 0) {
+		DBG_MSG("No proper file given");
+		return FALSE;
+	}
+	if (lFilesize < (long)BIG_BLOCK_SIZE * 3) {
+		DBG_MSG("This file is too small to be a Word document");
+		return FALSE;
+	}
+
+	iTailLen = (int)(lFilesize % BIG_BLOCK_SIZE);
+	switch (iTailLen) {
+	case 0:		/* No tail, as it should be */
+		break;
+	case 1:
+	case 2:		/* Filesize mismatch or a buggy email program */
+		if ((int)(lFilesize % 3) == iTailLen) {
+			DBG_DEC(lFilesize);
+			return FALSE;
+		}
+		/*
+		 * Ignore extra bytes caused by buggy email programs.
+		 * They have bugs in their base64 encoding or decoding.
+		 * 3 bytes -> 4 ascii chars -> 3 bytes
+		 */
+		DBG_MSG("Document with extra bytes");
+		break;
+	default:	/* Wrong filesize for a Word document */
+		DBG_DEC(lFilesize);
+		DBG_DEC(iTailLen);
+		return FALSE;
+	}
+	return bCheckBytes(pFile, aucBytes, elementsof(aucBytes));
+} /* end of bIsWordFileWithOLE */
+
+/*
+ * This function checks whether the given file is or is not a RTF document
+ */
+BOOL
+bIsRtfFile(FILE *pFile)
+{
+	static UCHAR	aucBytes[] =
+		{ '{', '\\', 'r', 't', 'f', '1' };
+
+	DBG_MSG("bIsRtfFile");
+
+	return bCheckBytes(pFile, aucBytes, elementsof(aucBytes));
+} /* end of bIsRtfFile */
+
+/*
+ * This function checks whether the given file is or is not a WP document
+ */
+BOOL
+bIsWordPerfectFile(FILE *pFile)
+{
+	static UCHAR	aucBytes[] =
+		{ 0xff, 'W', 'P', 'C' };
+
+	DBG_MSG("bIsWordPerfectFile");
+
+	return bCheckBytes(pFile, aucBytes, elementsof(aucBytes));
+} /* end of bIsWordPerfectFile */
+
+/*
+ * This function checks whether the given file is or is not a "Win Word 1 or 2"
+ * document
+ */
+BOOL
+bIsWinWord12File(FILE *pFile, long lFilesize)
+{
+	static UCHAR	aucBytes[2][4] = {
+		{ 0x9b, 0xa5, 0x21, 0x00 },	/* Win Word 1.x */
+		{ 0xdb, 0xa5, 0x2d, 0x00 },	/* Win Word 2.0 */
+	};
+	int	iIndex;
+
+	DBG_MSG("bIsWinWord12File");
+
+	if (pFile == NULL || lFilesize < 0) {
+		DBG_MSG("No proper file given");
+		return FALSE;
+	}
+	if (lFilesize < 384) {
+		DBG_MSG("This file is too small to be a Word document");
+		return FALSE;
+	}
+
+	for (iIndex = 0; iIndex < (int)elementsof(aucBytes); iIndex++) {
+		if (bCheckBytes(pFile,
+				aucBytes[iIndex],
+				elementsof(aucBytes[iIndex]))) {
+			return TRUE;
+		}
+	}
+	return FALSE;
+} /* end of bIsWinWord12File */
+
+/*
+ * This function checks whether the given file is or is not a "Mac Word 4 or 5"
+ * document
+ */
+BOOL
+bIsMacWord45File(FILE *pFile)
+{
+	static UCHAR	aucBytes[2][6] = {
+		{ 0xfe, 0x37, 0x00, 0x1c, 0x00, 0x00 },	/* Mac Word 4 */
+		{ 0xfe, 0x37, 0x00, 0x23, 0x00, 0x00 },	/* Mac Word 5 */
+	};
+	int	iIndex;
+
+	DBG_MSG("bIsMacWord45File");
+
+	for (iIndex = 0; iIndex < (int)elementsof(aucBytes); iIndex++) {
+		if (bCheckBytes(pFile,
+				aucBytes[iIndex],
+				elementsof(aucBytes[iIndex]))) {
+			return TRUE;
+		}
+	}
+	return FALSE;
+} /* end of bIsMacWord45File */
+
+/*
+ * iGuessVersionNumber - guess the Word version number from first few bytes
+ *
+ * Returns the guessed version number or -1 when no guess it possible
+ */
+int
+iGuessVersionNumber(FILE *pFile, long lFilesize)
+{
+	if(bIsWordForDosFile(pFile, lFilesize)) {
+		return 0;
+	}
+	if (bIsWinWord12File(pFile, lFilesize)) {
+		return 2;
+	}
+	if (bIsMacWord45File(pFile)) {
+		return 5;
+	}
+	if (bIsWordFileWithOLE(pFile, lFilesize)) {
+		return 6;
+	}
+	return -1;
+} /* end of iGuessVersionNumber */
+
+/*
+ * iGetVersionNumber - get the Word version number from the header
+ *
+ * Returns the version number or -1 when unknown
+ */
+int
+iGetVersionNumber(const UCHAR *aucHeader)
+{
+	USHORT	usFib, usChse;
+
+	usFib = usGetWord(0x02, aucHeader);
+	if (usFib >= 0x1000) {
+		/* To big: must be MacWord using Big Endian */
+		DBG_HEX(usFib);
+		usFib = usGetWordBE(0x02, aucHeader);
+	}
+	DBG_DEC(usFib);
+	bOldMacFile = FALSE;
+	switch (usFib) {
+	case   0:
+		DBG_MSG("Word for DOS");
+		return 0;
+	case  28:
+		DBG_MSG("Word 4 for Macintosh");
+		bOldMacFile = TRUE;
+		return 4;
+	case  33:
+		DBG_MSG("Word 1.x for Windows");
+		return 1;
+	case  35:
+		DBG_MSG("Word 5 for Macintosh");
+		bOldMacFile = TRUE;
+		return 5;
+	case  45:
+		DBG_MSG("Word 2 for Windows");
+		return 2;
+	case 101:
+	case 102:
+		DBG_MSG("Word 6 for Windows");
+		return 6;
+	case 103:
+	case 104:
+		usChse = usGetWord(0x14, aucHeader);
+		DBG_DEC(usChse);
+		switch (usChse) {
+		case 0:
+			DBG_MSG("Word 7 for Win95");
+			return 7;
+		case 256:
+			DBG_MSG("Word 6 for Macintosh");
+			bOldMacFile = TRUE;
+			return 6;
+		default:
+			DBG_FIXME();
+			if ((int)ucGetByte(0x05, aucHeader) == 0xe0) {
+				DBG_MSG("Word 7 for Win95");
+				return 7;
+			}
+			DBG_MSG("Word 6 for Macintosh");
+			bOldMacFile = TRUE;
+			return 6;
+		}
+	default:
+		usChse = usGetWord(0x14, aucHeader);
+		DBG_DEC(usChse);
+		if (usFib < 192) {
+			/* Unknown or unsupported version of Word */
+			DBG_DEC(usFib);
+			return -1;
+		}
+		DBG_MSG_C(usChse != 256, "Word97 for Win95/98/NT");
+		DBG_MSG_C(usChse == 256, "Word98 for Macintosh");
+		return 8;
+	}
+} /* end of iGetVersionNumber */
+
+/*
+ * TRUE if the current file was made by Word version 6 or older on an
+ * Apple Macintosh, otherwise FALSE.
+ * This function hides the methode of how to find out from the rest of the
+ * program.
+ */
+BOOL
+bIsOldMacFile(void)
+{
+	return bOldMacFile;
+} /* end of bIsOldMacFile */
+
+/*
+ * iInitDocument - initialize a document
+ *
+ * Returns the version of Word that made the document or -1
+ */
+int
+iInitDocument(FILE *pFile, long lFilesize)
+{
+	int	iGuess, iWordVersion;
+
+	iGuess = iGuessVersionNumber(pFile, lFilesize);
+	switch (iGuess) {
+	case 0:
+		iWordVersion = iInitDocumentDOS(pFile, lFilesize);
+		break;
+	case 2:
+		iWordVersion = iInitDocumentWIN(pFile, lFilesize);
+		break;
+	case 5:
+		iWordVersion = iInitDocumentMAC(pFile, lFilesize);
+		break;
+	case 6:
+		iWordVersion = iInitDocumentOLE(pFile, lFilesize);
+		break;
+	default:
+		DBG_DEC(iGuess);
+		iWordVersion = -1;
+		break;
+	}
+	return iWordVersion;
+} /* end of iInitDocument */
+
+/*
+ * vFreeDocument - free a document by free-ing its parts
+ */
+void
+vFreeDocument(void)
+{
+	DBG_MSG("vFreeDocument");
+
+	/* Free the memory */
+	vDestroyTextBlockList();
+	vDestroyDataBlockList();
+	vDestroyListInfoList();
+	vDestroyRowInfoList();
+	vDestroyStyleInfoList();
+	vDestroyFontInfoList();
+	vDestroyStylesheetList();
+	vDestroyPictInfoList();
+	vDestroyDocumentInfoList();
+	vDestroySectionInfoList();
+	vDestroyHdrFtrInfoList();
+	vDestroyPropModList();
+	vDestroyNotesInfoLists();
+	vDestroyFontTable();
+	vDestroySummaryInfo();
+} /* end of vFreeDocument */
diff --git a/wordmac.c b/wordmac.c
new file mode 100644
index 0000000..c6a8f26
--- /dev/null
+++ b/wordmac.c
@@ -0,0 +1,108 @@
+/*
+ * wordmac.c
+ * Copyright (C) 2002-2004 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Deal with the MAC internals of a MS Word file
+ */
+
+#include "antiword.h"
+
+
+/*
+ * bGetDocumentText - make a list of the text blocks of a Word document
+ *
+ * Return TRUE when succesful, otherwise FALSE
+ */
+static BOOL
+bGetDocumentText(FILE *pFile, const UCHAR *aucHeader)
+{
+	text_block_type	tTextBlock;
+	ULONG	ulBeginOfText, ulEndOfText;
+	ULONG	ulTextLen;
+	UCHAR	ucDocStatus;
+	BOOL    bFastSaved;
+
+	fail(pFile == NULL);
+	fail(aucHeader == NULL);
+
+	DBG_MSG("bGetDocumentText");
+
+	NO_DBG_PRINT_BLOCK(aucHeader, 0x20);
+
+	/* Get the status flags from the header */
+	ucDocStatus = ucGetByte(0x0a, aucHeader);
+	DBG_HEX(ucDocStatus);
+	bFastSaved = (ucDocStatus & BIT(5)) != 0;
+	DBG_MSG_C(bFastSaved, "This document is Fast Saved");
+	if (bFastSaved) {
+		werr(0, "MacWord: fast saved documents are not supported yet");
+		return FALSE;
+	}
+
+	/* Get length information */
+	ulBeginOfText = ulGetLongBE(0x14, aucHeader);
+	DBG_HEX(ulBeginOfText);
+	ulEndOfText = ulGetLongBE(0x18, aucHeader);
+	DBG_HEX(ulEndOfText);
+	ulTextLen = ulEndOfText - ulBeginOfText;
+	DBG_DEC(ulTextLen);
+	tTextBlock.ulFileOffset = ulBeginOfText;
+	tTextBlock.ulCharPos = ulBeginOfText;
+	tTextBlock.ulLength = ulTextLen;
+	tTextBlock.bUsesUnicode = FALSE;
+	tTextBlock.usPropMod = IGNORE_PROPMOD;
+	if (!bAdd2TextBlockList(&tTextBlock)) {
+		DBG_HEX(tTextBlock.ulFileOffset);
+		DBG_HEX(tTextBlock.ulCharPos);
+		DBG_DEC(tTextBlock.ulLength);
+		DBG_DEC(tTextBlock.bUsesUnicode);
+		DBG_DEC(tTextBlock.usPropMod);
+		return FALSE;
+	}
+	return TRUE;
+} /* end of bGetDocumentText */
+
+/*
+ * iInitDocumentMAC - initialize an MAC document
+ *
+ * Returns the version of Word that made the document or -1
+ */
+int
+iInitDocumentMAC(FILE *pFile, long lFilesize)
+{
+	int	iWordVersion;
+	BOOL	bSuccess;
+	USHORT	usIdent;
+	UCHAR	aucHeader[256];
+
+	fail(pFile == NULL);
+
+	if (lFilesize < 256) {
+		return -1;
+	}
+
+	/* Read the headerblock */
+	if (!bReadBytes(aucHeader, 256, 0x00, pFile)) {
+		return -1;
+	}
+	/* Get the "magic number" from the header */
+	usIdent = usGetWord(0x00, aucHeader);
+	DBG_HEX(usIdent);
+	fail(usIdent != 0x37fe);	/* MacWord 4 and 5 */
+	iWordVersion = iGetVersionNumber(aucHeader);
+	if (iWordVersion != 4 && iWordVersion != 5) {
+		werr(0, "This file is not from ''Mac Word 4 or 5'.");
+		return -1;
+	}
+	bSuccess = bGetDocumentText(pFile, aucHeader);
+	if (bSuccess) {
+		vGetPropertyInfo(pFile, NULL,
+				NULL, 0, NULL, 0,
+				aucHeader, iWordVersion);
+		vSetDefaultTabWidth(pFile, NULL,
+				NULL, 0, NULL, 0,
+				aucHeader, iWordVersion);
+	}
+	return bSuccess ? iWordVersion : -1;
+} /* end of iInitDocumentMAC */
diff --git a/wordole.c b/wordole.c
new file mode 100644
index 0000000..8a95fb9
--- /dev/null
+++ b/wordole.c
@@ -0,0 +1,804 @@
+/*
+ * wordole.c
+ * Copyright (C) 1998-2004 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Deal with the OLE internals of a MS Word file
+ */
+
+#include <string.h>
+#include "antiword.h"
+
+/* Private type for Property Set Storage entries */
+typedef struct pps_entry_tag {
+	ULONG	ulNext;
+	ULONG	ulPrevious;
+	ULONG	ulDir;
+	ULONG	ulSB;
+	ULONG	ulSize;
+	int	iLevel;
+	char	szName[32];
+	UCHAR	ucType;
+} pps_entry_type;
+
+/* Show that a PPS number or index should not be used */
+#define PPS_NUMBER_INVALID	0xffffffffUL
+
+
+/* Macro to make sure all such statements will be identical */
+#define FREE_ALL()		\
+	do {\
+		vDestroySmallBlockList();\
+		aulRootList = xfree(aulRootList);\
+		aulSbdList = xfree(aulSbdList);\
+		aulBbdList = xfree(aulBbdList);\
+		aulSBD = xfree(aulSBD);\
+		aulBBD = xfree(aulBBD);\
+	} while(0)
+
+
+/*
+ * ulReadLong - read four bytes from the given file and offset
+ */
+static ULONG
+ulReadLong(FILE *pFile, ULONG ulOffset)
+{
+	UCHAR	aucBytes[4];
+
+	fail(pFile == NULL);
+
+	if (!bReadBytes(aucBytes, 4, ulOffset, pFile)) {
+		werr(1, "Read long 0x%lx not possible", ulOffset);
+	}
+	return ulGetLong(0, aucBytes);
+} /* end of ulReadLong */
+
+/*
+ * vName2String - turn the name into a proper string.
+ */
+static void
+vName2String(char *szName, const UCHAR *aucBytes, size_t tNameSize)
+{
+	char	*pcChar;
+	size_t	tIndex;
+
+	fail(aucBytes == NULL || szName == NULL);
+
+	if (tNameSize < 2) {
+		szName[0] = '\0';
+		return;
+	}
+	for (tIndex = 0, pcChar = szName;
+	     tIndex < 2 * tNameSize;
+	     tIndex += 2, pcChar++) {
+		*pcChar = (char)aucBytes[tIndex];
+	}
+	szName[tNameSize - 1] = '\0';
+} /* end of vName2String */
+
+/*
+ * tReadBlockIndices - read the Big/Small Block Depot indices
+ *
+ * Returns the number of indices read
+ */
+static size_t
+tReadBlockIndices(FILE *pFile, ULONG *aulBlockDepot,
+	size_t tMaxRec, ULONG ulOffset)
+{
+	size_t	tDone;
+	int	iIndex;
+	UCHAR	aucBytes[BIG_BLOCK_SIZE];
+
+	fail(pFile == NULL || aulBlockDepot == NULL);
+	fail(tMaxRec == 0);
+
+	/* Read a big block with BBD or SBD indices */
+	if (!bReadBytes(aucBytes, BIG_BLOCK_SIZE, ulOffset, pFile)) {
+		werr(0, "Reading big block from 0x%lx is not possible",
+			ulOffset);
+		return 0;
+	}
+	/* Split the big block into indices, an index is four bytes */
+	tDone = min(tMaxRec, (size_t)BIG_BLOCK_SIZE / 4);
+	for (iIndex = 0; iIndex < (int)tDone; iIndex++) {
+		aulBlockDepot[iIndex] = ulGetLong(4 * iIndex, aucBytes);
+		NO_DBG_DEC(aulBlockDepot[iIndex]);
+	}
+	return tDone;
+} /* end of tReadBlockIndices */
+
+/*
+ * bGetBBD - get the Big Block Depot indices from the index-blocks
+ */
+static BOOL
+bGetBBD(FILE *pFile, const ULONG *aulDepot, size_t tDepotLen,
+	ULONG *aulBBD, size_t tBBDLen)
+{
+	ULONG	ulBegin;
+	size_t	tToGo, tDone;
+	int	iIndex;
+
+	fail(pFile == NULL || aulDepot == NULL || aulBBD == NULL);
+
+	DBG_MSG("bGetBBD");
+
+	tToGo = tBBDLen;
+	for (iIndex = 0; iIndex < (int)tDepotLen && tToGo != 0; iIndex++) {
+		ulBegin = (aulDepot[iIndex] + 1) * BIG_BLOCK_SIZE;
+		NO_DBG_HEX(ulBegin);
+		tDone = tReadBlockIndices(pFile, aulBBD, tToGo, ulBegin);
+		fail(tDone > tToGo);
+		if (tDone == 0) {
+			return FALSE;
+		}
+		aulBBD += tDone;
+		tToGo -= tDone;
+	}
+	return tToGo == 0;
+} /* end of bGetBBD */
+
+/*
+ * bGetSBD - get the Small Block Depot indices from the index-blocks
+ */
+static BOOL
+bGetSBD(FILE *pFile, const ULONG *aulDepot, size_t tDepotLen,
+	ULONG *aulSBD, size_t tSBDLen)
+{
+	ULONG	ulBegin;
+	size_t	tToGo, tDone;
+	int	iIndex;
+
+	fail(pFile == NULL || aulDepot == NULL || aulSBD == NULL);
+
+	DBG_MSG("bGetSBD");
+
+	tToGo = tSBDLen;
+	for (iIndex = 0; iIndex < (int)tDepotLen && tToGo != 0; iIndex++) {
+		fail(aulDepot[iIndex] >= ULONG_MAX / BIG_BLOCK_SIZE);
+		ulBegin = (aulDepot[iIndex] + 1) * BIG_BLOCK_SIZE;
+		NO_DBG_HEX(ulBegin);
+		tDone = tReadBlockIndices(pFile, aulSBD, tToGo, ulBegin);
+		fail(tDone > tToGo);
+		if (tDone == 0) {
+			return FALSE;
+		}
+		aulSBD += tDone;
+		tToGo -= tDone;
+	}
+	return tToGo == 0;
+} /* end of bGetSBD */
+
+/*
+ * vComputePPSlevels - compute the levels of the Property Set Storage entries
+ */
+static void
+vComputePPSlevels(pps_entry_type *atPPSlist, pps_entry_type *pNode,
+			int iLevel, int iRecursionLevel)
+{
+	fail(atPPSlist == NULL || pNode == NULL);
+	fail(iLevel < 0 || iRecursionLevel < 0);
+
+	if (iRecursionLevel > 25) {
+		/* This removes the possibility of an infinite recursion */
+		DBG_DEC(iRecursionLevel);
+		return;
+	}
+	if (pNode->iLevel <= iLevel) {
+		/* Avoid entering a loop */
+		DBG_DEC(iLevel);
+		DBG_DEC(pNode->iLevel);
+		return;
+	}
+
+	pNode->iLevel = iLevel;
+
+	if (pNode->ulDir != PPS_NUMBER_INVALID) {
+		vComputePPSlevels(atPPSlist,
+				&atPPSlist[pNode->ulDir],
+				iLevel + 1,
+				iRecursionLevel + 1);
+	}
+	if (pNode->ulNext != PPS_NUMBER_INVALID) {
+		vComputePPSlevels(atPPSlist,
+				&atPPSlist[pNode->ulNext],
+				iLevel,
+				iRecursionLevel + 1);
+	}
+	if (pNode->ulPrevious != PPS_NUMBER_INVALID) {
+		vComputePPSlevels(atPPSlist,
+				&atPPSlist[pNode->ulPrevious],
+				iLevel,
+				iRecursionLevel + 1);
+	}
+} /* end of vComputePPSlevels */
+
+/*
+ * bGetPPS - search the Property Set Storage for three sets
+ *
+ * Return TRUE if the WordDocument PPS is found
+ */
+static BOOL
+bGetPPS(FILE *pFile,
+	const ULONG *aulRootList, size_t tRootListLen, pps_info_type *pPPS)
+{
+	pps_entry_type	*atPPSlist;
+	ULONG	ulBegin, ulOffset, ulTmp;
+	size_t	tNbrOfPPS, tNameSize;
+	int	iIndex, iStartBlock, iRootIndex;
+	BOOL	bWord, bExcel;
+	UCHAR	aucBytes[PROPERTY_SET_STORAGE_SIZE];
+
+	fail(pFile == NULL || aulRootList == NULL || pPPS == NULL);
+
+	DBG_MSG("bGetPPS");
+
+	NO_DBG_DEC(tRootListLen);
+
+	bWord = FALSE;
+	bExcel = FALSE;
+	(void)memset(pPPS, 0, sizeof(*pPPS));
+
+	/* Read and store all the Property Set Storage entries */
+
+	tNbrOfPPS = tRootListLen * BIG_BLOCK_SIZE / PROPERTY_SET_STORAGE_SIZE;
+	atPPSlist = xcalloc(tNbrOfPPS, sizeof(pps_entry_type));
+	iRootIndex = 0;
+
+	for (iIndex = 0; iIndex < (int)tNbrOfPPS; iIndex++) {
+		ulTmp = (ULONG)iIndex * PROPERTY_SET_STORAGE_SIZE;
+		iStartBlock = (int)(ulTmp / BIG_BLOCK_SIZE);
+		ulOffset = ulTmp % BIG_BLOCK_SIZE;
+		ulBegin = (aulRootList[iStartBlock] + 1) * BIG_BLOCK_SIZE +
+				ulOffset;
+		NO_DBG_HEX(ulBegin);
+		if (!bReadBytes(aucBytes, PROPERTY_SET_STORAGE_SIZE,
+							ulBegin, pFile)) {
+			werr(0, "Reading PPS %d is not possible", iIndex);
+			atPPSlist = xfree(atPPSlist);
+			return FALSE;
+		}
+		tNameSize = (size_t)usGetWord(0x40, aucBytes);
+		tNameSize = (tNameSize + 1) / 2;
+		vName2String(atPPSlist[iIndex].szName, aucBytes, tNameSize);
+		atPPSlist[iIndex].ucType = ucGetByte(0x42, aucBytes);
+		if (atPPSlist[iIndex].ucType == 5) {
+			iRootIndex = iIndex;
+		}
+		atPPSlist[iIndex].ulPrevious = ulGetLong(0x44, aucBytes);
+		atPPSlist[iIndex].ulNext = ulGetLong(0x48, aucBytes);
+		atPPSlist[iIndex].ulDir = ulGetLong(0x4c, aucBytes);
+		atPPSlist[iIndex].ulSB = ulGetLong(0x74, aucBytes);
+		atPPSlist[iIndex].ulSize = ulGetLong(0x78, aucBytes);
+		atPPSlist[iIndex].iLevel = INT_MAX;
+		if ((atPPSlist[iIndex].ulPrevious >= (ULONG)tNbrOfPPS &&
+		     atPPSlist[iIndex].ulPrevious != PPS_NUMBER_INVALID) ||
+		    (atPPSlist[iIndex].ulNext >= (ULONG)tNbrOfPPS &&
+		     atPPSlist[iIndex].ulNext != PPS_NUMBER_INVALID) ||
+		    (atPPSlist[iIndex].ulDir >= (ULONG)tNbrOfPPS &&
+		     atPPSlist[iIndex].ulDir != PPS_NUMBER_INVALID)) {
+			DBG_DEC(iIndex);
+			DBG_DEC(atPPSlist[iIndex].ulPrevious);
+			DBG_DEC(atPPSlist[iIndex].ulNext);
+			DBG_DEC(atPPSlist[iIndex].ulDir);
+			DBG_DEC(tNbrOfPPS);
+			werr(0, "The Property Set Storage is damaged");
+			atPPSlist = xfree(atPPSlist);
+			return FALSE;
+		}
+	}
+
+#if 0 /* defined(DEBUG) */
+	DBG_MSG("Before");
+	for (iIndex = 0; iIndex < (int)tNbrOfPPS; iIndex++) {
+		DBG_MSG(atPPSlist[iIndex].szName);
+		DBG_HEX(atPPSlist[iIndex].ulDir);
+		DBG_HEX(atPPSlist[iIndex].ulPrevious);
+		DBG_HEX(atPPSlist[iIndex].ulNext);
+		DBG_DEC(atPPSlist[iIndex].ulSB);
+		DBG_HEX(atPPSlist[iIndex].ulSize);
+		DBG_DEC(atPPSlist[iIndex].iLevel);
+	}
+#endif /* DEBUG */
+
+	/* Add level information to each entry */
+	vComputePPSlevels(atPPSlist, &atPPSlist[iRootIndex], 0, 0);
+
+	/* Check the entries on level 1 for the required information */
+	NO_DBG_MSG("After");
+	for (iIndex = 0; iIndex < (int)tNbrOfPPS; iIndex++) {
+#if 0 /* defined(DEBUG) */
+		DBG_MSG(atPPSlist[iIndex].szName);
+		DBG_HEX(atPPSlist[iIndex].ulDir);
+		DBG_HEX(atPPSlist[iIndex].ulPrevious);
+		DBG_HEX(atPPSlist[iIndex].ulNext);
+		DBG_DEC(atPPSlist[iIndex].ulSB);
+		DBG_HEX(atPPSlist[iIndex].ulSize);
+		DBG_DEC(atPPSlist[iIndex].iLevel);
+#endif /* DEBUG */
+		if (atPPSlist[iIndex].iLevel != 1 ||
+		    atPPSlist[iIndex].ucType != 2 ||
+		    atPPSlist[iIndex].szName[0] == '\0' ||
+		    atPPSlist[iIndex].ulSize == 0) {
+			/* This entry can be ignored */
+			continue;
+		}
+		if (pPPS->tWordDocument.ulSize == 0 &&
+		    STREQ(atPPSlist[iIndex].szName, "WordDocument")) {
+			pPPS->tWordDocument.ulSB = atPPSlist[iIndex].ulSB;
+			pPPS->tWordDocument.ulSize = atPPSlist[iIndex].ulSize;
+			bWord = TRUE;
+		} else if (pPPS->tData.ulSize == 0 &&
+			   STREQ(atPPSlist[iIndex].szName, "Data")) {
+			pPPS->tData.ulSB = atPPSlist[iIndex].ulSB;
+			pPPS->tData.ulSize = atPPSlist[iIndex].ulSize;
+		} else if (pPPS->t0Table.ulSize == 0 &&
+			   STREQ(atPPSlist[iIndex].szName, "0Table")) {
+			pPPS->t0Table.ulSB = atPPSlist[iIndex].ulSB;
+			pPPS->t0Table.ulSize = atPPSlist[iIndex].ulSize;
+		} else if (pPPS->t1Table.ulSize == 0 &&
+			   STREQ(atPPSlist[iIndex].szName, "1Table")) {
+			pPPS->t1Table.ulSB = atPPSlist[iIndex].ulSB;
+			pPPS->t1Table.ulSize = atPPSlist[iIndex].ulSize;
+		} else if (pPPS->tSummaryInfo.ulSize == 0 &&
+			   STREQ(atPPSlist[iIndex].szName,
+						"\005SummaryInformation")) {
+			pPPS->tSummaryInfo.ulSB = atPPSlist[iIndex].ulSB;
+			pPPS->tSummaryInfo.ulSize = atPPSlist[iIndex].ulSize;
+		} else if (pPPS->tDocSummaryInfo.ulSize == 0 &&
+			   STREQ(atPPSlist[iIndex].szName,
+					"\005DocumentSummaryInformation")) {
+			pPPS->tDocSummaryInfo.ulSB = atPPSlist[iIndex].ulSB;
+			pPPS->tDocSummaryInfo.ulSize = atPPSlist[iIndex].ulSize;
+		} else if (STREQ(atPPSlist[iIndex].szName, "Book") ||
+			   STREQ(atPPSlist[iIndex].szName, "Workbook")) {
+			bExcel = TRUE;
+		}
+	}
+
+	/* Free the space for the Property Set Storage entries */
+	atPPSlist = xfree(atPPSlist);
+
+	/* Draw your conclusions */
+	if (bWord) {
+		return TRUE;
+	}
+
+	if (bExcel) {
+		werr(0, "Sorry, but this is an Excel spreadsheet");
+	} else {
+		werr(0, "This OLE file does not contain a Word document");
+	}
+	return FALSE;
+} /* end of bGetPPS */
+
+/*
+ * vGetBbdList - make a list of the places to find big blocks
+ */
+static void
+vGetBbdList(FILE *pFile, int iNbr, ULONG *aulBbdList, ULONG ulOffset)
+{
+	int	iIndex;
+
+	fail(pFile == NULL);
+	fail(iNbr > 127);
+	fail(aulBbdList == NULL);
+
+	NO_DBG_DEC(iNbr);
+	for (iIndex = 0; iIndex < iNbr; iIndex++) {
+                aulBbdList[iIndex] =
+                        ulReadLong(pFile, ulOffset + 4 * (ULONG)iIndex);
+		NO_DBG_DEC(iIndex);
+                NO_DBG_HEX(aulBbdList[iIndex]);
+        }
+} /* end of vGetBbdList */
+
+/*
+ * bGetDocumentText - make a list of the text blocks of a Word document
+ *
+ * Return TRUE when succesful, otherwise FALSE
+ */
+static BOOL
+bGetDocumentText(FILE *pFile, const pps_info_type *pPPS,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const ULONG *aulSBD, size_t tSBDLen,
+	const UCHAR *aucHeader, int iWordVersion)
+{
+	ULONG	ulBeginOfText;
+	ULONG	ulTextLen, ulFootnoteLen, ulEndnoteLen;
+	ULONG	ulHdrFtrLen, ulMacroLen, ulAnnotationLen;
+	ULONG	ulTextBoxLen, ulHdrTextBoxLen;
+	UINT	uiQuickSaves;
+	BOOL	bFarEastWord, bTemplate, bFastSaved, bEncrypted, bSuccess;
+	USHORT	usIdent, usDocStatus;
+
+	fail(pFile == NULL || pPPS == NULL);
+	fail(aulBBD == NULL);
+	fail(aulSBD == NULL);
+
+	DBG_MSG("bGetDocumentText");
+
+	/* Get the "magic number" from the header */
+	usIdent = usGetWord(0x00, aucHeader);
+	DBG_HEX(usIdent);
+	bFarEastWord = usIdent == 0x8098 || usIdent == 0x8099 ||
+			usIdent == 0xa697 || usIdent == 0xa699;
+	/* Get the status flags from the header */
+	usDocStatus = usGetWord(0x0a, aucHeader);
+	DBG_HEX(usDocStatus);
+	bTemplate = (usDocStatus & BIT(0)) != 0;
+	DBG_MSG_C(bTemplate, "This document is a Template");
+	bFastSaved = (usDocStatus & BIT(2)) != 0;
+	uiQuickSaves = (UINT)(usDocStatus & 0x00f0) >> 4;
+	DBG_MSG_C(bFastSaved, "This document is Fast Saved");
+	DBG_DEC_C(bFastSaved, uiQuickSaves);
+	bEncrypted = (usDocStatus & BIT(8)) != 0;
+	if (bEncrypted) {
+		werr(0, "Encrypted documents are not supported");
+		return FALSE;
+	}
+
+	/* Get length information */
+	ulBeginOfText = ulGetLong(0x18, aucHeader);
+	DBG_HEX(ulBeginOfText);
+	switch (iWordVersion) {
+	case 6:
+	case 7:
+		ulTextLen = ulGetLong(0x34, aucHeader);
+		ulFootnoteLen = ulGetLong(0x38, aucHeader);
+		ulHdrFtrLen = ulGetLong(0x3c, aucHeader);
+		ulMacroLen = ulGetLong(0x40, aucHeader);
+		ulAnnotationLen = ulGetLong(0x44, aucHeader);
+		ulEndnoteLen = ulGetLong(0x48, aucHeader);
+		ulTextBoxLen = ulGetLong(0x4c, aucHeader);
+		ulHdrTextBoxLen = ulGetLong(0x50, aucHeader);
+		break;
+	case 8:
+		ulTextLen = ulGetLong(0x4c, aucHeader);
+		ulFootnoteLen = ulGetLong(0x50, aucHeader);
+		ulHdrFtrLen = ulGetLong(0x54, aucHeader);
+		ulMacroLen = ulGetLong(0x58, aucHeader);
+		ulAnnotationLen = ulGetLong(0x5c, aucHeader);
+		ulEndnoteLen = ulGetLong(0x60, aucHeader);
+		ulTextBoxLen = ulGetLong(0x64, aucHeader);
+		ulHdrTextBoxLen = ulGetLong(0x68, aucHeader);
+		break;
+	default:
+		werr(0, "This version of Word is not supported");
+		return FALSE;
+	}
+	DBG_DEC(ulTextLen);
+	DBG_DEC(ulFootnoteLen);
+	DBG_DEC(ulHdrFtrLen);
+	DBG_DEC(ulMacroLen);
+	DBG_DEC(ulAnnotationLen);
+	DBG_DEC(ulEndnoteLen);
+	DBG_DEC(ulTextBoxLen);
+	DBG_DEC(ulHdrTextBoxLen);
+
+	/* Make a list of the text blocks */
+	switch (iWordVersion) {
+	case 6:
+	case 7:
+		if (bFastSaved) {
+			bSuccess = bGet6DocumentText(pFile,
+					bFarEastWord,
+					pPPS->tWordDocument.ulSB,
+					aulBBD, tBBDLen,
+					aucHeader);
+		} else {
+		  	bSuccess = bAddTextBlocks(ulBeginOfText,
+				ulTextLen +
+				ulFootnoteLen +
+				ulHdrFtrLen +
+				ulMacroLen + ulAnnotationLen +
+				ulEndnoteLen +
+				ulTextBoxLen + ulHdrTextBoxLen,
+				bFarEastWord,
+				IGNORE_PROPMOD,
+				pPPS->tWordDocument.ulSB,
+				aulBBD, tBBDLen);
+		}
+		break;
+	case 8:
+		bSuccess = bGet8DocumentText(pFile,
+				pPPS,
+				aulBBD, tBBDLen, aulSBD, tSBDLen,
+				aucHeader);
+		break;
+	default:
+		werr(0, "This version of Word is not supported");
+		bSuccess = FALSE;
+		break;
+	}
+
+	if (bSuccess) {
+		vSplitBlockList(pFile,
+				ulTextLen,
+				ulFootnoteLen,
+				ulHdrFtrLen,
+				ulMacroLen,
+				ulAnnotationLen,
+				ulEndnoteLen,
+				ulTextBoxLen,
+				ulHdrTextBoxLen,
+				!bFastSaved && iWordVersion == 8);
+	} else {
+		vDestroyTextBlockList();
+		werr(0, "I can't find the text of this document");
+	}
+	return bSuccess;
+} /* end of bGetDocumentText */
+
+/*
+ * vGetDocumentData - make a list of the data blocks of a Word document
+ */
+static void
+vGetDocumentData(FILE *pFile, const pps_info_type *pPPS,
+	const ULONG *aulBBD, size_t tBBDLen,
+	const UCHAR *aucHeader, int iWordVersion)
+{
+	options_type	tOptions;
+	ULONG	ulBeginOfText;
+	BOOL	bFastSaved, bHasImages, bSuccess;
+	USHORT	usDocStatus;
+
+	fail(pFile == NULL);
+	fail(pPPS == NULL);
+	fail(aulBBD == NULL);
+
+	/* Get the options */
+	vGetOptions(&tOptions);
+
+	/* Get the status flags from the header */
+	usDocStatus = usGetWord(0x0a, aucHeader);
+	DBG_HEX(usDocStatus);
+	bFastSaved = (usDocStatus & BIT(2)) != 0;
+	bHasImages = (usDocStatus & BIT(3)) != 0;
+
+	if (!bHasImages ||
+	    tOptions.eConversionType == conversion_text ||
+	    tOptions.eConversionType == conversion_fmt_text ||
+	    tOptions.eConversionType == conversion_xml ||
+	    tOptions.eImageLevel == level_no_images) {
+		/*
+		 * No images in the document or text-only output or
+		 * no images wanted, so no data blocks will be needed
+		 */
+		vDestroyDataBlockList();
+		return;
+	}
+
+	/* Get length information */
+	ulBeginOfText = ulGetLong(0x18, aucHeader);
+	DBG_HEX(ulBeginOfText);
+
+	/* Make a list of the data blocks */
+	switch (iWordVersion) {
+	case 6:
+	case 7:
+		/*
+		 * The data blocks are in the text stream. The text stream
+		 * is in "fast saved" format or "normal saved" format
+		 */
+		if (bFastSaved) {
+			bSuccess = bGet6DocumentData(pFile,
+					pPPS->tWordDocument.ulSB,
+					aulBBD, tBBDLen,
+					aucHeader);
+		} else {
+		  	bSuccess = bAddDataBlocks(ulBeginOfText,
+					(ULONG)LONG_MAX,
+					pPPS->tWordDocument.ulSB,
+					aulBBD, tBBDLen);
+		}
+		break;
+	case 8:
+		/*
+		 * The data blocks are in the data stream. The data stream
+		 * is always in "normal saved" format
+		 */
+		bSuccess = bAddDataBlocks(0, (ULONG)LONG_MAX,
+				pPPS->tData.ulSB, aulBBD, tBBDLen);
+		break;
+	default:
+		werr(0, "This version of Word is not supported");
+		bSuccess = FALSE;
+		break;
+	}
+
+	if (!bSuccess) {
+		vDestroyDataBlockList();
+		werr(0, "I can't find the data of this document");
+	}
+} /* end of vGetDocumentData */
+
+/*
+ * iInitDocumentOLE - initialize an OLE document
+ *
+ * Returns the version of Word that made the document or -1
+ */
+int
+iInitDocumentOLE(FILE *pFile, long lFilesize)
+{
+	pps_info_type	PPS_info;
+	ULONG	*aulBBD, *aulSBD;
+	ULONG	*aulRootList, *aulBbdList, *aulSbdList;
+	ULONG	ulBdbListStart, ulAdditionalBBDlist;
+	ULONG	ulRootStartblock, ulSbdStartblock, ulSBLstartblock;
+	ULONG	ulStart, ulTmp;
+	long	lMaxBlock;
+	size_t	tBBDLen, tSBDLen, tNumBbdBlocks, tRootListLen;
+	int	iWordVersion, iIndex, iToGo;
+	BOOL	bSuccess;
+	USHORT	usIdent, usDocStatus;
+	UCHAR	aucHeader[HEADER_SIZE];
+
+	fail(pFile == NULL);
+
+	lMaxBlock = lFilesize / BIG_BLOCK_SIZE - 2;
+	DBG_DEC(lMaxBlock);
+	if (lMaxBlock < 1) {
+		return -1;
+	}
+	tBBDLen = (size_t)(lMaxBlock + 1);
+	tNumBbdBlocks = (size_t)ulReadLong(pFile, 0x2c);
+	DBG_DEC(tNumBbdBlocks);
+	ulRootStartblock = ulReadLong(pFile, 0x30);
+	DBG_DEC(ulRootStartblock);
+	ulSbdStartblock = ulReadLong(pFile, 0x3c);
+	DBG_DEC(ulSbdStartblock);
+	ulAdditionalBBDlist = ulReadLong(pFile, 0x44);
+	DBG_HEX(ulAdditionalBBDlist);
+	ulSBLstartblock = ulReadLong(pFile,
+			(ulRootStartblock + 1) * BIG_BLOCK_SIZE + 0x74);
+	DBG_DEC(ulSBLstartblock);
+	tSBDLen = (size_t)(ulReadLong(pFile,
+			(ulRootStartblock + 1) * BIG_BLOCK_SIZE + 0x78) /
+			SMALL_BLOCK_SIZE);
+	/* All to be xcalloc-ed pointers to NULL */
+	aulRootList = NULL;
+	aulSbdList = NULL;
+	aulBbdList = NULL;
+	aulSBD = NULL;
+	aulBBD = NULL;
+/* Big Block Depot */
+	aulBbdList = xcalloc(tNumBbdBlocks, sizeof(ULONG));
+	aulBBD = xcalloc(tBBDLen, sizeof(ULONG));
+	iToGo = (int)tNumBbdBlocks;
+	vGetBbdList(pFile, min(iToGo, 109),  aulBbdList, 0x4c);
+	ulStart = 109;
+	iToGo -= 109;
+	while (ulAdditionalBBDlist != END_OF_CHAIN && iToGo > 0) {
+		ulBdbListStart = (ulAdditionalBBDlist + 1) * BIG_BLOCK_SIZE;
+		vGetBbdList(pFile, min(iToGo, 127),
+					aulBbdList + ulStart, ulBdbListStart);
+		ulAdditionalBBDlist = ulReadLong(pFile,
+					ulBdbListStart + 4 * 127);
+		DBG_DEC(ulAdditionalBBDlist);
+		DBG_HEX(ulAdditionalBBDlist);
+		ulStart += 127;
+		iToGo -= 127;
+	}
+	if (!bGetBBD(pFile, aulBbdList, tNumBbdBlocks, aulBBD, tBBDLen)) {
+		FREE_ALL();
+		return -1;
+	}
+	aulBbdList = xfree(aulBbdList);
+/* Small Block Depot */
+	aulSbdList = xcalloc(tBBDLen, sizeof(ULONG));
+	aulSBD = xcalloc(tSBDLen, sizeof(ULONG));
+	for (iIndex = 0, ulTmp = ulSbdStartblock;
+	     iIndex < (int)tBBDLen && ulTmp != END_OF_CHAIN;
+	     iIndex++, ulTmp = aulBBD[ulTmp]) {
+		if (ulTmp >= (ULONG)tBBDLen) {
+			DBG_DEC(ulTmp);
+			DBG_DEC(tBBDLen);
+			werr(1, "The Big Block Depot is damaged");
+		}
+		aulSbdList[iIndex] = ulTmp;
+		NO_DBG_HEX(aulSbdList[iIndex]);
+	}
+	if (!bGetSBD(pFile, aulSbdList, tBBDLen, aulSBD, tSBDLen)) {
+		FREE_ALL();
+		return -1;
+	}
+	aulSbdList = xfree(aulSbdList);
+/* Root list */
+	for (tRootListLen = 0, ulTmp = ulRootStartblock;
+	     tRootListLen < tBBDLen && ulTmp != END_OF_CHAIN;
+	     tRootListLen++, ulTmp = aulBBD[ulTmp]) {
+		if (ulTmp >= (ULONG)tBBDLen) {
+			DBG_DEC(ulTmp);
+			DBG_DEC(tBBDLen);
+			werr(1, "The Big Block Depot is damaged");
+		}
+	}
+	if (tRootListLen == 0) {
+		werr(0, "No Rootlist found");
+		FREE_ALL();
+		return -1;
+	}
+	aulRootList = xcalloc(tRootListLen, sizeof(ULONG));
+	for (iIndex = 0, ulTmp = ulRootStartblock;
+	     iIndex < (int)tBBDLen && ulTmp != END_OF_CHAIN;
+	     iIndex++, ulTmp = aulBBD[ulTmp]) {
+		if (ulTmp >= (ULONG)tBBDLen) {
+			DBG_DEC(ulTmp);
+			DBG_DEC(tBBDLen);
+			werr(1, "The Big Block Depot is damaged");
+		}
+		aulRootList[iIndex] = ulTmp;
+		NO_DBG_DEC(aulRootList[iIndex]);
+	}
+	fail(tRootListLen != (size_t)iIndex);
+	bSuccess = bGetPPS(pFile, aulRootList, tRootListLen, &PPS_info);
+	aulRootList = xfree(aulRootList);
+	if (!bSuccess) {
+		FREE_ALL();
+		return -1;
+	}
+/* Small block list */
+	if (!bCreateSmallBlockList(ulSBLstartblock, aulBBD, tBBDLen)) {
+		FREE_ALL();
+		return -1;
+	}
+
+	if (PPS_info.tWordDocument.ulSize < MIN_SIZE_FOR_BBD_USE) {
+		DBG_DEC(PPS_info.tWordDocument.ulSize);
+		FREE_ALL();
+		werr(0, "I'm afraid the text stream of this file "
+			"is too small to handle.");
+		return -1;
+	}
+	/* Read the headerblock */
+	if (!bReadBuffer(pFile, PPS_info.tWordDocument.ulSB,
+			aulBBD, tBBDLen, BIG_BLOCK_SIZE,
+			aucHeader, 0, HEADER_SIZE)) {
+		FREE_ALL();
+		return -1;
+	}
+	usIdent = usGetWord(0x00, aucHeader);
+	DBG_HEX(usIdent);
+	fail(usIdent != 0x8098 &&	/* Word 7 for oriental languages */
+	     usIdent != 0x8099 &&	/* Word 7 for oriental languages */
+	     usIdent != 0xa5dc &&	/* Word 6 & 7 */
+	     usIdent != 0xa5ec &&	/* Word 7 & 97 & 98 */
+	     usIdent != 0xa697 &&	/* Word 7 for oriental languages */
+	     usIdent != 0xa699);	/* Word 7 for oriental languages */
+	iWordVersion = iGetVersionNumber(aucHeader);
+	if (iWordVersion < 6) {
+		FREE_ALL();
+		werr(0, "This file is from a version of Word before Word 6.");
+		return -1;
+	}
+
+	/* Get the status flags from the header */
+	usDocStatus = usGetWord(0x0a, aucHeader);
+        if (usDocStatus & BIT(9)) {
+		PPS_info.tTable = PPS_info.t1Table;
+	} else {
+		PPS_info.tTable = PPS_info.t0Table;
+	}
+	/* Clean the entries that should not be used */
+	memset(&PPS_info.t0Table, 0, sizeof(PPS_info.t0Table));
+	memset(&PPS_info.t1Table, 0, sizeof(PPS_info.t1Table));
+
+	bSuccess = bGetDocumentText(pFile, &PPS_info,
+			aulBBD, tBBDLen, aulSBD, tSBDLen,
+			aucHeader, iWordVersion);
+	if (bSuccess) {
+		vGetDocumentData(pFile, &PPS_info,
+			aulBBD, tBBDLen, aucHeader, iWordVersion);
+		vGetPropertyInfo(pFile, &PPS_info,
+			aulBBD, tBBDLen, aulSBD, tSBDLen,
+			aucHeader, iWordVersion);
+		vSetDefaultTabWidth(pFile, &PPS_info,
+			aulBBD, tBBDLen, aulSBD, tSBDLen,
+			aucHeader, iWordVersion);
+		vGetNotesInfo(pFile, &PPS_info,
+			aulBBD, tBBDLen, aulSBD, tSBDLen,
+			aucHeader, iWordVersion);
+	}
+	FREE_ALL();
+	return bSuccess ? iWordVersion : -1;
+} /* end of iInitDocumentOLE */
diff --git a/wordtypes.h b/wordtypes.h
new file mode 100644
index 0000000..d71dc8f
--- /dev/null
+++ b/wordtypes.h
@@ -0,0 +1,317 @@
+/*
+ * wordtypes.h
+ * Copyright (C) 1998-2004 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Typedefs for the interpretation of MS Word files
+ */
+
+#if !defined(__wordtypes_h)
+#define __wordtypes_h 1
+
+#include <time.h>
+#if defined(__riscos)
+#include "DeskLib:Font.h"
+#include "DeskLib:Wimp.h"
+#endif /* __riscos */
+
+typedef unsigned char	UCHAR;
+typedef unsigned short	USHORT;
+typedef unsigned int	UINT;
+typedef unsigned long	ULONG;
+
+#if defined(__riscos)
+typedef struct diagram_tag {
+	drawfile_info	tInfo;
+	window_handle	tMainWindow;
+	window_handle	tScaleWindow;
+	menu_ptr	pSaveMenu;
+	long		lXleft;			/* In DrawUnits */
+	long		lYtop;			/* In DrawUnits */
+	size_t		tMemorySize;
+	int		iScaleFactorCurr;	/* In percentage */
+	int		iScaleFactorTemp;	/* In percentage */
+	char		szFilename[19+1];
+} diagram_type;
+#else
+typedef struct diagram_tag {
+	FILE		*pOutFile;
+	long		lXleft;			/* In DrawUnits */
+	long		lYtop;			/* In DrawUnits */
+} diagram_type;
+typedef UCHAR		drawfile_fontref;
+#endif /* __riscos */
+
+typedef struct output_tag {
+	char	*szStorage;
+	long	lStringWidth;		/* In millipoints */
+	size_t	tStorageSize;
+	size_t	tNextFree;
+	USHORT	usFontStyle;
+	USHORT	usFontSize;
+	UCHAR	ucFontColor;
+	drawfile_fontref	tFontRef;
+	struct output_tag	*pPrev;
+	struct output_tag	*pNext;
+} output_type;
+
+/* Types of conversion */
+typedef enum conversion_tag {
+	conversion_unknown = 0,
+	conversion_text,
+	conversion_draw,
+	conversion_ps,
+	conversion_xml,
+	conversion_pdf,
+	conversion_fmt_text
+} conversion_type;
+
+/* Types of encoding */
+typedef enum encoding_tag {
+	encoding_neutral = 100,
+	encoding_latin_1 = 801,
+	encoding_latin_2 = 802,
+	encoding_cyrillic = 805,
+	encoding_utf_8 = 1601
+} encoding_type;
+
+/* Font translation table entry */
+typedef struct font_table_tag {
+	USHORT	usFontStyle;
+	UCHAR	ucWordFontNumber;
+	UCHAR	ucFFN;
+	UCHAR	ucEmphasis;
+	UCHAR	ucInUse;
+	char	szWordFontname[65];
+	char	szOurFontname[33];
+} font_table_type;
+
+/* Options */
+typedef enum image_level_tag {
+	level_gs_special = 0,
+	level_no_images,
+	level_ps_2,
+	level_ps_3,
+	level_default = level_ps_2
+} image_level_enum;
+
+typedef struct options_tag {
+	int		iParagraphBreak;
+	conversion_type	eConversionType;
+	BOOL		bHideHiddenText;
+	BOOL		bRemoveRemovedText;
+	BOOL		bUseLandscape;
+	encoding_type	eEncoding;
+	int		iPageHeight;		/* In points */
+	int		iPageWidth;		/* In points */
+	image_level_enum	eImageLevel;
+#if defined(__riscos)
+	BOOL		bAutofiletypeAllowed;
+	int		iScaleFactor;		/* As a percentage */
+#endif /* __riscos */
+} options_type;
+
+/* Property Set Storage */
+typedef struct pps_tag {
+	ULONG	ulSB;
+	ULONG	ulSize;
+} pps_type;
+typedef struct pps_info_tag {
+	pps_type	tWordDocument;	/* Text stream */
+	pps_type	tData;		/* Data stream */
+	pps_type	tTable;		/* Table stream */
+	pps_type	tSummaryInfo;	/* Summary Information */
+	pps_type	tDocSummaryInfo;/* Document Summary Information */
+	pps_type	t0Table;	/* Table 0 stream */
+	pps_type	t1Table;	/* Table 1 stream */
+} pps_info_type;
+
+/* Record of data block information */
+typedef struct data_block_tag {
+	ULONG	ulFileOffset;
+	ULONG	ulDataPos;
+	ULONG	ulLength;
+} data_block_type;
+
+/* Record of text block information */
+typedef struct text_block_tag {
+	ULONG	ulFileOffset;
+	ULONG	ulCharPos;
+	ULONG	ulLength;
+	BOOL	bUsesUnicode;	/* This block uses 16 bits per character */
+	USHORT	usPropMod;
+} text_block_type;
+
+/* Record of the document block information */
+typedef struct document_block_tag {
+	time_t	tCreateDate;		/* Unix timestamp */
+	time_t	tRevisedDate;		/* Unix timestamp */
+	USHORT	usDefaultTabWidth;	/* In twips */
+	UCHAR	ucHdrFtrSpecification;
+} document_block_type;
+
+/* Record of table-row block information */
+typedef struct row_block_tag {
+	ULONG	ulFileOffsetStart;
+	ULONG	ulFileOffsetEnd;
+	ULONG	ulCharPosStart;
+	ULONG	ulCharPosEnd;
+	short	asColumnWidth[TABLE_COLUMN_MAX+1];	/* In twips */
+	UCHAR	ucNumberOfColumns;
+	UCHAR	ucBorderInfo;
+} row_block_type;
+
+/* Various level types */
+typedef enum level_type_tag {
+	level_type_none = 0,
+	level_type_outline,
+	level_type_numbering,
+	level_type_sequence,
+	level_type_pause
+} level_type_enum;
+
+typedef enum list_id_tag {
+	no_list = 0,
+	text_list,
+	footnote_list,
+	hdrftr_list,
+	macro_list,
+	annotation_list,
+	endnote_list,
+	textbox_list,
+	hdrtextbox_list,
+	end_of_lists
+} list_id_enum;
+
+/* Linked list of style description information */
+typedef struct style_block_tag {
+	ULONG	ulFileOffset;   /* The style start with this character */
+	list_id_enum	eListID;/* The fileoffset is in this list */
+	BOOL	bNumPause;
+	BOOL	bNoRestart;	/* Don't restart by more significant levels */
+	USHORT	usIstd;		/* Current style */
+	USHORT	usIstdNext;	/* Next style unless overruled */
+	USHORT	usStartAt;	/* Number at the start of a list */
+	USHORT	usBeforeIndent;	/* Vertical indent before paragraph in twips */
+	USHORT	usAfterIndent;	/* Vertical indent after paragraph in twips */
+	USHORT	usListIndex;	/* Before Word 8 this field was not filled */
+	USHORT	usListChar;	/* Character for an itemized list (Unicode) */
+	short	sLeftIndent;	/* Left indentation in twips */
+	short	sLeftIndent1;	/* First line left indentation in twips */
+	short	sRightIndent;	/* Right indentation in twips */
+	UCHAR	ucAlignment;
+	UCHAR	ucNFC;		/* Number format code */
+	UCHAR	ucNumLevel;
+	UCHAR	ucListLevel;	/* Before Word 8 this field was not filled */
+	char	szListChar[4];	/* Character for an itemized list */
+} style_block_type;
+
+/* Font description information */
+typedef struct font_block_tag {
+	ULONG	ulFileOffset;
+	USHORT	usFontStyle;
+	USHORT	usFontSize;
+	UCHAR	ucFontNumber;
+	UCHAR	ucFontColor;
+} font_block_type;
+
+/* Picture description information */
+typedef struct picture_block_tag {
+	ULONG	ulFileOffset;
+	ULONG	ulFileOffsetPicture;
+	ULONG	ulPictureOffset;
+} picture_block_type;
+
+/* Section description information */
+typedef struct section_block_tag {
+	BOOL	bNewPage;
+	USHORT	usNeedPrevLvl;		/* Print previous level numbers */
+	USHORT	usHangingIndent;
+	UCHAR	aucNFC[9];		/* Number format code */
+	UCHAR	ucHdrFtrSpecification;	/* Which headers/footers Word < 8 */
+} section_block_type;
+
+/* Header/footer description information */
+typedef struct hdrftr_block_tag {
+	output_type	*pText;
+	long		lHeight;	/* In DrawUnits */
+} hdrftr_block_type;
+
+/* Footnote description information */
+typedef struct footnote_block_tag {
+	char		*szText;
+} footnote_block_type;
+
+/* List description information */
+typedef struct list_block_tag {
+	ULONG	ulStartAt;	/* Number at the start of a list */
+	BOOL	bNoRestart;	/* Don't restart by more significant levels */
+	USHORT	usListChar;	/* Character for an itemized list (Unicode) */
+	short	sLeftIndent;	/* Left indentation in twips */
+	UCHAR	ucNFC;		/* Number format code */
+} list_block_type;
+
+/* Types of images */
+typedef enum imagetype_tag {
+	imagetype_is_unknown = 0,
+	imagetype_is_external,
+	imagetype_is_emf,
+	imagetype_is_wmf,
+	imagetype_is_pict,
+	imagetype_is_jpeg,
+	imagetype_is_png,
+	imagetype_is_dib
+} imagetype_enum;
+
+/* Types of compression */
+typedef enum compression_tag {
+	compression_unknown = 0,
+	compression_none,
+	compression_rle4,
+	compression_rle8,
+	compression_jpeg,
+	compression_zlib
+} compression_enum;
+
+/* Image information */
+typedef struct imagedata_tag {
+	/* The type of the image */
+	imagetype_enum	eImageType;
+	/* Information from the Word document */
+	size_t	tPosition;
+	size_t	tLength;
+	int	iHorSizeScaled;		/* Size in points */
+	int	iVerSizeScaled;		/* Size in points */
+	/* Information from the image */
+	int	iWidth;			/* Size in pixels */
+	int	iHeight;		/* Size in pixels */
+	int	iComponents;		/* Number of color components */
+	UINT	uiBitsPerComponent;	/* Bits per color component */
+	BOOL	bAdobe;	/* Image includes Adobe comment marker */
+	compression_enum	eCompression;	/* Type of compression */
+	BOOL	bColorImage;	/* Is color image */
+	int	iColorsUsed;	/* 0 = uses the maximum number of colors */
+	UCHAR 	aucPalette[256][3];	/* RGB palette */
+} imagedata_type;
+
+typedef enum row_info_tag {
+	found_nothing,
+	found_a_cell,
+	found_not_a_cell,
+	found_end_of_row,
+	found_not_end_of_row
+} row_info_enum;
+
+typedef enum notetype_tag {
+	notetype_is_footnote,
+	notetype_is_endnote,
+	notetype_is_unknown
+} notetype_enum;
+
+typedef enum image_info_tag {
+	image_no_information,
+	image_minimal_information,
+	image_full_information
+} image_info_enum;
+
+#endif /* __wordtypes_h */
diff --git a/wordwin.c b/wordwin.c
new file mode 100644
index 0000000..d31b7be
--- /dev/null
+++ b/wordwin.c
@@ -0,0 +1,209 @@
+/*
+ * wordwin.c
+ * Copyright (C) 2002-2005 A.J. van Os; Released under GPL
+ *
+ * Description:
+ * Deal with the WIN internals of a MS Word file
+ */
+
+#include "antiword.h"
+
+
+/*
+ * bGetDocumentText - make a list of the text blocks of a Word document
+ *
+ * Return TRUE when succesful, otherwise FALSE
+ */
+static BOOL
+bGetDocumentText(FILE *pFile, const UCHAR *aucHeader)
+{
+	text_block_type	tTextBlock;
+	ULONG	ulBeginOfText;
+	ULONG	ulTextLen, ulFootnoteLen;
+	ULONG	ulHdrFtrLen, ulMacroLen, ulAnnotationLen;
+	UINT	uiQuickSaves;
+	USHORT	usDocStatus;
+	BOOL	bTemplate, bFastSaved, bEncrypted, bSuccess;
+
+	fail(pFile == NULL);
+	fail(aucHeader == NULL);
+
+	DBG_MSG("bGetDocumentText");
+
+	/* Get the status flags from the header */
+	usDocStatus = usGetWord(0x0a, aucHeader);
+	DBG_HEX(usDocStatus);
+	bTemplate = (usDocStatus & BIT(0)) != 0;
+	DBG_MSG_C(bTemplate, "This document is a Template");
+	bFastSaved = (usDocStatus & BIT(2)) != 0;
+	uiQuickSaves = (UINT)(usDocStatus & 0x00f0) >> 4;
+	DBG_MSG_C(bFastSaved, "This document is Fast Saved");
+	DBG_DEC_C(bFastSaved, uiQuickSaves);
+	if (bFastSaved) {
+		werr(0, "Word2: fast saved documents are not supported yet");
+		return FALSE;
+	}
+	bEncrypted = (usDocStatus & BIT(8)) != 0;
+	if (bEncrypted) {
+		werr(0, "Encrypted documents are not supported");
+		return FALSE;
+	}
+
+	/* Get length information */
+	ulBeginOfText = ulGetLong(0x18, aucHeader);
+	DBG_HEX(ulBeginOfText);
+	ulTextLen = ulGetLong(0x34, aucHeader);
+	ulFootnoteLen = ulGetLong(0x38, aucHeader);
+	ulHdrFtrLen = ulGetLong(0x3c, aucHeader);
+	ulMacroLen = ulGetLong(0x40, aucHeader);
+	ulAnnotationLen = ulGetLong(0x44, aucHeader);
+	DBG_DEC(ulTextLen);
+	DBG_DEC(ulFootnoteLen);
+	DBG_DEC(ulHdrFtrLen);
+	DBG_DEC(ulMacroLen);
+	DBG_DEC(ulAnnotationLen);
+	if (bFastSaved) {
+		bSuccess = FALSE;
+	} else {
+		tTextBlock.ulFileOffset = ulBeginOfText;
+		tTextBlock.ulCharPos = ulBeginOfText;
+		tTextBlock.ulLength = ulTextLen +
+				ulFootnoteLen +
+				ulHdrFtrLen + ulMacroLen + ulAnnotationLen;
+		tTextBlock.bUsesUnicode = FALSE;
+		tTextBlock.usPropMod = IGNORE_PROPMOD;
+		bSuccess = bAdd2TextBlockList(&tTextBlock);
+		DBG_HEX_C(!bSuccess, tTextBlock.ulFileOffset);
+		DBG_HEX_C(!bSuccess, tTextBlock.ulCharPos);
+		DBG_DEC_C(!bSuccess, tTextBlock.ulLength);
+		DBG_DEC_C(!bSuccess, tTextBlock.bUsesUnicode);
+		DBG_DEC_C(!bSuccess, tTextBlock.usPropMod);
+	}
+
+	if (bSuccess) {
+		vSplitBlockList(pFile,
+				ulTextLen,
+				ulFootnoteLen,
+				ulHdrFtrLen,
+				ulMacroLen,
+				ulAnnotationLen,
+				0,
+				0,
+				0,
+				FALSE);
+	} else {
+		vDestroyTextBlockList();
+		werr(0, "I can't find the text of this document");
+	}
+	return bSuccess;
+} /* end of bGetDocumentText */
+
+/*
+ * vGetDocumentData - make a list of the data blocks of a Word document
+ */
+static void
+vGetDocumentData(FILE *pFile, const UCHAR *aucHeader)
+{
+	data_block_type	tDataBlock;
+	options_type	tOptions;
+	ULONG	ulEndOfText, ulBeginCharInfo;
+	BOOL	bFastSaved, bHasImages, bSuccess;
+	USHORT	usDocStatus;
+
+	/* Get the options */
+	vGetOptions(&tOptions);
+
+	/* Get the status flags from the header */
+	usDocStatus = usGetWord(0x0a, aucHeader);
+	DBG_HEX(usDocStatus);
+	bFastSaved = (usDocStatus & BIT(2)) != 0;
+	bHasImages = (usDocStatus & BIT(3)) != 0;
+
+	if (!bHasImages ||
+	    tOptions.eConversionType == conversion_text ||
+	    tOptions.eConversionType == conversion_fmt_text ||
+	    tOptions.eConversionType == conversion_xml ||
+	    tOptions.eImageLevel == level_no_images) {
+		/*
+		 * No images in the document or text-only output or
+		 * no images wanted, so no data blocks will be needed
+		 */
+		vDestroyDataBlockList();
+		return;
+	}
+
+	if (bFastSaved) {
+		bSuccess = FALSE;
+	} else {
+		/* This datablock is too big, but it contains all images */
+		ulEndOfText = ulGetLong(0x1c, aucHeader);
+		DBG_HEX(ulEndOfText);
+		ulBeginCharInfo = ulGetLong(0xa0, aucHeader);
+		DBG_HEX(ulBeginCharInfo);
+		if (ulBeginCharInfo > ulEndOfText) {
+			tDataBlock.ulFileOffset = ulEndOfText;
+			tDataBlock.ulDataPos = ulEndOfText;
+			tDataBlock.ulLength = ulBeginCharInfo - ulEndOfText;
+			bSuccess = bAdd2DataBlockList(&tDataBlock);
+			DBG_HEX_C(!bSuccess, tDataBlock.ulFileOffset);
+			DBG_HEX_C(!bSuccess, tDataBlock.ulDataPos);
+			DBG_DEC_C(!bSuccess, tDataBlock.ulLength);
+		} else {
+			bSuccess = ulBeginCharInfo == ulEndOfText;
+		}
+	}
+
+	if (!bSuccess) {
+		vDestroyDataBlockList();
+		werr(0, "I can't find the data of this document");
+	}
+} /* end of vGetDocumentData */
+
+/*
+ * iInitDocumentWIN - initialize an WIN document
+ *
+ * Returns the version of Word that made the document or -1
+ */
+int
+iInitDocumentWIN(FILE *pFile, long lFilesize)
+{
+	int	iWordVersion;
+	BOOL	bSuccess;
+	USHORT	usIdent;
+	UCHAR	aucHeader[384];
+
+	fail(pFile == NULL);
+
+	if (lFilesize < 384) {
+		return -1;
+	}
+
+	/* Read the headerblock */
+	if (!bReadBytes(aucHeader, 384, 0x00, pFile)) {
+		return -1;
+	}
+	/* Get the "magic number" from the header */
+	usIdent = usGetWord(0x00, aucHeader);
+	DBG_HEX(usIdent);
+	fail(usIdent != 0xa59b &&	/* WinWord 1.x */
+		usIdent != 0xa5db);	/* WinWord 2.0 */
+	iWordVersion = iGetVersionNumber(aucHeader);
+	if (iWordVersion != 1 && iWordVersion != 2) {
+		werr(0, "This file is not from ''Win Word 1 or 2'.");
+		return -1;
+	}
+	bSuccess = bGetDocumentText(pFile, aucHeader);
+	if (bSuccess) {
+		vGetDocumentData(pFile, aucHeader);
+		vGetPropertyInfo(pFile, NULL,
+				NULL, 0, NULL, 0,
+				aucHeader, iWordVersion);
+		vSetDefaultTabWidth(pFile, NULL,
+				NULL, 0, NULL, 0,
+				aucHeader, iWordVersion);
+		vGetNotesInfo(pFile, NULL,
+				NULL, 0, NULL, 0,
+				aucHeader, iWordVersion);
+	}
+	return bSuccess ? iWordVersion : -1;
+} /* end of iInitDocumentWIN */
diff --git a/xmalloc.c b/xmalloc.c
new file mode 100644
index 0000000..b64bc44
--- /dev/null
+++ b/xmalloc.c
@@ -0,0 +1,136 @@
+/*
+ * xmalloc.c
+ * Copyright (C) 1998-2005 A.J. van Os
+ *
+ * Description:
+ * Extended malloc and friends
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "antiword.h"
+
+static char *szMessage =
+	"Memory allocation failed, unable to continue";
+#if defined(__dos) && !defined(__DJGPP__)
+static char *szDosMessage =
+	"DOS can't allocate this kind of memory, unable to continue";
+#endif /* __dos && !__DJGPP__ */
+
+
+/*
+ * xmalloc - Allocates dynamic memory
+ *
+ * See malloc(3), but unlike malloc(3) xmalloc does not return in case
+ * of error.
+ */
+void *
+xmalloc(size_t tSize)
+{
+	void	*pvTmp;
+
+	TRACE_MSG("xmalloc");
+
+	if (tSize == 0) {
+		tSize = 1;
+	}
+	pvTmp = malloc(tSize);
+	if (pvTmp == NULL) {
+		DBG_MSG("xmalloc returned NULL");
+		DBG_DEC(tSize);
+		werr(1, szMessage);
+	}
+	return pvTmp;
+} /* end of xmalloc */
+
+/*
+ * xcalloc - Allocates and zeros dynamic memory
+ *
+ * See calloc(3), but unlike calloc(3) xcalloc does not return in case of error
+ */
+void *
+xcalloc(size_t tNmemb, size_t tSize)
+{
+	void	*pvTmp;
+
+	TRACE_MSG("xcalloc");
+
+#if defined(__dos) && !defined(__DJGPP__)
+	if ((ULONG)tNmemb * (ULONG)tSize > 0xffffUL) {
+		DBG_DEC((ULONG)tNmemb * (ULONG)tSize);
+		werr(1, szDosMessage);
+	}
+#endif /* __dos && !__DJGPP__ */
+
+	if (tNmemb == 0 || tSize == 0) {
+		tNmemb = 1;
+		tSize = 1;
+	}
+	pvTmp = calloc(tNmemb, tSize);
+	if (pvTmp == NULL) {
+		DBG_MSG("xcalloc returned NULL");
+		werr(1, szMessage);
+	}
+	return pvTmp;
+} /* end of xcalloc */
+
+/*
+ * xrealloc - Changes the size of a memory object
+ *
+ * See realloc(3), but unlike realloc(3) xrealloc does not return in case
+ * of error.
+ */
+void *
+xrealloc(void *pvArg, size_t tSize)
+{
+	void	*pvTmp;
+
+	TRACE_MSG("xrealloc");
+
+	pvTmp = realloc(pvArg, tSize);
+	if (pvTmp == NULL) {
+		DBG_MSG("realloc returned NULL");
+		werr(1, szMessage);
+	}
+	return pvTmp;
+} /* end of xrealloc */
+
+/*
+ * xstrdup - Duplicate a string
+ *
+ * See strdup(3), but unlike strdup(3) xstrdup does not return in case
+ * of error.
+ *
+ * NOTE:
+ * Does not use strdup(3), because some systems don't have it.
+ */
+char *
+xstrdup(const char *szArg)
+{
+	char	*szTmp;
+
+	TRACE_MSG("xstrdup");
+
+	szTmp = xmalloc(strlen(szArg) + 1);
+	strcpy(szTmp, szArg);
+	return szTmp;
+} /* end of xstrdup */
+
+/*
+ * xfree - Deallocates dynamic memory
+ *
+ * See free(3).
+ *
+ * returns NULL;
+ * This makes p=xfree(p) possible, free memory and overwrite the pointer to it.
+ */
+void *
+xfree(void *pvArg)
+{
+	TRACE_MSG("xfree");
+
+	if (pvArg != NULL) {
+		free(pvArg);
+	}
+	return NULL;
+} /* end of xfree */
diff --git a/xml.c b/xml.c
new file mode 100644
index 0000000..92048ad
--- /dev/null
+++ b/xml.c
@@ -0,0 +1,1438 @@
+/*
+ * xml.c
+ * Copyright (C) 2002-2005 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Functions to deal with the XML/DocBook format
+ *
+ */
+
+#include <string.h>
+#include "antiword.h"
+
+
+#define vAddEndTagsUntil1(p,t)	vAddEndTagsUntil2(p,t,TAG_NOTAG)	
+
+#if defined(DEBUG)
+#define vStackTrace()	__vStackTrace(__LINE__)
+#else
+#define vStackTrace()	/* EMPTY */
+#endif /* DEBUG */
+
+/* The character set */
+static encoding_type	eEncoding = encoding_neutral;
+/* Word version */
+static int	iWordVersion = -1;
+/* Special treatment for files from Word 4/5/6 on an Apple Macintosh */
+static BOOL	bOldMacFile = FALSE;
+/* Text is emphasised */
+static BOOL	bEmphasisOpen = FALSE;
+/* Text is superscript */
+static BOOL	bSuperscriptOpen = FALSE;
+/* Text is subscript */
+static BOOL	bSubscriptOpen = FALSE;
+/* Title is open */
+static BOOL	bTitleOpen = FALSE;
+/* Table is open */
+static BOOL	bTableOpen = FALSE;
+/* Footnote is open */
+static BOOL	bFootnoteOpen = FALSE;
+/* Current paragraph level */
+static UINT	uiParagraphLevel = 0;
+/* Current list level */
+static UINT	uiListLevel = 0;
+/* Current list level is still empty */
+static BOOL	bEmptyListLevel = TRUE;
+/* Current header level */
+static USHORT	usHeaderLevelCurrent = 0;
+/* Current header level is still empty */
+static BOOL	bEmptyHeaderLevel = TRUE;
+/* Number of columns in the current table */
+static int	iTableColumnsCurrent = 0;
+/* Footnote number */
+static UINT	uiFootnoteNumber = 0;
+
+/* Constants for the stack */
+#define INITIAL_STACK_SIZE	10
+#if defined(DEBUG)
+#define EXTENSION_STACK_SIZE	 2
+#else
+#define EXTENSION_STACK_SIZE	10
+#endif /* DEBUG */
+
+/* Variables for the stack */
+static UCHAR	*aucStack = NULL;
+static size_t	tStacksize = 0;
+static size_t	tStackNextFree = 0;
+
+/* Constants for the tags */
+#define TAG_NOTAG		(UCHAR)0
+#define TAG_AUTHOR		(UCHAR)1
+#define TAG_BEGINPAGE		(UCHAR)2
+#define TAG_BOOK		(UCHAR)3
+#define TAG_BOOKINFO		(UCHAR)4
+#define TAG_CHAPTER		(UCHAR)5
+#define TAG_COLSPEC		(UCHAR)6
+#define TAG_CORPNAME		(UCHAR)7
+#define TAG_DATE		(UCHAR)8
+#define TAG_EMPHASIS		(UCHAR)9
+#define TAG_ENTRY		(UCHAR)10
+#define TAG_FILENAME		(UCHAR)11
+#define TAG_FOOTNOTE		(UCHAR)12
+#define TAG_INFORMALTABLE	(UCHAR)13
+#define TAG_ITEMIZEDLIST	(UCHAR)14
+#define TAG_LISTITEM		(UCHAR)15
+#define TAG_ORDEREDLIST		(UCHAR)16
+#define TAG_PARA		(UCHAR)17
+#define TAG_ROW			(UCHAR)18
+#define TAG_SECT1		(UCHAR)19
+#define TAG_SECT2		(UCHAR)20
+#define TAG_SECT3		(UCHAR)21
+#define TAG_SECT4		(UCHAR)22
+#define TAG_SECT5		(UCHAR)23
+#define TAG_SUBSCRIPT		(UCHAR)24
+#define TAG_SUBTITLE		(UCHAR)25
+#define TAG_SUPERSCRIPT		(UCHAR)26
+#define TAG_SURNAME		(UCHAR)27
+#define TAG_TBODY		(UCHAR)28
+#define TAG_TGROUP		(UCHAR)29
+#define TAG_TITLE		(UCHAR)30
+
+typedef struct docbooktags_tag {
+	UCHAR	ucTagnumber;
+	char	szTagname[15];
+	BOOL	bAddNewlineStart;
+	BOOL	bAddNewlineEnd;
+} docbooktags_type;
+
+static const docbooktags_type atDocBookTags[] = {
+	{	TAG_NOTAG, 		"!ERROR!",	TRUE,	TRUE	},
+	{	TAG_AUTHOR,		"author",	TRUE,	TRUE	},
+	{	TAG_BEGINPAGE,		"beginpage",	TRUE,	TRUE	},
+	{	TAG_BOOK, 		"book",		TRUE,	TRUE	},
+	{	TAG_BOOKINFO, 		"bookinfo",	TRUE,	TRUE	},
+	{	TAG_CHAPTER, 		"chapter",	TRUE,	TRUE	},
+	{	TAG_COLSPEC,		"colspec",	TRUE,	TRUE	},
+	{	TAG_CORPNAME,		"corpname",	FALSE,	FALSE	},
+	{	TAG_DATE,		"date",		FALSE,	FALSE	},
+	{	TAG_EMPHASIS,		"emphasis",	FALSE,	FALSE	},
+	{	TAG_ENTRY,		"entry",	TRUE,	TRUE	},
+	{	TAG_FILENAME,		"filename",	FALSE,	FALSE	},
+	{	TAG_FOOTNOTE,		"footnote",	FALSE,	FALSE	},
+	{	TAG_INFORMALTABLE,	"informaltable",TRUE,	TRUE	},
+	{	TAG_ITEMIZEDLIST,	"itemizedlist",	TRUE,	TRUE	},
+	{	TAG_LISTITEM,		"listitem",	TRUE,	TRUE	},
+	{	TAG_ORDEREDLIST,	"orderedlist",	TRUE,	TRUE	},
+	{	TAG_PARA, 		"para",		TRUE,	TRUE	},
+	{	TAG_ROW,		"row",		TRUE,	TRUE	},
+	{	TAG_SECT1, 		"sect1",	TRUE,	TRUE	},
+	{	TAG_SECT2, 		"sect2",	TRUE,	TRUE	},
+	{	TAG_SECT3, 		"sect3",	TRUE,	TRUE	},
+	{	TAG_SECT4, 		"sect4",	TRUE,	TRUE	},
+	{	TAG_SECT5, 		"sect5",	TRUE,	TRUE	},
+	{	TAG_SUBSCRIPT,		"subscript",	FALSE,	FALSE	},
+	{	TAG_SUBTITLE,		"subtitle",	FALSE,	FALSE	},
+	{	TAG_SUPERSCRIPT,	"superscript",	FALSE,	FALSE	},
+	{	TAG_SURNAME,		"surname",	FALSE,	FALSE	},
+	{	TAG_TBODY,		"tbody",	TRUE,	TRUE	},
+	{	TAG_TGROUP,		"tgroup",	TRUE,	TRUE	},
+	{	TAG_TITLE, 		"title",	FALSE,	FALSE	},
+};
+
+static void	vAddStartTag(diagram_type *, UCHAR, const char *);
+static void	vAddEndTag(diagram_type *, UCHAR);
+static void	vAddCombinedTag(diagram_type *, UCHAR, const char *);
+static void	vPrintChar(diagram_type *, char);
+
+
+#if defined(DEBUG)
+/*
+ * vCheckTagTable - check the tag table
+ */
+static void
+vCheckTagTable(void)
+{
+	size_t	tIndex;
+
+	for (tIndex = 0; tIndex < elementsof(atDocBookTags); tIndex++) {
+		if (tIndex != (size_t)atDocBookTags[tIndex].ucTagnumber) {
+			DBG_DEC(tIndex);
+			werr(1, "Array atDocBookTags is broken");
+		}
+	}
+} /* end of vCheckTagTable */
+
+/*
+ * __vStackTrace - show a stack trace
+ */
+static void
+__vStackTrace(int iLine)
+{
+	int	iIndex;
+
+	fprintf(stderr, "%s[%3d]:\n", __FILE__, iLine);
+
+	if (tStackNextFree == 0) {
+		fprintf(stderr, "The stack is empty\n");
+		return;
+	}
+	for (iIndex = (int)tStackNextFree - 1; iIndex >= 0; iIndex--) {
+		fprintf(stderr, "%2d: %2d: '%s'\n",
+			iIndex,
+			(int)atDocBookTags[(UINT)aucStack[iIndex]].ucTagnumber,
+			atDocBookTags[(UINT)aucStack[iIndex]].szTagname);
+	}
+} /* end of __vStackTrace */
+#endif /* DEBUG */
+
+/*
+ * vPushStack - push a tag onto the stack
+ */
+static void
+vPushStack(UCHAR ucTag)
+{
+	fail(tStackNextFree > tStacksize);
+
+	if (tStackNextFree == tStacksize) {
+		/* The stack is full; enlarge the stack */
+		tStacksize += EXTENSION_STACK_SIZE;
+		aucStack = xrealloc(aucStack, tStacksize * sizeof(UCHAR));
+		DBG_DEC(tStacksize);
+	}
+
+	fail(tStackNextFree >= tStacksize);
+
+	aucStack[tStackNextFree++] = ucTag;
+} /* end of vPushStack */
+
+/*
+ * vPopStack - pop a tag from the stack
+ */
+static UCHAR
+ucPopStack(void)
+{
+	DBG_DEC_C(tStackNextFree > tStacksize, tStackNextFree);
+	DBG_DEC_C(tStackNextFree > tStacksize, tStacksize);
+	fail(tStackNextFree > tStacksize);
+	fail(tStackNextFree == 0);
+
+	if (tStackNextFree == 0) {
+		werr(1, "The stack is empty, unable to continue");
+		return TAG_NOTAG;
+	}
+	return aucStack[--tStackNextFree];
+} /* end of ucPopStack */
+
+/*
+ * vReadStack - read a tag from the top of the stack
+ */
+static UCHAR
+ucReadStack(void)
+{
+	DBG_DEC_C(tStackNextFree > tStacksize, tStackNextFree);
+	DBG_DEC_C(tStackNextFree > tStacksize, tStacksize);
+	fail(tStackNextFree > tStacksize);
+
+	if (tStackNextFree == 0) {
+		/* The stack is empty */
+		return TAG_NOTAG;
+	}
+	return aucStack[tStackNextFree - 1];
+} /* end of ucReadStack */
+
+/*
+ * vPrintLevel - print the tag level
+ */
+static void
+vPrintLevel(FILE *pOutFile)
+{
+	size_t	tIndex;
+
+	fail(pOutFile == NULL);
+
+	for (tIndex = 0; tIndex < tStackNextFree; tIndex++) {
+		(void)putc(' ', pOutFile);
+	}
+} /* end of vPrintLevel */
+
+/*
+ * vPrintFootnote - print a footnote
+ */
+static void
+vPrintFootnote(diagram_type *pDiag, UINT uiFootnoteIndex)
+{
+	const char	*szText, *pcTmp;
+	BOOL	bSuScript;
+	UCHAR	ucTopTag;
+
+	TRACE_MSG("vPrintFootnote");
+
+	szText = szGetFootnootText(uiFootnoteIndex);
+
+	if (szText == NULL) {
+		szText = "";
+	}
+
+	/* Remove the subscript/superscript (if any) */
+	ucTopTag = ucReadStack();
+	bSuScript = ucTopTag == TAG_SUBSCRIPT || ucTopTag == TAG_SUPERSCRIPT;
+	if (bSuScript) {
+		vAddEndTag(pDiag, ucTopTag);
+	}
+
+	/* Start a footnote */
+	vAddStartTag(pDiag, TAG_FOOTNOTE, NULL);
+	vAddStartTag(pDiag, TAG_PARA, NULL);
+
+	/* Print a footnote */
+	for (pcTmp = szText; *pcTmp != '\0'; pcTmp++) {
+		if (*pcTmp == PAR_END) {
+			if (*(pcTmp + 1) != PAR_END && *(pcTmp + 1) != '\0') {
+				/* PAR_END is not empty and not last */
+				vAddEndTag(pDiag, TAG_PARA);
+				vAddStartTag(pDiag, TAG_PARA, NULL);
+			}
+		} else {
+			vPrintChar(pDiag, *pcTmp);
+		}
+	}
+
+	/* End a footnote */
+	vAddEndTag(pDiag, TAG_PARA);
+	vAddEndTag(pDiag, TAG_FOOTNOTE);
+
+	/* Repair the subscript/superscript (if any) */
+	if (bSuScript) {
+		vAddStartTag(pDiag, ucTopTag, NULL);
+	}
+} /* end of vPrintFootnote */
+
+/*
+ * vPrintChar - print a character with XML encoding
+ */
+static void
+vPrintChar(diagram_type *pDiag, char cChar)
+{
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+
+	switch (cChar) {
+	case FOOTNOTE_OR_ENDNOTE:
+		uiFootnoteNumber++;
+		vPrintFootnote(pDiag, uiFootnoteNumber - 1);
+		break;
+	case '<':
+		fprintf(pDiag->pOutFile, "%s", "&lt;");
+		break;
+	case '>':
+		fprintf(pDiag->pOutFile, "%s", "&gt;");
+		break;
+	case '&':
+		fprintf(pDiag->pOutFile, "%s", "&amp;");
+		break;
+	default:
+		(void)putc(cChar, pDiag->pOutFile);
+		break;
+	}
+} /* end of vPrintChar */
+
+/*
+ * vPrintSpecialChar - convert and print a character
+ */
+static void
+vPrintSpecialChar(diagram_type *pDiag, USHORT usChar)
+{
+	ULONG   ulChar;
+	size_t  tLen, tIndex;
+	char    szResult[4];
+
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+	fail(iWordVersion < 0);
+	fail(eEncoding == encoding_neutral);
+
+	ulChar = ulTranslateCharacters(usChar, 0, iWordVersion,
+				conversion_xml, eEncoding, bOldMacFile);
+	tLen = tUcs2Utf8(ulChar, szResult, sizeof(szResult));
+	if (tLen == 1) {
+		vPrintChar(pDiag, szResult[0]);
+	} else {
+		for (tIndex = 0; tIndex < tLen; tIndex++) {
+			(void)putc(szResult[tIndex], pDiag->pOutFile);
+		}
+	}
+} /* end of vPrintSpecialChar */
+
+/*
+ * vPrintSpecialString - convert and print a string
+ */
+static void
+vPrintSpecialString(diagram_type *pDiag, const char *szString)
+{
+	int	iIndex;
+	USHORT	usChar;
+
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+	fail(szString == NULL);
+
+	for (iIndex = 0; szString[iIndex] != '\0'; iIndex++) {
+		usChar = (USHORT)(UCHAR)szString[iIndex];
+		vPrintSpecialChar(pDiag, usChar);
+	}
+} /* end of vPrintSpecialString */
+
+/*
+ * vAddStartTag - add the specified start tag to the file
+ */
+static void
+vAddStartTag(diagram_type *pDiag, UCHAR ucTag, const char *szAttribute)
+{
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+	fail((size_t)ucTag >= elementsof(atDocBookTags));
+
+	if (atDocBookTags[(UINT)ucTag].bAddNewlineStart) {
+		fprintf(pDiag->pOutFile, "\n");
+		vPrintLevel(pDiag->pOutFile);
+	}
+
+	if (szAttribute == NULL || szAttribute[0] == '\0') {
+		fprintf(pDiag->pOutFile, "<%s>",
+			atDocBookTags[(UINT)ucTag].szTagname);
+	} else {
+		fprintf(pDiag->pOutFile, "<%s %s>",
+			atDocBookTags[(UINT)ucTag].szTagname, szAttribute);
+	}
+
+	if (atDocBookTags[(UINT)ucTag].bAddNewlineEnd) {
+		fprintf(pDiag->pOutFile, "\n");
+		pDiag->lXleft = 0;
+	}
+
+	vPushStack(ucTag);
+
+	/* Set global variables */
+	switch (ucTag) {
+	case TAG_CHAPTER:
+		usHeaderLevelCurrent = 1;
+		bEmptyHeaderLevel = TRUE;
+		break;
+	case TAG_SECT1:
+		usHeaderLevelCurrent = 2;
+		bEmptyHeaderLevel = TRUE;
+		break;
+	case TAG_SECT2:
+		usHeaderLevelCurrent = 3;
+		bEmptyHeaderLevel = TRUE;
+		break;
+	case TAG_SECT3:
+		usHeaderLevelCurrent = 4;
+		bEmptyHeaderLevel = TRUE;
+		break;
+	case TAG_SECT4:
+		usHeaderLevelCurrent = 5;
+		bEmptyHeaderLevel = TRUE;
+		break;
+	case TAG_SECT5:
+		usHeaderLevelCurrent = 6;
+		bEmptyHeaderLevel = TRUE;
+		break;
+	case TAG_TITLE:
+		fail(uiParagraphLevel != 0);
+		bTitleOpen = TRUE;
+		break;
+	case TAG_FOOTNOTE:
+		bFootnoteOpen = TRUE;
+		break;
+	case TAG_PARA:
+		fail(bTitleOpen && !bFootnoteOpen);
+		uiParagraphLevel++;
+		bEmptyHeaderLevel = FALSE;
+		break;
+	case TAG_EMPHASIS:
+		bEmphasisOpen = TRUE;
+		break;
+	case TAG_ITEMIZEDLIST:
+	case TAG_ORDEREDLIST:
+		uiListLevel++;
+		bEmptyListLevel = TRUE;
+		bEmptyHeaderLevel = FALSE;
+		break;
+	case TAG_LISTITEM:
+		bEmptyListLevel = FALSE;
+		break;
+	case TAG_SUPERSCRIPT:
+		bSuperscriptOpen = TRUE;
+		break;
+	case TAG_SUBSCRIPT:
+		bSubscriptOpen = TRUE;
+		break;
+	case TAG_INFORMALTABLE:
+		bTableOpen = TRUE;
+		bEmptyHeaderLevel = FALSE;
+		break;
+	default:
+		break;
+	}
+} /* end of vAddStartTag */
+
+/*
+ * vAddEndTag - add the specified end tag to the file
+ */
+static void
+vAddEndTag(diagram_type *pDiag, UCHAR ucTag)
+{
+	UCHAR	ucTopTag;
+
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+	fail((size_t)ucTag >= elementsof(atDocBookTags));
+
+#if defined(DEBUG)
+	ucTopTag = ucReadStack();
+	if (ucTag != ucTopTag) {
+		DBG_DEC(ucTag);
+		DBG_MSG(atDocBookTags[(UINT)ucTag].szTagname);
+		vStackTrace();
+	}
+#endif /* DEBUG */
+
+	ucTopTag = ucPopStack();
+	fail((size_t)ucTopTag >= elementsof(atDocBookTags));
+	if (ucTag != ucTopTag) {
+		DBG_DEC(ucTag);
+		DBG_DEC(ucTopTag);
+		DBG_FIXME();
+		werr(1, "Impossible tag sequence, unable to continue");
+	}
+
+	if (atDocBookTags[(UINT)ucTag].bAddNewlineEnd) {
+		fprintf(pDiag->pOutFile, "\n");
+		vPrintLevel(pDiag->pOutFile);
+	}
+
+	fprintf(pDiag->pOutFile, "</%s>", atDocBookTags[(UINT)ucTag].szTagname);
+
+	if (atDocBookTags[(UINT)ucTag].bAddNewlineStart) {
+		fprintf(pDiag->pOutFile, "\n");
+		pDiag->lXleft = 0;
+	}
+
+	/* Set global variables */
+	switch (ucTag) {
+	case TAG_CHAPTER:
+		usHeaderLevelCurrent = 0;
+		break;
+	case TAG_SECT1:
+		usHeaderLevelCurrent = 1;
+		break;
+	case TAG_SECT2:
+		usHeaderLevelCurrent = 2;
+		break;
+	case TAG_SECT3:
+		usHeaderLevelCurrent = 3;
+		break;
+	case TAG_SECT4:
+		usHeaderLevelCurrent = 4;
+		break;
+	case TAG_SECT5:
+		usHeaderLevelCurrent = 5;
+		break;
+	case TAG_TITLE:
+		bTitleOpen = FALSE;
+		break;
+	case TAG_FOOTNOTE:
+		bFootnoteOpen = FALSE;
+		break;
+	case TAG_PARA:
+		uiParagraphLevel--;
+		break;
+	case TAG_EMPHASIS:
+		bEmphasisOpen = FALSE;
+		break;
+	case TAG_SUPERSCRIPT:
+		bSuperscriptOpen = FALSE;
+		break;
+	case TAG_ITEMIZEDLIST:
+	case TAG_ORDEREDLIST:
+		uiListLevel--;
+		break;
+	case TAG_SUBSCRIPT:
+		bSubscriptOpen = FALSE;
+		break;
+	case TAG_INFORMALTABLE:
+		bTableOpen = FALSE;
+		iTableColumnsCurrent = 0;
+		break;
+	default:
+		break;
+	}
+} /* end of vAddEndTag */
+
+/*
+ * vAddEndTagOptional - add the specified end tag to the file if needed
+ */
+static void
+vAddEndTagOptional(diagram_type *pDiag, UCHAR ucTag)
+{
+	UCHAR	ucTopTag;
+
+	ucTopTag = ucReadStack();
+	if (ucTag == ucTopTag) {
+		vAddEndTag(pDiag, ucTag);
+	}
+} /* end of vAddEndTagOptional */
+
+/*
+ * vAddCombinedTag - add the specified start and end tag to the file
+ */
+static void
+vAddCombinedTag(diagram_type *pDiag, UCHAR ucTag, const char *szAttribute)
+{
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+	fail((size_t)ucTag >= elementsof(atDocBookTags));
+
+	if (atDocBookTags[(UINT)ucTag].bAddNewlineStart) {
+		fprintf(pDiag->pOutFile, "\n");
+		vPrintLevel(pDiag->pOutFile);
+	}
+
+	if (szAttribute == NULL || szAttribute[0] == '\0') {
+		fprintf(pDiag->pOutFile, "<%s/>",
+			atDocBookTags[(UINT)ucTag].szTagname);
+	} else {
+		fprintf(pDiag->pOutFile, "<%s %s/>",
+			atDocBookTags[(UINT)ucTag].szTagname, szAttribute);
+	}
+
+	if (atDocBookTags[(UINT)ucTag].bAddNewlineStart) {
+		fprintf(pDiag->pOutFile, "\n");
+		pDiag->lXleft = 0;
+	}
+} /* end of vAddCombinedTag */
+
+/*
+ * vAddEndTagsUntil2 - add end tags until one the specified tags is seen
+ */
+static void
+vAddEndTagsUntil2(diagram_type *pDiag, UCHAR ucTag1, UCHAR ucTag2)
+{
+	UCHAR	ucTopTag;
+
+	do {
+		ucTopTag = ucReadStack();
+		switch (ucTopTag) {
+                case TAG_CHAPTER:
+                case TAG_SECT1:
+                case TAG_SECT2:
+                case TAG_SECT3:
+                case TAG_SECT4:
+                case TAG_SECT5:
+			if (bEmptyHeaderLevel) {
+				/*
+				 * An empty chapter is legal in Word,
+				 * but not in DocBook.
+				 */
+				vAddCombinedTag(pDiag, TAG_PARA, NULL);
+				bEmptyHeaderLevel = FALSE;
+			}
+			break;
+		case TAG_ITEMIZEDLIST:
+		case TAG_ORDEREDLIST:
+			if (bEmptyListLevel) {
+				/*
+				 * A list without items is legal in Word,
+				 * but not in DocBook. (Nor are empty items)
+				 */
+				vAddStartTag(pDiag, TAG_LISTITEM, NULL);
+				vAddCombinedTag(pDiag, TAG_PARA, NULL);
+				vAddEndTag(pDiag, TAG_LISTITEM);
+				bEmptyListLevel = FALSE;
+			}
+			break;
+		default:
+			break;
+		}
+		vAddEndTag(pDiag, ucTopTag);
+	} while (ucTopTag != ucTag1 && ucTopTag != ucTag2);
+} /* end of vAddEndTagsUntil2 */
+
+/*
+ * vCreateBookIntro - create title and bookinfo
+ */
+void
+vCreateBookIntro(diagram_type *pDiag, int iVersion)
+{
+	const char	*szTitle, *szSubject, *szAuthor;
+	const char	*szLastSaveDtm, *szCompany;
+	const char	*szLanguage;
+	char		szTmp[13];
+
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+	fail(iVersion < 0);
+	fail(eEncoding == encoding_neutral);
+
+	iWordVersion = iVersion;
+	bOldMacFile = bIsOldMacFile();
+	szTitle = szGetTitle();
+	szSubject = szGetSubject();
+	szAuthor = szGetAuthor();
+	szLastSaveDtm = szGetLastSaveDtm();
+	szCompany = szGetCompany();
+
+	/* Start Book */
+	szLanguage = szGetLanguage();
+	if (szLanguage != NULL) {
+		DBG_MSG(szLanguage);
+		sprintf(szTmp, "lang='%.5s'", szLanguage);
+		szLanguage = szTmp;
+	}
+	vAddStartTag(pDiag, TAG_BOOK, szLanguage);
+
+	/* Book title */
+	if (szTitle != NULL && szTitle[0] != '\0') {
+		vAddStartTag(pDiag, TAG_TITLE, NULL);
+		vPrintSpecialString(pDiag, szTitle);
+		vAddEndTag(pDiag, TAG_TITLE);
+	}
+	/* Bookinfo */
+	if ((szTitle != NULL && szTitle[0] != '\0') ||
+	    (szSubject != NULL && szSubject[0] != '\0') ||
+	    (szAuthor != NULL && szAuthor[0] != '\0') ||
+	    (szLastSaveDtm != NULL && szLastSaveDtm[0] != '\0') ||
+	    (szCompany != NULL && szCompany[0] != '\0')) {
+		vAddStartTag(pDiag, TAG_BOOKINFO, NULL);
+		if (szTitle != NULL && szTitle[0] != '\0') {
+			vAddStartTag(pDiag, TAG_TITLE, NULL);
+			vPrintSpecialString(pDiag, szTitle);
+			vAddEndTag(pDiag, TAG_TITLE);
+		}
+		if (szSubject != NULL && szSubject[0] != '\0') {
+			vAddStartTag(pDiag, TAG_SUBTITLE, NULL);
+			vPrintSpecialString(pDiag, szSubject);
+			vAddEndTag(pDiag, TAG_SUBTITLE);
+		}
+		if (szAuthor != NULL && szAuthor[0] != '\0') {
+			vAddStartTag(pDiag, TAG_AUTHOR, NULL);
+			vAddStartTag(pDiag, TAG_SURNAME, NULL);
+			vPrintSpecialString(pDiag, szAuthor);
+			vAddEndTag(pDiag, TAG_SURNAME);
+			vAddEndTag(pDiag, TAG_AUTHOR);
+		}
+		if (szLastSaveDtm != NULL && szLastSaveDtm[0] != '\0') {
+			vAddStartTag(pDiag, TAG_DATE, NULL);
+			vPrintSpecialString(pDiag, szLastSaveDtm);
+			vAddEndTag(pDiag, TAG_DATE);
+		}
+		if (szCompany != NULL && szCompany[0] != '\0') {
+			vAddStartTag(pDiag, TAG_CORPNAME, NULL);
+			vPrintSpecialString(pDiag, szCompany);
+			vAddEndTag(pDiag, TAG_CORPNAME);
+		}
+		vAddEndTag(pDiag, TAG_BOOKINFO);
+	}
+} /* end of vCreateBookIntro */
+
+/*
+ * vPrologueXML - perform the XML initialization
+ */
+void
+vPrologueXML(diagram_type *pDiag, const options_type *pOptions)
+{
+
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+	fail(pOptions == NULL);
+
+#if defined(DEBUG)
+	vCheckTagTable();
+#endif /* DEBUG */
+
+	/* Set global variables to their start values */
+	eEncoding = pOptions->eEncoding;
+	bEmphasisOpen = FALSE;
+	bSuperscriptOpen = FALSE;
+	bSubscriptOpen = FALSE;
+	bTitleOpen = FALSE;
+	bTableOpen = FALSE;
+	bFootnoteOpen = FALSE;
+	uiParagraphLevel = 0;
+	uiListLevel = 0;
+	bEmptyListLevel = TRUE;
+	usHeaderLevelCurrent = 0;
+	bEmptyHeaderLevel = TRUE;
+	iTableColumnsCurrent = 0;
+	uiFootnoteNumber = 0;
+
+	pDiag->lXleft = 0;
+	pDiag->lYtop = 0;
+
+	/* Create an empty stack */
+	tStacksize = INITIAL_STACK_SIZE;
+	aucStack = xcalloc(tStacksize, sizeof(UCHAR));
+	tStackNextFree = 0;
+} /* end of vPrologueXML */
+
+/*
+ * vEpilogueXML - clean up after everything is done
+ */
+void
+vEpilogueXML(diagram_type *pDiag)
+{
+	vStackTrace();
+
+	vAddEndTagsUntil1(pDiag, TAG_BOOK);
+
+	vStackTrace();
+
+	/* Destroy the stack */
+	fail(tStackNextFree != 0);
+	tStacksize = 0;
+	aucStack = xfree(aucStack);
+	tStackNextFree = 0;
+} /* end of vEpilogueXML */
+
+/*
+ * vPrintXML - print a XML string
+ */
+static void
+vPrintXML(diagram_type *pDiag, const char *szString, size_t tStringLength,
+		USHORT usFontstyle)
+{
+	const char	*szAttr;
+	int	iCount;
+	size_t	tNextFree;
+	BOOL	bNotReady, bEmphasisNew, bSuperscriptNew, bSubscriptNew;
+	UCHAR	ucTopTag, aucStorage[3];
+
+	fail(szString == NULL);
+
+	if (szString == NULL || szString[0] == '\0' || tStringLength == 0) {
+		return;
+	}
+
+	if (tStringLength == 1 && szString[0] == FOOTNOTE_OR_ENDNOTE) {
+		/* Don't do anything special for just a single footnote */
+		bEmphasisNew = FALSE;
+		bSuperscriptNew = FALSE;
+		bSubscriptNew = FALSE;
+	} else {
+		/* Situation normal */
+		bEmphasisNew = bIsBold(usFontstyle) ||
+				bIsItalic(usFontstyle) ||
+				bIsUnderline(usFontstyle) ||
+				bIsStrike(usFontstyle);
+		bSuperscriptNew = bIsSuperscript(usFontstyle);
+		bSubscriptNew = bIsSubscript(usFontstyle);
+	}
+
+	/* End what has to be ended (or more to keep the stack happy) */
+	tNextFree = 0;
+	bNotReady = TRUE;
+	do {
+		ucTopTag = ucReadStack();
+		switch (ucTopTag) {
+		case TAG_EMPHASIS:
+			fail(!bEmphasisOpen);
+			if (bEmphasisNew) {
+				aucStorage[tNextFree++] = ucTopTag;
+			}
+			vAddEndTag(pDiag, ucTopTag);
+			break;
+		case TAG_SUPERSCRIPT:
+			fail(!bSuperscriptOpen);
+			if (bSuperscriptNew) {
+				aucStorage[tNextFree++] = ucTopTag;
+			}
+			vAddEndTag(pDiag, ucTopTag);
+			break;
+		case TAG_SUBSCRIPT:
+			fail(!bSubscriptOpen);
+			if (bSubscriptNew) {
+				aucStorage[tNextFree++] = ucTopTag;
+			}
+			vAddEndTag(pDiag, ucTopTag);
+			break;
+		default:
+			bNotReady = FALSE;
+			break;
+		}
+		fail(tNextFree > elementsof(aucStorage));
+		fail(bNotReady && tNextFree == elementsof(aucStorage));
+	} while (bNotReady);
+
+	/* Just te make sure */
+	vStartOfParagraphXML(pDiag, 1);
+
+	/* Restart to keep the stack happy */
+	for (iCount = (int)tNextFree - 1; iCount > 0; iCount--) {
+		vAddStartTag(pDiag, aucStorage[iCount], NULL);
+	}
+
+	/* Start what has to be started */
+	if (bEmphasisNew && !bEmphasisOpen) {
+		if (bIsBold(usFontstyle)) {
+			szAttr = "role='bold'";
+		} else if (bIsItalic(usFontstyle)) {
+			szAttr = NULL;
+		} else if (bIsUnderline(usFontstyle)) {
+			szAttr = "role='underline'";
+		} else if (bIsStrike(usFontstyle)) {
+			szAttr = "role='strikethrough'";
+		} else {
+			szAttr = NULL;
+		}
+		vAddStartTag(pDiag, TAG_EMPHASIS, szAttr);
+	}
+	if (bSuperscriptNew && !bSuperscriptOpen) {
+		vAddStartTag(pDiag, TAG_SUPERSCRIPT, NULL);
+	}
+	if (bSubscriptNew && !bSubscriptOpen) {
+		vAddStartTag(pDiag, TAG_SUBSCRIPT, NULL);
+	}
+
+	/* The print the string */
+	for (iCount = 0; iCount < (int)tStringLength; iCount++) {
+		vPrintChar(pDiag, szString[iCount]);
+	}
+} /* end of vPrintXML */
+
+/*
+ * vMove2NextLineXML - move to the next line
+ */
+void
+vMove2NextLineXML(diagram_type *pDiag)
+{
+	fail(pDiag == NULL);
+
+	/*
+	if (uiParagraphLevel != 0) {
+		We need something like HTML's <BR> tag
+	}
+	*/
+} /* end of vMove2NextLineXML */
+
+/*
+ * vSubstringXML - put a sub string into a diagram
+ */
+void
+vSubstringXML(diagram_type *pDiag,
+	const char *szString, size_t tStringLength, long lStringWidth,
+	USHORT usFontstyle)
+{
+	fail(pDiag == NULL || szString == NULL);
+	fail(pDiag->pOutFile == NULL);
+	fail(pDiag->lXleft < 0);
+	fail(tStringLength != strlen(szString));
+
+	if (szString[0] == '\0' || tStringLength == 0) {
+		return;
+	}
+
+	vPrintXML(pDiag, szString, tStringLength, usFontstyle);
+	pDiag->lXleft += lStringWidth;
+} /* end of vSubstringXML */
+
+/*
+ * Create an start of a paragraph
+ * Only works on paragraph level one, because Word doesn't allow paragraphs
+ * in paragraphs. Other paragraph levels result from DocBooks special needs.
+ */
+void
+vStartOfParagraphXML(diagram_type *pDiag, UINT uiMaxLevel)
+{
+	fail(pDiag == NULL);
+
+	if (uiParagraphLevel >= uiMaxLevel || bTitleOpen) {
+		/* In Word a title is just a paragraph */
+		return;
+	}
+	if (uiListLevel != 0 && bEmptyListLevel) {
+		/* No paragraphs in a list before the first listitem */
+		return;
+	}
+	if (usHeaderLevelCurrent == 0) {
+		/* No paragraphs without an open header */
+		vAddStartTag(pDiag, TAG_CHAPTER, NULL);
+		/* Dummy title */
+		vAddCombinedTag(pDiag, TAG_TITLE, NULL);
+	}
+	vAddStartTag(pDiag, TAG_PARA, NULL);
+} /* end of vStartOfParagraphXML */
+
+/*
+ * Create an end of a paragraph
+ * Only for paragraph level one and for titles
+ */
+void
+vEndOfParagraphXML(diagram_type *pDiag, UINT uiMaxLevel)
+{
+	UCHAR	ucTopTag;
+
+	fail(pDiag == NULL);
+
+	if (uiParagraphLevel > uiMaxLevel) {
+		DBG_DEC(uiParagraphLevel);
+		return;
+	}
+
+	for(;;) {
+		ucTopTag = ucReadStack();
+		switch (ucTopTag) {
+		case TAG_EMPHASIS:
+			fail(!bEmphasisOpen);
+			vAddEndTag(pDiag, TAG_EMPHASIS);
+			break;
+		case TAG_SUPERSCRIPT:
+			fail(!bSuperscriptOpen);
+			vAddEndTag(pDiag, TAG_SUPERSCRIPT);
+			break;
+		case TAG_SUBSCRIPT:
+			fail(!bSubscriptOpen);
+			vAddEndTag(pDiag, TAG_SUBSCRIPT);
+			break;
+		case TAG_TITLE:
+			fail(!bTitleOpen);
+			vAddEndTag(pDiag, TAG_TITLE);
+			return;
+		case TAG_PARA:
+			fail(uiParagraphLevel == 0);
+			vAddEndTag(pDiag, TAG_PARA);
+			return;
+		case TAG_TBODY:
+		case TAG_TGROUP:
+		case TAG_INFORMALTABLE:
+			fail(!bTableOpen);
+			vAddEndTag(pDiag, ucTopTag);
+			break;
+		case TAG_NOTAG:
+			DBG_FIXME();
+			werr(1, "Impossible tag sequence, unable to continue");
+			break;
+		default:
+			DBG_DEC(ucTopTag);
+			DBG_MSG_C((size_t)ucTopTag < elementsof(atDocBookTags),
+				atDocBookTags[(UINT)ucTopTag].szTagname);
+			return;
+		}
+	}
+} /* end of vEndOfParagraphXML */
+
+/*
+ * Create an end of a page
+ */
+void
+vEndOfPageXML(diagram_type *pDiag)
+{
+	if (bTableOpen || usHeaderLevelCurrent == 0) {
+		/* No beginpage in a table or outside a chapter */
+		return;
+	}
+	if (bTitleOpen) {
+		/* A beginpage is not allowed when in a title */
+		/* So start a new paragraph */
+		vEndOfParagraphXML(pDiag, UINT_MAX);
+		vStartOfParagraphXML(pDiag, UINT_MAX);
+		return;
+	}
+	vAddCombinedTag(pDiag, TAG_BEGINPAGE, NULL);
+} /* end of vEndOfPageXML */
+
+/*
+ * vCloseHeaderLevels - close the specified header levels
+ */
+static void
+vCloseHeaderLevels(diagram_type *pDiag, USHORT usIstd)
+{
+	BOOL	bNotReady;
+	UCHAR	ucTopTag;
+
+	DBG_MSG("vCloseHeaderLevels");
+	DBG_DEC(usIstd);
+	DBG_DEC(usHeaderLevelCurrent);
+
+	vStackTrace();
+
+	bNotReady = TRUE;
+	do {
+		ucTopTag = ucReadStack();
+		switch (ucTopTag) {
+		case TAG_TITLE:
+		case TAG_PARA:
+			vAddEndTag(pDiag, ucTopTag);
+			break;
+		default:
+			bNotReady = FALSE;
+			break;
+		}
+	} while (bNotReady);
+
+	vStackTrace();
+
+	while (usHeaderLevelCurrent >= usIstd) {
+		if (bEmptyHeaderLevel) {
+			vAddCombinedTag(pDiag, TAG_PARA, NULL);
+			bEmptyHeaderLevel = FALSE;
+		}
+		switch (usHeaderLevelCurrent) {
+		case 1: vAddEndTag(pDiag, TAG_CHAPTER); break;
+		case 2: vAddEndTag(pDiag, TAG_SECT1); break;
+		case 3: vAddEndTag(pDiag, TAG_SECT2); break;
+		case 4: vAddEndTag(pDiag, TAG_SECT3); break;
+		case 5: vAddEndTag(pDiag, TAG_SECT4); break;
+		case 6: vAddEndTag(pDiag, TAG_SECT5); break;
+		default:
+			DBG_DEC(usHeaderLevelCurrent);
+			DBG_FIXME();
+			return;
+		}
+	}
+
+	DBG_DEC(usHeaderLevelCurrent);
+
+	vStackTrace();
+} /* end of vCloseHeaderLevels */
+
+/*
+ * vSetHeadersXML - set the headers
+ */
+void
+vSetHeadersXML(diagram_type *pDiag, USHORT usIstd)
+{
+	fail(pDiag == NULL);
+
+	if (usIstd == 0 || usIstd > 6) {
+		DBG_DEC_C(usIstd != 0 && usIstd <= 9, usIstd);
+		return;
+	}
+	DBG_DEC(usIstd);
+
+	if (bTableOpen || uiListLevel != 0) {
+		/* No headers when you're in a table or in a list */
+		return;
+	}
+
+	/* Close levels */
+	vCloseHeaderLevels(pDiag, usIstd);
+
+	DBG_DEC(usHeaderLevelCurrent);
+
+	/* Open levels */
+	while (usHeaderLevelCurrent < usIstd) {
+		switch (usHeaderLevelCurrent) {
+		case 0: vAddStartTag(pDiag, TAG_CHAPTER, NULL); break;
+		case 1: vAddStartTag(pDiag, TAG_SECT1, NULL); break;
+		case 2: vAddStartTag(pDiag, TAG_SECT2, NULL); break;
+		case 3: vAddStartTag(pDiag, TAG_SECT3, NULL); break;
+		case 4: vAddStartTag(pDiag, TAG_SECT4, NULL); break;
+		case 5: vAddStartTag(pDiag, TAG_SECT5, NULL); break;
+		default:
+			DBG_DEC(usHeaderLevelCurrent);
+			DBG_FIXME();
+			return;
+		}
+		fail(usIstd == 0);
+		/* The next paragraph should be a title */
+		if (usHeaderLevelCurrent < usIstd) {
+			/* This chapter level is not in the Word document */
+			vAddCombinedTag(pDiag, TAG_TITLE, NULL);
+		} else {
+			vAddStartTag(pDiag, TAG_TITLE, NULL);
+		}
+	}
+} /* end of vSetHeadersXML */
+
+/*
+ * Create a start of a list
+ */
+void
+vStartOfListXML(diagram_type *pDiag, UCHAR ucNFC, BOOL bIsEndOfTable)
+{
+	const char	*szAttr;
+	UCHAR		ucTag;
+
+	fail(pDiag == NULL);
+
+	if (bIsEndOfTable) {
+		/* FIXME: until a list in a table is allowed */
+		vEndOfTableXML(pDiag);
+	}
+
+	if (bTableOpen) {
+		/* FIXME: a list in a table should be allowed */
+		return;
+	}
+
+	if (usHeaderLevelCurrent == 0) {
+		/* No list without an open header */
+		vAddStartTag(pDiag, TAG_CHAPTER, NULL);
+		/* Dummy title */
+		vAddCombinedTag(pDiag, TAG_TITLE, NULL);
+	}
+
+	switch (ucNFC) {
+	case LIST_ARABIC_NUM:
+	case LIST_ORDINAL_NUM:
+	case LIST_NUMBER_TXT:
+	case LIST_ORDINAL_TXT:
+	case LIST_OUTLINE_NUM:
+		ucTag = TAG_ORDEREDLIST;
+		szAttr = "numeration='arabic'";
+		break;
+	case LIST_UPPER_ROMAN:
+		ucTag = TAG_ORDEREDLIST;
+		szAttr = "numeration='upperroman'";
+		break;
+	case LIST_LOWER_ROMAN:
+		ucTag = TAG_ORDEREDLIST;
+		szAttr = "numeration='lowerroman'";
+		break;
+	case LIST_UPPER_ALPHA:
+		ucTag = TAG_ORDEREDLIST;
+		szAttr = "numeration='upperalpha'";
+		break;
+	case LIST_LOWER_ALPHA:
+		ucTag = TAG_ORDEREDLIST;
+		szAttr = "numeration='loweralpha'";
+		break;
+	case LIST_SPECIAL:
+	case LIST_SPECIAL2:
+	case LIST_BULLETS:
+		ucTag = TAG_ITEMIZEDLIST;
+		szAttr = "mark='bullet'";
+		break;
+	default:
+		ucTag = TAG_ORDEREDLIST;
+		szAttr = "numeration='arabic'";
+		DBG_HEX(ucNFC);
+		DBG_FIXME();
+		break;
+	}
+	vAddStartTag(pDiag, ucTag, szAttr);
+} /* end of vStartOfListXML */
+
+/*
+ * Create an end of a list
+ */
+void
+vEndOfListXML(diagram_type *pDiag)
+{
+	fail(pDiag == NULL);
+
+	if (bTableOpen) {
+		/* FIXME: a list in a table should be allowed */
+		return;
+	}
+
+	if (uiListLevel != 0) {
+		vStackTrace();
+		vAddEndTagsUntil2(pDiag, TAG_ITEMIZEDLIST, TAG_ORDEREDLIST);
+		vStackTrace();
+	}
+} /* end of vEndOfListXML */
+
+/*
+ * Create a start of a list item
+ */
+void
+vStartOfListItemXML(diagram_type *pDiag, BOOL bNoMarks)
+{
+	const char	*szAttr;
+	UCHAR	ucTopTag;
+
+	fail(pDiag == NULL);
+
+	if (bTableOpen) {
+		/* FIXME: a list in a table should be allowed */
+		return;
+	}
+
+	ucTopTag = ucReadStack();
+	if (ucTopTag != TAG_ITEMIZEDLIST && ucTopTag != TAG_ORDEREDLIST) {
+		/* Must end a previous list item first */
+		vAddEndTagsUntil1(pDiag, TAG_LISTITEM);
+	}
+
+	DBG_DEC_C(ucReadStack() != TAG_ITEMIZEDLIST &&
+		ucReadStack() != TAG_ORDEREDLIST, ucReadStack());
+
+	/* Start a new list item */
+	szAttr = bNoMarks ? "override='none'" : NULL;
+	vAddStartTag(pDiag, TAG_LISTITEM, szAttr);
+	/* Start a new paragraph (independant of level) */
+	vAddStartTag(pDiag, TAG_PARA, NULL);
+} /* end of vStartOfListItemXML */
+
+/*
+ * Create a start of a table
+ */
+static void
+vStartOfTable(diagram_type *pDiag, UCHAR ucBorderInfo)
+{
+	const char	*szFrame;
+	BOOL	bNotReady;
+	UCHAR	ucTopTag;
+	char	cColSep, cRowSep;
+	char	szAttr[40];
+
+	fail(pDiag == NULL);
+
+	/* Close elements that cannot contain a table */
+	bNotReady = TRUE;
+	do {
+		ucTopTag = ucReadStack();
+		switch (ucTopTag) {
+		case TAG_TITLE:
+			fail(!bTitleOpen);
+			vAddEndTag(pDiag, TAG_TITLE);
+			break;
+		case TAG_EMPHASIS:
+			fail(!bEmphasisOpen);
+			vAddEndTag(pDiag, TAG_EMPHASIS);
+			break;
+		case TAG_SUPERSCRIPT:
+			fail(!bSuperscriptOpen);
+			vAddEndTag(pDiag, TAG_SUPERSCRIPT);
+			break;
+		case TAG_SUBSCRIPT:
+			fail(!bSubscriptOpen);
+			vAddEndTag(pDiag, TAG_SUBSCRIPT);
+			break;
+		default:
+			bNotReady = FALSE;
+			break;
+		}
+	} while (bNotReady);
+
+	/* Create table attributes */
+	switch (ucBorderInfo) {
+	case TABLE_BORDER_TOP:
+		szFrame = "top";
+		break;
+	case TABLE_BORDER_LEFT|TABLE_BORDER_RIGHT:
+		szFrame = "sides";
+		break;
+	case TABLE_BORDER_TOP|TABLE_BORDER_BOTTOM:
+		szFrame = "topbot";
+		break;
+	case TABLE_BORDER_BOTTOM:
+		szFrame = "bottom";
+		break;
+	case TABLE_BORDER_TOP|TABLE_BORDER_LEFT|
+	     TABLE_BORDER_BOTTOM|TABLE_BORDER_RIGHT:
+		szFrame = "all";
+		break;
+	default:
+		szFrame = "none";
+		break;
+	}
+	cColSep = bIsTableBorderLeft(ucBorderInfo) ||
+		  bIsTableBorderRight(ucBorderInfo) ? '1' : '0';
+	cRowSep = bIsTableBorderTop(ucBorderInfo) ||
+		  bIsTableBorderBottom(ucBorderInfo) ? '1' : '0';
+
+	sprintf(szAttr, "frame='%.6s' colsep='%c' rowsep='%c'",
+			szFrame, cColSep, cRowSep);
+
+	if (usHeaderLevelCurrent == 0) {
+		/* No table without an open header */
+		vAddStartTag(pDiag, TAG_CHAPTER, NULL);
+		/* Dummy title */
+		vAddCombinedTag(pDiag, TAG_TITLE, NULL);
+	}
+	vAddStartTag(pDiag, TAG_INFORMALTABLE, szAttr);
+} /* end of vStartOfTable */
+
+/*
+ * Create a start of a table group
+ */
+static void
+vStartOfTableGroup(diagram_type *pDiag,
+	int iNbrOfColumns, const short *asColumnWidth)
+{
+	double	dWidth;
+	int	iIndex;
+	char	szCols[6 + 3 * sizeof(int) + 1 + 1];
+	char	szColWidth[10 + 3 * sizeof(short) + 3 + 3 + 1];
+
+	fail(iNbrOfColumns < 1);
+	fail(asColumnWidth == NULL);
+
+	sprintf(szCols, "cols='%d'", iNbrOfColumns);
+	vAddStartTag(pDiag, TAG_TGROUP, szCols);
+
+	for (iIndex= 0; iIndex < iNbrOfColumns; iIndex++) {
+		fail(asColumnWidth[iIndex] < 0);
+		dWidth = dTwips2Points(asColumnWidth[iIndex]);
+		if (dWidth <= 1.0) {
+			strcpy(szColWidth, "colwidth='1.00pt'");
+		} else {
+			sprintf(szColWidth, "colwidth='%.2fpt'", dWidth);
+		}
+		vAddCombinedTag(pDiag, TAG_COLSPEC, szColWidth);
+	}
+} /* end of vStartOfTableGroup */
+
+/*
+ * Create an end of a table
+ */
+void
+vEndOfTableXML(diagram_type *pDiag)
+{
+	fail(pDiag == NULL);
+
+	if (bTableOpen) {
+		vAddEndTag(pDiag, TAG_TBODY);
+		vAddEndTag(pDiag, TAG_TGROUP);
+		vAddEndTag(pDiag, TAG_INFORMALTABLE);
+	}
+} /* end of vEndOfTableXML */
+
+/*
+ * Add a table row
+ */
+void
+vAddTableRowXML(diagram_type *pDiag, char **aszColTxt,
+	int iNbrOfColumns, const short *asColumnWidth, UCHAR ucBorderInfo)
+{
+	size_t	tCount, tStringLength;
+	int	iIndex;
+
+	fail(pDiag == NULL);
+	fail(pDiag->pOutFile == NULL);
+	fail(aszColTxt == NULL);
+	fail(iNbrOfColumns < 1);
+	fail(asColumnWidth == NULL);
+
+	if (iNbrOfColumns != iTableColumnsCurrent) {
+		/* A new number of columns */
+		/* End the old table body and table group (if they exist) */
+		vAddEndTagOptional(pDiag, TAG_TBODY);
+		vAddEndTagOptional(pDiag, TAG_TGROUP);
+		if (!bTableOpen) {
+			/* No table yet. Start a new table */
+			vStartOfTable(pDiag, ucBorderInfo);
+		}
+		/* Start a new table group and a new table body */
+		vStartOfTableGroup(pDiag, iNbrOfColumns, asColumnWidth);
+		vAddStartTag(pDiag, TAG_TBODY, NULL);
+		iTableColumnsCurrent = iNbrOfColumns;
+	}
+
+	/* Add the table row */
+	vAddStartTag(pDiag, TAG_ROW, NULL);
+	for (iIndex = 0; iIndex < iNbrOfColumns; iIndex++) {
+		/* Add a table cell */
+		fail(aszColTxt[iIndex] == NULL);
+		vAddStartTag(pDiag, TAG_ENTRY, NULL);
+		tStringLength = strlen(aszColTxt[iIndex]);
+		for (tCount = 0; tCount < tStringLength; tCount++) {
+			vPrintChar(pDiag, aszColTxt[iIndex][tCount]);
+		}
+		vAddEndTag(pDiag, TAG_ENTRY);
+	}
+	vAddEndTag(pDiag, TAG_ROW);
+} /* end of vAddTableRowXML */