]> git.saurik.com Git - wxWidgets.git/commitdiff
Corrected memory.cpp checkpoint bug; added Tex2RTF
authorJulian Smart <julian@anthemion.co.uk>
Sat, 2 Jan 1999 00:45:39 +0000 (00:45 +0000)
committerJulian Smart <julian@anthemion.co.uk>
Sat, 2 Jan 1999 00:45:39 +0000 (00:45 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@1306 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

60 files changed:
distrib/msw/generic.rsp
distrib/msw/zipdist.bat
docs/latex/wx/window.tex
samples/bombs/makefile.unx
src/common/memory.cpp
utils/tex2rtf/docs/back.gif [new file with mode: 0644]
utils/tex2rtf/docs/books.gif [new file with mode: 0644]
utils/tex2rtf/docs/bullet.bmp [new file with mode: 0644]
utils/tex2rtf/docs/contents.gif [new file with mode: 0644]
utils/tex2rtf/docs/fancyhea.sty [new file with mode: 0644]
utils/tex2rtf/docs/forward.gif [new file with mode: 0644]
utils/tex2rtf/docs/install.txt [new file with mode: 0644]
utils/tex2rtf/docs/makeidx.sty [new file with mode: 0644]
utils/tex2rtf/docs/mysober.sty [new file with mode: 0644]
utils/tex2rtf/docs/mytitle.sty [new file with mode: 0644]
utils/tex2rtf/docs/notes.txt [new file with mode: 0644]
utils/tex2rtf/docs/psbox.tex [new file with mode: 0644]
utils/tex2rtf/docs/readme.txt [new file with mode: 0644]
utils/tex2rtf/docs/refs.bib [new file with mode: 0644]
utils/tex2rtf/docs/screen.bmp [new file with mode: 0644]
utils/tex2rtf/docs/screen.gif [new file with mode: 0644]
utils/tex2rtf/docs/screen.shg [new file with mode: 0644]
utils/tex2rtf/docs/tex2rtf.hpj [new file with mode: 0644]
utils/tex2rtf/docs/tex2rtf.ini [new file with mode: 0644]
utils/tex2rtf/docs/tex2rtf.tex [new file with mode: 0644]
utils/tex2rtf/docs/tex2rtf.wmf [new file with mode: 0644]
utils/tex2rtf/docs/texhelp.sty [new file with mode: 0644]
utils/tex2rtf/docs/up.gif [new file with mode: 0644]
utils/tex2rtf/docs/verbatim.sty [new file with mode: 0644]
utils/tex2rtf/src/bmputils.h [new file with mode: 0644]
utils/tex2rtf/src/books.bmp [new file with mode: 0644]
utils/tex2rtf/src/dos.def [new file with mode: 0644]
utils/tex2rtf/src/htmlutil.cpp [new file with mode: 0644]
utils/tex2rtf/src/makefile.b32 [new file with mode: 0644]
utils/tex2rtf/src/makefile.bcc [new file with mode: 0644]
utils/tex2rtf/src/makefile.dos [new file with mode: 0644]
utils/tex2rtf/src/makefile.g95 [new file with mode: 0644]
utils/tex2rtf/src/makefile.nt [new file with mode: 0644]
utils/tex2rtf/src/makefile.unx [new file with mode: 0644]
utils/tex2rtf/src/makefile.wat [new file with mode: 0644]
utils/tex2rtf/src/makengui.nt [new file with mode: 0644]
utils/tex2rtf/src/maths.cpp [new file with mode: 0644]
utils/tex2rtf/src/readshg.cpp [new file with mode: 0644]
utils/tex2rtf/src/readshg.h [new file with mode: 0644]
utils/tex2rtf/src/rtfutils.cpp [new file with mode: 0644]
utils/tex2rtf/src/rtfutils.h [new file with mode: 0644]
utils/tex2rtf/src/table.cpp [new file with mode: 0644]
utils/tex2rtf/src/table.h [new file with mode: 0644]
utils/tex2rtf/src/tex2any.cpp [new file with mode: 0644]
utils/tex2rtf/src/tex2any.h [new file with mode: 0644]
utils/tex2rtf/src/tex2rtf.cpp [new file with mode: 0644]
utils/tex2rtf/src/tex2rtf.def [new file with mode: 0644]
utils/tex2rtf/src/tex2rtf.h [new file with mode: 0644]
utils/tex2rtf/src/tex2rtf.ico [new file with mode: 0644]
utils/tex2rtf/src/tex2rtf.ini [new file with mode: 0644]
utils/tex2rtf/src/tex2rtf.rc [new file with mode: 0644]
utils/tex2rtf/src/tex2rtf.xpm [new file with mode: 0644]
utils/tex2rtf/src/texutils.cpp [new file with mode: 0644]
utils/tex2rtf/src/wxhlpblk.h [new file with mode: 0644]
utils/tex2rtf/src/xlputils.cpp [new file with mode: 0644]

index 37a5f1f542625d5c6c66b42dc8ffb55b3ae15a04..4be8358cfd024b998be50c77eae93ecd9cb4d80f 100644 (file)
@@ -98,25 +98,6 @@ utils/wxhelp/src/*.ico
 utils/wxhelp/src/*.def
 utils/wxhelp/src/*.rc
 
 utils/wxhelp/src/*.def
 utils/wxhelp/src/*.rc
 
-utils/tex2rtf/src/wxwin/*.*
-utils/tex2rtf/src/*.cpp
-utils/tex2rtf/src/*.h
-utils/tex2rtf/src/make*.*
-utils/tex2rtf/src/*.xbm
-utils/tex2rtf/src/*.xpm
-utils/tex2rtf/src/*.sty
-utils/tex2rtf/src/*.ini
-utils/tex2rtf/src/*.inf
-utils/tex2rtf/lib/dummy
-utils/tex2rtf/src/*.bmp
-utils/tex2rtf/src/*.ico
-utils/tex2rtf/src/*.def
-utils/tex2rtf/src/*.rc
-utils/tex2rtf/tools/lacheck/*.*
-utils/tex2rtf/tools/tcheck/*.awk
-utils/tex2rtf/tools/tcheck/*.pl
-utils/tex2rtf/tools/tcheck/*.bat
-
 utils/wxtree/src/*.cpp
 utils/wxtree/src/*.h
 utils/wxtree/src/makefile*
 utils/wxtree/src/*.cpp
 utils/wxtree/src/*.h
 utils/wxtree/src/makefile*
index d8c4e4dedab36d35d9273269c3a055bab87ceb33..f6d91e089b32c8ed5de28c3ea955838e37e43974 100755 (executable)
@@ -35,6 +35,9 @@ zip32 -@ %dest\wx200cw.zip < %src\distrib\msw\cw.rsp
 
 zip32 -@ %dest\ogl3.zip < %src\utils\ogl\distrib\ogl.rsp
 
 
 zip32 -@ %dest\ogl3.zip < %src\utils\ogl\distrib\ogl.rsp
 
+rem Tex2RTF
+zip32 -@ %dest\tex2rtf.zip < %src\distrib\msw\tex2rtf.rsp
+
 cd %dest
 
 echo wxWindows archived.
 cd %dest
 
 echo wxWindows archived.
index b5ef3bc1e06326c748813d8ae197e64aed0d34a9..de69d259e308a83c12be9939b80c3a63bc041c7b 100644 (file)
@@ -20,7 +20,7 @@ window class.
 for this style.}
 \twocolitem{\windowstyle{wxDOUBLE\_BORDER}}{Displays a double border. Windows only.}
 \twocolitem{\windowstyle{wxSUNKEN\_BORDER}}{Displays a sunken border.}
 for this style.}
 \twocolitem{\windowstyle{wxDOUBLE\_BORDER}}{Displays a double border. Windows only.}
 \twocolitem{\windowstyle{wxSUNKEN\_BORDER}}{Displays a sunken border.}
-\twocolitem{\windowstyle{wxRAISED\_BORDER}}{Displays a sunken border.}
+\twocolitem{\windowstyle{wxRAISED\_BORDER}}{Displays a raised border.}
 \twocolitem{\windowstyle{wxSTATIC\_BORDER}}{Displays a border suitable for a static control.}
 \twocolitem{\windowstyle{wxTRANSPARENT\_WINDOW}}{The window is transparent, that is, it will not receive paint
 events. Windows only.}
 \twocolitem{\windowstyle{wxSTATIC\_BORDER}}{Displays a border suitable for a static control.}
 \twocolitem{\windowstyle{wxTRANSPARENT\_WINDOW}}{The window is transparent, that is, it will not receive paint
 events. Windows only.}
index 118dabbfd4ea390636bc50e0d47f8babb2e59d71..340c83b5178663c9af43d3c3b1754f1351b91f59 100644 (file)
@@ -13,5 +13,5 @@ PROGRAM=bombs
 
 OBJECTS = bombs.o bombs1.o game.o
 
 
 OBJECTS = bombs.o bombs1.o game.o
 
-include ../../src/makeprog.env
+include ../../../src/makeprog.env
 
 
index 55a2a2b3410800938679bba0dd40b20a03234210..046c703af2d8fe011ad306581586511810e81fea 100644 (file)
@@ -909,7 +909,7 @@ int wxDebugContext::CountObjectsLeft(bool sinceCheckpoint)
   wxMemStruct *from = NULL;
   if (sinceCheckpoint && checkPoint)
     from = checkPoint->m_next;
   wxMemStruct *from = NULL;
   if (sinceCheckpoint && checkPoint)
     from = checkPoint->m_next;
-  if (from == (wxMemStruct*) NULL)
+  else
     from = wxDebugContext::GetHead () ;
 
   for (wxMemStruct * st = from; st != 0; st = st->m_next)
     from = wxDebugContext::GetHead () ;
 
   for (wxMemStruct * st = from; st != 0; st = st->m_next)
diff --git a/utils/tex2rtf/docs/back.gif b/utils/tex2rtf/docs/back.gif
new file mode 100644 (file)
index 0000000..8a61076
Binary files /dev/null and b/utils/tex2rtf/docs/back.gif differ
diff --git a/utils/tex2rtf/docs/books.gif b/utils/tex2rtf/docs/books.gif
new file mode 100644 (file)
index 0000000..26ff394
Binary files /dev/null and b/utils/tex2rtf/docs/books.gif differ
diff --git a/utils/tex2rtf/docs/bullet.bmp b/utils/tex2rtf/docs/bullet.bmp
new file mode 100644 (file)
index 0000000..aad8fc7
Binary files /dev/null and b/utils/tex2rtf/docs/bullet.bmp differ
diff --git a/utils/tex2rtf/docs/contents.gif b/utils/tex2rtf/docs/contents.gif
new file mode 100644 (file)
index 0000000..3dddfa3
Binary files /dev/null and b/utils/tex2rtf/docs/contents.gif differ
diff --git a/utils/tex2rtf/docs/fancyhea.sty b/utils/tex2rtf/docs/fancyhea.sty
new file mode 100644 (file)
index 0000000..83914fa
--- /dev/null
@@ -0,0 +1,145 @@
+% fancyheadings.sty version 1.92
+% Fancy headers and footers.
+% Piet van Oostrum, Dept of Computer Science, University of Utrecht
+% Padualaan 14, P.O. Box 80.089, 3508 TB Utrecht, The Netherlands
+% Telephone: +31-30-531806. piet@cs.ruu.nl (mcvax!sun4nl!ruuinf!piet)
+% Sep 16, 1994
+% version 1.4: Correction for use with \reversemargin
+% Sep 29, 1994:
+% version 1.5: Added the \iftopfloat, \ifbotfloat and \iffloatpage commands
+% Oct 4, 1994:
+% version 1.6: Reset single spacing in headers/footers for use with
+% setspace.sty or doublespace.sty
+% Oct 4, 1994:
+% version 1.7: changed \let\@mkboth\markboth to
+% \def\@mkboth{\protect\markboth} to make it more robust
+% Dec 5, 1994:
+% version 1.8: corrections for amsbook/amsart: define \@chapapp and (more
+% importantly) use the \chapter/sectionmark definitions from ps@headings if
+% they exist (which should be true for all standard classes).
+% May 31, 1995:
+% version 1.9: The proposed \renewcommand{\headrulewidth}{\iffloatpage...
+% construction in the doc did not work properly with the fancyplain style. 
+% June 1, 1995:
+% version 1.91: The definition of \@mkboth wasn't restored on subsequent
+% \pagestyle{fancy}'s.
+% June 1, 1995:
+% version 1.92: The sequence \pagestyle{fancyplain} \pagestyle{plain}
+% \pagestyle{fancy} would erroneously select the plain version.
+
+\def\lhead{\@ifnextchar[{\@xlhead}{\@ylhead}}
+\def\@xlhead[#1]#2{\gdef\@elhead{#1}\gdef\@olhead{#2}}
+\def\@ylhead#1{\gdef\@elhead{#1}\gdef\@olhead{#1}}
+
+\def\chead{\@ifnextchar[{\@xchead}{\@ychead}}
+\def\@xchead[#1]#2{\gdef\@echead{#1}\gdef\@ochead{#2}}
+\def\@ychead#1{\gdef\@echead{#1}\gdef\@ochead{#1}}
+
+\def\rhead{\@ifnextchar[{\@xrhead}{\@yrhead}}
+\def\@xrhead[#1]#2{\gdef\@erhead{#1}\gdef\@orhead{#2}}
+\def\@yrhead#1{\gdef\@erhead{#1}\gdef\@orhead{#1}}
+
+\def\lfoot{\@ifnextchar[{\@xlfoot}{\@ylfoot}}
+\def\@xlfoot[#1]#2{\gdef\@elfoot{#1}\gdef\@olfoot{#2}}
+\def\@ylfoot#1{\gdef\@elfoot{#1}\gdef\@olfoot{#1}}
+
+\def\cfoot{\@ifnextchar[{\@xcfoot}{\@ycfoot}}
+\def\@xcfoot[#1]#2{\gdef\@ecfoot{#1}\gdef\@ocfoot{#2}}
+\def\@ycfoot#1{\gdef\@ecfoot{#1}\gdef\@ocfoot{#1}}
+
+\def\rfoot{\@ifnextchar[{\@xrfoot}{\@yrfoot}}
+\def\@xrfoot[#1]#2{\gdef\@erfoot{#1}\gdef\@orfoot{#2}}
+\def\@yrfoot#1{\gdef\@erfoot{#1}\gdef\@orfoot{#1}}
+
+\newdimen\headrulewidth
+\newdimen\footrulewidth
+\newdimen\plainheadrulewidth
+\newdimen\plainfootrulewidth
+\newdimen\headwidth
+\newif\if@fancyplain
+\def\fancyplain#1#2{\if@fancyplain#1\else#2\fi}
+
+% Command to reset various things in the headers:
+% a.o.  single spacing (taken from setspace.sty)
+% and the catcode of ^^M (so that epsf files in the header work if a
+% verbatim crosses a page boundary)
+\def\fancy@reset{\restorecr
+ \def\baselinestretch{1}%
+ \ifx\undefined\@newbaseline% NFSS not present; 2.09 or 2e
+  \ifx\@currsize\normalsize\@normalsize\else\@currsize\fi%
+ \else% NFSS (2.09) present
+  \@newbaseline%
+ \fi}
+
+% Initialization of the head and foot text.
+
+\headrulewidth 0.4pt
+\footrulewidth\z@
+\plainheadrulewidth\z@
+\plainfootrulewidth\z@
+
+\lhead[\fancyplain{}{\sl\rightmark}]{\fancyplain{}{\sl\leftmark}}
+%  i.e. empty on ``plain'' pages, \rightmark on even, \leftmark on odd pages
+\chead{}
+\rhead[\fancyplain{}{\sl\leftmark}]{\fancyplain{}{\sl\rightmark}}
+%  i.e. empty on ``plain'' pages, \leftmark on even, \rightmark on odd pages
+\lfoot{}
+\cfoot{\rm\thepage} % page number
+\rfoot{}
+
+% Put together a header or footer given the left, center and
+% right text, fillers at left and right and a rule.
+% The \lap commands put the text into an hbox of zero size,
+% so overlapping text does not generate an errormessage.
+
+\def\@fancyhead#1#2#3#4#5{#1\hbox to\headwidth{\fancy@reset\vbox{\hbox
+{\rlap{\parbox[b]{\headwidth}{\raggedright#2\strut}}\hfill
+\parbox[b]{\headwidth}{\centering#3\strut}\hfill
+\llap{\parbox[b]{\headwidth}{\raggedleft#4\strut}}}\headrule}}#5}
+
+
+\def\@fancyfoot#1#2#3#4#5{#1\hbox to\headwidth{\fancy@reset\vbox{\footrule
+\hbox{\rlap{\parbox[t]{\headwidth}{\raggedright#2\strut}}\hfill
+\parbox[t]{\headwidth}{\centering#3\strut}\hfill
+\llap{\parbox[t]{\headwidth}{\raggedleft#4\strut}}}}}#5}
+
+\def\headrule{{\if@fancyplain\let\headrulewidth\plainheadrulewidth\fi
+\hrule\@height\headrulewidth\@width\headwidth \vskip-\headrulewidth}}
+
+\def\footrule{{\if@fancyplain\let\footrulewidth\plainfootrulewidth\fi
+\vskip-0.3\normalbaselineskip\vskip-\footrulewidth
+\hrule\@width\headwidth\@height\footrulewidth\vskip0.3\normalbaselineskip}}
+
+\def\ps@fancy{%
+\@ifundefined{@chapapp}{\let\@chapapp\chaptername}{}%for amsbook
+\@ifundefined{chapter}{\def\sectionmark##1{\markboth
+{\uppercase{\ifnum \c@secnumdepth>\z@
+ \thesection\hskip 1em\relax \fi ##1}}{}}%
+\def\subsectionmark##1{\markright {\ifnum \c@secnumdepth >\@ne
+ \thesubsection\hskip 1em\relax \fi ##1}}}%
+{\def\chaptermark##1{\markboth {\uppercase{\ifnum \c@secnumdepth>\m@ne
+ \@chapapp\ \thechapter. \ \fi ##1}}{}}
+\def\sectionmark##1{\markright{\uppercase{\ifnum \c@secnumdepth >\z@
+ \thesection. \ \fi ##1}}}}%
+\csname ps@headings\endcsname % use \ps@headings defaults if they exist
+\ps@@fancy
+\gdef\ps@fancy{\@fancyplainfalse\ps@@fancy}%
+\headwidth\textwidth}
+\def\ps@fancyplain{\ps@fancy \let\ps@plain\ps@plain@fancy}
+\def\ps@plain@fancy{\@fancyplaintrue\ps@@fancy}
+\def\ps@@fancy{%
+\def\@mkboth{\protect\markboth}%
+\def\@oddhead{\@fancyhead\@lodd\@olhead\@ochead\@orhead\@rodd}%
+\def\@oddfoot{\@fancyfoot\@lodd\@olfoot\@ocfoot\@orfoot\@rodd}%
+\def\@evenhead{\@fancyhead\@rodd\@elhead\@echead\@erhead\@lodd}%
+\def\@evenfoot{\@fancyfoot\@rodd\@elfoot\@ecfoot\@erfoot\@lodd}%
+}
+\def\@lodd{\if@reversemargin\hss\else\relax\fi}
+\def\@rodd{\if@reversemargin\relax\else\hss\fi}
+
+\let\latex@makecol\@makecol
+\def\@makecol{\let\topfloat\@toplist\let\botfloat\@botlist\latex@makecol}
+\def\iftopfloat#1#2{\ifx\topfloat\empty #2\else #1\fi}
+\def\ifbotfloat#1#2{\ifx\botfloat\empty #2\else #1\fi}
+\def\iffloatpage#1#2{\if@fcolmade #1\else #2\fi}
+
diff --git a/utils/tex2rtf/docs/forward.gif b/utils/tex2rtf/docs/forward.gif
new file mode 100644 (file)
index 0000000..9c81e8c
Binary files /dev/null and b/utils/tex2rtf/docs/forward.gif differ
diff --git a/utils/tex2rtf/docs/install.txt b/utils/tex2rtf/docs/install.txt
new file mode 100644 (file)
index 0000000..6224eec
--- /dev/null
@@ -0,0 +1,43 @@
+Installation Instructions for Tex2RTF
+-------------------------------------
+
+Binaries are supplied for Windows 3.1 and for Sun workstations.
+
+If these don't work for you, or you are using a different system, you
+will need to compile Tex2RTF. There are several options for doing this.
+
+(1) GUI version
+
+If you want to have a graphical interface for Tex2RTF
+(not essential for a conversion utility!) then you
+will need to download wxWindows from skye.aiai.ed.ac.uk
+(192.41.104.6) in the directory /pub/wxwin/beta, files
+wx150?_*.tar.Z (or .gz) where ? is the latest beta letter,
+currently i.
+
+On UNIX, you will then need to decide whether you want to produce
+an XView or Motif version (provided you have one of these
+toolkits), and change the makefiles in accordingly,
+in wx/src/x, wx/src/base and wx/utils/tex2rtf/src.
+
+Use the makefile target 'xview' or 'motif' from each of the directories
+wx/src/x and wx/utils/tex2rtf/src.
+
+Under Windows, just type 'nmake -f makefile.dos' if you're
+using a Microsoft-compatible compiler (you'll need to
+change the makefiles or build project files for other compilers.)
+
+(2) Non-GUI version
+
+Under UNIX, simply use the target 'nogui'. The supplied files in the
+src/wxwin directory supply the essential utilities from wxWindows, and
+Tex2RTF will be built as a command-line program.
+
+On a PC, add 'NOGUI=1' to the makefile command line. Note that the small
+amount of memory available under DOS can cause catastrophic crashes for
+large input files, due to the lack of memory checking, so be warned! The
+Windows version is a more sensible choice.
+
+-------------------------------------------------------------------------
+Julian Smart, February 1993
+J.Smart@ed.ac.uk
diff --git a/utils/tex2rtf/docs/makeidx.sty b/utils/tex2rtf/docs/makeidx.sty
new file mode 100644 (file)
index 0000000..4fbb9ae
--- /dev/null
@@ -0,0 +1,11 @@
+% makeidx.sty 20-Jan-87   modified for international usage
+%
+% Modified by J.Schrod (TeXsys).
+% according to the suggestion of H.Partl (TU Wien) in german.sty
+% to make caption names adaptable to other languages.
+\@ifundefined{seeterm}{\def\seeterm{see}}{} % <-----------
+\def\see#1#2{{\em \seeterm\/} #1}
+\def\printindex{\@input{\jobname.ind}}
diff --git a/utils/tex2rtf/docs/mysober.sty b/utils/tex2rtf/docs/mysober.sty
new file mode 100644 (file)
index 0000000..a6f73a6
--- /dev/null
@@ -0,0 +1,154 @@
+% SOBER.STY van Nico Poppelier
+% Adapted by Julian Smart for his own
+% nefarious purposes
+% --------------------------------------
+% Koppen van secties, subsecties, ...
+% --------------------------------------
+%
+% --------------------------------------
+% fontgrootte en regelafstand
+% (met de notatie X/Y wordt bedoeld
+%  'letter X op regelafstand Y')
+% --------------------------------------
+%
+%                10pt     11pt     12pt
+% \scriptsize    7/ 8     8/ 9.5   8/ 9.5
+% \tiny          5/ 6     6/ 7     6/ 7
+% \small         9/11    10/12    11/13.6
+% \footnotesize  8/ 9.5   9/11    10/12
+% \@normalsize  10/12    11/13.6  12/15
+% \large        12/14    12/14    14/18
+% \Large        14/18    14/18    17/22
+% \LARGE        17/22    17/22    20/25
+% \huge         20/25    20/25    25/30
+% \Huge         25/30    25/30    25/30
+%
+% de syntax van \@startsection is:
+%   \@startsection
+%     {Name}{Level}{Indent}{Before_skip}{After_Skip}{Type_face}
+%     Indent     : inspring van kop vanaf linkermarge
+%     Before_skip: wit boven kopje
+%                  (< 0 geeft aan dat eerste alinea niet inspringt)
+%     After_skip : wit onder kopje indien >= 0
+%                  horizontaal wit na kopje,
+%                  met kopje op de regel indien < 0
+%
+% notatie voor <glue>: <dimen>(<stretch>)(<shrink>)
+%
+% in LaTeX's standaard-stijlen (onafhankelijk van \@ptsize):
+%
+%               Indent     Before_skip           After_skip     Type_face
+% section       0          -3.5ex (-1ex)(-0.2ex)  2.3ex(0.2ex) \Large\bf
+% subsection    0          -3.25ex(-1ex)(-0.2ex)  1.5ex(0.2ex) \large\bf
+% subsubsection 0          -3.25ex(-1ex)(-0.2ex)  1.5ex(0.2ex) \normalsize\bf
+% paragraph     0           3.25ex( 1ex)( 0.2ex) -1em()()      \normalsize\bf
+% subparagraph  \parindent  3.25ex( 1ex)( 0.2ex) -1em()()      \normalsize\bf
+%
+%
+% in een soberder uitvoering (onafhankelijk van \@ptsize):
+%
+\def\section{\@startsection{section}{1}
+%{\z@}{-2.5ex plus -0.5ex minus -0.1ex}{0.5ex plus 0.1ex}{\large\bf}}
+{\z@}{-2.5ex plus -0.5ex minus -0.1ex}{0.5ex plus 0.1ex}{\large\bf}}
+\def\subsection{\@startsection{subsection}{2}
+{\z@}{-2.25ex plus -0.3ex minus -0.2ex}{0.05ex plus 0.05ex}{\normalsize\bf}}
+\def\subsubsection{\@startsection{subsubsection}{3}
+{\z@}{-2.25ex plus -0.3ex minus -0.2ex}{0.05ex plus 0.05ex}{\normalsize\sc}}
+\def\paragraph{\@startsection{paragraph}{4}
+{\z@}{2ex plus 0.5ex minus 0.1ex}{-0.7em}{\normalsize\it}}
+\def\subparagraph{\@startsection{subparagraph}{4}
+{\parindent}{2ex plus 0.5ex minus 0.1ex}{-0.7em}{\normalsize\it}}
+%
+% --------------------------------------
+% Hoofdstuk-koppen
+% --------------------------------------
+%
+% LaTeX's book style (standaard documentstijl) definieert
+% de hoofdstuk-koppen onafhankelijk van \@ptsize
+%
+
+\def\@makechapterhead#1{\vspace*{20pt}%
+% Next line repaired by Piet van Oostrum - June 14, 1991.
+%{\parindent 0pt\Large\bf \ifnum\c@secnumdepth>\m@ne\thechapter \fi
+{\parindent 0pt\LARGE\bf \ifnum\c@secnumdepth>\m@ne\thechapter. \hskip 1em \fi%
+{\raggedright\LARGE\bf #1}\\\rule[10pt]{\textwidth}{0.3mm}\par\nobreak \vskip25pt} }
+
+\def\@makeschapterhead#1{
+ \vspace*{20pt} { \parindent 0pt \raggedright
+ \LARGE\bf#1\par\nobreak\vskip25pt } }
+%
+% --------------------------------------
+% List-omgevingen (itemize en enumerate)
+% --------------------------------------
+%
+% De volgende parameters zijn relevant in een list-omgeving:
+%
+%   \labelsep     : afstand tussen label en item
+%   \labelwidth   : breedte van label
+%   \leftmargin   : afstand tussen linkermarge en item
+%   \rightmargin  : afstand tussen item en rechtermarge
+%   \listparindent: indentatie voor vervolg-alinea's in item
+%   \parsep       : verticaal wit tussen vervolg-alinea's in item
+%   \itemsep      : verticaal wit tussen opeenvolgende item's
+%   \topsep,
+%   \partopsep    : wit boven item 1 = \topsep + \parskip
+%                    (geen alinea-overgang boven lijst)
+%                   wit boven item 1 = \topsep + \parskip + \partopsep
+%                    (alinea-overgang boven lijst)
+%
+% zie verder LaTeX-boek 5.7.1 en C.5.3
+% --------------------------------------
+%
+% De parameters voor niveau 1 worden gedefinieerd op top-niveau en
+% \@listi definieert uitsluitend \leftmargin
+%
+% size = small (9pt, 10pt, 11pt)
+\def\@listi{\topsep 0.4ex \parsep 0pt \itemsep \parsep}
+% \topsep 4pt(2pt)(2pt)  6pt(2pt)(2pt)  9pt(3pt)(5pt)
+% \parsep 2pt(1pt)(1pt)  3pt(2pt)(1pt) 4.5pt(2pt)(1pt)
+%
+% size = footnotesize (8pt, 9pt, 10pt)
+\def\@listi{\topsep 0.4ex \parsep 0pt \itemsep \parsep}
+% \topsep 3pt(1pt)(1pt) 4pt(2pt)(2pt) 6pt(2pt)(2pt)
+% \parsep 2pt(1pt)(1pt) 2pt(1pt)(1pt) 3pt(2pt)(1pt)
+%
+% size = normalsize (and bigger)
+% \parskip    0pt(1pt) 0pt(1pt) 0pt(1pt)
+% \parindent  15pt 17pt 1.5em
+% \topsep      8pt(2pt)(4pt) 9pt(3pt)(5pt) 10pt(4pt)(6pt)
+% \partopsep   2pt(1pt)(1pt) 3pt(1pt)(2pt) 3pt(2pt)(2pt)
+% \itemsep     4pt(2pt)(1pt) 4.5pt(2pt)(1pt)  5pt(2.5pt)(1pt
+% \parsep  4pt(2pt)(1pt) 4.5pt(2pt)(1pt) 5pt(2.5pt)(1pt)
+\topsep 0.4ex \partopsep 0pt \itemsep 0pt \parsep 0pt
+%
+% \leftmargini  2.5em \leftmarginii 2.2em \leftmarginiii 1.87em
+% \leftmarginiv 1.7em \leftmarginv  1.0em \leftmarginvi  1.0em
+%
+% \leftmargin\leftmargini
+% \labelwidth\leftmargini\advance\labelwidth-\labelsep
+% \labelsep 0.5em
+%
+% \def\@listi{\leftmargin\leftmargini}
+%
+\def\@listii{\leftmargin\leftmarginii
+ \labelwidth\leftmarginii\advance\labelwidth-\labelsep
+% \topsep 4pt(2pt)(1pt) 4.5pt(2pt)(1pt) 5pt(2.5pt)(1pt)
+% \parsep 2pt(1pt)(1pt) 2pt(1pt)(1pt)   2.5pt(1pt)(1pt)
+ \topsep 0pt \parsep 0pt \itemsep \parsep}
+%
+\def\@listiii{\leftmargin\leftmarginiii
+ \labelwidth\leftmarginiii\advance\labelwidth-\labelsep
+% \topsep    2pt(1pt)(1pt) 2pt(1pt)(1pt) 2.5pt(1pt)(1pt)
+% \partopsep 1pt(0pt)(1pt) 1pt(0pt)(1pt) 1pt(0pt)(1pt)
+ \parsep \z@ \topsep 0pt \partopsep 0pt \itemsep \topsep}
+%
+% \def\@listiv{\leftmargin\leftmarginiv
+%  \labelwidth\leftmarginiv\advance\labelwidth-\labelsep}
+%
+% \def\@listv{ \leftmargin\leftmarginv
+%  \labelwidth\leftmarginv\advance\labelwidth-\labelsep}
+%
+% \def\@listvi{\leftmargin\leftmarginvi
+%  \labelwidth\leftmarginvi\advance\labelwidth-\labelsep}
+
diff --git a/utils/tex2rtf/docs/mytitle.sty b/utils/tex2rtf/docs/mytitle.sty
new file mode 100644 (file)
index 0000000..4a20d7b
--- /dev/null
@@ -0,0 +1,33 @@
+% mytitle.sty
+% Julian Smart's Enhanced Titlepage
+
+\def\maketitle{\begin{titlepage}
+\let\footnotesize\small \let\footnoterule\relax \setcounter{page}{0}
+%\null
+%\vfil
+\vspace*{2cm}\begin{flushleft}
+{\huge \sf\@title\\\rule{\textwidth}{0.5mm}} \vskip 3em {\large \lineskip .75em
+{\sf\@author}
+\par}
+\vskip 1.5em {\large\sf \@date \par} \end{flushleft} \par
+\@thanks
+\vfill
+{\sf\small\begin{flushright}%
+Artificial Intelligence Applications Institute\\
+University of Edinburgh\\
+80 South Bridge\\
+EH1 1HN\\
+Tel. 0131-650-2746
+\end{flushright}}
+\null
+\end{titlepage}
+\setcounter{footnote}{0} \let\thanks\relax
+\gdef\@thanks{}\gdef\@author{}\gdef\@title{}\let\maketitle\relax}
+\def\abstractname{Abstract} % <----------
+\def\abstract{\titlepage
+\null\vfil
+\begin{center}
+{\bf \abstractname} % <----------
+% {\bf Abstract}
+\end{center}}
+\def\endabstract{\par\vfil\null\endtitlepage}
diff --git a/utils/tex2rtf/docs/notes.txt b/utils/tex2rtf/docs/notes.txt
new file mode 100644 (file)
index 0000000..6e830c5
--- /dev/null
@@ -0,0 +1,140 @@
+Implementation notes
+--------------------
+
+Files
+-----
+
+The library tex2any.lib contains the generic Latex parser.
+It comprises tex2any.cc, tex2any.h and texutils.cc.
+
+The executable Tex2RTF is made up of tex2any.lib,
+tex2rtf.cc (main driver and user interface), and specific
+drivers for generating output: rtfutils.cc, htmlutil.cc
+and xlputils.cc.
+
+Data structures
+---------------
+
+Class declarations are found in tex2any.h.
+
+TexMacroDef holds a macro (Latex command) definition: name, identifier,
+number of arguments, whether it should be ignored, etc. Integer
+identifiers are used for each Latex command for efficiency when
+generating output. A hash table MacroDefs stores all the TexMacroDefs,
+indexed on command name.
+
+Each unit of a Latex file is stored in a TexChunk. A TexChunk can be
+a macro, argument or just a string: a TexChunk macro has child
+chunks for the arguments, and each argument will have one or more
+children for representing another command or a simple string.
+
+Parsing
+-------
+
+Parsing is relatively add hoc. read_a_line reads in a line at a time,
+doing some processing for file commands (e.g. input, verbatiminclude).
+File handles are stored in a stack so file input commands may be nested.
+
+ParseArg parses an argument (which might be the whole Latex input,
+which is treated as an argument) or a single command, or a command
+argument. The parsing gets a little hairy because an environment,
+a normal command and bracketed commands (e.g. {\bf thing}) all get
+parsed into the same format. An environment, for example,
+is usually a one-argument command, as is {\bf thing}. It also
+deals with user-defined macros.
+
+Whilst parsing, the function MatchMacro gets called to
+attempt to find a command following a backslash (or the
+start of an environment). ParseMacroBody parses the
+arguments of a command when one is found.
+
+Generation
+----------
+
+The upshot of parsing is a hierarchy of TexChunks.
+TraverseFromDocument calls the recursive TraverseFromChunk,
+and is called by the 'client' converter application to
+start the generation process. TraverseFromChunk
+calls the two functions OnMacro and OnArgument,
+twice for each chunk to allow for preprocessing
+and postprocessing of each macro or argument.
+
+The client defines OnMacro and OnArgument to test
+the command identifier, and output the appropriate
+code. To help do this, the function TexOutput
+outputs to the current stream(s), and
+SetCurrentOutput(s) allows the setting of one
+or two output streams for the output to be sent to.
+Usually two outputs at a time are sufficient for
+hypertext applications where a title is likely
+to appear in an index and as a section header.
+
+There are support functions for getting the string
+data for the current chunk (GetArgData) and the
+current chunk (GetArgChunk). If you have a handle
+on a chunk, you can output it several times by calling
+TraverseChildrenFromChunk (not TraverseFromChunk because
+that causes infinite recursion).
+
+The client (here, Tex2RTF) also defines OnError and OnInform output
+functions appropriate to the desired user interface.
+
+References
+----------
+
+Adding, finding and resolving references are supported
+with functions from texutils.cc. WriteTexReferences
+and ReadTexReferences allow saving and reading references
+between conversion processes, rather like real LaTeX.
+
+Bibliography
+------------
+
+Again texutils.cc provides functions for reading in .bib files and
+resolving references. The function OutputBibItem gives a generic way
+outputting bibliography items, by 'faking' calls to OnMacro and
+OnArgument, allowing the existing low-level client code to take care of
+formatting.
+
+Units
+-----
+
+Unit parsing code is in texutils.cc as ParseUnitArgument. It converts
+units to points.
+
+Common errors
+-------------
+
+1) Macro not found: \end{center} ...
+
+Rewrite:
+
+\begin{center}
+{\large{\underline{A}}}
+\end{center}
+
+as:
+
+\begin{center}
+{\large \underline{A}}
+\end{center}
+
+2) Tables crash RTF. Set 'compatibility ' to TRUE in .ini file; also
+check for \\ end of row characters on their own on a line, insert
+correct number of ampersands for the number of columns.  E.g.
+
+hello & world\\
+\\
+
+becomes
+
+hello & world\\
+&\\
+
+3) If list items indent erratically, try increasing
+listItemIndent to give more space between label and following text.
+A global replace of '\item [' to '\item[' may also be helpful to remove
+unnecessary space before the item label.
+
+4) Missing figure or section references: ensure all labels _directly_ follow captions
+or sections (no intervening white space).
diff --git a/utils/tex2rtf/docs/psbox.tex b/utils/tex2rtf/docs/psbox.tex
new file mode 100644 (file)
index 0000000..b7438f4
--- /dev/null
@@ -0,0 +1,520 @@
+%
+%              %%%%%%%    %%%%%        %%%%%%    %%%%%   %     %
+%              %      %  %             %     %  %     %   %   %
+%              %      %  %             %     %  %     %    % %
+%              %%%%%%%    %%%%%        %%%%%%   %     %     %
+%              %               %       %     %  %     %    % %
+%              %               %       %     %  %     %   %   %
+%              %         %%%%%%        %%%%%%    %%%%%   %     %
+%
+%              By Jean Orloff
+%              Comments & suggestions by e-mail: ORLOFF@surya11.cern.ch
+%              No modification of this file allowed if not e-sent to me.
+%
+% A simple way to measure the size of encapsulated postscript figures
+%   from inside TeX, and to use it for automatically formatting texts
+%   with inserted figures. Works both under Plain TeX-based macros
+%   (Phyzzx, Harvmac, Psizzl, ...) and LaTeX environment.
+% Provides exactly the same result on any PostScript printer provided
+%   the single instruction \psfor... is changed to fit the needs of the
+%   particular dvi->ps translator used.
+% History:
+%   1.31: adds \psforDVIALW(?)
+%   1.30: adds \splitfile & \joinfiles for multi-file management
+%   1.24: fix error handling & add \psonlyboxes
+%   1.23: adds \putsp@ce for OzTeX fix
+%   1.22: makes \drawingBox \global for use in Phyzzx
+%   1.21: accepts %%BoundingBox: (atend)
+%   1.20: tries to add \psfordvitps for the TeXPS package.
+%   1.10: adds \psforoztex, error handling...
+%2345678 1 2345678 2 2345678 3 2345678 4 2345678 5 2345678 6 2345678 7 23456789
+%
+\def\temp{1.31}
+\let\tempp=\relax
+\expandafter\ifx\csname psboxversion\endcsname\relax
+  \message{version: \temp}
+\else
+    \ifdim\temp cm>\psboxversion cm
+      \message{version: \temp}
+    \else
+      \message{psbox(\psboxversion) is already loaded: I won't load
+        psbox(\temp)!}
+      \let\temp=\psboxversion
+      \let\tempp=\endinput
+    \fi
+\fi
+\tempp
+\let\psboxversion=\temp
+\catcode`\@=11
+% Every macro likes a little privacy...
+%
+% Some common defs
+%
+\def\execute#1{#1}% NOT stupid: cs in #1 are then identified BEFORE execution
+\def\psm@keother#1{\catcode`#112\relax}% borrowed from latex
+\def\executeinspecs#1{%
+\execute{\begingroup\let\do\psm@keother\dospecials\catcode`\^^M=9#1\endgroup}}
+%
+%Trying to tame the variety of \special commands for Postscript: the
+%  universal internal command \PSspeci@l##1##2 takes ##1 to be the
+%  filename and ##2 to be the integer scale factor*1000 (as for usual
+%   TeX \scale commands)
+%
+\def\psfortextures{%     For TeXtures on the Macintosh
+%-----------------
+\def\PSspeci@l##1##2{%
+\special{illustration ##1\space scaled ##2}%
+}}
+%
+\def\psfordvitops{%      For the DVItoPS converter on IBM mainframes
+%----------------
+\def\PSspeci@l##1##2{%
+\special{dvitops: import ##1\space \the\drawingwd \the\drawinght}%
+}}
+%
+\def\psfordvips{%      For DVIPS converter on VAX, UNIX and PC's
+%--------------
+\def\PSspeci@l##1##2{%
+%    \special{/@scaleunit 1000 def}% never read dox without trying!
+\d@my=0.1bp \d@mx=\drawingwd \divide\d@mx by\d@my%
+\special{PSfile=##1\space llx=\psllx\space lly=\pslly\space%
+urx=\psurx\space ury=\psury\space rwi=\number\d@mx}%
+}}
+%
+\def\psforoztex{%        For the OzTeX shareware on the Macintosh
+%--------------
+\def\PSspeci@l##1##2{%
+\special{##1 \space
+      ##2 1000 div dup scale
+      \putsp@ce{\number-\psllx} \putsp@ce{\number-\pslly} translate
+}%
+}}
+\def\putsp@ce#1{#1 }
+%
+\def\psfordvitps{%       From the UNIX TeXPS package, vers.>3.12
+%---------------
+% Convert a dimension into the number \psn@sp (in scaled points)
+\def\psdimt@n@sp##1{\d@mx=##1\relax\edef\psn@sp{\number\d@mx}}
+\def\PSspeci@l##1##2{%
+% psfig.psr contains the def of "startTexFig": if you can locate it
+% and include the correct pathname, it should work
+\special{dvitps: Include0 "psfig.psr"}% contains def of "startTexFig"
+\psdimt@n@sp{\drawingwd}
+\special{dvitps: Literal "\psn@sp\space"}
+\psdimt@n@sp{\drawinght}
+\special{dvitps: Literal "\psn@sp\space"}
+\psdimt@n@sp{\psllx bp}
+\special{dvitps: Literal "\psn@sp\space"}
+\psdimt@n@sp{\pslly bp}
+\special{dvitps: Literal "\psn@sp\space"}
+\psdimt@n@sp{\psurx bp}
+\special{dvitps: Literal "\psn@sp\space"}
+\psdimt@n@sp{\psury bp}
+\special{dvitps: Literal "\psn@sp\space startTexFig\space"}
+\special{dvitps: Include1 "##1"}
+\special{dvitps: Literal "endTexFig\space"}
+}}
+\def\psforDVIALW{%   Try for dvialw, a UNIX public domain
+%---------------
+\def\PSspeci@l##1##2{
+\special{language "PS"
+literal "##2 1000 div dup scale"
+include "##1"}}}
+\def\psonlyboxes{%     Draft-like behaviour if none of the others works
+%---------------
+\def\PSspeci@l##1##2{%
+\at(0cm;0cm){\boxit{\vbox to\drawinght
+  {\vss
+  \hbox to\drawingwd{\at(0cm;0cm){\hbox{(##1)}}\hss}
+  }}}
+}%
+}
+%
+\def\psloc@lerr#1{%
+\let\savedPSspeci@l=\PSspeci@l%
+\def\PSspeci@l##1##2{%
+\at(0cm;0cm){\boxit{\vbox to\drawinght
+  {\vss
+  \hbox to\drawingwd{\at(0cm;0cm){\hbox{(##1) #1}}\hss}
+  }}}
+\let\PSspeci@l=\savedPSspeci@l% restore normal output for other figs!
+}%
+}
+%
+%\def\psfor...  add your own!
+%
+%  \ReadPSize{PSfilename} reads the dimensions of a PostScript drawing
+%      and stores it in \drawinght(wd)
+\newread\pst@mpin
+\newdimen\drawinght\newdimen\drawingwd
+\newdimen\psxoffset\newdimen\psyoffset
+\newbox\drawingBox
+\newif\ifNotB@undingBox
+\newhelp\PShelp{Proceed: you'll have a 5cm square blank box instead of
+your graphics (Jean Orloff).}
+\def\@mpty{}
+\def\s@tsize#1 #2 #3 #4\@ndsize{
+  \def\psllx{#1}\def\pslly{#2}%
+  \def\psurx{#3}\def\psury{#4}%  needed by a crazyness of dvips!
+  \ifx\psurx\@mpty\NotB@undingBoxtrue% this is not a valid one!
+  \else
+    \drawinght=#4bp\advance\drawinght by-#2bp
+    \drawingwd=#3bp\advance\drawingwd by-#1bp
+%  !Units related by crazy factors as bp/pt=72.27/72 should be BANNED!
+  \fi
+  }
+\def\sc@nline#1:#2\@ndline{\edef\p@rameter{#1}\edef\v@lue{#2}}
+\def\g@bblefirstblank#1#2:{\ifx#1 \else#1\fi#2}
+\def\psm@keother#1{\catcode`#112\relax}% borrowed from latex
+\def\execute#1{#1}% Seems stupid, but cs are identified BEFORE execution
+{\catcode`\%=12
+\xdef\B@undingBox{%%BoundingBox}
+}   %% is not a true comment in PostScript, even if % is!
+\def\ReadPSize#1{
+ \edef\PSfilename{#1}
+ \openin\pst@mpin=#1\relax
+ \ifeof\pst@mpin \errhelp=\PShelp
+   \errmessage{I haven't found your postscript file (\PSfilename)}
+   \psloc@lerr{was not found}
+   \s@tsize 0 0 142 142\@ndsize
+   \closein\pst@mpin
+ \else
+   \immediate\write\psbj@inaux{#1,}
+   \loop
+     \executeinspecs{\catcode`\ =10\global\read\pst@mpin to\n@xtline}
+     \ifeof\pst@mpin
+       \errhelp=\PShelp
+       \errmessage{(\PSfilename) is not an Encapsulated PostScript File:
+           I could not find any \B@undingBox: line.}
+       \edef\v@lue{0 0 142 142:}
+       \psloc@lerr{is not an EPSFile}
+       \NotB@undingBoxfalse
+     \else
+       \expandafter\sc@nline\n@xtline:\@ndline
+       \ifx\p@rameter\B@undingBox\NotB@undingBoxfalse
+         \edef\t@mp{%
+           \expandafter\g@bblefirstblank\v@lue\space\space\space}
+         \expandafter\s@tsize\t@mp\@ndsize
+       \else\NotB@undingBoxtrue
+       \fi
+     \fi
+   \ifNotB@undingBox\repeat
+   \closein\pst@mpin
+ \fi
+\message{#1}
+}
+%
+% \psboxto(xdim;ydim){psfilename}: you specify the dimensions and
+%    TeX uniformly scales to fit the largest one. If xdim=0pt, the
+%    scale is fully determined by ydim and vice versa.
+%    Notice: psboxes are a real vboxes; couldn't take hbox otherwise all
+%    indentation and all cr's would be interpreted as spaces (hugh!).
+%
+\newcount\xscale \newcount\yscale \newdimen\pscm\pscm=1cm
+\newdimen\d@mx \newdimen\d@my
+\let\ps@nnotation=\relax
+\def\psboxto(#1;#2)#3{\vbox{
+   \ReadPSize{#3}
+   \divide\drawingwd by 1000
+   \divide\drawinght by 1000
+   \d@mx=#1
+   \ifdim\d@mx=0pt\xscale=1000
+         \else \xscale=\d@mx \divide \xscale by \drawingwd\fi
+   \d@my=#2
+   \ifdim\d@my=0pt\yscale=1000
+         \else \yscale=\d@my \divide \yscale by \drawinght\fi
+   \ifnum\yscale=1000
+         \else\ifnum\xscale=1000\xscale=\yscale
+                    \else\ifnum\yscale<\xscale\xscale=\yscale\fi
+              \fi
+   \fi
+   \divide \psxoffset by 1000\multiply\psxoffset by \xscale
+   \divide \psyoffset by 1000\multiply\psyoffset by \xscale
+   \global\divide\pscm by 1000
+   \global\multiply\pscm by\xscale
+   \multiply\drawingwd by\xscale \multiply\drawinght by\xscale
+   \ifdim\d@mx=0pt\d@mx=\drawingwd\fi
+   \ifdim\d@my=0pt\d@my=\drawinght\fi
+   \message{scaled \the\xscale}
+ \hbox to\d@mx{\hss\vbox to\d@my{\vss
+   \global\setbox\drawingBox=\hbox to 0pt{\kern\psxoffset\vbox to 0pt{
+      \kern-\psyoffset
+      \PSspeci@l{\PSfilename}{\the\xscale}
+      \vss}\hss\ps@nnotation}
+   \global\ht\drawingBox=\the\drawinght
+   \global\wd\drawingBox=\the\drawingwd
+   \baselineskip=0pt
+   \copy\drawingBox
+ \vss}\hss}
+  \global\psxoffset=0pt
+  \global\psyoffset=0pt% These are local to one figure
+  \global\pscm=1cm
+  \global\drawingwd=\drawingwd
+  \global\drawinght=\drawinght
+}}
+%
+% \psboxscaled{scalefactor*1000}{PSfilename} allows to bypass the
+%   rounding errors of TeX integer divisions for situations where the
+%   TeX box should fit the original BoundingBox with a precision better
+%   than 1/1000.
+%
+\def\psboxscaled#1#2{\vbox{
+  \ReadPSize{#2}
+  \xscale=#1
+  \message{scaled \the\xscale}
+  \divide\drawingwd by 1000\multiply\drawingwd by\xscale
+  \divide\drawinght by 1000\multiply\drawinght by\xscale
+  \divide \psxoffset by 1000\multiply\psxoffset by \xscale
+  \divide \psyoffset by 1000\multiply\psyoffset by \xscale
+  \global\divide\pscm by 1000
+  \global\multiply\pscm by\xscale
+  \global\setbox\drawingBox=\hbox to 0pt{\kern\psxoffset\vbox to 0pt{
+     \kern-\psyoffset
+     \PSspeci@l{\PSfilename}{\the\xscale}
+     \vss}\hss\ps@nnotation}
+  \global\ht\drawingBox=\the\drawinght
+  \global\wd\drawingBox=\the\drawingwd
+  \baselineskip=0pt
+  \copy\drawingBox
+  \global\psxoffset=0pt
+  \global\psyoffset=0pt% These are local to one figure
+  \global\pscm=1cm
+  \global\drawingwd=\drawingwd
+  \global\drawinght=\drawinght
+}}
+%
+%  \psbox{PSfilename} makes a TeX box having the minimal size to
+%      enclose the picture
+\def\psbox#1{\psboxscaled{1000}{#1}}
+%
+%
+%  \joinfiles file1, file2, ...n \into joinedfilename .
+%     makes one file out of many
+%  \splitfile joinedfilename
+%     the opposite
+%
+%\def\execute#1{#1}% NOT stupid: cs in #1 are then identified BEFORE execution
+%\def\psm@keother#1{\catcode`#112\relax}% borrowed from latex
+%\def\executeinspecs#1{%
+%\execute{\begingroup\let\do\psm@keother\dospecials\catcode`\^^M=9#1\endgroup}}
+%\newread\pst@mpin
+\newif\ifn@teof\n@teoftrue
+\newif\ifc@ntrolline
+\newif\ifmatch
+\newread\j@insplitin
+\newwrite\j@insplitout
+\newwrite\psbj@inaux
+\immediate\openout\psbj@inaux=psbjoin.aux
+\immediate\write\psbj@inaux{\string\joinfiles}
+\immediate\write\psbj@inaux{\jobname,}
+%
+% We redefine input to keep track of the various files inputted
+%
+\immediate\let\oldinput=\input
+\def\input#1 {
+ \immediate\write\psbj@inaux{#1,}
+ \oldinput #1 }
+\def\empty{}
+\def\setmatchif#1\contains#2{
+  \def\match##1#2##2\endmatch{
+    \def\tmp{##2}
+    \ifx\empty\tmp
+      \matchfalse
+    \else
+      \matchtrue
+    \fi}
+  \match#1#2\endmatch}
+\def\warnopenout#1#2{
+ \setmatchif{TrashMe,psbjoin.aux,psbjoin.all}\contains{#2}
+ \ifmatch
+ \else
+   \immediate\openin\pst@mpin=#2
+   \ifeof\pst@mpin
+     \else
+     \errhelp{If the content of this file is so precious to you, abort (ie
+press x or e) and rename it before retrying.}
+     \errmessage{I'm just about to replace your file named #2}
+   \fi
+   \immediate\closein\pst@mpin
+ \fi
+ \message{#2}
+ \immediate\openout#1=#2}
+%  No comments allowed below: % will have an unusual catcode
+{
+\catcode`\%=12
+\gdef\splitfile#1 {
+ \immediate\openin\j@insplitin=#1
+ \message{Splitting file #1 into:}
+ \warnopenout\j@insplitout{TrashMe}
+ \loop
+   \ifeof
+     \j@insplitin\immediate\closein\j@insplitin\n@teoffalse
+   \else
+     \n@teoftrue
+     \executeinspecs{\global\read\j@insplitin to\spl@tinline\expandafter
+       \ch@ckbeginnewfile\spl@tinline%Beginning-Of-File-Named:%\endcheck}
+     \ifc@ntrolline
+     \else
+       \toks0=\expandafter{\spl@tinline}
+       \immediate\write\j@insplitout{\the\toks0}
+     \fi
+   \fi
+ \ifn@teof\repeat
+ \immediate\closeout\j@insplitout}
+\gdef\ch@ckbeginnewfile#1%Beginning-Of-File-Named:#2%#3\endcheck{
+ \def\t@mp{#1}
+ \ifx\empty\t@mp
+   \def\t@mp{#3}
+   \ifx\empty\t@mp
+     \global\c@ntrollinefalse
+   \else
+     \immediate\closeout\j@insplitout
+     \warnopenout\j@insplitout{#2}
+     \global\c@ntrollinetrue
+   \fi
+ \else
+   \global\c@ntrollinefalse
+ \fi}
+\gdef\joinfiles#1\into#2 {
+ \message{Joining following files into}
+ \warnopenout\j@insplitout{#2}
+ \message{:}
+ {
+ \edef\w@##1{\immediate\write\j@insplitout{##1}}
+ \w@{% This text was produced with psbox's \string\joinfiles.}
+ \w@{% To decompose and tex it:}
+ \w@{%-save this with a filename CONTAINING ONLY LETTERS, and no extensions}
+ \w@{% (say, JOINTFIL), in some uncrowded directory;}
+ \w@{%-make sure you can \string\input\space psbox.tex (version>=1.3);}
+ \w@{%-tex JOINTFIL using Plain, or LaTeX, or whatever is needed by}
+ \w@{% the first part in the joining (after splitting JOINTFIL into}
+ \w@{% it's constituents, TeX will try to process it as it stands).}
+ \w@{\string\input\space psbox.tex}
+ \w@{\string\splitfile{\string\jobname}}
+ }
+ \tre@tfilelist#1, \endtre@t
+ \immediate\closeout\j@insplitout}
+\gdef\tre@tfilelist#1, #2\endtre@t{
+ \def\t@mp{#1}
+ \ifx\empty\t@mp
+   \else
+   \llj@in{#1}
+   \tre@tfilelist#2, \endtre@t
+ \fi}
+\gdef\llj@in#1{
+ \immediate\openin\j@insplitin=#1
+ \ifeof\j@insplitin
+   \errmessage{I couldn't find file #1.}
+   \else
+   \message{#1}
+   \toks0={%Beginning-Of-File-Named:#1}
+   \immediate\write\j@insplitout{\the\toks0}
+   \executeinspecs{\global\read\j@insplitin to\oldj@ininline}
+   \loop
+     \ifeof\j@insplitin\immediate\closein\j@insplitin\n@teoffalse
+       \else\n@teoftrue
+       \executeinspecs{\global\read\j@insplitin to\j@ininline}
+       \toks0=\expandafter{\oldj@ininline}
+       \let\oldj@ininline=\j@ininline
+       \immediate\write\j@insplitout{\the\toks0}
+     \fi
+   \ifn@teof
+   \repeat
+   \immediate\closein\j@insplitin
+ \fi}
+}
+% To be put at the end of a file, for making an tar-like file containing
+%   everything it used.
+\def\autojoin{
+ \immediate\write\psbj@inaux{\string\into\space psbjoin.all}
+ \immediate\closeout\psbj@inaux
+ \input psbjoin.aux
+}
+%
+%  Annotations & Captions etc...
+%
+%
+% \centinsert{anybox} is just a centered \midinsert, but is included as
+%    people barely use the original inserts from TeX.
+%
+\def\centinsert#1{\midinsert\line{\hss#1\hss}\endinsert}
+\def\psannotate#1#2{\def\ps@nnotation{#2\global\let\ps@nnotation=\relax}#1}
+\def\pscaption#1#2{\vbox{
+   \setbox\drawingBox=#1
+   \copy\drawingBox
+   \vskip\baselineskip
+   \vbox{\hsize=\wd\drawingBox\setbox0=\hbox{#2}
+     \ifdim\wd0>\hsize
+       \noindent\unhbox0\tolerance=5000
+    \else\centerline{\box0}
+    \fi
+}}}
+% for compatibility with older versions
+\def\psfig#1#2#3{\pscaption{\psannotate{#1}{#2}}{#3}}
+\def\psfigurebox#1#2#3{\pscaption{\psannotate{\psbox{#1}}{#2}}{#3}}
+%
+% \at(#1;#2)#3 puts #3 at #1-higher and #2-right of the current
+%    position without moving it (to be used in annotations).
+\def\at(#1;#2)#3{\setbox0=\hbox{#3}\ht0=0pt\dp0=0pt
+  \rlap{\kern#1\vbox to0pt{\kern-#2\box0\vss}}}
+%
+% \gridfill(ht;wd) makes a 1cm*1cm grid of ht by wd whose lower-left
+%   corner is the current point
+\newdimen\gridht \newdimen\gridwd
+\def\gridfill(#1;#2){
+  \setbox0=\hbox to 1\pscm
+  {\vrule height1\pscm width.4pt\leaders\hrule\hfill}
+  \gridht=#1
+  \divide\gridht by \ht0
+  \multiply\gridht by \ht0
+  \gridwd=#2
+  \divide\gridwd by \wd0
+  \multiply\gridwd by \wd0
+  \advance \gridwd by \wd0
+  \vbox to \gridht{\leaders\hbox to\gridwd{\leaders\box0\hfill}\vfill}}
+%
+% Useful to measure where to put annotations
+\def\fillinggrid{\at(0cm;0cm){\vbox{
+  \gridfill(\drawinght;\drawingwd)}}}
+%
+% \textleftof\anybox: Sample text\endtext
+%   inserts "Sample text" on the left of \anybox ie \vbox, \psbox.
+%   \textrightof is the symmetric (not documented, too uggly)
+% Welcome any suggestion about clean wraparound macros from
+%   TeXhackers reading this
+%
+\def\textleftof#1:{
+  \setbox1=#1
+  \setbox0=\vbox\bgroup
+    \advance\hsize by -\wd1 \advance\hsize by -2em}
+\def\textrightof#1:{
+  \setbox0=#1
+  \setbox1=\vbox\bgroup
+    \advance\hsize by -\wd0 \advance\hsize by -2em}
+\def\endtext{
+  \egroup
+  \hbox to \hsize{\valign{\vfil##\vfil\cr%
+\box0\cr%
+\noalign{\hss}\box1\cr}}}
+%
+% \frameit{\thick}{\skip}{\anybox}
+%    draws with thickness \thick a box around \anybox, leaving \skip of
+%    blank around it. eg \frameit{0.5pt}{1pt}{\hbox{hello}}
+% \boxit{\anybox} is a shortcut.
+\def\frameit#1#2#3{\hbox{\vrule width#1\vbox{
+  \hrule height#1\vskip#2\hbox{\hskip#2\vbox{#3}\hskip#2}%
+        \vskip#2\hrule height#1}\vrule width#1}}
+\def\boxit#1{\frameit{0.4pt}{0pt}{#1}}
+%
+%
+\catcode`\@=12 % cs containing @ are unreachable
+%
+% CUSTOMIZE YOUR DEFAULT DRIVER:
+%    Uncomment the line corresponding to your TeX system:
+%\psfortextures%     For TeXtures on the Macintosh
+%\psforoztex   %     For OzTeX shareware on the Macintosh
+%\psfordvitops %     For the DVItoPS converter for TeX on IBM mainframes
+ \psfordvips   %     For DVIPS converter on VAX and UNIX
+%\psfordvitps  %     For dvitps from TeXPS package under UNIX
+%\psforDVIALW  %     For DVIALW, UNIX public domain
+%\psonlyboxes  %     Blank Boxes (when all else fails).
diff --git a/utils/tex2rtf/docs/readme.txt b/utils/tex2rtf/docs/readme.txt
new file mode 100644 (file)
index 0000000..6709d2e
--- /dev/null
@@ -0,0 +1,81 @@
+
++++++                      Announcing Tex2RTF                         +++++
++++++  A Free LaTeX to RTF, Windows Help RTF, HTML & wxHelp converter +++++
+
+Purpose
+=======
+
+  *  Allows you to maintain manuals in printed and hypertext formats.
+
+  *  Allows conversion of existing LaTeX documents to word processor
+     formats (usually some 'tweaking' is required to conform to
+     Tex2RTF restrictions).
+
+Input
+=====
+
+A LaTeX subset with some additional hypertext macros; no maths,
+minimal table support.
+
+Caveat: Please do not expect to convert arbitrary LaTex files without
+editing: this is not the primary intention of Tex2RTF. Success converting
+existing LaTeX depends on your expectations and the style in which
+the LaTeX was written. Tex2RTF does not accept pure TeX (non-LaTeX)
+documents.
+
+Output
+======
+
+  *  ordinary RTF
+
+  *  Windows Help hypertext RTF
+
+  *  HTML (the World Wide Web hypertext format)
+
+  *  wxHelp (the wxWindows GUI library help file format)
+
+Installation
+============
+
+Under Windows, please run the supplied install.exe program. The Tex2RTF
+manual itself serves as an example input file, in the docs subdirectory
+with various .sty, .ini, and .gif files that you may need for your
+own documents. See the online manual for further details.
+
+Platforms supported
+===================
+
+  *  SPARC Open Look
+
+  *  SPARC Motif
+
+  *  Windows 3.1
+
+Where to get it
+===============
+
+The latest version of Tex2RTF can be accessed by anonymous ftp from
+ftp.aiai.ed.ac.uk in the directory /pub/packages/tex2rtf.
+The WWW pages are at http://www.aiai.ed.ac.uk/~jacs/tex2rtf.html.
+
+Tex2RTF was developed using the free Open Look/Motif/Windows 3.1 C++
+class library wxWindows, also available from the above FTP site in the
+/pub/packages/wxwin directory.
+The wxWindows WWW pages are at http://www.aiai.ed.ac.uk/~jacs/wxwin.html.
+
+
+------------------------------------------------------------------
+Julian Smart, November 1995
+
+Artificial Intelligence Applications Institute
+University of Edinburgh
+80 South Bridge
+Edinburgh
+Scotland
+EH1 1HN
+
+EMAIL: J.Smart@ed.ac.uk
+TEL:   0131 650 2746
+
+
+
diff --git a/utils/tex2rtf/docs/refs.bib b/utils/tex2rtf/docs/refs.bib
new file mode 100644 (file)
index 0000000..0d145e5
--- /dev/null
@@ -0,0 +1,35 @@
+@techreport{robins87,
+author = {Robins, Gabriel},
+title = {The {ISI} grapher: a portable tool for displaying graphs pictorially (ISI/RS-87-196)},
+institution = {University of South California},
+year = {1987},
+month = {September}
+}
+@book{helpbook,
+author = {Boggan, Scott and Fakas, David and Welinske, Joe}
+, title = {Developing on-line help for {W}indows}
+, publisher = {Sams Publishing}
+, address = {11711 North College, Carmel, Indiana 46032, USA}
+, year = {1993}
+}
+@book{kopka,
+author = {Kopka, Helmut and Daly, Patrick W.}
+, title = {A Guide to LaTeX}
+, publisher = {Addison-Wesley}
+, year = {1993}
+}
+@book{pfeiffer,
+author = {Pfeiffer, Katherine Shelly}
+, title = {Word for Windows Design Companion}
+, publisher = {Ventana Press}
+, year = {1994}
+}
+@manual{smart93a,
+author = {Smart, Julian}
+, title = {wxWindows 1.50 User Manual}
+, publisher = {Artificial Intelligence Applications Institute}
+, organization = {University of Edinburgh}
+, address = {80 South Bridge, Edinburgh, EH1 1HN}
+, year = {1993}
+}
+
diff --git a/utils/tex2rtf/docs/screen.bmp b/utils/tex2rtf/docs/screen.bmp
new file mode 100644 (file)
index 0000000..5dacb09
Binary files /dev/null and b/utils/tex2rtf/docs/screen.bmp differ
diff --git a/utils/tex2rtf/docs/screen.gif b/utils/tex2rtf/docs/screen.gif
new file mode 100644 (file)
index 0000000..be8d929
Binary files /dev/null and b/utils/tex2rtf/docs/screen.gif differ
diff --git a/utils/tex2rtf/docs/screen.shg b/utils/tex2rtf/docs/screen.shg
new file mode 100644 (file)
index 0000000..5ec685c
Binary files /dev/null and b/utils/tex2rtf/docs/screen.shg differ
diff --git a/utils/tex2rtf/docs/tex2rtf.hpj b/utils/tex2rtf/docs/tex2rtf.hpj
new file mode 100644 (file)
index 0000000..1cd112a
--- /dev/null
@@ -0,0 +1,17 @@
+[OPTIONS]
+BMROOT=.
+TITLE=Tex2RTF Manual
+CONTENTS=Contents
+COMPRESS=HIGH
+
+[FILES]
+tex2rtf.rtf
+
+[CONFIG]
+CreateButton("Up", "&Up", "JumpId(`tex2rtf.hlp', `Contents')")
+BrowseButtons()
+
+[MAP]
+
+[BITMAPS]
+
diff --git a/utils/tex2rtf/docs/tex2rtf.ini b/utils/tex2rtf/docs/tex2rtf.ini
new file mode 100644 (file)
index 0000000..fae52d1
--- /dev/null
@@ -0,0 +1,21 @@
+; Tex2RTF initialisation file for 16-bit WinHelp
+runTwice = yes
+titleFontSize = 12
+authorFontSize = 10
+chapterFontSize = 12
+sectionFontSize = 12
+subsectionFontSize = 12
+headerRule = yes
+footerRule = yes
+useHeadingStyles = yes
+contentsDepth = 2
+listItemIndent=40
+winHelpContents = yes
+winHelpVersion = 3 ; 3 for Windows 3.x, 4 for Windows 95
+generateHPJ = yes
+htmlBrowseButtons = bitmap
+winHelpTitle = "Tex2RTF Manual"
+truncateFilenames = yes
+combineSubSections = yes
+htmlIndex = yes
+htmlFrameContents = no
diff --git a/utils/tex2rtf/docs/tex2rtf.tex b/utils/tex2rtf/docs/tex2rtf.tex
new file mode 100644 (file)
index 0000000..014c3e2
--- /dev/null
@@ -0,0 +1,3299 @@
+\documentstyle[a4,makeidx,verbatim,texhelp,fancyhea,mysober,mytitle]{report}%
+\input{psbox.tex}
+\newcommand{\commandref}[2]{\helpref{{\tt $\backslash$#1}}{#2}}%
+\newcommand{\commandrefn}[2]{\helprefn{{\tt $\backslash$#1}}{#2}\index{#1}}%
+\newcommand{\commandpageref}[2]{\latexignore{\helprefn{{\tt $\backslash$#1}}{#2}}\latexonly{{\tt $\backslash$#1} {\it page \pageref{#2}}}\index{#1}}%
+\newcommand{\indexit}[1]{#1\index{#1}}%
+\newcommand{\inioption}[1]{{\bf {\tt #1}}\index{#1}}%
+\parskip=10pt%
+\parindent=0pt%
+%\backgroundcolour{255;255;255}\textcolour{0;0;0}% Has an effect in HTML only
+\winhelpignore{\title{Manual for Tex2RTF 1.64:\\A \LaTeX\ to RTF and HTML converter}%
+\author{Julian Smart}%
+\date{October 1997}%
+}%
+\winhelponly{\title{Manual for Tex2RTF 1.64}%
+\author{by Julian Smart\\$$\image{1cm;0cm}{tex2rtf.wmf}$$}%
+}%
+\makeindex%
+\begin{document}%
+\maketitle%
+\pagestyle{fancyplain}%
+\bibliographystyle{plain}%
+\pagenumbering{roman}%
+\setheader{{\it CONTENTS}}{}{}{}{}{{\it CONTENTS}}%
+\setfooter{\thepage}{}{}{}{}{\thepage}%
+\tableofcontents%
+
+\chapter*{Copyright notice}%
+\setheader{{\it COPYRIGHT}}{}{}{}{}{{\it COPYRIGHT}}%
+\setfooter{\thepage}{}{}{}{}{\thepage}%
+
+Copyright (c) 1997 Julian Smart.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose is hereby granted without fee, provided that the
+above copyright notice, author statement and this permission notice appear in
+all copies of this software and related documentation.
+
+THE SOFTWARE IS PROVIDED ``AS-IS'' AND WITHOUT WARRANTY OF ANY KIND, EXPRESS,
+IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
+MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+IN NO EVENT SHALL JULIAN SMART OR THE ARTIFICIAL INTELLIGENCE
+APPLICATIONS INSTITUTE OR UNIVERSITY OF EDINBURGH BE LIABLE FOR ANY
+SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY
+OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+\chapter{Introduction}%
+\pagenumbering{arabic}%
+\setheader{{\it CHAPTER \thechapter}}{}{}{}{}{{\it CHAPTER \thechapter}}%
+\setfooter{\thepage}{}{}{}{}{\thepage}%
+
+This document describes a utility for converting \popref{\LaTeX}{latexgloss}\ files into
+several other formats.
+
+Only a subset of \LaTeX\ can be processed by this utility, especially
+since the target document language will never perfectly match \LaTeX.
+Whether the quality of the results is good enough will depend upon the
+application and your own expectations. {\it This caveat is worth emphasizing}, because
+many people assume that any old \LaTeX\ document will go through without modification: it might,
+but the chances are you'll need to modify it a bit for Tex2RTF. Tex2RTF was written with
+portable document maintenance and generation in mind, with less emphasis on accepting all \LaTeX\ syntax.
+You have been warned!
+
+Tex2RTF is heavily biased towards making on-line, hypertext versions of
+\rtfsp\LaTeX\ documents, but the \popref{RTF}{rtf} converter can be used to generate linear,
+paper-based documents too.
+
+The latest version of Tex2RTF, plus source code, can be accessedfrom:
+
+\begin{verbatim}
+http://web.ukonline.co.uk/julian.smart/tex2rtf
+ftp://www.remstar.com/pub/wxwin/tex2rtf
+\end{verbatim}
+
+It is available in Sun Open Look, Motif, Windows 3.1, Windows 95/NT, and
+non-GUI UNIX versions.
+
+Tex2RTF was developed using the free Open Look, Motif and Windows 3.1
+C++ class library \popref{wxWindows}{wxwindows}.
+
+\section{Status of Tex2RTF}\index{status of Tex2RTF}%
+
+Tex2RTF is under continual development, often following users'
+suggestions. From version 1.33, Tex2RTF is effectively in a second phase
+of development. In addition to the bare minimum of syntax and facilities
+for producing useable help systems or linear RTF, commands are being
+added to allow visually effective, even aesthetically pleasing,
+documentation to be produced.
+
+Examples are the \verb$\indented$, \verb$\twocollist$ and \verb$\marginpar$\rtfsp
+commands; over time I hope to be able to reproduce most of the popular
+styles of formatting and presentation in Windows Help files, whilst
+allowing a reasonable equivalent to be generated in the other formats.
+
+Some new developments in the various formats still need to be catered
+for by Tex2RTF, such as Windows 95 help files and HTML 3.0. Features
+that can be added to Tex2RTF as a result of these developments include
+math and inline image map support in HTML, table support in Windows
+Help, and generally better formatting abilities in both. However, documentation
+about these formats is sketchy at the time of writing (October 1995).
+
+\section{Acknowledgements}\index{acknowledgements}%
+
+Thanks are due to the many people in AIAI and on the Internet at large
+who have pointed out bugs or shortcomings in Tex2RTF. Michel Lavaud has been
+a great help in giving advice for improvements to the manual.
+
+\section{Change log}\index{change log}%
+
+Version 1.64, October 20th 1998
+
+\begin{itemize}\itemsep=0pt
+\item Added \verb$\insertatlevel$ command.
+\end{itemize}
+
+Version 1.63, October 21st 1997
+
+\begin{itemize}\itemsep=0pt
+\item Debugged problem with Word bookmarks not being inserted for unnumbered
+sections.
+\end{itemize}
+
+Version 1.62, August 18th 1997
+
+\begin{itemize}\itemsep=0pt
+\item Added contributed changes by Andreas Münzenmaier to support German
+accents by allowing the characters to be placed in input files, and also
+converting them back to character codes in the WinHelp {\tt .cnt} file.
+\item Now \verb$\helpref$ causes page references to be inserted in linear RTF,
+or section references if not on Word mode.
+\item WinHelp table caption bug fixed.
+\end{itemize}
+
+Version 1.61, June 11th 1997
+
+\begin{itemize}\itemsep=0pt
+\item \verb$\fcol$ now works in HTML using the FONT tag.
+\item \verb$\twocollist$ works in indented paragraphs, and is now
+implemented properly using tables in HTML.
+\item New boolean option {\bf combineSubSections} added, which switches off
+the generation of separate HTML files below section level. This can reduce the
+number of HTML files substantially.
+\end{itemize}
+
+Version 1.60, February 18th 1997
+
+\begin{itemize}\itemsep=0pt
+\item The index command now allows complex LaTeX instead of inserting the
+first argument verbatim.
+\end{itemize}
+
+Version 1.59, February 14th 1997
+
+\begin{itemize}\itemsep=0pt
+\item Added special processing for a chapter called Popups.
+\end{itemize}
+
+Version 1.58, August 1st 1996
+
+\begin{itemize}\itemsep=0pt
+\item Added HTML settings: backgroundImage, backgroundColour, textColour,
+linkColour, followedLinkColour. 
+\item Added \verb$\backgroundimage$, \verb$\backgroundcolour$, \verb$\linkcolour$,
+\verb$followedLinkColour$. \verb$\background$ now obsolete (but behaviour is
+backward compatible).
+\item The default background colour is now white.
+\item Debugged HTML \verb$\ss$ (put in wrong place in code).
+\end{itemize}
+
+Version 1.57, July 27th 1996
+
+\begin{itemize}\itemsep=0pt
+\item Added upperCaseNames setting; now all links in HTML files are in lower
+case unless specified otherwise.
+\end{itemize}
+
+Version 1.56, May 25th 1996
+
+\begin{itemize}\itemsep=0pt
+\item Debugged \verb$\special$ processing for HTML (escaped characters such ampersand).
+\item Added contentsDepth for Word RTF contents page.
+\item Removed overlapping href in HTML pages.
+\end{itemize}
+
+Version 1.55, May 6th 1996
+
+\begin{itemize}\itemsep=0pt
+\item \verb$\verb$ support corrected for HTML.
+\item Added {\it abstractName} setting.
+\item Debugged incorrect centring for HTML buttons.
+\end{itemize}
+
+Version 1.54, Feburary 28th 1996
+
+\begin{itemize}\itemsep=0pt
+\item Bug fix for 24-bit bitmap inclusion when generating RTF:
+caused a floating point error.
+\item Added htmlIndex setting, to generate an {\tt .htx} index file of an HTML document for
+use in wxHelp version 2 or other programs.
+\item Fixed header/footer bug.
+\item Change colons to spaces for WinHelp RTF keywords, since the colon has a specific meaning in WinHelp.
+\end{itemize}
+
+Version 1.53, January 1995
+
+\begin{itemize}\itemsep=0pt
+\item Now stores paths from file inclusions, so that if you include
+a file A from a separate directory, which then includes a file B
+relative to that directory, Tex2RTF will search in the path
+of A to find file B.
+\end{itemize}
+
+Version 1.52, December 1995
+
+\begin{itemize}\itemsep=0pt
+\item \verb$\helpref$ and related commands now generate italicized instead
+of bold `anchor' text for linear formats.
+\item Cured bug where Tex2RTF could hang on start up, while reading
+the {\tt tex2rtf.ini} file. This occurred when a comment finished with
+the end of file.
+\item Split the commands reference in two (\LaTeX\ and Tex2RTF commands),
+and added a {\it Commands by category} section.
+\item Removed a bug that caused HTML output to be garbled on the
+second pass.
+\end{itemize}
+
+Version 1.51: Windows 95 enhancements.
+
+\begin{itemize}\itemsep=0pt
+\item Added settings winHelpContents (for generating {\tt .cnt} file), winHelpVersion (for specifying
+target version of WinHelp).
+\item Added space to non-scrolling region of topic.
+\item If winHelpVersion is 4, makes non-scrolling region grey and the rest yellow.
+\item Added \verb$\settransparency$ command for WinHelp 4 transparent bitmaps.
+\end{itemize}
+
+Version 1.50:
+
+\begin{itemize}\itemsep=0pt
+\item Tidied up HTML generation (headers and bodies in the right places).
+\item Eliminated extra space after verbatim in HTML.
+\item Added support for simple tables in HTML.
+\item Added \verb$\textcolour$, \verb$\background$ for colouring text and background in HTML.
+\item Added \verb$\copyright$, \verb$\registered$ symbols in HTML.
+\item Added \verb$\imagel$, \verb$\imager$ for left and right aligned images
+in HTML.
+\item Added \verb$\brclear$ for clearing image alignment in HTML.
+\item Added \LaTeX\ font size support in HTML (\verb$\small$, \verb$\large$ etc.) using Netscape font extensions.
+\item HTML button-bar change: always shows the same buttons, but may make one or more insensitive. Changing button positions
+could be very annoying.
+\item Tidied up RTF generation for non-Word viewers ({\it useWord} set to {\it false}). Will now look reasonable using
+Windows 95 Quick View and WordPad: WordPad doesn't do tables but does bitmaps, and QuickView does tables but not
+bitmaps. Such is life.
+\end{itemize}
+
+Version 1.49:
+
+\begin{itemize}\itemsep=0pt
+\item Cured some bugs (char used for fgetc instead of int) so now compiles for
+WIN32s.
+\end{itemize}
+
+Version 1.48:
+
+\begin{itemize}\itemsep=0pt
+\item Added some LaTeX2e fonts commands such as \verb$\rmfamily$, \verb$\textrm$, \verb$\emph$.
+Most of these are aliases for other commands.
+\end{itemize}
+
+Up to version 1.47:
+
+\begin{itemize}\itemsep=0pt
+\item Added \verb$\backslashraw$, \verb$\rbraceraw$ and \verb$\lbraceraw$ commands
+to help output arbitrary RTF.
+\item Added \verb$\sethotspotcolour$, \verb$\sethotspotunderline$ commands for controlling
+WinHelp hotspot appearance.
+\item Added truncateFilenames option.
+\item Improved HTML inline image handling.
+\end{itemize}
+
+Up to version 1.46:
+
+\begin{itemize}
+\itemsep=0pt
+\item Added \verb$\urlref$ command for specifying HTML URLs.
+\item Started support for translating .SHG files to HTML .map files
+(this works if compiled under Borland, not MS VC++ for some reason!)
+\item Fixed nasty memory bug in HTML code (thanks Petr).
+\end{itemize}
+
+Version 1.40:
+
+\begin{itemize}
+\itemsep=0pt
+\item Added {\it generateHPJ} option for generating the .HPJ WinHelp project file
+\item Added support for DDE via a small command set
+\end{itemize}
+
+Version 1.39:
+
+\begin{itemize}
+\itemsep=0pt
+\item Option for using Word's INCLUDEPICTURE or IMPORT field, since the method that
+works for Works, doesn't work for Word! See {\it bitmapMethod} in the
+settings section.
+\end{itemize}
+
+Version 1.37-1.38:
+
+\begin{itemize}
+\itemsep=0pt
+\item Improved bibliography reading and cured some minor bugs
+\item Added \verb$\ss$ German sharp s
+\item Added rudimentary \verb$\special$ command (simply copies the argument
+to the output)
+\item Added missing '.' in subsubsection reference
+\item Added primitive internationalisation support with contentsName, tablesName etc.
+\end{itemize}
+
+Version 1.36:
+
+\begin{itemize}
+\itemsep=0pt
+\item All HTML special characters now correctly delimited by a semicolon.
+\item Cured HTML section-duplicating bug I introduced in 1.35.
+\item Cured too much spacing after sections in RTF, introduced in 1.35.
+\end{itemize}
+
+Version 1.35:
+
+\begin{itemize}
+\itemsep=0pt
+\item Added TCHECK tool, to help track down common Tex2RTF syntax problems.
+\item Included Kresten Thorup's LACHECK \LaTeX\ checking tool with DOS executable.
+\item Now ignores \verb|\@| command.
+\item Table of contents now includes numbered subsubsections.
+\end{itemize}
+
+Version 1.34:
+
+\begin{itemize}
+\itemsep=0pt
+\item Added \verb$\multicolumn$ `support' to stop RTF readers crashing.
+\item Added {\it useWord, defaultColumnWidth, compatibility} options to {\tt .ini} file.
+\item \verb$\comment$ environment now doesn't complain about unknown syntax.
+\item Added \verb$\toocomplex$ environment that treats its contents as
+verbatim in output, treated as normal output in true \LaTeX.
+\item End-of-line comments allowed in in {\tt .ini} files, using semicolon,
+percent or hash characters to denote a comment.
+\item For linear RTF, Word for Windows support for \verb$\printindex$,\rtfsp
+\verb$\index$, \verb$\pageref$, \verb$\listoftables$, \verb$\listoffigures$, contents page.
+\item Added RTF support for various symbols.
+\item Added colour support, with \verb$\definecolour$, \verb$\fcol$ and \verb$\bcol$ commands.
+\item Fixed some bugs: page numbering problems, macros deleted after first pass.
+\end{itemize}
+
+Version 1.33:
+
+\begin{itemize}
+\itemsep=0pt
+\item Added -charset command-line switch.
+\item Added \verb$\itemsep$, \verb$\twocolumn$, \verb$\onecolumn$, \verb$\setfooter$, \verb$\setheader$, \verb$\pagestyle$,
+\verb$\pagenumbering$, \verb$\thechapter$, \verb$\thesection$, \verb$\thepage$, \verb$\thebibliography$, \verb$\bibitem$ commands.
+\item New environment called \verb$\twocollist$ for making two-column lists,
+with formatting optimized for target file format.
+\item New \verb$\indented$ environment for controlling indentation.
+\item List indentation and bulleting improved.
+\item Added commands \verb$\normalbox$, \verb$\normalboxd$ for putting borders around text.
+\item Many options can now be specified in the {\tt .ini} file along with custom macros.
+\item Cured bug that put too much vertical space after some commands.
+\item Improved table formatting.
+\item Optional `Up' button in WinHelp files for easier navigation.
+\item Verbatim lines followed by \verb$\par$ in RTF, to improve WinHelp wrapping.
+\item Conversion may now be aborted under Windows by attempting to close the application.
+\item Added conditional output for all formats: \verb$\latexignore$, \verb$\latexonly$, \verb$\rtfignore$, \verb$\rtfonly$,
+\verb$\winhelpignore$, \verb$\winhelponly$, \verb$\htmlignore$, \verb$\htmlonly$, \verb$\xlpignore$, \verb$\xlponly$.
+\item HTML generator can now add Contents, Up, $<<$ and $>>$ buttons (text or bitmap) to
+each page except titlepage.
+\end{itemize}
+
+Version 1.32:
+
+\begin{itemize}
+\itemsep=0pt
+\item \verb$\footnote$ command now supported in WinHelp RTF, and \verb$\footnotepopup$\rtfsp
+added.
+\end{itemize}
+
+Version 1.31:
+
+\begin{itemize}
+\itemsep=0pt
+\item \verb$\footnote$ command now supported, in linear RTF only.
+\item Added {\tt -bufsize} option, for converting large documents.
+\end{itemize}
+
+Version 1.30:
+
+\begin{itemize}
+\itemsep=0pt
+\item \verb$\image$ command now scales metafiles (but not bitmaps).
+\item Fixed macro loading bug, now informs the user of the found macro filename.
+\item Now supports paragraph and subparagraph commands.
+\item Support for some accents added.
+\item \verb$\verb$ command now supported.
+\item Bug in subsubsection handling fixed.
+\item Can save conversion log in a text file.
+\end{itemize}
+
+Version 1.22:
+
+\begin{itemize}
+\itemsep=0pt
+\item More informative, warns against use of some commands.
+\item Added compile-time support for non-GUI environments (such as plain UNIX).
+\item Improved HTML support.
+\end{itemize}
+
+\chapter{Running Tex2RTF}\index{running Tex2RTF}%
+\setheader{{\it CHAPTER \thechapter}}{}{}{}{}{{\it CHAPTER \thechapter}}%
+\setfooter{\thepage}{}{}{}{}{\thepage}%
+
+Tex2RTF may be run in a number of ways: with or without command line arguments,
+interactively or in batch mode, and with an optional initialisation file
+for specifying \LaTeX\ macros and detailed options.
+
+Tex2RTF accepts two arguments (input and output filenames) and trailing
+(optional) switches.  If both filenames are given, the utility will work
+in batch mode.  Otherwise, if Tex2RTF has been compiled for GUI
+operation, a main window will be shown, with appropriate menu items for
+selecting input and output filenames, starting off the conversion
+process, and so on.
+
+Note that if the file {\tt bullet.bmp}\index{bullets} is found by Tex2RTF, this bitmap
+will be used as the bullet for items in \verb$\itemize$ lists, for WinHelp
+output. Otherwise, a symbol will be inserted (linear RTF) or bold `o'
+will be used instead (all other formats).
+
+Syntax error reporting is fairly minimal. Unrecognised macro errors may
+actually be produced by an unbalanced brace or passing the wrong number of
+arguments to a command, so look in the vicinity of the error for the
+real cause.
+
+\normalbox{Some of the syntax that is OK for true \LaTeX\ but which trips up
+Tex2RTF, may be detected by the TCHECK\index{TCHECK} program included in the tools
+directory of the Tex2RTF distribution. Some \LaTeX\ errors may be picked up
+by the LACHECK\index{LACHECK} program, also found in the tools directory.}
+
+It is recommended that you run Tex2RTF twice in order to be sure of
+resolving all references and including an up-to-date contents page.
+
+If importing RTF files into Word for Windows\index{Microsoft Word}, you may need to reformat
+the document. The easiest way to do this is to select all text with
+CTRL-A, then reformat with F9. Reformat again to ensure all references
+are resolved. For the second format, respond with {\it Update Entire
+Table} to prompts.
+
+\winhelponly{
+\section{Tex2RTF Interface}
+
+This is the Tex2RTF interface under Windows. Click on an area of the
+picture for more information.
+
+$$\imagemap{1cm;0cm}{screen}{mapref}$$
+
+\subsection{Menu bar}\label{menubar}
+
+Use the menubar for interactive operations.
+
+\subsection{Message area}\label{messagearea}
+
+Tex2RTF writes warning and error messages on this window.
+
+\subsection{Status line}\label{statusline}
+
+Displays help on menu items as the user drags the cursor over the menus.
+
+\subsection{Mode indicator}\label{modeindicator}
+
+Displays the output mode Tex2RTF is currently in.
+}
+
+\section{Command line arguments}\index{command line arguments}%
+
+These are the optional arguments you may give Tex2RTF on the command line.
+
+\twocolwidtha{5cm}
+\begin{twocollist}
+\twocolitem{{\bf -bufsize}}{Specifies buffer size in K (default 60 under Windows,
+500 under UNIX). Large files (particularly large verbatim environments)
+may require a large buffer size, equal to the largest argument of a \LaTeX\ command.
+Note that this value may not be larger than 64 under Windows.}
+\twocolitem{{\bf -html}}{Specifies HTML (World Wide Web) output.}
+\twocolitem{{\bf -interactive}}{Forces interactive mode even if both
+filenames are given.}
+\twocolitem{{\bf -charset charset}}{Specifies a character set for
+RTF production. This can be one of ansi, mac, pc, and pca.
+The default is ansi.}
+\twocolitem{{\bf -macros filename}}{Specifies a file for the custom macro
+file -- see \helpref{Macro not found error}{macronotfound}.}
+\twocolitem{{\bf -rtf}}{Specifies linear RTF output.}
+\twocolitem{{\bf -sync}}{Forces synchronous mode (no yielding to other
+processes) -- usually use this in non-interactive mode.}
+\twocolitem{{\bf -twice}}{Tells Tex2RTF to run the conversion twice to ensure all
+references and citations are resolved and the contents page included.}
+\twocolitem{{\bf -winhelp}}{Specifies Windows Help RTF output.}
+\end{twocollist}
+
+\section{Initialisation file syntax}\label{inifile}\index{initialisation file}%
+
+The initialisation file contains further detailed options for
+customising Tex2RTF's behaviour. A file may be specified
+with the {\tt -macros} command line switch, otherwise Tex2RTF
+looks for the file {\tt tex2rtf.ini} in the working directory
+or input file directory.
+
+The file may comprise macro\index{macros} (command) definitions or option settings.
+
+The syntax for a macro definition is:
+
+\begin{verbatim}
+    \name [number of args] {...LaTeX code...}
+\end{verbatim}
+
+For example:
+
+\begin{verbatim}
+    \crazy      [2]{{\bf #2} is crazy but #1 is not}
+    \something  [0]{}
+    \julian     [0]{Julian Smart}
+\end{verbatim}
+
+The syntax for an option setting is:
+
+\begin{verbatim}
+    name = value
+\end{verbatim}
+
+or 
+
+\begin{verbatim}
+    name = "value"
+\end{verbatim}
+
+For example:
+
+\begin{verbatim}
+    conversionMode = RTF
+    runTwice = true
+    titleFontSize = 12
+    authorFontSize = 10
+    headerRule = yes
+    footerRule = yes
+\end{verbatim}
+
+Options expecting boolean values accept {\it 1, 0, true, false, yes, no} in any combination of upper or
+lower case.
+
+End-of-line comments are allowed in an initialisation file, using the
+hash, semicolon or percent signs to denote the start of a comment, which runs
+until the end of the line.
+
+\subsection{Tex2RTF options}\index{options in initialisation file}\index{tex2rtf.ini}\index{initialisation file}\index{macros}%
+
+These are the allowable options in an initialisation file.
+
+\subsubsection{General options}\label{generaloptions}
+
+\twocolwidtha{5cm}
+\begin{twocollist}
+\htmlignore{\twocolitemruled{Option}{Description}}
+\twocolitem{\inioption{compatibility}}{Set to true for maximum \LaTeX\ compatibility, e.g. if
+tables crash RTF readers. Should be false (default) if the Tex2RTF guidelines
+are followed, e.g. use of $\backslash${\tt row} command in tabular environment.}
+\twocolitem{\inioption{conversionMode}}{One of RTF, WinHelp, XLP (or wxHelp), and HTML.}
+\twocolitem{\inioption{ignoreInput}}{Adds the filename to the list of files ignored by the $\backslash${\tt input} command.
+The only default filename in the list is {\tt psbox.tex}.}
+\twocolitem{\inioption{isInteractive}}{If true, runs in interactive mode (the default).}
+\twocolitem{\inioption{runTwice}}{If true, runs the converter twice.}
+\end{twocollist}
+
+\subsubsection{Presentation options}\index{options, presentation}%
+
+\begin{twocollist}
+\htmlignore{\twocolitemruled{Option}{Description}}
+\twocolitem{\inioption{authorFontSize}}{Specifies the point size for the author and date (RTF only).}
+\twocolitem{\inioption{chapterFontSize}}{Specifies the point size for chapter headings (RTF only).}
+\twocolitem{\inioption{documentFontSize}}{One of 10, 11 and 12, to specify the main font size
+independently of the \LaTeX\ document style command.}
+\twocolitem{\inioption{sectionFontSize}}{Specifies the point size for section headings (RTF only).}
+\twocolitem{\inioption{subsectionFontSize}}{Specifies the point size for subsection headings (RTF only).}
+\twocolitem{\inioption{titleFontSize}}{Specifies the point size for the title (RTF only).}
+\twocolitem{\inioption{chapterName}}{The string used when referencing chapters. The default is ``chapter".}
+\twocolitem{\inioption{sectionName}}{The string used when referencing sections. The default is ``section".}
+\twocolitem{\inioption{subsectionName}}{The string used when referencing subsections. The default is ``subsection".}
+\twocolitem{\inioption{subsubsectionName}}{The string used when referencing subsubsections. The default is ``subsubsection".}
+\twocolitem{\inioption{indexName}}{The string used for printing the index heading. The default is ``Index".}
+\twocolitem{\inioption{contentsName}}{The string used for printing the contents heading. The default is ``Contents".}
+\twocolitem{\inioption{abstractName}}{The string used for printing the abstract heading. The default is ``Abstract".}
+\twocolitem{\inioption{tablesName}}{The string used for printing the list of tables heading. The default is ``List of Tables".}
+\twocolitem{\inioption{tableName}}{The string used when referencing a table. The default is ``table".}
+\twocolitem{\inioption{figuresName}}{The string used for printing the list of figures heading. The default is ``List of Figures".}
+\twocolitem{\inioption{figureName}}{The string used when referencing a figure. The default is ``figure".}
+\twocolitem{\inioption{glossaryName}}{The string used for printing the glossary heading. The default is ``Glossary".}
+\twocolitem{\inioption{referencesName}}{The string used for printing the references heading. The default is ``References".}
+\end{twocollist}
+
+\subsubsection{RTF and WinHelp options}\label{rtfwinhelpoptions}\index{options, RTF}\index{RTF}%
+
+\begin{twocollist}
+\htmlignore{\twocolitemruled{Option}{Description}}
+\twocolitem{\inioption{bitmapMethod}}{Can be ``hex'' (embed the hex data in the file with a $\backslash$dibitmap keyword),
+``includepicture'' (use the MS Word 6.0 INCLUDEPICTURE field) or ``import'' (an earlier name
+for INCLUDEPICTURE). ``hex'' may be used for importing into MS Works, but this doesn't work
+for Word 6.0. The default is ``includepicture''.}
+\twocolitem{\inioption{contentsDepth}}{The depth of headings that is displayed in the table of contents. The default
+is 4 but you may wish to reduce this, for example for manuals that document C++ and have a large number of
+headings for member functions.}
+\twocolitem{\inioption{defaultColumnWidth}}{The width in points for columns in tables
+where the width of the column is not set by using {\it p} in the tabular
+argument. The default is 100.}
+\twocolitem{\inioption{footerRule}}{If true, draws a rule above footers (linear RTF only).}
+\twocolitem{\inioption{generateHPJ}}{If true, generates a .HPJ project file (WinHelp mode only).}
+\twocolitem{\inioption{headerRule}}{If true, draws a rule below headers (linear RTF only).}
+\twocolitem{\inioption{listLabelIndent}}{Specifies the size of list item label indentation, in points.
+The default is 18.}
+\twocolitem{\inioption{listItemIndent}}{Specifies the size of list item indentation, in points. The default
+is 40.}
+\twocolitem{\inioption{indexSubsections}}{If true (the default), subsection and subsubsection
+titles are indexed in RTF mode.}
+\twocolitem{\inioption{mirrorMargins}}{If true, margins are mirrored in twosided documents (linear RTF only).}
+\twocolitem{\inioption{useWord}}{If true (the default), Word for Windows RTF
+formatting is used where possibly, e.g. for the table of contents, list of
+tables, and list of figures.}
+\twocolitem{\inioption{useHeadingStyles}}{If true (the default), sections are marked with
+appropriate heading styles for generating the table of contents in RTF.}
+\twocolitem{\inioption{useUpButton}}{If true (the default), WinHelp files will be generated with an {\bf Up}\rtfsp
+button to make browsing easier. Note that you need to put an extra line in the CONFIG section
+of your .HPJ file:
+
+{\tt CreateButton("Up", "\&Up", "JumpId(`name.hlp', `Contents')")}
+
+where {\tt name.hlp} is the name of your help file.}
+%%% NEED TO BREAK THE LIST AT THE PAGE BREAK BECAUSE LATEX IS STUPID
+%%% UNFORTUNATELY, Tex2RTF IS STUPIDER SO NEED TO COMMENT OUT THIS
+%%% LINE WHEN MAKING HTML, RTF, XLP
+%\latexonly{\end{twocollist}\newpage\begin{twocollist}}
+\twocolitem{\inioption{winHelpContents}}{If yes, ok or true, a WinHelp {\tt .cnt} file will be generated (used in Windows 95 for either old WinHelp
+files or new WinHelp 4 files).}
+\twocolitem{\inioption{winHelpVersion}}{The version of WinHelp being targetted. This affects the generated {\tt .hpj} file and features
+such as transparent bitmaps which are new to version 4 or later. The default is 3.}
+\twocolitem{\inioption{winHelpTitle}}{Windows Help file title, inserted into the project file if {\it generateHPJ} is true.}
+\end{twocollist}
+
+\subsubsection{HTML options}\label{htmloptions}\index{options, HTML}\index{HTML}%
+
+\begin{twocollist}
+\htmlignore{\twocolitemruled{Option}{Description}}
+\twocolitem{\inioption{htmlBrowseButtons}}{Allows generation of Contents, Up, browse back and browse forward
+buttons on each HTML page except title page. Specify none, text or bitmap. If you specify
+bitmap, make sure that the files {\tt contents.gif}, {\tt up.gif}, {\tt back.gif} and {\tt forward.gif} are in the
+directory where the HTML files will reside: samples are given in the docs directory.}
+\twocolitem{\inioption{truncateFilenames}}{If true, uses {\tt .htm} suffix instead of {\tt .html},
+and truncates filenames within HTML documents.}
+\twocolitem{\inioption{htmlIndex}}{If true, specifies generation of an {\tt .htx} index file for an HTML document.
+This file can be used in wxHelp version 2 or other programs. The file consists of a number of lines,
+each line with three fields separated by bar characters: the indexed phrase, the file, and a label in the file.}
+\twocolitem{\inioption{upperCaseNames}}{If true, filenames in links are in upper case. By default
+filenames are in lower case.}
+\twocolitem{\inioption{backgroundColour}}{Specifies the RGB background colour for the document, e.g. {\tt 255;255;255} for white.
+The default is white.}
+\twocolitem{\inioption{backgroundImage}}{Specifies the RGB background image for the document, e.g. {\tt tile.gif}.}
+\twocolitem{\inioption{textColour}}{Specifies the RGB text colour for the document, e.g. {\tt 0;0;0} for black.}
+\twocolitem{\inioption{linkColour}}{Specifies the RGB link colour for the document, e.g. {\tt 0;0;255} for blue.}
+\twocolitem{\inioption{followedLinkColour}}{Specifies the RGB followed link colour for the document, e.g. {\tt 0;0;255} for blue.}
+\twocolitem{\inioption{combineSubSections}}{If true (or yes), switches off
+the generation of separate HTML files below section level. This can reduce the
+number of HTML files substantially. A subsection contents list is inserted before
+the first subsection.}
+\end{twocollist}
+
+\section{DDE commands}\index{DDE}%
+
+A Windows program can hold a conversation with Tex2RTF using DDE. The Tex2RTF server name is
+``TEX2RTF'', and the topic name to use is also ``TEX2RTF''.
+
+Tex2RTF functionality is accessed using the DDE {\it Execute} message.
+The {\it Execute} data should consist of a command name and possibly one
+argument, e.g.
+
+\begin{verbatim}
+    INPUT c:\docs\mine.tex
+\end{verbatim}
+
+If the command is not recognised, a standard TEX2RTF.INI option is assumed.
+
+The {\it Request} DDE message can be used to query the return status of an {\it Execute}
+command, and will be one of {\it OK} (no error), {\it CONVERSION ERROR}, or a more
+specific error string.
+
+The following DDE commands may be used:
+
+\begin{twocollist}
+\htmlignore{\twocolitemruled{Command}{Description}}
+\twocolitem{\inioption{EXIT}}{Takes no argument, and exits Tex2RTF.}
+\twocolitem{\inioption{GO}}{Takes no argument, and initiates the conversion.}
+\twocolitem{\inioption{INPUT}}{Takes a file name as the argument, and sets the input file to be this name.}
+\twocolitem{\inioption{MINIMIZE}}{Takes no argument, and minimizes Tex2RTF.}
+\twocolitem{\inioption{OUTPUT}}{Takes a file name as the argument, and sets the input file to be this name.}
+\twocolitem{\inioption{RESTORE}}{The same as SHOW.}
+\twocolitem{\inioption{SHOW}}{Takes no argument, and unminimizes Tex2RTF.}
+\end{twocollist}
+
+\section{Performance issues}\index{performance}%
+
+Since Tex2RTF reads the whole file into memory, a lot of memory is needed.
+For very large documents, 16MB of RAM is adviseable.
+
+I tested conversion of the wxWindows 1.63 manual on both VC++ 1.5 and
+Watcom WIN32s versions of Tex2RTF, both running under Windows 3.11 on a
+Gateway P60 with 16MB of RAM and a 2MB disk cache. Two passes were
+made, with 1.5MB of WinHelp RTF being generated. The unoptimized 16-bit
+version took 169 seconds. The optimized WIN32s version took 126 seconds,
+a significant improvement. Systems with faster disk subsystems should see
+an even better relative performance of the 32-bit version.
+
+\chapter{Writing documents with Tex2RTF}\index{LaTeX}%
+\setheader{{\it CHAPTER \thechapter}}{}{}{}{}{{\it CHAPTER \thechapter}}%
+\setfooter{\thepage}{}{}{}{}{\thepage}%
+
+\section{Why use \LaTeX?}
+
+\LaTeX\ happens to be a very convenient format if you need to produce
+documents (such as manuals, help facilities, up-to-date information) in
+both printed and on-line media. Being a language rather than a WYSIWYG system,
+it allows explicit specification of layout and document structure, lending
+itself well to hypertext applications and automatic document generation.
+Many people also prefer to use \LaTeX\ for ordinary use since it encourages
+a logical document structure and the user is not distracted by having to perfect
+the appearance; many layout decisions are taken by \LaTeX\ automatically.
+
+Although \LaTeX\ is not as fancy as modern word processors and desk-top
+publishing packages, it is for many purposes quite adequate, and sometimes
+more flexible than its modern counterparts.
+
+The conversion utility gives \LaTeX\ a new lease of life by allowing
+virtually all other wordprocessor formats to be generated from documents
+containing a reasonable subset of \LaTeX\ syntax. From the same \LaTeX\ 
+sources, we can now generate printed manuals, Windows Help files, \popref{wxHelp}{wxhelp}\rtfsp
+files, RTF-compatible word processor formats such as MS Word, and \popref{HTML}{html}\rtfsp
+files for use in the World Wide Web. Since the conversion tool is
+free, as are \LaTeX, HTML viewers, wxHelp and (effectively) Windows
+Help, there are no financial or time penalties for providing
+documentation in a wide range of printed and hypertext formats.
+
+\section{Help versus the printed page}\index{on-line help}%
+
+The purist may argue, quite rightly, that on-line help systems and
+printed manuals have different characteristics; help windows tend to be
+much smaller than pages, help topics should be more stand-alone than
+pages in a manual, navigation methods are very different, etc. Therefore,
+help systems should be {\it based} on printed documentation but
+separately hand-crafted into hypertext help, preferably by an
+independent person or team.
+
+This might be the ideal, but many organisations or individuals simply
+do not have the time: on-line help wouldn't get done if the
+documentation effort had to be doubled. However, Tex2RTF does provide
+some commands to allow tailoring the documentation to printed or
+on-line form, such as \verb$\helponly$ and \verb$\helpignore$. An awareness
+of the design issues should go a long way to making the compromise
+a good one, so a book such as {\it Developing On-line Help for Windows} \cite{helpbook} is highly recommended.
+
+\section{Output Formats}\index{output formats}%
+
+At present the following output formats are supported:
+
+\begin{itemize}
+\itemsep=0pt
+\item RTF (Rich Text Format)\index{RTF}. This is the most well developed
+converter. RTF is commonly used as a document exchange format amongst
+Windows-based applications, and is the input for the Windows Help
+Compiler. Tex2RTF supports both linear documents and Windows Help
+hypertext format.
+\item HTML (Hypertext Markup Language)\index{HTML}. This an SGML-based format
+commonly used by documents in the World Wide Web distributed hypertext
+system, and formats text dynamically rather like Windows Help.
+\item wxHelp\index{wxHelp}. This is the platform-independent help system for
+the class library wxWindows (see the wxWindows User Manual \cite{smart93a}).
+It can display ASCII files with embedded codes
+for changing font styles, but no formatting is done by wxHelp.
+\end{itemize}
+
+\section{What compromises must I make?}\index{compromises}\index{LaTeX}%
+
+As a \LaTeX\ user, you need to be aware that some commands or facilities
+don't transfer to other formats, either because they are not supported
+by the target format or because the converter does not support them. 
+Maths formatting is a good example of an unsupported feature.
+
+Sometimes \LaTeX\ facilities must be accessed in a slightly different
+way to support the variety of formats, particularly hypertext formats
+where \LaTeX\ references are often replaced by hypertext jumps (but must
+still look right in printed documentation). Tables don't transfer well
+to RTF and HTML (and not at all to wxHelp) but an attempt is made
+to approximate tables so long as special row commands are used, instead
+of the usual end of row delimiter.
+
+Bibliographies are handled quite well since the utilities can read in\rtfsp
+{\tt .bib} files and resolve citations. Numbers are used in citations;
+the references are not yet sorted alphabetically.
+
+Pictures\index{pictures} are handled in a limited way: if the PSBOX\index{PSBOX} macro package is
+used, an \verb$\image$ command can be used to place Encapsulated PostScript
+files in \LaTeX, and Windows RGB-encoded bitmap files or placeable
+metafiles when converting to RTF.
+
+Nested file inclusion\index{file inclusion} is handled with \verb$\input$, \verb$\include$ and \verb$\verbatiminput$,
+and the comment environment is supported. However, using \verb$\input$\rtfsp
+to include macro packages is not advisable. If you do this,
+make sure you add a line in the Tex2RTF initialisation file to ignore
+this file, unless it's a simple \LaTeX\ file that conforms to Tex2RTF
+restrictions. The file {\tt psbox.tex} is the only file ignored
+by Tex2RTF by default.
+
+Because of the way \LaTeX\ is parsed, some syntax\index{syntax restrictions} has to conform to a
+few simple rules. Commands such as \verb$\bf$ and \verb$\it$ need to occur
+immediately after a left brace, and have a block of their own, since
+the text within their scope is regarded as its argument. This syntax
+means the same thing as using \verb$\begin ... \end$, which is usually
+a one argument command (the argument is the text between the \verb$\begin$\rtfsp
+and \verb$\end$). See \helpref{Space}{space}.
+
+As a Windows hypertext help writer\index{on-line help}, you don't have access to all RTF
+commands but you'll be able to get most of what you want. In particular,
+any \LaTeX\ document you write will automatically be a hypertext
+document, because the converter takes advantage of the hierarchy of
+sections. Further jumps can be placed using the commands
+\rtfsp\commandrefn{label}{label}, \commandrefn{helpref}{helpref},
+\rtfsp\commandrefn{helprefn}{helprefn}, and \commandrefn{popref}{popref}.
+Tex2RTF outputs help files that may be read linearly using the
+\rtfsp$<<$ and $>>$ buttons, and an additonal Up button for
+ease of navigation.
+
+When writing HTML, multiple files are generated from one \LaTeX\ file
+since browsing HTML works best with many small files rather than a few
+large ones.
+
+wxHelp files are least well supported since there is no formatting
+support, only font style, sizes and colours. Still, some hypertext help
+support on UNIX/X platforms is better than none. wxHelp is now being rewritten (March 1996)
+to use HTML files.
+
+Sometimes you will use a local macro package that is unrecognised by
+the converters. In this case, you may define a custom macro file
+where macros are defined in terms of supported \LaTeX\ commands
+and text. Even if the result is not the same as in \LaTeX, you
+can probably end up with something adequate, and at least avoid
+undefined macro errors. See \helpref{Initialisation file syntax}{inifile} for
+further information.
+
+\section{Changes to LaTeX syntax}
+
+Here are the conventions you need to observe to satisfy the Tex2RTF
+parser.
+
+\subsection{Space}\label{space}\index{space}%
+
+Tex2RTF attempts to insert spaces where \LaTeX\ assumes whitespace.
+However, for the benefit of RTF conversion, you need to use the \commandrefn{rtfsp}{rtfsp} command
+where a command or brace within a paragraph begins or ends with a macro. For example:
+
+\begin{verbatim}
+    Within a paragraph, you need to be careful about commands
+    \rtfsp{\it that begin at the start of a line.}
+\end{verbatim}
+
+As normal with \LaTeX, two newlines represents a paragraph break,
+although \commandrefn{par}{par} can also be used at the end of a paragraph.
+
+You need to have a blank line between section and some environment
+commands and the first paragraph or your document will look rather
+weird, e.g. headings running into paragraphs.
+
+wxHelp is more fussy than \LaTeX\ or RTF: you need to use percent
+characters at line ends liberally to eliminate newlines after commands
+on single lines.
+
+\subsection{Command arguments}\index{LaTeX commands}%
+
+Commands that have one or more arguments can be used in the following
+three ways:
+
+\begin{verbatim}
+    \bf{Some text.}
+
+    \begin{bf}
+    Some text.
+    \end{bf}
+
+    {\bf Some text.}
+\end{verbatim}
+
+The first method is a normal \LaTeX\ command.
+
+The second method is called an {\it environment}; \LaTeX\ has specific
+environments that do not always correspond to normal commands, but
+Tex2RTF recognizes environments and normal commands interchangeably, so
+long as the command has no more than two arguments.
+
+With the third method, it is important that the command has its own
+pair of braces, and that the command immediately follows the first brace.
+Otherwise, the parser cannot parse the argument(s) properly.
+With multiple arguments, each should be enclosed in braces.
+
+Optional arguments are specified using square brackets or parentheses.
+
+The braces that start command arguments must not be seperated from
+the other arguments by whitespace. For example, the following produces
+an error:
+
+\begin{verbatim}
+    \image{5cm;0cm}
+    {picture.eps}
+\end{verbatim}
+
+and should be replaced by 
+
+\begin{verbatim}
+    \image{5cm;0cm}{picture.eps}
+\end{verbatim}
+
+\subsection{Avoid the setlength command}
+
+Using the $\backslash$setlength command doesn't work, since its first
+argument looks like a command with the wrong number of arguments. Use an
+alternative form instead, e.g.
+
+\begin{verbatim}
+    \parindent 0pt
+\end{verbatim}
+
+instead of
+
+\begin{verbatim}
+    \setlength{\parindent}{0pt}
+\end{verbatim}
+
+\subsection{Units}\index{units}%
+
+Only a subset of \LaTeX\ units may be used for specifying dimensions.
+Valid units are {\tt pt, mm, cm} and {\tt in}. Units should usually
+be specified for dimensions or the results may be unexpected.
+
+\subsection{Labels}\index{labels}%
+
+The \verb$\label$ command may be used for sections and figure captions,
+but must come immediately after the section or caption commands with no
+intervening whitespace.
+
+\subsection{Tables}\label{tables}\index{tables}%
+
+For best layout, table rows should be enclosed in a \verb$\row$\rtfsp
+or \verb$\ruledrow$ command, since Tex2RTF can't cope with parsing
+the \LaTeX\ tabular syntax unaided. However, if you really don't want
+to go through \LaTeX\ files inserting new syntax, set the {\it compatibility}\rtfsp
+flag to TRUE in your {\tt tex2rtf.ini} file. In this mode, Tex2RTF tries to make
+the best of a bad job, but the results won't be optimal (e.g., no table
+borders). Without this flag set, normal \LaTeX\ tables can crash RTF readers
+such as Word for Windows.
+
+\section{Tex2RTF for non-LaTeX users}\index{LaTeX}%
+
+You don't need to have \LaTeX\ installed to use Tex2RTF. You
+can still output RTF files to be imported into your favourite
+word processor, and hypertext files for on-line help.
+
+This chapter gives a very brief introduction to \LaTeX. For further
+information, Kopka and Daly's {\it A Guide to \LaTeX} \cite{kopka} is
+recommended.
+
+\subsection{What is \LaTeX?}
+
+\LaTeX\ is a macro package built on top of the typesetting package,
+\TeX. \TeX\ was written by Donald Knuth in the 1970s, and Leslie
+Lamport wrote \LaTeX\ as a higher-level, easier way to write \TeX.
+
+\TeX\ was quite advanced for its day, and is still used (particularly by
+academics) because of its free availability and its flexibility in
+typesetting maths and other symbols. It's more like a programming
+language than a word processor, with embedded commands prefixed by a
+backslash and block structure. Like programs, \TeX\ documents are
+processed by a `compiler', outputting a .dvi file, which is a device
+independent file which can be read by many converters for output
+onto physical devices, such as screens and printers.
+
+A reason for its longevity is the ability to add facilities to
+\TeX, using macro packages that define new commands.
+
+\LaTeX\ is the most popular way to write \TeX. Although WYSIWYG
+word processors and DTP packages are outstripping \LaTeX, the increasing
+interest in hypertext and mark-up languages makes \LaTeX\ relevant as
+a similar language to SGML documents (such as World Wide Web HTML files).
+
+Also, languages such as \LaTeX\ (and Rich Text Format, which it resembles
+in many ways) are {\it complementary} to WYSIWYG packages. These languages
+allow automatic production and translation of documents, where manual
+mark-up is impractical or undesirable.
+
+Since the source code of \TeX\ and \LaTeX\ is in the public domain,
+there are many free and commercial implementations of \LaTeX\ for almost
+every computer in existance. Of PC implementations, EmTeX is arguably
+the best and most complete. You can download it from various FTP sites.
+
+If you don't want to use \LaTeX\ itself, you may wish to use a program
+called lacheck to check your documents before using Tex2RTF, since it
+catches some mistakes that Tex2RTF doesn't.
+
+\subsection{Document structure}
+
+Here is a sample of a typical \LaTeX\ document:
+
+\begin{verbatim}
+    \documentstyle[a4,texhelp]{report}
+    \title{A title}
+    \author{Julian Smart}
+    \date{October 1993}
+    \begin{document}
+    \maketitle
+
+    \chapter{Introduction}
+
+    ...
+
+    \section{A section}
+
+    ...
+
+    \end{document}
+\end{verbatim}
+
+The first line is always a \verb$\documentstyle$ command. The square brackets
+enclose optional {\it style} files (suffix {\tt .sty}) that alter the appearance
+of the document or provide new commands, and the curly brackets enclose
+the mandatory style, in this case `report'.
+
+Before the document begins properly with \verb$\begin{document}$,
+you can write various commands that have an effect on the appearance of the
+document or define title page information. The \verb$\maketitle$ command
+writes the title page using information defined previously (title, author,
+date).
+
+A report has chapters, which are divided into sections, and can be further
+divided into subsections and subsubsections. To start a new section, you
+write the appropriate section command with the section heading; there is
+no specific end section command, since a new section heading or the end
+of the document will indicate the end of the previous section.
+
+An article is divided into sections, subsections and subsubsections, but
+has no chapters. This is so an article can be included in a report as a chapter.
+
+Tex2RTF is written to deal with reports best, so stick with the report
+style if you can.
+
+\subsection{Command syntax}
+
+There are several kinds of commands in \LaTeX. Most involve a keyword
+prefixed with a backslash. Here are some examples:
+
+\begin{verbatim}
+    \titlepage
+
+    \centerline{This is a centred line}
+
+    \begin{center}
+    This is a centred
+    paragraph
+    \end{center}
+
+    {\bf This is bold font}
+\end{verbatim}
+
+The first example has no arguments. The second has one argument. The third
+example is an {\it environment} which uses the begin and end keywords instead
+of a pair of braces to enclose an argument (usually one). The fourth is an example
+of using a command within a pair of braces: the command applies to the scope within
+the braces. Tex2RTF treats this form as if it were a command with one argument,
+with the right brace delimiting the argument. In this case, the command must
+immediately follow a left brace as shown.
+
+Commands may be nested, but not overlapped.
+
+\subsection{Space}\index{space}%
+
+In \LaTeX, white space is mostly ignored, line breaks make no difference.
+However, \LaTeX\ interprets two successive newlines (a blank line) as
+denoting a paragraph break. You may also use the \verb$\par$ command to end
+a paragraph.
+
+\section{Hypertext features}\index{hypertext}%
+
+\LaTeX\ is inherently suitable for specifying hypertext documents since
+it encourages description of the logical structure of a document using
+section commands. Therefore, a \LaTeX\ document is automatically
+a hypertext document, without any further editing.
+
+For Windows Help, a single RTF file is generated with topics
+corresponding to sections. A top level contents page shows each chapter
+or top-level section, and each chapter or section ends with a list of
+further sections or subsections. Tex2RTF outputs help files that may be
+read linearly using the \rtfsp$<<$ and $>>$ buttons.
+
+Similarly, a single wxHelp XLP file is generated.
+
+For HTML, a different file is generated for each section, since the
+XMOSAIC browser works best with a large number of small files. The files
+are named automatically based on the name of the output file, with the
+contents page filename being formed from the output filename with {\tt
+\_contents} appended to the name. If the truncateFilenames option is
+begin used, then the contents page is just the root name, with a .htm
+suffix. The conversion may result in the generation of several hundred
+files for a large \LaTeX\  input file. 
+
+To specify explicit jumps around a hypertext file, the \commandrefn{helpref}{helpref} command is
+used. The first argument is the text to be displayed at the point of reference,
+which will be highlighted in a hypertext file to allow jumping to a reference.
+The second argument is the reference label (there should be a corresponding
+\rtfsp\commandrefn{label}{label} command in the file, following a section or figure).
+
+To use extra Tex2RTF features in proper \LaTeX, such as \verb$\helpref$\rtfsp
+and the C++ and CLIPS class reference documentation features, include
+the style file {\tt texhelp.sty}.
+
+\section{Special sections}\index{special sections}%
+
+The treatment of bibliography, glossary and index are worth special mention.
+
+\subsection{Bibliography}\label{bibsection}\index{bibliography}%
+
+Tex2RTF recognises standard \LaTeX\ bibliography files (usually with {\tt .bib} extension)
+and resolves citations. The \commandrefn{bibliography}{bibliographycmd}\rtfsp
+command reads the given {\tt .bib} file and includes a list of
+references at that point in the input. Only numbered, unsorted
+references are catered for at the moment, with no variation in
+bibliography style. A {\bf References} heading is placed in the contents
+section. Note that Tex2RTF must be run twice to ensure the citations are
+resolved properly.
+
+Tex2RTF can also cope with the \verb$\thebibliography$ environment, with \rtfsp 
+\verb$\bibitem$ commands, so long as the text following the first \verb$\bibitem$\rtfsp 
+argument is enclosed in braces as if it were a second argument.
+
+\subsection{Glossary}\label{glossarysection}\index{glossary}%
+
+Glossaries are formatted according to the following scheme.
+The \commandrefn{helpglossary}{helpglossary} environment is used together with
+the \commandrefn{gloss}{gloss} command for glossary entries. In \LaTeX\ this
+is interpreted as a description list, and each glossary entry is an item.
+In on-line help, each glossary entry is a section.
+
+A labelled glossary entry command may be referenced by \commandrefn{popref}{popref}\rtfsp 
+to provide a quick popup explanation of a term.
+
+\subsection{Index}\index{index}%
+
+The explicit index is assumed to be redundant in on-line help, since
+search facilities are provided. Therefore the \verb$\printindex$ command
+does nothing in on-line versions. In linear RTF an index field is
+added, and \commandrefn{index}{index} marks words for inserting in the index.
+
+In Windows Help, all section headings and C++ function names are treated
+as keywords. A keyword may be ambiguous, that is, refer to more than one
+section in the help file.  This automatic indexing may not always be
+adequate, so the \LaTeX\ \commandrefn{index}{index} command may be used
+to add keywords.
+
+In wxHelp, all section headings are indexed.
+
+\section{Authoring HTML documents}
+
+When an HTML document is generated, the suffix `\_contents' is appended
+to the input file root. This will be the contents page for the document.
+A number of further HTML files will be generated, possibly a large number
+for a document with a large number of sections. If you are running
+a 16-bit Windows version of Tex2RTF, you may wish to use
+the {\it truncateFilenames} option to generate DOS filenames with
+appropriately truncated references inside the HTML files.
+
+\normalbox{Tip: to reduce the number of sections generated and make
+the document more linear, you could define new chapter and section
+commands. Alias them to the normal commands in real LaTeX (edit {\tt texhelp.sty}), and
+to appropriate bold/large headings (but not section commands) in
+the Tex2RTF initialisation file.}
+
+Each HTML section file (except for the contents page) is given browse
+buttons, similar to a Windows Help file: Contents, Up, Down, Back, Forward.
+You can set {\it htmlBrowseButtons} to specify whether bitmaps or text should
+be used for these buttons. On a text-only browser, the buttons will show
+as text even if images have been specified.
+
+As well as the usual jumps within a document, you can use the \commandref{urlref}{urlref} command to jump
+to other documents. `Advanced features' which are implemented for HTML include:
+
+\begin{itemize}\itemsep=0pt
+\item Simple tables: \commandref{tabular}{tabular} command
+\item Background colour/bitmap: \commandref{backgroundcolour}{backgroundcolour} and
+\rtfsp\commandref{backgroundimage}{backgroundimage}
+\item Text colour: \commandref{textcolour}{textcolour} command
+\end{itemize}
+
+See \helpref{HTML options}{htmloptions} for relevant initialisation file
+switches.
+
+\section{Authoring Windows Help documents}\index{WinHelp files}%
+
+To produce a Windows Help file, you need to generate a WinHelp RTF file
+with Tex2RTF and then invoke a Windows Help compiler (such as hc505.exe)
+to translate this to a .hlp file.
+
+WinHelp support has split into two streams, Windows 3.1 help format
+and Windows 95 (WinHelp 4) format. You control this with the {\it winHelpVersion} option,
+setting it to 3 for Windows 3.1, and 4 for Windows 95. In the latter case,
+you also need the Help Compiler for Windows (hcw.exe and associated components)
+which are available in the WIN32 SDK and with Windows 95 compilers.
+
+Tex2RTF can produce a Windows 95 {\tt .cnt} file if {\it winHelpContents}\index{CNT file} is switched
+on. This file is used to generate the new-style contents page, allowing
+hierarchical browsing of the topic contents. In fact this file can be used
+with ordinary Windows 3.1 files on Windows 95: so to hedge your bets,
+generate a Windows 3.1 help file along with {\tt .cnt} file.
+
+Tex2RTF also generates (optionally) a {\tt .hpj} (Help Project) file\index{HPJ file} which is
+fed to the help compiler and specifies the RTF file being used amongst
+other things. In WinHelp 4 mode, Tex2RTF adds entries to the project
+to enhance the appearance of the help file. In particular, the
+non-scrolling (topic title) region is coloured grey, and the rest
+is coloured a light yellow in keeping with other Windows 95 help
+files.
+
+\normalbox{Tip: you can maintain two versions of a help file
+by specifying an alternative {\tt .ini} file on the command
+line when invoking Tex2RTF, and compiling to a different directory.
+Tex2RTF instructs the help compiler to use the input file directory
+to find bitmaps and metafiles, so using a different output directory
+is not a problem. See the Tex2RTF {\tt src/makefile.dos} for an example
+of maintaining both formats.}
+
+There is a slight wrinkle with generation of the {\tt .cnt} file:
+to work around a `feature' in the Windows 95 help compiler, Tex2RTF may insert
+extra book icons in the contents page. So your contents page
+may not exactly match the structure in your LaTeX file.
+
+`Advanced features' which are implemented for WinHelp include:
+
+\begin{itemize}\itemsep=0pt
+\item Transparency: \commandref{settransparency}{settransparency} command
+\item Colour: \commandref{definecolour}{definecolour}, \commandref{fcol}{fcol}, \commandref{bcol}{bcol} commands
+\item Hot spot appearance: \commandref{sethotspotcolour}{sethotspotcolour}, \commandref{sethotspotunderline}{sethotspotunderline} commands
+\end{itemize}
+
+Tex2RTF automatically generates browse buttons for jumping to the
+above, previous and next topics. 
+
+See \helpref{RTF/WinHelp options}{rtfwinhelpoptions} for
+relevant initialisation file switches.
+
+\section{Authoring linear RTF documents}\index{RTF}%
+
+Linear RTF documents come in two main flavours. It can produce simple
+RTF that can be read by a wide variety of readers, such as
+Windows 95 WordPad, the Windows 95 viewer, and most word processors.
+Tex2RTF can also output MS Word compatible RTF which has special
+fields for contents page and index formatting, headings, and
+other enhancements.
+
+Use the {\it useWord} initialisation file flag to switch Word mode
+on or off.
+Hypertext links (using \verb$\helpref$ and other commands) will be formatted as
+bold `anchor' text plus a section or figure number in parentheses.
+
+In Word mode, using an index section generates a proper Word index.
+Similarly, a Word table of contents, list of figures, list of tables
+and page reference may be generated.
+
+See \helpref{RTF/WinHelp options}{rtfwinhelpoptions} for
+relevant initialisation file switches.
+
+\section{Authoring wxHelp documents}\index{wxHelp}%
+
+The wxHelp (.xlp) file is the most basic kind of file that Tex2RTF
+can handle. Since spacing is passed through to the output, you need to
+format your input document appropriately, with lines of reasonable length.
+
+The generated xlp file is an ASCII file that can be read directly by
+wxHelp, the generic wxWindows help viewer.
+
+\chapter{Command reference}\index{command reference}%
+\setheader{{\it CHAPTER \thechapter}}{}{}{}{}{{\it CHAPTER \thechapter}}%
+\setfooter{\thepage}{}{}{}{}{\thepage}%
+
+The following lists commands which are recognised by the converters. The reader
+can assume that commands not mentioned here are unrecognised or ignored.
+
+Each command is listed with its name, the number of arguments it takes
+(excluding optional arguments), and a description. Note that if the
+command is used as an environment (using \verb$\begin$ and \verb$\end$) then
+the number of arguments must be either one or two. For example, the\rtfsp
+\verb$\tabular$ environment takes two arguments: a first argument for
+specifying the formatting, and the second argument for the body of the
+environment.
+
+\begin{verbatim}
+    \begin{tabular}{|l|l|}
+    \row{One&Two}
+    \row{Three&Four}
+    \end{tabular}
+\end{verbatim}
+
+\section{\LaTeX\ Commands}
+
+\subsection*{abstract:1}\label{abstract}
+
+This standard \LaTeX\ environment prepares an abstract page, and is
+treated as an ordinary chapter or section in on-line help.
+
+\subsection*{addcontentsline:3}\label{addcontentsline}
+
+Adds a chapter title to the contents page. Linear RTF. Rarely required.
+
+%\subsection*{appendix}
+%\subsection*{arabic}
+%\subsection*{array}
+\subsection*{author:1}\label{author}
+
+Defines the author, for output when \verb$\maketitle$ is used.
+
+\subsection*{backslash:0}\label{backslash}
+
+Outputs a backslash in math mode (should be enclosed by two dollar symbols).
+
+\subsection*{bf:1}\label{bf}
+
+Specifies bold font.
+
+\subsection*{bffamily:1}\label{bffamily}
+
+Specifies bold font.
+
+\subsection*{bibitem:2}\label{bibitem}
+
+For parsing convenience, \verb$\bibitem$ requires two arguments: a cite key and item.
+\rtfsp\LaTeX\ syntax permits writing this as if it were two arguments,
+even though it is in fact only one. This command is used within
+a \commandrefn{thebibliography}{thebibliography} environment. The preferred
+method is to store references in {\tt .bib} files and use the \commandrefn{bibliography}{bibliographycmd}\rtfsp
+command to generate a bibliography section automatically.
+
+\subsection*{bibliographystyle:1}\label{bibliographystyle}
+
+Currently doesn't affect the style of bibliography, but probably will
+in the future.
+
+\subsection*{bibliography:0}\label{bibliographycmd}
+
+Includes the bibliography at this point in the document. See the section
+on \helpref{bibliographies}{bibsection}.
+
+%\subsection*{caption*}
+\subsection*{caption:1}\label{caption}
+
+Specifies a caption (within a \commandrefn{figure}{figure} or \commandrefn{table}{table} environment). This may
+be followed immediately by a \commandrefn{label}{label} command.
+
+\subsection*{cdots:0}\label{cdots}
+
+Outputs three dots.
+
+\subsection*{centerline:1}\label{centerline}
+
+Centres (or centers!) a line of text.
+
+%\subsection*{centering}
+\subsection*{center:1}\label{center}
+
+Centres a block of text.
+
+\subsection*{chapter:1}\label{chapter}
+
+Outputs a chapter heading. If the chapter's name is Popups\index{popups}, the chapter title will not be
+put in the contents, to allow popups to be placed in a document without the popup
+sections being directly accessible.
+
+\subsection*{chapter*:1}\label{chaptersX}
+
+Outputs a chapter heading with no contents entry.
+
+\subsection*{cite:1}\label{cite}
+
+Cite a reference. The argument is a reference key as defined in a \LaTeX\ {\tt .bib}\rtfsp
+file.
+
+\subsection*{comment:1}\label{comment}
+
+An environment that allows large comments in \LaTeX\ files: the argument
+is ignored in all formats. Useful for commenting out parts of files that
+cannot be handled by \LaTeX, such as the picture environment. See also\rtfsp
+\commandrefn{toocomplex}{toocomplex}.
+
+\subsection*{date:1}\label{date}
+
+Specifies the date of a document; only output by \commandrefn{maketitle}{maketitle}.
+
+\subsection*{description:1}\label{description}
+
+A list environment, where each \commandrefn{item}{item} command must be
+followed by optional square-bracketed text which will be highlighted.
+
+%\subsection*{destruct:1}\label{destruct}
+
+\subsection*{document:1}\label{document}
+
+This environment should enclose the body of a document.
+
+\subsection*{documentstyle:1}\label{documentstyle}
+
+Specifies the main style (report, article etc.) and, optionally, style files
+such as {\tt texhelp.sty}. A report has \commandrefn{chapters}{chapter}, while an article's top-level
+sections are specified using \commandrefn{section}{section}.
+
+%\subsection*{doublespace}\label{doublespace}
+\subsection*{em:1}\label{em}
+
+Emphasizes text (italic in RTF).
+
+\subsection*{emph:1}\label{emph}
+
+Same as \commandrefn{em}{em}.
+
+\subsection*{enumerate:1}\label{enumerate}
+
+Enumerate list environment: numbers the \commandrefn{items}{item}.
+
+%\subsection*{equation}\label{equation}
+%\subsection*{evensidemargin}
+%\subsection*{fbox:1}\label{fbox}
+
+\subsection*{figure:1}\label{figure}
+
+A figure environment: does nothing special, except allows interpretation of
+embedded \helpref{caption}{caption} commands as figures rather than (say) tables.
+
+\subsection*{flushleft:1}\label{flushleft}
+
+Flushes the given text to the left margin.
+
+\subsection*{flushright:1}\label{flushright}
+
+Flushes the given text to the right margin.
+
+%\subsection*{footheight}\label{footheight}
+\subsection*{footnote:1}\label{footnote}
+
+In linear RTF, a footnote is created. Whether this appears at the end of
+the section or the bottom of the page appears to depend on the current
+document style, at least for MS Word 6.0 for Windows. The default seems
+to be to put the footnotes at the end of the section, which is probably
+not the best assumption.
+
+In WinHelp RTF, a bracketed number is generated for the footnote
+and the footnote becomes a popup topic. It is probably preferable
+to change footnote commands to \commandref{footnotepopup}{footnotepopup},
+or \commandref{popref}{popref} references to glossary entries.
+
+This command is not supported for formats other than \LaTeX,
+linear RTF and WinHelp RTF.
+
+\subsection*{hline:0}\label{hline}
+
+Within a \commandrefn{tabular}{tabular} environment, draws a horizontal
+rule below the current row. Note that this does not work in RTF for the
+last row of a table, in which case the command \commandrefn{ruledrow}{ruledrow}\rtfsp
+should be used instead.
+
+\subsection*{hrule:0}\label{hrule}
+
+Draws a horizontal line below the current paragraph. For example:
+
+\begin{verbatim}
+    This paragraph should have a horizontal rule following it.\hrule
+\end{verbatim}
+
+gives:
+
+This paragraph should have a horizontal rule following it.\hrule
+
+%\subsection*{hspace*}\label{hspaceX}
+%\subsection*{hspace}\label{hspace}
+%\subsection*{hskip*}\label{hskipX}
+%\subsection*{hskip}\label{hskip}
+
+\subsection*{huge:1}\label{huge1}
+
+Outputs the argument in huge text.
+
+\subsection*{Huge:1}\label{Huge2}
+
+Outputs the argument in huger text than \commandrefn{huge}{huge1}.
+
+\subsection*{HUGE:1}\label{HUGE3}
+
+Outputs the argument in huger text than \commandrefn{Huge}{Huge2}.
+
+\subsection*{include:1}\label{include}
+
+Include the given file. The command must not be preceded by any whitespace,
+and spurious whitespace between elements of the command will also
+trip up Tex2RTF.
+
+\subsection*{index:1}\label{index}
+
+In WinHelp mode, adds a keyword to the keyword list for the current
+topic. This keyword must currently be straight text, with no embedded
+commands. The conversion process must be run twice (without quitting
+Tex2RTF inbetween) to resolve the keyword references.
+
+\subsection*{input:1}\label{input}
+
+Include the given file. The command must not be preceded by any whitespace,
+and spurious whitespace between elements of the command will also
+trip up Tex2RTF.
+
+\subsection*{insertatlevel:2}\label{insertatlevel}
+
+Insert some text at a particular level of the document. For example,
+
+\begin{verbatim}
+  \insertatlevel{2}{Some text}
+\end{verbatim}
+
+inserts "Some text" at level 2 (for a report, the current section). This
+allows you to insert headings into an automatically-generated section contents,
+for example.
+
+\subsection*{it:1}\label{it}
+
+Marks the argument in italic.
+
+\subsection*{itemize:1}\label{itemize}
+
+Indents each \commandrefn{item}{item} of a list and precedes with a bullet.
+If the file {\tt bullet.bmp} is found by Tex2RTF, this bitmap will be
+used as the bullet (WinHelp RTF); otherwise, a symbol or bold `o' will be used instead,
+depending on output format.
+
+Use \commandrefn{itemsep}{itemsep} to specify the separation between
+list items. Currently this only works for linear or WinHelp RTF output.
+If the value is more than zero, an extra paragraph is inserted.
+
+\subsection*{item:0}\label{item}
+
+Marks an item of a \commandrefn{itemize}{itemize}, \commandrefn{description}{description} or \commandrefn{enumerate}{enumerate}
+list. Items within a description environment should have an `optional' argument
+in square brackets which will be highlighted.
+
+\subsection*{itemsep:0}\label{itemsep}
+
+Use this command to specify the separation between
+list items. Currently this only works for linear or WinHelp RTF output.
+If the value is zero, no extra paragraph is inserted; if the value
+is more than zero, an extra paragraph is inserted.
+
+\subsection*{itshape:1}\label{itshape}
+
+Marks the argument in italic.
+
+%\subsection*{kill}\label{kill}
+\subsection*{label:1}\label{label}
+
+Labels the chapter, section, subsection, subsubsection or figure caption
+with the given label. This must be an ASCII string, and duplicate items
+with different case letters are not allowed.
+
+The command must follow immediately after the section or caption command,
+with no intervening whitespace.
+
+\subsection*{large:1}\label{large1}
+
+Marks the argument in large text.
+
+\subsection*{Large:1}\label{Large2}
+
+Makes the argument display in larger text than \commandrefn{large}{large1}.
+
+\subsection*{LARGE:1}\label{LARGE3}
+
+Makes the argument display in larger text than \commandrefn{Large}{Large2}.
+
+\subsection*{LaTeX:0}\label{LaTeX}
+
+Outputs the annoying \LaTeX\ upper and lower case name.
+
+\subsection*{ldots:0}\label{ldots}
+
+Outputs three dots.
+
+%\subsection*{linebreak}\label{linebreak}
+%\subsection*{listoffigures}\label{listoffigures}
+%\subsection*{listoftables}\label{listoftables}
+%\subsection*{makeglossary}\label{makeglossary}
+%\subsection*{makeindex}\label{makeindex}
+\subsection*{maketitle:0}\label{maketitle}
+
+Makes the article or report title by outputting the \commandrefn{title}{title},
+\rtfsp\commandrefn{author}{author} and optionally \commandrefn{date}{date}.
+
+%\subsection*{markright}\label{markright}
+%\subsection*{markboth}\label{markboth}
+
+\subsection*{marginparwidth:1}\label{marginparwidth}
+
+Specifies the width of a margin paragraph.
+
+\subsection*{marginpar:1}\label{marginpar}
+
+Inserts a marginal note. It is best to use the Tex2RTF extensions \rtfsp
+\commandrefn{marginparodd}{marginparodd} and \commandrefn{marginpareven}{marginpareven} \rtfsp
+for best results.
+
+\subsection*{marginpareven:1}\label{marginpareven}
+
+Inserts a marginal note on even pages. This is required for RTF generation since
+it is impossible for Tex2RTF to know in advance which side of paper the marginal note
+will fall upon, and the text has to be positioned using absolute dimensions.
+If only one sided output is required, use \commandrefn{marginparodd}{marginparodd} \rtfsp
+instead.
+
+\subsection*{marginparodd:1}\label{marginparodd}
+
+Inserts a marginal note on odd pages. This is required for RTF generation since
+it is impossible for Tex2RTF to know in advance which side of paper the marginal note
+will fall upon, and the text has to be positioned using absolute dimensions.
+
+Also, even if one-sided output is required, this command should be used instead
+of \verb$\marginpar$ because the \LaTeX\ command allows it to be used
+just before a paragraph. Normally, if this were done, the marginal note would
+not be aligned with the paragraph succeeding it. For example:
+
+\begin{verbatim}
+    \marginparodd{{\it Note:} if nothing happens, perhaps you
+    have not plugged your computer in at the mains.}%
+    To start using your computer, push the Power button
+    and wait for text to appear on the screen.
+\end{verbatim}
+
+Note the percent sign after the \verb$\marginparodd$ command: without it,
+\LaTeX\ refuses to believe that the following text is part of the
+same paragraph, and will print the note at the wrong place.
+
+You should use \commandrefn{textwidth}{textwidth} to allow space for marginal
+notes, and also \commandrefn{marginparwidth}{marginparwidth} to specify the size of
+the marginal note.
+
+In WinHelp, HTML and wxHelp, marginal notes are treated as normal text delineated
+with horizontal rules above and below.
+
+%\subsection*{mbox:1}\label{mbox}
+
+\subsection*{mdseries:1}\label{mdseries}
+
+Changes to a medium-weight font. Un-emboldens in RTF mode, no effect in other modes.
+
+\subsection*{multicolumn:3}\label{multicolumn}
+
+Used in \commandrefn{tabular}{tabular} environment to denote a cell that
+spans more than one column. Only supplied for compatibility with
+existing \LaTeX\ files, since all it does in RTF is output the correct
+number of cell commands, with the multicolumn text squashed into one cell.
+
+\subsection*{newcommand:3}\label{newcommand}
+
+Define a new command; arguments are the command, the number of
+arguments, and the command body. For example:
+
+\begin{verbatim}
+    \newcommand{\crazy}[2]{{\bf #1} is crazy but {\bf #2} is not.}
+\end{verbatim}
+
+The command must have no whitespace at the start of the line or between
+the three arguments.
+
+New commands may also be defined in the {\tt tex2rtf.ini} file using
+slightly different syntax (see \helpref{Macro not found error}{macronotfound}).
+
+%\subsection*{newcounter}\label{newcounter}
+%\subsection*{newline}\label{newline}
+\subsection*{newpage:0}\label{newpage}
+
+Inserts a page break.
+
+\subsection*{nocite:1}\label{nocite}
+
+Specifies that this reference should appear in the bibliography,
+but the citation should not appear in the text.
+
+See also \commandrefn{cite}{cite}.
+
+\subsection*{noindent:0}\label{noindent}
+
+Sets paragraph indentation to zero. See also \commandrefn{parindent}{parindent}.
+
+%\subsection*{nolinebreak}\label{nolinebreak}
+%\subsection*{nopagebreak}\label{nopagebreak}
+
+\subsection*{normalsize:1}\label{normalsize}
+
+Sets the font size back to normal.
+
+\subsection*{onecolumn:0}\label{onecolumn}
+
+Sets the number of columns to one. \LaTeX\ and linear RTF only.
+
+%\subsection*{oddsidemargin}\label{oddsidemargin}
+%\subsection*{pagebreak}\label{pagebreak}
+\subsection*{pageref:1}\label{pageref}
+
+In linear RTF, generates a page reference to the given label.
+
+\subsection*{pagestyle:1}\label{pagestyle}
+
+If argument is {\tt fancyplain} or {\tt fancy}, Tex2RTF
+separates the header from the rest of the page with a rule.
+This command must be defined for headers and footers to
+work properly. See also \commandrefn{setheader}{setheader},
+\commandrefn{setfooter}{setfooter}.
+
+\LaTeX\ and linear RTF only.
+
+\subsection*{pagenumbering:1}\label{pagenumbering}
+
+The argument may be one of:
+
+\begin{description}
+\itemsep=0pt
+\item[alph] a, b, ...
+\item[Alph] A, B, ...
+\item[arabic] 1, 2, ...
+\item[roman] i, ii, ...
+\item[Roman] I, II, ...
+\end{description}
+
+\LaTeX\ and linear RTF only.
+
+\subsection*{paragraph:0}\label{paragraph}
+
+Behaves as for a subsubsection.
+
+\subsection*{paragraph*:0}\label{paragraphX}
+
+Behaves as for a subsubsection.
+
+\subsection*{parindent:1}\label{parindent}
+
+Indents the first line of succeeding paragraphs by the given amount.
+
+\subsection*{parskip:1}\label{parskip}
+
+Changes the spacing between paragraphs. In fact, in RTF this will cause
+two \commandrefn{par}{par} commands to be output if parskip is greater
+than zero.
+
+%\subsection*{part*}\label{partX}
+%\subsection*{part}\label{part}
+\subsection*{par:0}\label{par}
+
+Causes the paragraph to end at this point. \LaTeX\ and Tex2RTF also
+treat two consecutive newlines as a paragraph break.
+
+%\subsection*{pfunc}\label{pfunc}
+%\subsection*{picture}\label{picture}
+\subsection*{printindex:0}\label{printindex}
+
+In linear RTF, inserts an index.
+
+\subsection*{quote:1}\label{quote}
+
+Indents a short quotation.
+
+\subsection*{quotation:1}\label{quotation}
+
+Indents a long quotation.
+
+%\subsection*{raggedbottom}\label{raggedbottom}
+%\subsection*{raggedleft}\label{raggedleft}
+%\subsection*{raggedright}\label{raggedright}
+
+\subsection*{ref:1}\label{ref}
+
+In \LaTeX\ and linear RTF, refers to a \commandrefn{label}{label} and
+causes the number of that section or figure to be printed.
+
+\subsection*{rm:1}\label{rm}
+
+Causes the argument to be formatted in a plain, roman font.
+In fact, does nothing in RTF, HTML and XLP modes.
+
+\subsection*{rmfamily:1}\label{rmfamily}
+
+Causes the argument to be formatted in a plain, roman font.
+In fact, does nothing in RTF, HTML and XLP modes.
+
+%\subsection*{roman}\label{roman1}
+%\subsection*{Roman}\label{Roman2}
+
+\subsection*{sc:1}\label{sc}
+
+Prints the output in small capitals.
+
+\subsection*{scshape:1}\label{scshape}
+
+Prints the output in small capitals.
+
+\subsection*{section:1}\label{section}
+
+Section header, with an entry in the contents page.
+
+\subsection*{section*:1}\label{sectionX}
+
+Section header, with no entry in the contents page.
+
+%\subsection*{setcounter}\label{setcounter}
+\subsection*{sf:1}\label{sf}
+
+Should format in a sans-serif font. Does nothing in Tex2RTF.
+
+\subsection*{sffamily:1}\label{sffamily}
+
+Should format in a sans-serif font. Does nothing in Tex2RTF.
+
+\subsection*{shortcite:1}\label{shortcite}
+
+The same as \commandrefn{cite}{cite}.
+
+%\subsection*{singlespace}\label{singlespace}
+%\subsection*{sloppypar}\label{sloppypar}
+%\subsection*{sloppy}\label{sloppy}
+
+\subsection*{sl:1}\label{sl}
+
+In Tex2RTF, the same as \commandrefn{it}{it}. The LaTeX interpretation is `slanted text'.
+
+\subsection*{slshape:1}\label{slshape}
+
+In Tex2RTF, the same as \commandrefn{itshape}{itshape}. The LaTeX interpretation is `slanted text'.
+
+\subsection*{small:1}\label{small}
+
+Prints the argument in a small font.
+
+\subsection*{special:1}\label{special}
+
+Simply copies the argument to the output file without processing
+(except \verb$\}$ is translated to \verb$}$, and \verb$\{$ is
+translated to \verb${$, to allow for insertion of braces).
+
+\subsection*{ss:0}\label{ss}
+
+Outputs the German sharp S character \ss.
+
+%\subsection*{subitem}\label{subitem}
+\subsection*{subparagraph:1}\label{subparagraph}
+
+Behaves as for a subsubsection.
+
+\subsection*{subparagraph*:1}\label{subparagraphX}
+
+Behaves as for a subsubsection.
+
+\subsection*{subsection:1}\label{subsection}
+
+Subsection header, with an entry in the contents page. 
+
+\subsection*{subsection*:1}\label{subsectionX}
+
+Subsection header, with no entry in the contents page. 
+
+\subsection*{subsubsection:1}\label{subsubsection}
+
+Subsubsection header, with an entry in the contents page. 
+
+\subsection*{subsubsection*:1}\label{subsubsectionX}
+
+Subsubsection header, with no entry in the contents page. 
+
+\subsection*{tabbing:1}\label{tabbing}
+
+Tabbing environment: doesn't work properly in RTF.
+
+\subsection*{table:1}\label{table}
+
+An environment for tables. The only thing that Tex2RTF does with this
+is to interpret an embedded \helpref{caption}{caption} command differently
+from figures.
+
+\subsection*{tableofcontents:0}\label{tableofcontents}
+
+Inserts the table of contents at this point. In linear RTF mode, a
+proper Word for Windows table of contents will be inserted unless either
+of the variables {\it insertTOC} or {\it useWord} is set to {\it false}.
+
+\subsection*{tabular:2}\label{tabular}
+
+Tabular environment: an attempt is made to output something
+reasonable in RTF and HTML formats, although currently only simple
+tables will work. The first argument specifies the column formatting.
+a pipe symbol (\verb$|$) denotes a vertical border, one of {\tt l, r, c}\rtfsp
+signifies a normal column of default width, and {\tt p} followed by
+a dimension specifies a column of given width. It is recommended that
+the {\tt p} is used since Tex2RTF cannot deduce a column width in the
+same way that \LaTeX\ can.
+
+Horizontal rules are achieved with \commandrefn{hline}{hline}; two together
+signify a double rule. Note that in HTML, all rows and the table itself are bordered
+automatically.
+
+Use the Tex2RTF \commandrefn{row}{row} and \commandrefn{ruledrow}{ruledrow} commands
+for best effect.
+
+For two-column tables that work in WinHelp files, use \commandrefn{twocollist}{twocollist} instead.
+
+Example:
+
+\begin{verbatim}
+    \begin{tabular}{|l|p{8.5cm}|}\hline
+    \row{{\bf A.I.}&{\bf Simulation}}\hline\hline
+    \row{rules&constraints/methods}
+    \row{planning&design of experiments}
+    \row{diagnosis&analysis of results}
+    \ruledrow{learning&detection of connections}
+    \end{tabular}
+\end{verbatim}
+
+This produces:
+
+\begin{tabular}{|l|p{8.5cm}|}\hline
+\row{{\bf A.I.}&{\bf Simulation}}\hline\hline
+\row{rules&constraints/methods}
+\row{planning&design of experiments}
+\row{diagnosis&analysis of results}
+\ruledrow{learning&detection of connections}
+\end{tabular}
+
+%\subsection*{tab:1}\label{tab}
+\subsection*{TeX:0}\label{TeX}
+
+Outputs the annoying \TeX\ upper and lower case name.
+
+\subsection*{textbf:1}\label{textbf}
+
+Same as \commandrefn{bf}{bf}.
+
+\subsection*{textit:1}\label{textit}
+
+Same as \commandrefn{it}{it}.
+
+\subsection*{textrm:1}\label{textrm}
+
+Same as \commandrefn{rm}{rm}.
+
+\subsection*{textsf:1}\label{textsf}
+
+Same as \commandrefn{sf}{sf}.
+
+\subsection*{textsc:1}\label{textsc}
+
+Same as \commandrefn{sc}{sc}.
+
+\subsection*{textsl:1}\label{textsl}
+
+Same as \commandrefn{sl}{sl}.
+
+\subsection*{texttt:1}\label{texttt}
+
+Same as \commandrefn{tt}{tt}.
+
+
+\subsection*{textwidth:1}\label{textwidth}
+
+Sets the text width (valid for RTF only). This might be used
+in conjunction with \commandrefn{marginpar}{marginpar}, for example,
+to leave space for marginal notes.
+
+%\subsection*{textheight}\label{textheight}
+\subsection*{thebibliography:1}\label{thebibliography}
+
+An environment for specifying the bibliography as a series of\rtfsp
+\commandrefn{bibitem}{bibitem} commands; the preferred method is to use
+\rtfsp{\tt .bib} files and \commandrefn{bibliography}{bibliographycmd} instead.
+
+%\subsection*{titlepage:0}\label{titlepage}
+
+\subsection*{title:1}\label{title}
+
+Sets the title, to be output when the command \commandrefn{maketitle}{maketitle}\rtfsp
+is used.
+
+\subsection*{tiny:1}\label{tiny}
+
+Prints the argument in a very small font.
+
+\subsection*{today:0}\label{today}
+
+Outputs today's date.
+
+%\subsection*{topmargin}\label{topmargin}
+%\subsection*{topskip}\label{topskip}
+\subsection*{tt:1}\label{tt}
+
+Outputs the argument in teletype font.
+
+\subsection*{ttfamily:1}\label{ttfamily}
+
+Outputs the argument in teletype font.
+
+%\subsection*{typein}\label{typein}
+\subsection*{typeout:1}\label{typeout}
+
+Outputs the text on the Tex2RTF text window.
+
+\subsection*{twocolumn:0}\label{twocolumn}
+
+Sets the number of columns to two. \LaTeX\ and linear RTF only.
+
+\subsection*{underline:1}\label{underline}
+
+Underlines the argument.
+  
+\subsection*{upshape:1}\label{upshape}
+
+Changes to an upright font. Un-italicizes in RTF mode, no effect in other modes.
+
+\subsection*{verbatiminput:1}\label{verbatiminput}
+
+Include the given file as if it were within a \commandrefn{verbatim}{verbatim}\rtfsp
+environment. The command must not be preceded by any whitespace,
+and spurious whitespace between elements of the command will also
+trip up Tex2RTF.
+
+\subsection*{verbatim:1}\label{verbatim}
+
+Uses a fixed-width font to format the argument without interpreting
+any \LaTeX\ commands.
+
+\subsection*{verb}\label{verb}
+
+The \verb$\verb$ command is like the \commandref{verbatim}{verbatim} environment,
+but for small amounts of text. The syntax is:
+
+\begin{verbatim}
+    \verb<char><text><char>
+\end{verbatim}
+
+The character {\it char} is used as a delimiter; it may be any character
+not ocurring in the following text, except asterisk.
+
+For example, \verb@\verb$\thing%^&$@ produces \verb$\thing%^&$.
+
+%\subsection*{verse}\label{verse}
+%\subsection*{vfill}\label{vfill}
+%\subsection*{vline}\label{vline}
+%\subsection*{void}\label{void}
+%\subsection*{vrule}\label{vrule}
+%\subsection*{vspace*}\label{vspaceX}
+%\subsection*{vskip*}\label{vskipX}
+%\subsection*{vspace}\label{vspace}
+%\subsection*{vskip}\label{vskip}
+
+
+\section{Tex2RTF Commands}
+
+\subsection*{backgroundcolour:1}\label{backgroundcolour}
+
+Specifies the page background colour, in HTML only. The argument consists
+of three numbers from 0 to 255 separated by semicolons, for red, green and blue values respectively.
+
+\begin{verbatim}
+    \backgroundcolour{255;255;255}
+    \backgroundcolour{0;0;255}
+\end{verbatim}
+
+The first example sets the background to white, the second sets the background to blue.
+
+Instead of using a LaTeX command, you may find it more convenient to use the equivalent {\tt .ini} file
+setting, {\it backgroundColour}.
+
+\subsection*{backgroundimage:1}\label{backgroundimage}
+
+Specifies the page background image, in HTML only. The argument
+is a URL for the GIF file to be used as the background.
+
+For example:
+
+\begin{verbatim}
+    \backgroundimage{tile.gif}
+\end{verbatim}
+
+This sets the background to a tile file.
+
+Instead of using a LaTeX command, you may find it more convenient to use the equivalent {\tt .ini} file
+setting, {\it backgroundImage}.
+
+\subsection*{backslashraw:0}\label{backslashraw}
+
+Outputs a raw backslash into the output (not LaTeX). Useful when
+inserting RTF (for example) that cannot be dealt with by Tex2RTF.
+E.g.
+
+\begin{verbatim}
+    \backslashraw{'e3}
+\end{verbatim}
+
+inserts the text \verb$\'e3$ into the RTF file.
+
+\subsection*{bcol:2}\label{bcol}
+
+Sets the background colour for a block of text (RTF only). Has no known effect
+in the RTF readers currently tried (Word for Window and Windows Help).
+
+See also \commandrefn{definecolour}{definecolour}, \commandrefn{fcol}{fcol}.
+
+%\subsection*{baselineskip}
+%\subsection*{boxit:1}\label{boxit}
+
+\subsection*{brclear:0}\label{brclear}
+
+Stops aligning content following a left or right-aligned image in HTML only.
+
+See also \commandrefn{imagel}{imagel}, \commandrefn{imager}{imager}.
+
+\subsection*{cextract:0}\label{cextract}
+
+Prints a C++ extraction operator (\cextract).
+
+\subsection*{chapterheading:1}\label{chapterheading}
+
+Like \commandrefn{chapter}{chapter}, but does not increment the chapter
+number and does not print a chapter number in the printed documentation
+contents page, or in the chapter heading. Used to implement \helpref{glossaries}{glossarysection} and
+other sections that are not real chapters.
+
+\subsection*{cinsert:0}\label{cinsert}
+
+Prints a C++ insertion operator (\cinsert).
+
+\subsection*{class:1}\label{class}
+
+Outputs the argument, an index entry (\LaTeX\ only) and a keyword entry (WinHelp only).
+Used in class reference documentation.
+
+%\subsection*{cleardoublepage}
+%\subsection*{clearpage}
+%\subsection*{cline}
+\subsection*{clipsfunc:3}\label{clipsfunc}
+
+Formats a CLIPS function, given the return value, function name, and
+arguments.
+
+%\subsection*{columnsep}
+\subsection*{copyright:0}\label{copyright}
+
+Outputs the copyright symbol.
+
+\subsection*{cparam:2}\label{cparam}
+
+Formats a CLIPS type and argument. Used within the third argument of
+a \commandrefn{clipsfunc}{clipsfunc} command.
+
+\subsection*{definecolour:4}\label{definecolour}
+
+Defines a new colour that can be used in the document (RTF only). This
+command can also be spelt \verb$\definecolor$.
+
+The first argument is the lower-case name of the colour, and the following
+three arguments specify the red, green and blue intensities, in the range 0 to 255.
+
+The default colours are equivalent to the following definitions:
+
+\begin{verbatim}
+    \definecolour{black}{0}{0}{0}
+    \definecolour{cyan}{0}{255}{255}
+    \definecolour{green}{0}{255}{0}
+    \definecolour{magenta}{255}{0}{255}
+    \definecolour{red}{255}{0}{0}
+    \definecolour{yellow}{255}{255}{0}
+    \definecolour{white}{255}{255}{255}
+\end{verbatim}
+
+To use colours in a document, use the \commandrefn{fcol}{fcol} and \commandrefn{bcol}{bcol} commands.
+
+Note that a document that defines its own colours should be converted twice within
+the same Tex2RTF session.
+
+\subsection*{fcol:2}\label{fcol}
+
+Sets the foreground colour for a block of text (RTF and HTML).
+
+For example:
+
+\begin{verbatim}
+    This sentence is brightened up by some \fcol{red}{red text}.
+\end{verbatim}
+
+gives:
+
+This sentence is brightened up by some \fcol{red}{red text}.
+
+See also \commandrefn{definecolour}{definecolour}, \commandrefn{bcol}{bcol}.
+
+\subsection*{followedlinkcolour:1}\label{followedlinkcolour}
+
+Specifies the followed link colour for the whole page, HTML only. The argument consists
+of three numbers from 0 to 255 separated by semicolons, for red, green and blue values respectively.
+
+For example:
+
+\begin{verbatim}
+    \followedlinkcolour{255;255;255}
+    \followedlinkcolour{0;0;255}
+\end{verbatim}
+
+The first example sets the followed link text to white, and the second sets the followed link text to blue.
+
+See also \commandrefn{backgroundcolour}{backgroundcolour}, \commandrefn{textcolour}{textcolour},
+\rtfsp\commandrefn{linkcolour}{linkcolour}.
+
+Instead of using a LaTeX command, you may find it more convenient to use the equivalent {\tt .ini} file
+setting, {\it followedLinkColour}.
+
+\subsection*{footnotepopup:2}\label{footnotepopup}
+
+In linear RTF, a footnote is created following the first argument, as with
+\commandref{footnote}{footnote}.
+
+In WinHelp RTF, a the first argument is highlighted and becomes
+a popup reference to the second argument. See also \commandref{footnote}{footnote}\rtfsp
+and \commandref{popref}{popref}.
+
+This command is not supported for formats other than \LaTeX,
+linear RTF and WinHelp RTF.
+
+%\subsection*{footskip}\label{footskip}
+%\subsection*{framebox:1}\label{framebox}
+
+\subsection*{functionsection:1}\label{functionsection}
+
+Defines a subsection, adding the C++ function name to the \LaTeX\ index or the
+WinHelp keyword list.
+
+Should be followed by a \commandrefn{func}{func} command to specify function
+details.
+
+\subsection*{func:3}\label{func}
+
+Defines a C++ function, given the return type, function name, and parameter list.
+
+Should occur after a \commandrefn{functionsection}{functionsection} command.
+
+%\subsection*{glossary:}\label{glossary}
+\subsection*{gloss:1}\label{gloss}
+
+Marks a glossary entry. In \LaTeX, this is a synonym for an \commandrefn{item}{item}
+with an optional argument, within a \commandrefn{description}{description} environment,
+and the argument is added to the index.
+
+In Windows Help, this is identical to a \commandrefn{section*}{sectionX} in a report.
+
+If labels are associated with the glossary entries, they can be referenced by
+\commandref{helpref}{helpref} or \commandref{popref}{popref} jumps. A glossary entry is
+currently the only type of destination that popref may refer to.
+
+This is an example of making a glossary in a report:
+
+\begin{verbatim}
+    \begin{helpglossary}
+
+    \gloss{API}\label{api}
+
+    Application Programmer's Interface - a set of calls and
+    classes defining how a library (in this case, wxWindows)
+    can be used.
+
+    \gloss{Canvas}\label{canvas}
+
+    A canvas in XView and wxWindows is a subwindow...
+
+    \gloss{DDE}\label{dde}
+
+    Dynamic Data Exchange - Microsoft's interprocess
+    communication protocol. wxWindows provides an abstraction
+    of DDE under both Windows and UNIX.
+
+    \end{helpglossary}
+\end{verbatim}
+
+%\subsection*{headheight}\label{headheight}
+\subsection*{helpglossary:1}\label{helpglossary}
+
+An environment for making a glossary (not standard \LaTeX). See \commandrefn{gloss}{gloss} for
+usage.
+
+\subsection*{helpignore:1}\label{helpignore}
+
+Ignores the argument in Tex2RTF generated files, but not \LaTeX.
+
+\subsection*{helponly:1}\label{helponly}
+
+Only outputs the argument in Tex2RTF generated files.
+
+\subsection*{helpinput:1}\label{helpinput}
+
+Only includes the given file in Tex2RTF generated files.
+
+\subsection*{helpfontfamily:1}\label{helpfontfamily}
+
+Specifies the font family for Tex2RTF generated files. The argument
+may be Swiss or Times.
+
+\subsection*{helpfontsize:1}\label{helpfontsize}
+
+Specifies the font size for Tex2RTF generated files.
+
+\subsection*{helpref:2}\label{helpref}
+
+Specifies a jump to a labelled chapter, section, subsection subsubsection
+or figure.
+
+The first argument is text to be highlighted (mouseable in help systems)
+and the second is the reference label. In linear documents, the section number
+is given following the text, unless the \commandrefn{helprefn}{helprefn} command
+is used instead, where the section number is suppressed.
+
+Note that when generating HTML, the label {\it contents} is automatically defined,
+and may be referenced using \verb$\helpref$.
+
+\subsection*{helprefn:2}\label{helprefn}
+
+Specifies a jump to a labelled chapter, section, subsection subsubsection
+or figure.
+
+The first argument is text to be highlighted (mouseable in help systems)
+and the second is the reference label.  See \commandrefn{helpref}{helpref} for
+the form where the section number is printed in linear documents.
+
+%\subsection*{hfill}\label{hfill}
+\subsection*{htmlignore:1}\label{htmlignore}
+
+Ignores the argument in HTML.
+
+\subsection*{htmlonly:1}\label{htmlonly}
+
+Only outputs the argument in HTML.
+
+\subsection*{image:2}\label{image}
+
+This is translated to a PSBOX macro package \verb$\psboxto$ command in \LaTeX,
+the first argument being a sizing command and the second a filename.
+
+In HTML mode, the second argument is used to generate a PostScript file reference.
+
+In RTF mode, the second argument is tried with first a BMP extension and
+then a WMF extension to find a suitable Windows bitmap file, placeable
+metafile, or segmented hypergraphics file (.SHG). If a suitable file is
+found, in Windows Help mode a {\tt bmc}\rtfsp command is inserted into
+the RTF file with a reference to the file. In linear RTF mode, the
+bitmap or metafile is converted into hex and inserted into the RTF
+document.
+
+Note that only RGB-encoded Windows bitmaps, or placeable metafiles, are
+valid for input to Tex2RTF. You can convert a RLE (run length encoded)
+bitmap file into a (bigger) RGB file using a program such as Paintshop
+Pro. A placeable metafile has a special header with dimension
+information. One may be constructed by a wxWindows program by calling
+the function wxMakeMetafilePlaceable. The Microsoft Windows SDK has a
+sample program that loads and steps through placeable and ordinary
+metafiles.
+
+Another wrinkle is that programs differ in the methods they
+use to recognise pictures in RTF files. You may need to use the {\it bitmapMethod} setting,
+which can be ``hex'' (embed the hex data in the file with a \verb$\dibitmap$ keyword),
+``includepicture'' (use the MS Word 6.0 INCLUDEPICTURE field) or ``import''
+(an earlier name for INCLUDEPICTURE).
+
+Here is an example of using the \verb$\image$ command.
+
+\begin{verbatim}
+    \begin{figure}
+    $$\image{5cm;0cm}{heart.ps}$$
+
+    \caption{My picture}\label{piccy}
+    \end{figure}
+\end{verbatim}
+
+The dollars centre the image in the horizontal plane. The syntax
+of the first argument to \verb$\image$ is taken from syntax used by the \verb$\psbox$\rtfsp
+package: it allows specification of the horizontal and vertical
+dimensions of the image. Scaling will take place for PostScript
+and metafile images. A value of zero indicates that the image should
+be scaled in proportion to the non-zero dimension. Zeros for both
+dimensions will leave the image unscaled in the case of metafiles,
+or scaled to fit the page in the case of PostScript.
+
+See also \commandrefn{imagel}{imagel}, \commandrefn{imager}{imager} for aligned images in
+HTML.
+
+\subsection*{imagel:2}\label{imagel}
+
+Similar to \commandrefn{image}{image}, but left-aligns the image with respect to the following
+content. Use \commandrefn{brclear}{brclear} to stop aligning the content to the right of the image.
+
+See also \commandrefn{imager}{imager}.
+
+\subsection*{imagemap:3}\label{imagemap}
+
+This is translated to an HTML image map reference, or (in LaTeX) a PostScript psbox
+command. This allows images in HTML to have hotspots, where the user clicks on a
+part of the image and the browser jumps to a particular file.
+
+The first argument is the same as the first argument to the \commandref{image}{image}\rtfsp
+command (ignored in HTML). The second argument must be the name of the
+image map entry, and the second is the filename to be displayed inline.
+
+\begin{verbatim}
+    \imagemap{}{tree.gif}{myname}
+\end{verbatim}
+
+translates to:
+
+\begin{verbatim}
+    <a href="/cgi-bin/imagemap/mymap">
+      <img src="tree.gif" ismap></a><p>
+\end{verbatim}
+
+The snag with this is that, apart from the inconvenience of having to
+register a map file with the server, the map file will also have
+references to particular HTML files. If they exist in the current
+document, these names are not known until the file is generated. In which case, the
+map entries should probably refer to symbolic links that can be easily
+changed later.
+
+\subsection*{imager:2}\label{imager}
+
+Similar to \commandrefn{image}{image}, but right-aligns the image with respect to the following
+content. Use \commandrefn{brclear}{brclear} to stop aligning the content to the left of the image.
+
+See also \commandrefn{imagel}{imagel}.
+
+%\subsection*{includeonly}\label{includeonly}
+\subsection*{indented:2}\label{indented}
+
+Environment supplied by Tex2RTF to allow (possibly nested) indentation of
+\LaTeX\ and RTF text. The first argument is the amount to be indented.
+
+For example:
+
+\begin{verbatim}
+    \begin{indented}{2cm}
+    This text should be indented by a couple of centimetres.
+    This can be useful to highlight paragraphs.
+    \end{indented}
+\end{verbatim}
+
+produces:
+
+\begin{indented}{2cm}
+This text should be indented by a couple of centimetres. This can be
+useful to highlight paragraphs.
+\end{indented}
+
+\subsection*{latexignore:1}\label{latexignore}
+
+Ignores the argument in \LaTeX.
+
+\subsection*{latexonly:1}\label{latexonly}
+
+Only prints the argument in \LaTeX.
+
+%\subsection*{lbox}\label{lbox}
+
+\subsection*{lbraceraw:0}\label{lbraceraw}
+
+Outputs a raw left brace into the output (not LaTeX). Useful when
+inserting RTF (for example) that cannot be dealt with by Tex2RTF.
+
+\subsection*{linkcolour:1}\label{linkcolour}
+
+Specifies the link colour for the whole page, HTML only. The argument consists
+of three numbers from 0 to 255 separated by semicolons, for red, green and blue values respectively.
+
+For example:
+
+\begin{verbatim}
+    \linkcolour{255;255;255}
+    \linkcolour{0;0;255}
+\end{verbatim}
+
+The first example sets the link text to white, and the second sets the link text to blue.
+
+See also \commandrefn{backgroundcolour}{backgroundcolour}, \commandrefn{textcolour}{textcolour},
+\rtfsp\commandrefn{followedlinkcolour}{followedlinkcolour}.
+
+Instead of using a LaTeX command, you may find it more convenient to use the equivalent {\tt .ini} file
+setting, {\it linkColour}.
+
+\subsection*{membersection:1}\label{membersection}
+
+Used when formatting C++ classes to print a subsection for the member name.
+
+\subsection*{member:1}\label{member}
+
+Used to format a C++ member variable name.
+
+\subsection*{normalbox:1}\label{normalbox}
+
+Draws a box around the given paragraph in \LaTeX\ and RTF. In HTML
+and XLP formats, horizontal rules are drawn before and after the text.
+
+For example:
+
+\begin{verbatim}
+    \normalbox{This should be a boxed paragraph for highlighting
+    important information, such as information for registering
+    a shareware program.}
+\end{verbatim}
+
+gives:
+
+\normalbox{This should be a boxed paragraph for highlighting important
+information, such as information for registering a shareware program.}
+
+See also \commandrefn{normalboxd}{normalboxd} for double-bordered text.
+
+\subsection*{normalboxd:1}\label{normalboxd}
+
+Draws a double border around the given paragraph in \LaTeX\ and RTF. In
+HTML and XLP formats, horizontal rules are drawn before and after the
+text.
+
+For example:
+
+\begin{verbatim}
+    \normalboxd{This should be a boxed paragraph for
+    highlighting important information, such as information
+    for registering a shareware program.}
+\end{verbatim}
+
+gives:
+
+\normalboxd{This should be a boxed paragraph for highlighting important
+information,such as information for registering a shareware program.}
+
+See also \commandrefn{normalbox}{normalbox} for single-bordered text.
+
+\subsection*{param:1}\label{param}
+
+Formats a C++ type and argument pair. Should be used within the third argument
+of a a \commandrefn{func}{func} command.
+
+\subsection*{popref:2}\label{popref}
+
+Similar to \commandrefn{helprefn}{helprefn}, except that in Windows Help,
+the destination text is popped up in a small window to be dismissed with
+a mouse click, instead of going to a separate section.
+
+Currently this command can only refer to a labelled glossary entry; see
+\commandrefn{gloss}{gloss}.
+
+\subsection*{psboxto:2}\label{psboxto}
+
+Identical to \commandrefn{image}{image}.
+
+%\subsection*{psbox}\label{psbox}
+\subsection*{rbraceraw:0}\label{rbraceraw}
+
+Outputs a raw right brace into the output (not LaTeX). Useful when
+inserting RTF (for example) that cannot be dealt with by Tex2RTF.
+
+\subsection*{registered:0}\label{registered}
+
+Outputs the `registered' symbol in HTML, and (r) in other formats.
+
+\subsection*{row:1}\label{row}
+
+A Tex2RTF command signifying the row of a table within the \commandrefn{tabular}{tabular}\rtfsp
+environment. See also \commandrefn{ruledrow}{ruledrow}.
+
+\subsection*{ruledrow:1}\label{ruledrow}
+
+A Tex2RTF command signifying a ruled row of a table within the \commandrefn{tabular}{tabular}\rtfsp
+environment. See also \commandrefn{row}{row}.
+
+\subsection*{rtfignore:1}\label{rtfignore}
+
+Ignores the argument in linear RTF.
+
+\subsection*{rtfonly:1}\label{rtfonly}
+
+Only outputs the argument in linear RTF.
+
+\subsection*{rtfsp:0}\label{rtfsp}
+
+Outputs a space in RTF. Tex2RTF tries to insert a space where one is implied
+by a newline, but cannot cope where a line starts or ends with a command,
+in the middle of a paragraph. Use this command to insert a space explicitly.
+
+\subsection*{sectionheading:1}\label{sectionheading}
+
+Like \commandrefn{section}{section}, but does not increment the section
+number and does not print a section number in the printed documentation
+contents page, or in the section heading.
+
+\subsection*{setfooter:6}\label{setfooter}
+
+Tex2RTF has a non-standard way of setting headers and footers,
+but the default macro definitions in {\tt texhelp.sty} may be altered
+to your current method.
+
+The arguments are as follows:
+
+\begin{enumerate}
+\itemsep=0pt
+\item Left footer, even pages
+\item Centre footer, even pages
+\item Right footer, even pages
+\item Left footer, odd pages
+\item Centre footer, odd pages
+\item Right footer, odd pages
+\end{enumerate}
+
+For many documents, the first three arguments will be left empty.
+
+The behaviour for first pages of a chapter, section or document
+is to have a blank header, but print the footer.
+
+For best results, define headers and footers for {\it each chapter or
+section}.
+
+Note that this command works only for \LaTeX\ and linear RTF. See also\rtfsp
+\commandrefn{setheader}{setheader}.
+
+\subsection*{setheader:6}\label{setheader}
+
+Tex2RTF has a non-standard way of setting headers and footers,
+but the default macro definitions in {\tt texhelp.sty} may be altered
+to your current method.
+
+The arguments are as follows:
+
+\begin{enumerate}
+\itemsep=0pt
+\item Left header, even pages
+\item Centre header, even pages
+\item Right header, even pages
+\item Left header, odd pages
+\item Centre header, odd pages
+\item Right header, odd pages
+\end{enumerate}
+
+For many documents, the first three arguments will be left empty.
+If \commandrefn{pagestyle}{pagestyle} is not plain or empty, the
+header will separated from the rest of the page by a rule.
+
+The behaviour for first pages of a chapter, section or document
+is to have a blank header, but print the footer.
+
+For best results, define headers and footers for {\it each chapter or
+section}.
+
+Note that this command works only for \LaTeX\ and linear RTF. See also\rtfsp
+\commandrefn{setfooter}{setfooter}.
+
+\subsection*{sethotspotcolour:1}\label{sethotspotcolour}
+
+If the argument is yes, on or ok, subsequent WinHelp hotspots will be green.
+If any other value, the hotspots will be the normal text colour. Note that this
+doesn't apply to section hotspots, only to helpref hotspots.
+
+\subsection*{sethotspotunderline:1}\label{sethotspotunderline}
+
+If the argument is yes, on or ok, subsequent WinHelp hotspots will be
+underlined (the default). If any other value, the hotspots will not be
+underlined. Note that this doesn't apply to section hotspots, only to
+helpref hotspots.
+
+\subsection*{settransparency:1}\label{settransparency}
+
+WinHelp mode only (version 4 of WinHelp). If the argument is yes, on or ok, subsequent bitmaps
+will be inserted in transparent mode: areas of white will be made transparent.
+If the argument is any other value (such as no, ok or false), the bitmaps will not be transparent.
+
+\subsection*{textcolour:1}\label{textcolour}
+
+Specifies the text foreground colour for the whole page, HTML only. The argument consists
+of three numbers from 0 to 255 separated by semicolons, for red, green and blue values respectively.
+
+For example:
+
+\begin{verbatim}
+    \textcolour{255;255;255}
+    \textcolour{0;0;255}
+\end{verbatim}
+
+The first example sets the text to white, and the second sets the text to blue.
+
+See also \commandrefn{backgroundcolour}{backgroundcolour}, \commandrefn{linkcolour}{linkcolour},
+\rtfsp\commandrefn{followedlinkcolour}{followedlinkcolour}.
+
+Instead of using a LaTeX command, you may find it more convenient to use the equivalent {\tt .ini} file
+setting, {\it textColour}.
+
+\subsection*{toocomplex:1}\label{toocomplex}
+
+An environment for dealing with complex \LaTeX\ commands that
+Tex2RTF cannot handle. In normal \LaTeX, the argument will be output
+as normal. In Tex2RTF output, the argument will be output as verbatim text,
+for the user to hand-translate into the desired output format.
+
+See also \commandrefn{comment}{comment}.
+
+\subsection*{twocolitem:2}\label{twocolitem}
+
+Used to specify a row for a two column list, a Tex2RTF
+extension to optimize two-column lists for different
+file formats.  See \commandrefn{twocollist}{twocollist},
+\rtfsp\commandrefn{twocolitemruled}{twocolitemruled}.
+
+\subsection*{twocolitemruled:2}\label{twocolitemruled}
+
+Used to specify a ruled row for a two column list, a Tex2RTF
+extension to optimize two-column lists for different
+file formats.  See \commandrefn{twocollist}{twocollist},
+\rtfsp\commandrefn{twocolitem}{twocolitem}.
+
+\subsection*{twocollist:1}\label{twocollist}
+
+A Tex2RTF environment for specifying a table of two columns, often
+used in manuals and help files (for example, for listing commands and
+their meanings). The first column should be one line only, and
+the second can be an arbitrary number of paragraphs.
+
+The reason that a normal tabular environment cannot be used is that
+WinHelp does not allow borders in table cells, so a different method
+must be employed if any of the rows are to be ruled. In \LaTeX, a table
+is used to implement this environment. In RTF, indentation is used instead.
+
+Use this environment in conjunction with \commandrefn{twocolitem}{twocolitem} and\rtfsp
+\commandrefn{twocolitemruled}{twocolitemruled}. To set the widths of the first
+and second column, use \commandrefn{twocolwidtha}{twocolwidtha} and\rtfsp
+\commandrefn{twocolwidthb}{twocolwidthb}.
+
+Example:
+
+\begin{verbatim}
+    \htmlignore{\begin{twocollist}}
+    \twocolitemruled{{\bf Command}}{{\bf Description}}
+    \twocolitem{File}{The file menu is used to select various
+    file-related operations, such as saving and loading.}
+    \twocolitem{Edit}{The Edit menu is used for
+    selection, copying, pasting, etc.}
+    \end{twocollist}
+\end{verbatim}
+
+This produces:
+
+\begin{twocollist}
+\twocolitemruled{{\bf Command}}{{\bf Description}}
+\twocolitem{File}{The file menu is used to select various file-related
+operations, such as saving and loading.}
+\twocolitem{Edit}{The Edit menu is used for selection, copying, pasting, etc.}
+\end{twocollist}
+
+\subsection*{twocolwidtha:1}\label{twocolwidtha}
+
+Sets the width of the first column in a two column list to the given
+dimension. See also \commandrefn{twocollist}{twocollist} and \commandrefn{twocolwidthb}{twocolwidthb}.
+
+\subsection*{twocolwidthb:1}\label{twocolwidthb}
+
+Sets the width of the second column in a two column list to the given
+dimension. See also \commandrefn{twocollist}{twocollist} and \commandrefn{twocolwidtha}{twocolwidtha}.
+
+\subsection*{urlref:2}\label{urlref}
+
+Specifies a jump to a URL (univeral resource location).
+
+The first argument is text to be highlighted (mouseable in HTML browsers)
+and the second is the URL. In linear documents, the URL
+is given following the text.
+
+Example:
+
+\begin{verbatim}
+    See also the \urlref{wxWindows manual}
+      {http://www.aiai.ed.ac.uk/~jacs.html}.
+\end{verbatim}
+
+(the line is broken only to keep to this manual's page width).
+
+\subsection*{winhelpignore:1}\label{winhelpignore}
+
+Ignores the argument in WinHelp RTF.
+
+\subsection*{winhelponly:1}\label{winhelponly}
+
+Only outputs the argument in WinHelp RTF.
+
+\subsection*{xlpignore:1}\label{xlpignore}
+
+Ignores the argument in XLP mode (wxHelp files).
+
+\subsection*{xlponly:1}\label{xlponly}
+
+Only outputs the argument in XLP mode (wxHelp files).
+
+\section{Accents}\label{accents}
+
+The following \LaTeX\ accents work for RTF and HTML production:
+
+\begin{itemize}%
+\itemsep=0pt
+\item \verb$\'{a}$ produces \'{a}. Valid for a, e, i, o, u, A, E, I, O, U
+\item \verb$\`{a}$ produces \`{a}. Valid for a, e, i, o, u, y, A, E, I, O, U, Y
+\item \verb$\^{a}$ produces \^{a}. Valid for a, e, i, o, u, A, E, I, O, U
+\item \verb$\~{a}$ produces \~{a}. Valid for a, n, o, A, N, O
+\item \verb$\"{a}$ produces \"{a}. Valid for a, e, i, o, u, y, A, E, I, O, U, Y
+\item \verb$\.{a}$ produces \.{a}. Valid for a, A
+\end{itemize}
+
+\section{Commands by category}\index{commands}%
+
+Below are categories of \LaTeX\ commands, to help you find the right
+command for a particular purpose.
+
+\subsection{Font commands}
+
+\begin{itemize}\itemsep=0pt
+\item \commandpageref{bf}{bf}
+\item \commandpageref{bffamily}{bffamily}
+\item \commandpageref{em}{em}
+\item \commandpageref{emph}{emph}
+\item \commandpageref{huge}{huge1}
+\item \commandpageref{Huge}{Huge2}
+\item \commandpageref{HUGE}{HUGE3}
+\item \commandpageref{it}{it}
+\item \commandpageref{itshape}{itshape}
+\item \commandpageref{large}{large1}
+\item \commandpageref{Large}{Large2}
+\item \commandpageref{LARGE}{LARGE3}
+\item \commandpageref{mdseries}{mdseries}
+\item \commandpageref{normalsize}{normalsize}
+\item \commandpageref{rm}{rm}
+\item \commandpageref{rmfamily}{rmfamily}
+\item \commandpageref{sc}{sc}
+\item \commandpageref{scshape}{scshape}
+\item \commandpageref{sf}{sf}
+\item \commandpageref{sffamily}{sffamily}
+\item \commandpageref{sl}{sl}
+\item \commandpageref{slshape}{slshape}
+\item \commandpageref{small}{small}
+\item \commandpageref{textbf}{textbf}
+\item \commandpageref{textit}{textit}
+\item \commandpageref{textrm}{textrm}
+\item \commandpageref{textsf}{textsf}
+\item \commandpageref{textsc}{textsc}
+\item \commandpageref{textsl}{textsl}
+\item \commandpageref{texttt}{texttt}
+\item \commandpageref{tiny}{tiny}
+\item \commandpageref{tt}{tt}
+\item \commandpageref{ttfamily}{ttfamily}
+\item \commandpageref{underline}{underline}
+\item \commandpageref{upshape}{upshape}
+\end{itemize}
+
+\subsection{Paragraph formatting}
+
+\begin{itemize}\itemsep=0pt
+\item \commandpageref{centerline}{centerline}
+\item \commandpageref{comment}{comment}
+\item \commandpageref{flushleft}{flushleft}
+\item \commandpageref{footnote}{footnote}
+\item \commandpageref{indented}{indented}
+\item \commandpageref{marginparwidth}{marginparwidth}
+\item \commandpageref{marginpar}{marginpar}
+\item \commandpageref{marginpareven}{marginpareven}
+\item \commandpageref{marginparodd}{marginparodd}
+\item \commandpageref{multicolumn}{multicolumn}
+\item \commandpageref{newpage}{newpage}
+\item \commandpageref{noindent}{noindent}
+\item \commandpageref{onecolumn}{onecolumn}
+\item \commandpageref{parindent}{parindent}
+\item \commandpageref{parskip}{parskip}
+\item \commandpageref{par}{par}
+\item \commandpageref{quote}{quote}
+\item \commandpageref{quotation}{quotation}
+\item \commandpageref{textwidth}{textwidth}
+\item \commandpageref{twocolumn}{twocolumn}
+\item \commandpageref{verbatim}{verbatim}
+\item \commandpageref{verb}{verb}
+\end{itemize}
+
+\subsection{Special effects}
+
+\begin{itemize}\itemsep=0pt
+\item \commandpageref{backgroundcolour}{backgroundcolour}
+\item \commandpageref{backgroundimage}{backgroundimage}
+\item \commandpageref{backslashraw}{backslashraw}
+\item \commandpageref{bcol}{bcol}
+\item \commandpageref{definecolour}{definecolour}
+\item \commandpageref{fcol}{fcol}
+\item \commandpageref{followedlinkcolour}{followedlinkcolour}
+\item \commandpageref{helpfontfamily}{helpfontfamily}
+\item \commandpageref{helpfontsize}{helpfontsize}
+\item \commandpageref{hrule}{hrule}
+\item \commandpageref{linkcolour}{linkcolour}
+\item \commandpageref{normalbox}{normalbox}
+\item \commandpageref{normalboxd}{normalboxd}
+\item \commandpageref{sethotspotcolour}{sethotspotcolour}
+\item \commandpageref{sethotspotunderline}{sethotspotunderline}
+\item \commandpageref{settransparency}{settransparency}
+\item \commandpageref{textcolour}{textcolour}
+\item \commandpageref{typeout}{typeout}
+\end{itemize}
+
+\subsection{Lists}
+
+\begin{itemize}\itemsep=0pt
+\item \commandpageref{description}{description}
+\item \commandpageref{enumerate}{enumerate}
+\item \commandpageref{itemize}{itemize}
+\item \commandpageref{item}{item}
+\item \commandpageref{itemsep}{itemsep}
+\item \commandpageref{twocolitem}{twocolitem}
+\item \commandpageref{twocolitemruled}{twocolitemruled}
+\item \commandpageref{twocollist}{twocollist}
+\item \commandpageref{twocolwidtha}{twocolwidtha}
+\item \commandpageref{twocolwidthb}{twocolwidthb}
+\end{itemize}
+
+\subsection{Sectioning}
+
+\begin{itemize}\itemsep=0pt
+\item \commandpageref{chapter}{chapter}
+\item \commandpageref{chapter*}{chaptersX}
+\item \commandpageref{chapterheading}{chapterheading}
+\item \commandpageref{insertatlevel}{insertatlevel}
+\item \commandpageref{paragraph}{paragraph}
+\item \commandpageref{paragraph*}{paragraphX}
+\item \commandpageref{section}{section}
+\item \commandpageref{section*}{sectionX}
+\item \commandpageref{sectionheading}{sectionheading}
+\item \commandpageref{subparagraph}{subparagraph}
+\item \commandpageref{subparagraph*}{subparagraphX}
+\item \commandpageref{subsection}{subsection}
+\item \commandpageref{subsection*}{subsectionX}
+\item \commandpageref{subsubsection}{subsubsection}
+\item \commandpageref{subsubsection*}{subsubsectionX}
+\end{itemize}
+
+\subsection{Pictures}
+
+\begin{itemize}\itemsep=0pt
+\item \commandpageref{brclear}{brclear}
+\item \commandpageref{image}{image}
+\item \commandpageref{imagel}{imagel}
+\item \commandpageref{imagemap}{imagemap}
+\item \commandpageref{imager}{imager}
+\item \commandpageref{psboxto}{psboxto}
+\end{itemize}
+
+\subsection{References and jumps}
+
+\begin{itemize}\itemsep=0pt
+\item \commandpageref{footnotepopup}{footnotepopup}
+\item \commandpageref{helpref}{helpref}
+\item \commandpageref{helprefn}{helprefn}
+\item \commandpageref{label}{label}
+\item \commandpageref{pageref}{pageref}
+\item \commandpageref{popref}{popref}
+\item \commandpageref{ref}{ref}
+\item \commandpageref{urlref}{urlref}
+\end{itemize}
+
+\subsection{Tables and figures}
+
+\begin{itemize}\itemsep=0pt
+\item \commandpageref{caption}{caption}
+\item \commandpageref{figure}{figure}
+\item \commandpageref{hline}{hline}
+\item \commandpageref{ruledrow}{ruledrow}
+\item \commandpageref{tabbing}{tabbing}
+\item \commandpageref{tabular}{tabular}
+\end{itemize}
+
+\subsection{Table of contents}
+
+\begin{itemize}\itemsep=0pt
+\item \commandpageref{addcontentsline}{addcontentsline}
+\item \commandpageref{author}{author}
+\item \commandpageref{date}{date}
+\item \commandpageref{maketitle}{maketitle}
+\item \commandpageref{tableofcontents}{tableofcontents}
+\item \commandpageref{title}{title}
+\end{itemize}
+
+\subsection{Special sections}
+
+\begin{itemize}\itemsep=0pt
+\item \commandpageref{bibitem}{bibitem}
+\item \commandpageref{bibliographystyle}{bibliographystyle}
+\item \commandpageref{bibliography}{bibliographycmd}
+\item \commandpageref{cite}{cite}
+\item \commandpageref{gloss}{gloss}
+\item \commandpageref{helpglossary}{helpglossary}
+\item \commandpageref{index}{index}
+\item \commandpageref{nocite}{nocite}
+\item \commandpageref{printindex}{printindex}
+\item \commandpageref{shortcite}{shortcite}
+\item \commandpageref{thebibliography}{thebibliography}
+\end{itemize}
+
+
+\subsection{Symbols}
+
+\begin{itemize}\itemsep=0pt
+\item \commandpageref{backslash}{backslash}
+\item \commandpageref{cdots}{cdots}
+\item \commandpageref{cextract}{cextract}
+\item \commandpageref{cinsert}{cinsert}
+\item \commandpageref{copyright}{copyright}
+\item \commandpageref{LaTeX}{LaTeX}
+\item \commandpageref{lbraceraw}{lbraceraw}
+\item \commandpageref{ldots}{ldots}
+\item \commandpageref{rbraceraw}{rbraceraw}
+\item \commandpageref{registered}{registered}
+\item \commandpageref{rtfsp}{rtfsp}
+\item \commandpageref{ss}{ss}
+\item \commandpageref{TeX}{TeX}
+\item \commandpageref{today}{today}
+\end{itemize}
+
+\subsection{Document organisation}
+
+\begin{itemize}\itemsep=0pt
+\item \commandpageref{document}{document}
+\item \commandpageref{documentstyle}{documentstyle}
+\item \commandpageref{helpignore}{helpignore}
+\item \commandpageref{helponly}{helponly}
+\item \commandpageref{helpinput}{helpinput}
+\item \commandpageref{htmlignore}{htmlignore}
+\item \commandpageref{htmlonly}{htmlonly}
+\item \commandpageref{include}{include}
+\item \commandpageref{input}{input}
+\item \commandpageref{latexignore}{latexignore}
+\item \commandpageref{latexonly}{latexonly}
+\item \commandpageref{newcommand}{newcommand}
+\item \commandpageref{pagestyle}{pagestyle}
+\item \commandpageref{pagenumbering}{pagenumbering}
+\item \commandpageref{rtfignore}{rtfignore}
+\item \commandpageref{rtfonly}{rtfonly}
+\item \commandpageref{setfooter}{setfooter}
+\item \commandpageref{setheader}{setheader}
+\item \commandpageref{special}{special}
+\item \commandpageref{toocomplex}{toocomplex}
+\item \commandpageref{verbatiminput}{verbatiminput}
+\item \commandpageref{winhelpignore}{winhelpignore}
+\item \commandpageref{winhelponly}{winhelponly}
+\item \commandpageref{xlpignore}{xlpignore}
+\item \commandpageref{xlponly}{xlponly}
+\end{itemize}
+
+\chapter{Bugs and troubleshooting}\label{errors}\index{bugs}\index{errors}\index{troubleshooting}%
+\setheader{{\it CHAPTER \thechapter}}{}{}{}{}{{\it CHAPTER \thechapter}}%
+\setfooter{\thepage}{}{}{}{}{\thepage}%
+
+\section{Bugs}
+
+\begin{description}
+\item[Command parsing.] If a command is used followed by inappropriate
+argument syntax, Tex2RTF can crash. This an occur when a command is
+used in an asterisk form that is only formed in the non-asterisk
+variety. The non-asterisk form is assumed, which makes the following
+asterisk trip up the parser.
+\item[Setlength.] Using the $\backslash$setlength command doesn't work,
+since its first argument looks like a command with the wrong number
+of arguments. Use an alternative form instead, e.g. \verb$\parindent 0pt$ instead
+of \verb$\setlength{parindent}{0pt}$.
+\item[Newcommand bug.] Environments in a command definition confuse
+Tex2RTF. Use the command form instead (e.g. $\backslash$flushleft\{...\} instead
+of $\backslash$begin\{flushleft\} ... $\backslash$end\{flushleft\}.
+\item[Bibliography.] There's no flexibility in the way references
+are output: I expect I'll get round to doing something better,
+but only if people tell me they need it!
+\item[Tables.] Tables can't handle all \LaTeX\ syntax, and require
+the Tex2RTF \verb$\row$ commands for decent formatting. Still, it's
+better than it was (RTF only).
+\item[Indexes and glossaries.] Not completely supported.
+\item[Crashes.] Crashes may be due to an input file exceeding the fixed-size
+buffer used for converting command arguments, especially for the \verb$\verbatim$\rtfsp
+command. Use the {\tt -bufsize} switch to increase the buffer size.
+\item[Verbatiminput.] Verbatiminput files which do not end with a blank line
+can trip up following commands.
+\end{description}
+
+\section{Troubleshooting}
+
+Below are some common problems and possible solutions.
+
+\normalbox{Some of the syntax that is OK for true \LaTeX\ but which trips up
+Tex2RTF, may be detected by the TCHECK program included in the tools
+directory of the Tex2RTF distribution. Some \LaTeX\ errors may be picked up
+by the LACHECK program, also found in the tools directory.}
+
+\subsection{Macro not found}\label{macronotfound}\index{macro not found error}%
+
+This error may indicate that Tex2RTF has not implemented a standard
+\rtfsp\LaTeX\ command, or that a local macro package is being used that
+Tex2RTF does not know about. It can cause spurious secondary
+errors, such as not recognising the end document command.
+
+You can get round this by defining a macro file (default name {\tt tex2rtf.ini})
+containing command definitions, such as:
+
+\begin{verbatim}
+    \crazy      [2]{{\bf #2} is crazy but #1 is not}
+    \something  [0]{}
+    \julian     [0]{Julian Smart}
+\end{verbatim}
+
+New commands may be defined in \LaTeX\ files, but custom macro files
+will have to be defined when local style files are being used. See\rtfsp
+\helpref{Initialisation file syntax}{inifile} for further details.
+
+The `Macro not found' error can also be caused by a syntax error such as
+an unbalanced brace or passing the wrong number of arguments to a command,
+so look in the vicinity of the reported error for the real cause.
+
+Here is one obscure situation that causes this error:
+
+\begin{verbatim}
+    \begin{center}
+    {\large{\underline{A}}}
+    \end{center}
+\end{verbatim}
+
+The problem is too many curly brackets. This should be rewritten as:
+
+\begin{verbatim}
+    \begin{center}
+    {\large \underline{A}}
+    \end{center}
+\end{verbatim}
+
+Often you get a `Macro not found' error for \verb$\end{document}$. This
+is a spurious side-effect of an earlier error, usually an incorrect number
+of arguments to a command. The location of the true error is then anywhere
+in the document. To home in on the error, try putting a verbatim environment
+\rtfsp\verb$\begin{comment}...\end{comment}$ around much of the document,
+and then move the \verb$\begin{comment}$ line down until the error
+manifests itself.
+
+\subsection{Unresolved reference}\index{references, unresolved}%
+
+References and citations are usually resolved on a second pass of
+Tex2RTF. If this doesn't work, then a missing label or bibliographical
+entry is to blame.
+
+\subsection{Output crashes the RTF reader}
+
+This could be due to confusing table syntax. Set {\it compatibility} to\rtfsp
+{\it TRUE} in {\tt .ini} file; also check for end of row characters backslash characters
+on their own on a line, and insert correct number of ampersands for the number of
+columns.  E.g.
+
+\begin{verbatim}
+    hello & world\\
+    \\
+\end{verbatim}
+
+becomes
+
+\begin{verbatim}
+    hello & world\\
+    &\\
+\end{verbatim}
+
+\subsection{Erratic list indentation}
+
+Try increasing the value of the variable {\it listItemIndent} (default 40
+points) to give more space between label and following text. A global
+replacement of \verb$\item [$ with \verb$\item[$ may also be helpful to remove
+unnecessary space before the item label.
+
+\subsection{Missing figure or section reference}
+
+Ensure all labels {\it directly} follow captions or sections (no intervening
+white space).
+
+\subsection{Linear RTF looks odd}
+
+For viewing by programs other than MS Word, you should set the variable {\it useWord} to {\it false}. This
+will turn off some of the special RTF keywords recognised by Word (and possibly other advanced RTF readers).
+
+\subsection{Paragraphs preceding lists are formatted weirdly.}
+
+If a list has spurious spacing in it, e.g. before a \verb$\item$ command, the preceding
+paragraph can take on some of the list's indentation. This may be a WinHelp bug, or an aspect
+of RTF I don't fully understand. The solution is to remove unnecessary space.
+
+\subsection{Unresolved references in Word for Windows}\index{Microsoft Word}%
+
+If question marks appear instead of numbers for figures and tables,
+select all (e.g. CTRL-A), then press F9 {\it twice} to reformat the
+document twice. For the second format, respond with {\it Update Entire
+Table} to any prompts.
+
+\subsection{The Windows 95 help file contents hierarchy looks wrong}\index{WinHelp files}%
+
+WinHelp version 4 (or the WIN32 Help Compiler) does not allow a
+book in the contents list to be followed by a page at the same level.
+A book must be followed by a book, for some strange reason, otherwise
+the page will be tacked on to the pages of the book above it, i.e. placed
+at the wrong level.
+
+To get around this, Tex2RTF inserts a book in some places, if there
+was a book preceding it on the same level. This results in more
+navigation than necessary, but is better than a wrong contents page.
+
+\newpage
+
+% Puts books in the bibliography without needing to cite them in the
+% text
+\nocite{smart93a}%
+\nocite{kopka}%
+\nocite{pfeiffer}%
+
+\bibliography{refs}
+\addcontentsline{toc}{chapter}{Bibliography}
+\setheader{{\it REFERENCES}}{}{}{}{}{{\it REFERENCES}}%
+\setfooter{\thepage}{}{}{}{}{\thepage}%
+
+\begin{helpglossary}
+\setheader{{\it GLOSSARY}}{}{}{}{}{{\it GLOSSARY}}%
+\setfooter{\thepage}{}{}{}{}{\thepage}%
+
+\gloss{GUI}
+
+Graphical User Interface, such as Windows 3 or X.
+
+\gloss{HTML}\label{html}
+
+Hypertext Markup Language; an SGML document type, used for providing
+hypertext information on the World Wide Web, a distributed hypertext
+system on the Internet.
+
+\gloss{LaTeX}\label{latexgloss}
+
+A typesetting language implemented as a set of \TeX\ macros. It is
+distinguished for allowing specification of the document structure,
+whilst taking care of most layout concerns. It represents the opposite
+end of the spectrum from WYSIWYG word processors.
+
+\gloss{RTF}\label{rtf}
+
+Rich Text Format: an interchange format for word processor files,
+used for importing and exporting formatted documents, and as the
+input to the Windows Help compiler.
+
+\gloss{wxHelp}\label{wxhelp}
+
+wxHelp is the hypertext help facility used to provide on-line
+documentation for UNIX-based wxWindows applications. Under Windows 3.1,
+Windows Help is used instead.
+
+\gloss{wxWindows}\label{wxwindows}
+
+wxWindows is a free C++ toolkit for writing applications that are
+portable across several platforms. Currently these are Motif, Open Look,
+Windows 3.1 and Windows NT. Tex2RTF is written using wxWindows.
+
+\end{helpglossary}
+
+\addcontentsline{toc}{chapter}{Index}
+\setheader{{\it INDEX}}{}{}{}{}{{\it INDEX}}%
+\setfooter{\thepage}{}{}{}{}{\thepage}%
+\printindex%
+
+\end{document}
diff --git a/utils/tex2rtf/docs/tex2rtf.wmf b/utils/tex2rtf/docs/tex2rtf.wmf
new file mode 100644 (file)
index 0000000..2a17268
Binary files /dev/null and b/utils/tex2rtf/docs/tex2rtf.wmf differ
diff --git a/utils/tex2rtf/docs/texhelp.sty b/utils/tex2rtf/docs/texhelp.sty
new file mode 100644 (file)
index 0000000..df04b58
--- /dev/null
@@ -0,0 +1,282 @@
+% LaTeX style file
+% Name:   texhelp.sty
+% Author: Julian Smart
+%
+% Purpose
+% -------
+% Style file to enable the simultaneous preparation of printed LaTeX and on-line
+% hypertext manuals.
+% Use in conjunction with Tex2RTF (see Tex2RTF documentation).
+%
+% Note that if a non-ASCII character starts a newline and there should be a space
+% between the last word on the previous line and the first word on this line,
+% you need to use \rtfsp to generate a space in Windows Help. \rtfsp is ignored
+% in all other formats.
+%
+% Julian Smart
+% Artificial Intelligence Applications Institute
+%
+%
+% ============== C++/CLIPS Documentation Facilities ==============
+%
+% Each class definition should be typeset with e.g.
+%
+% \section{\class{Name}: Parent}
+%
+% followed by a description of the class.
+% Each member should follow:
+%
+% \membersection{wxName::Member}
+%
+% with a description of what this member does.
+% Then, one (or more if overloaded) member (function) in detail:
+%
+% \func{return type}{name}{args}
+% or
+% \member{type}{name}
+%
+% where args is a list of \param{type}{name}, ...
+
+% Function, e.g.
+% e.g. to typeset
+%
+% void DoIt(char *string);
+%
+% write:
+%
+% \func{void}{DoIt}{\param{char *}{string}}
+%
+
+\newcommand{\func}[3]{\hangafter=1\noindent\hangindent=10mm
+{{\it #1} {\bf #2}\index{#2}}(#3)}
+
+% For function/type definition where the name is a pointer,
+% e.g. to typeset
+%
+% typedef void (*wxFunction)(wxObject&)
+%
+% write:
+%
+% \pfunc{typedef void}{wxFunction}{param{wxObject&}}
+
+\newcommand{\pfunc}[3]{\hangafter=1\noindent\hangindent=10mm
+{{\it #1} ({\bf *#2})\index{#2}}(#3)}
+
+% Use an ordinary \section command for class name definitions.
+
+% This is used for a member, such as wxBitmap: GetDepth
+\newcommand{\membersection}[1]{\subsection*{#1}\index{#1}}
+
+% CLIPS function
+\newcommand{\clipsfunc}[3]{\hangafter=1\noindent\hangindent=10mm
+{{\bf #1} ({\bf #2}\index{#2}}#3)}
+
+\newcommand{\clipssection}[1]{\chapter{#1}}
+
+% This is used for a CLIPS function name
+\newcommand{\functionsection}[1]{\subsection*{#1}}
+
+% Member: a type and a name
+\newcommand{\member}[2]{{\bf #1 \it #2}}
+
+% C++ Parameter: a type and a name (no intervening space)
+\newcommand{\param}[2]{{\it #1}{\bf #2}}
+
+% CLIPS Parameter: a type and a name (one intervening space)
+\newcommand{\cparam}[2]{{\bf #1} {\it #2}}
+
+% Class: puts in index
+\newcommand{\class}[1]{#1\index{#1}}
+
+% Void type
+\newcommand{\void}{{\it void}}
+
+% Typeset destructor
+\newcommand{\destruct}[1]{{$\sim$}#1}
+
+% Typeset insert/extract operators
+\newcommand{\cinsert}{$<<$}
+\newcommand{\cextract}{$>>$}
+
+
+% =================== Hypertext facilities ===================
+%
+% To insert hyperlinks (or references, in Latex), \label the sections
+% or membersections \label{ref-label} immediately after the section, on the same line,
+% and use \helpref{text-to-show}{ref-label} to make a reference.
+%
+
+% Type text with section reference
+\newcommand{\helpref}[2]{{\it #1} (section \ref{#2}) }
+
+% Type text with URL in verbatim mode
+\newcommand{\urlref}[2]{#1 (\verb$#2$)}
+
+% Don't typeset section number in LaTeX
+\newcommand{\helprefn}[2]{{\it #1}}
+
+% Like helpref, but popup text in WinHelp instead of hyperlinked
+\newcommand{\popref}[2]{{\it #1}}
+
+% Like footnote, but popup text.
+\newcommand{\footnotepopup}[2]{{\it #1}\footnote{#2}}
+
+% =================== On-line help specific macros ===================
+%
+
+% Global document font size/family, help only.
+\newcommand{\helpfontsize}[1]{}
+\newcommand{\helpfontfamily}[1]{}
+
+% Ignore in all on-line help
+\newcommand{\helpignore}[1]{#1}
+% Only print in all on-line help
+\newcommand{\helponly}[1]{}
+
+% Ignore in LaTeX
+\newcommand{\latexignore}[1]{}
+% Only print in LaTeX
+\newcommand{\latexonly}[1]{#1}
+
+% Ignore in linear RTF
+\newcommand{\rtfignore}[1]{#1}
+% Only print in linear RTF
+\newcommand{\rtfonly}[1]{}
+
+% Ignore in WinHelp RTF
+\newcommand{\winhelpignore}[1]{#1}
+% Only print in WinHelp RTF
+\newcommand{\winhelponly}[1]{}
+
+% Ignore in wxHelp
+\newcommand{\xlpignore}[1]{#1}
+% Only print in wxHelp
+\newcommand{\xlponly}[1]{}
+
+% Ignore in HTML
+\newcommand{\htmlignore}[1]{#1}
+% Only print in HTML
+\newcommand{\htmlonly}[1]{}
+
+% Input a file only for help system (binder thickness is not a limitation
+% in help systems!)
+\newcommand{\helpinput}[1]{}
+
+\newcommand{\rtfsp}{ } % Force a space in RTF, ignore in Latex
+
+% =================== Miscellaneous macros ===================
+%
+% Headings consistent with generated ones
+\newcommand{\myheading}[1]{\vspace*{25pt}
+\begin{flushleft}
+{\LARGE \bf #1}
+\end{flushleft}
+\vskip 20pt
+}
+
+% Heading with entry in contents page.
+\newcommand{\chapterheading}[1]{\myheading{#1}
+\addcontentsline{toc}{chapter}{#1}}
+
+\newcommand{\sectionheading}[1]{\myheading{#1}
+\addcontentsline{toc}{section}{#1}}
+
+% Glossary environment
+\newenvironment{helpglossary}{\newpage\chapterheading{Glossary}\begin{description}}{\end{description}}
+
+% Glossary entry
+\newcommand{\gloss}[1]{\item[#1]\index{#1}}
+
+% Image: EPS in Latex, BMP or MF (whatever's available) in RTF. Requires psbox.
+\newcommand{\image}[2]{\psboxto(#1){#2}}
+
+% Image, left aligned (HTML)
+\newcommand{\imager}[2]{\psboxto(#1){#2}}
+
+% Image, right aligned (HTML)
+\newcommand{\imagel}[2]{\psboxto(#1){#2}}
+
+% Imagemap: principally for HTML only. In Latex,
+% acts like \image.
+\newcommand{\imagemap}[3]{\psboxto(#1){#2}}
+
+% Headers and footers
+% \setheader{EvenPageLeft}{EvenPageCentre}{EvenPageRight}
+% {OddPageLeft}{OddPageCentre}{OddPageRight}
+\newcommand{\setheader}[6]{
+\lhead[\fancyplain{}{#1}]{\fancyplain{}{#4}}
+\chead[\fancyplain{}{#2}]{\fancyplain{}{#5}}
+\rhead[\fancyplain{}{#3}]{\fancyplain{}{#6}}
+}
+
+% \setfooter{EvenPageLeft}{EvenPageCentre}{EvenPageRight}
+% {OddPageLeft}{OddPageCentre}{OddPageRight}
+\newcommand{\setfooter}[6]{
+\lfoot[\fancyplain{#1}{#1}]{\fancyplain{#4}{#4}}
+\cfoot[\fancyplain{#2}{#2}]{\fancyplain{#5}{#5}}
+\rfoot[\fancyplain{#3}{#3}]{\fancyplain{#6}{#6}}
+}
+
+% Needed for telling RTF where margin paragraph should go
+% in mirrored margins mode.
+\newcommand{\marginpareven}[1]{\hspace*{0pt}\marginpar{#1}}
+\newcommand{\marginparodd}[1]{\hspace*{0pt}\marginpar{#1}}
+
+% Environment for two-column table popular in WinHelp and manuals.
+\newcommand{\twocolwidtha}[1]{\def\twocolwidthaval{#1}}
+\newcommand{\twocolwidthb}[1]{\def\twocolwidthbval{#1}}
+\newcommand{\twocolspacing}[1]{\def\twocolspacingval{#1}}
+
+\twocolwidtha{3cm}
+\twocolwidthb{8.5cm}
+\twocolspacing{2}
+
+\newcommand{\twocolitem}[2]{#1 & #2\\}
+\newcommand{\twocolitemruled}[2]{#1 & #2\\\hline}
+
+\newenvironment{twocollist}{\renewcommand{\arraystretch}{\twocolspacingval}\begin{tabular}{lp{\twocolwidthbval}}}%
+{\end{tabular}\renewcommand{\arraystretch}{1}}
+
+% Specifying table rows for RTF compatibility
+\newcommand{\row}[1]{#1\\}
+
+% Use for the last ruled row for correct RTF generation.
+\newcommand{\ruledrow}[1]{#1\\\hline}
+
+% Indentation environment. Arg1 is left margin size
+\newenvironment{indented}[1]{\begin{list}{}{\leftmargin=#1}\item[]}%
+{\end{list}}
+
+% Framed box of text, normal formatting.
+\newcommand{\normalbox}[1]{\fbox{\vbox{#1}}}
+% Double-framed box of text.
+\newcommand{\normalboxd}[1]{\fbox{\fbox{\vbox{#1}}}}
+
+% WITHDRAWN -- can't do in RTF, easily.
+% Framed box of text, horizontally centred. Ragged right within box.
+% \newcommand{\centeredbox}[2]{\begin{center}\fbox{\parbox{#1}{\raggedright#2}}\end{center}}
+% Double-framed box of text, horizontally centred. Ragged right within box.
+% \newcommand{\centeredboxd}[2]{\begin{center}\fbox{\fbox{\parbox{#1}{\raggedright#2}}}\end{center}}
+
+% toocomplex environment: simply prints the argument in LaTeX,
+% comes out verbatim in all generated formats.
+\newenvironment{toocomplex}{}{}
+
+% Colour: dummy commands since LaTeX doesn't support colour.
+% \definecolour{name}{red}{blue}{green}
+% \fcol{name}{text} ; Foreground
+% \bcol{name}{text} ; Background
+\newcommand{\definecolour}[4]{}
+\newcommand{\definecolor}[4]{}
+\newcommand{\fcol}[2]{#2}
+\newcommand{\bcol}[2]{#2}
+\newcommand{\sethotspotcolour}[1]{}
+\newcommand{\sethotspotunderline}[1]{}
+\newcommand{\settransparency}[1]{}
+\newcommand{\backslashraw}[0]{}
+\newcommand{\lbraceraw}[0]{}
+\newcommand{\rbraceraw}[0]{}
+\newcommand{\registered}[0]{(r)}
+\newcommand{\background}[1]{}
+\newcommand{\textcolour}[1]{}
+\newcommand{\overview}[2]{See \helpref{#1}{#2}.}
diff --git a/utils/tex2rtf/docs/up.gif b/utils/tex2rtf/docs/up.gif
new file mode 100644 (file)
index 0000000..316d0d2
Binary files /dev/null and b/utils/tex2rtf/docs/up.gif differ
diff --git a/utils/tex2rtf/docs/verbatim.sty b/utils/tex2rtf/docs/verbatim.sty
new file mode 100644 (file)
index 0000000..462c329
--- /dev/null
@@ -0,0 +1,212 @@
+%% 
+%% This is file `verbatim.sty' generated
+%% on <1991/9/3> with the docstrip utility (v1.1l test). 
+%% 
+%% The original source file was `verbatim.doc'.
+%% 
+%% 
+%% Copyright (C) 1989,1990,1991 by Rainer Schoepf. All rights reserved. 
+%% 
+%% IMPORTANT NOTICE: 
+%% 
+%% You are not allowed to change this file. You may however copy this file 
+%% to a different name and then change this copy. 
+%% 
+%% You are allowed to distribute this file under the condition that it is 
+%% distributed together with all files mentioned in readme.mz4. If you 
+%% receive only some of these files from someone, complain! 
+%% 
+%% You are NOT ALLOWED to distribute this file alone. You are NOT ALLOWED 
+%% to take money for the distribution or use of this file (or a changed 
+%% version) except for some nominal charge for copying etc. 
+%% 
+%% Error Reports in case of UNCHANGED versions to 
+%% 
+%% Rainer Schoepf 
+%% Konrad-Zuse-Zentrum fuer Informationstechnik Berlin 
+%% Heilbronner Str. 10 
+%% W-1000 Berlin 31 
+%% Federal Republic of Germany 
+%% Internet: <SCHOEPF@SC.ZIB-Berlin.DE> 
+%% 
+\def\fileversion{v1.4f}
+\def\filedate{91/08/05}
+\def\docdate{91/08/05}
+
+%% \CheckSum{439}
+%% \CharacterTable
+%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%%   Digits        \0\1\2\3\4\5\6\7\8\9
+%%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%%   Dollar        \$     Percent       \%     Ampersand     \&
+%%   Acute accent  \'     Left paren    \(     Right paren   \)
+%%   Asterisk      \*     Plus          \+     Comma         \,
+%%   Minus         \-     Point         \.     Solidus       \/
+%%   Colon         \:     Semicolon     \;     Less than     \<
+%%   Equals        \=     Greater than  \>     Question mark \?
+%%   Commercial at \@     Left bracket  \[     Backslash     \\
+%%   Right bracket \]     Circumflex    \^     Underscore    \_
+%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%%   Right brace   \}     Tilde         \~}
+%%
+%% Style-option `verbatim' to use with LaTeX v2.09
+%% Copyright (C) 1989, 1990, 1991 by Rainer Sch\"opf, all rights reserved.
+\@ifundefined{verbatim@@@}{}{\endinput}
+\typeout{Style-Option: `verbatim'
+   \fileversion \space <\filedate>  (RmS)}
+\typeout{English Documentation
+   \@spaces \@spaces \space <\docdate>  (RmS)}
+\def\addto@hook#1#2{#1\expandafter{\the#1#2}}
+\newtoks\every@verbatim
+\every@verbatim={}
+\def\@makeother#1{\catcode`#112\relax}
+\begingroup
+ \catcode`\ =\active%
+\gdef\@vobeyspaces{\catcode`\ \active\let \@xobeysp}%
+\endgroup
+\def\@xobeysp{\leavevmode\penalty\@M\ }
+\newtoks\verbatim@line
+\def\verbatim@startline{\verbatim@line{}}
+\def\verbatim@addtoline#1{%
+  \verbatim@line\expandafter{\the\verbatim@line#1}}
+\def\verbatim@processline{\the\verbatim@line\par}
+\def\verbatim@finish{\ifcat$\the\verbatim@line$\else
+  \verbatim@processline\fi}
+\begingroup
+ \catcode`\`=\active
+ \gdef\verbatim@font{\tt \catcode96\active
+   \def`{\leavevmode\kern\z@\char96 }}
+\endgroup
+\def\@verbatim{\the\every@verbatim
+  \trivlist \item[]%
+  \leftskip\@totalleftmargin\rightskip\z@
+  \parindent\z@\parfillskip\@flushglue\parskip\z@
+  \@@par
+  \def\par{\leavevmode\null\@@par\penalty\interlinepenalty}%
+  \obeylines
+  \verbatim@font
+  \let\do\@makeother \dospecials}
+\def\verbatim{\@verbatim \frenchspacing\@vobeyspaces\verbatim@start}
+\@namedef{verbatim*}{\@verbatim\verbatim@start}
+\let\endverbatim=\endtrivlist
+\expandafter\let\csname endverbatim*\endcsname =\endtrivlist
+\def\comment{\@bsphack
+             \let\do\@makeother\dospecials\catcode`\^^M\active
+             \let\verbatim@startline\relax
+             \let\verbatim@addtoline\@gobble
+             \let\verbatim@processline\relax
+             \let\verbatim@finish\relax
+             \verbatim@}
+\let\endcomment=\@esphack
+\@ifundefined{vrb@catcodes}%
+  {\def\vrb@catcodes{%
+     \catcode`\!12\catcode`\[12\catcode`\]12}}{}
+\begingroup
+ \vrb@catcodes
+ \lccode`\!=`\\ \lccode`\[=`\{ \lccode`\]=`\}
+ \catcode`\~=\active \lccode`\~=`\^^M
+ \lccode`\C=`\C
+ \lowercase{%
+    \gdef\verbatim@start#1{%
+      \verbatim@startline
+      \if\noexpand#1\noexpand~%
+        \let\next\verbatim@
+      \else \def\next{\verbatim@#1}\fi
+      \next}%
+    \gdef\verbatim@#1~{\verbatim@@#1!end\@nil}%
+    \gdef\verbatim@@#1!end{%
+       \verbatim@addtoline{#1}%
+       \futurelet\next\verbatim@@@}%
+    \gdef\verbatim@@@#1\@nil{%
+       \ifx\next\@nil
+         \verbatim@processline
+         \verbatim@startline
+         \let\next\verbatim@
+       \else
+         \def\@tempa##1!end\@nil{\toks@{##1}}%
+           \@tempa#1\@nil
+         \@temptokena{!end}%
+         \edef\next{\noexpand\verbatim@test\the\toks@\noexpand~}%
+       \fi \next}%
+ \gdef\verbatim@test#1{%
+           \let\next\verbatim@test
+           \if\noexpand#1\noexpand~%
+             \expandafter\verbatim@addtoline
+               \expandafter{\the\@temptokena}%
+             \verbatim@processline
+             \verbatim@startline
+             \let\next\verbatim@
+           \else \if\noexpand#1
+             \@temptokena\expandafter{\the\@temptokena#1}%
+           \else \if\noexpand#1\noexpand[%
+             \let\@tempc\@empty
+             \let\next\verbatim@testend
+           \else
+             \expandafter\verbatim@addtoline
+               \expandafter{\the\@temptokena}%
+             \def\next{\verbatim@#1}%
+           \fi\fi\fi
+           \next}%
+    \gdef\verbatim@testend#1{%
+         \if\noexpand#1\noexpand~%
+           \expandafter\verbatim@addtoline
+             \expandafter{\the\@temptokena[}%
+           \expandafter\verbatim@addtoline
+             \expandafter{\@tempc}%
+           \verbatim@processline
+           \verbatim@startline
+           \let\next\verbatim@
+         \else\if\noexpand#1\noexpand]%
+           \let\next\verbatim@@testend
+         \else\if\noexpand#1\noexpand!%
+           \expandafter\verbatim@addtoline
+             \expandafter{\the\@temptokena[}%
+           \expandafter\verbatim@addtoline
+             \expandafter{\@tempc}%
+           \def\next{\verbatim@!}%
+         \else \expandafter\def\expandafter\@tempc\expandafter
+           {\@tempc#1}\fi\fi\fi
+         \next}%
+    \gdef\verbatim@@testend{%
+       \ifx\@tempc\@currenvir
+         \verbatim@finish
+         \edef\next{\noexpand\end{\@currenvir}%
+                    \noexpand\verbatim@rescan{\@currenvir}}%
+       \else
+         \expandafter\verbatim@addtoline
+           \expandafter{\the\@temptokena[}%
+           \expandafter\verbatim@addtoline
+             \expandafter{\@tempc]}%
+         \let\next\verbatim@
+       \fi
+       \next}%
+  \gdef\verbatim@rescan#1#2~{\if\noexpand~\noexpand#2~\else
+        \@warning{Characters dropped after `\string\end{#1}'}\fi}}
+\endgroup
+\def\verbatiminput{\begingroup
+  \@ifstar\sverbatim@input\verbatim@input}
+\def\sverbatim@input#1{\@verbatim
+  \@input{#1}\endtrivlist\endgroup\@doendpe}
+\def\verbatim@input#1{\@verbatim
+  \frenchspacing \@vobeyspaces
+  \@input{#1}\endtrivlist\endgroup\@doendpe}
+\begingroup
+  \lccode`\~=`\^^M
+  \lowercase{%
+    \gdef\verb{\begingroup
+      \verbatim@font
+      \catcode`\^^M\active
+      \def~{\endgroup\@latexerr{\string\verb\space command ended by
+                                end of line.}\@ehc}%
+    \let\do\@makeother \dospecials
+    \@ifstar\@sverb{\@vobeyspaces \frenchspacing \@sverb}}}
+\endgroup
+\def\@sverb#1{%
+  \catcode`#1\active
+  \lccode`\~`#1%
+  \lowercase{\let~\endgroup}%
+  \leavevmode\null}
+\endinput
+%% 
+%% End of file `verbatim.sty'.
diff --git a/utils/tex2rtf/src/bmputils.h b/utils/tex2rtf/src/bmputils.h
new file mode 100644 (file)
index 0000000..0f8b07a
--- /dev/null
@@ -0,0 +1,227 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        bmputils.h
+// Purpose:     Utilities for manipulating bitmap and metafile images for
+//              the purposes of conversion to RTF
+// Author:      Julian Smart
+// Modified by:
+// Created:     7.9.93
+// RCS-ID:      $Id$
+// Copyright:   (c) Julian Smart
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+static char hexArray[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
+  'C', 'D', 'E', 'F' };
+
+void DecToHex(int dec, char *buf)
+{
+  int firstDigit = (int)(dec/16.0);
+  int secondDigit = (int)(dec - (firstDigit*16.0));
+  buf[0] = hexArray[firstDigit];
+  buf[1] = hexArray[secondDigit];
+  buf[2] = 0;
+}
+static unsigned int getshort(FILE *fp)
+{
+  int c, c1;
+  c = getc(fp);  c1 = getc(fp);
+  return ((unsigned int) c) + (((unsigned int) c1) << 8);
+}
+
+static unsigned long getint(FILE *fp)
+{
+  int c, c1, c2, c3;
+  c = getc(fp);  c1 = getc(fp);  c2 = getc(fp);  c3 = getc(fp);
+  return (long)((long) c) +
+         (((long) c1) << 8) + 
+        (((long) c2) << 16) +
+        (((long) c3) << 24);
+}
+
+bool GetBMPHeader(FILE *fp, int *Width, int *Height, int *Planes, int *BitsPerPixel)
+{
+  unsigned long bfSize, bfOffBits, biSize, biWidth, biHeight, biPlanes;
+  unsigned long biBitCount, biCompression, biSizeImage, biXPelsPerMeter;
+  unsigned long biYPelsPerMeter, biClrUsed, biClrImportant;
+
+  /* read the file type (first two bytes) */
+  int c = getc(fp); int c1 = getc(fp);
+  if (c!='B' || c1!='M') { return FALSE; }
+
+  bfSize = getint(fp);
+  getshort(fp);         /* reserved and ignored */
+  getshort(fp);
+  bfOffBits = getint(fp);
+
+  biSize          = getint(fp);
+  biWidth         = getint(fp);
+  biHeight        = getint(fp);
+  biPlanes        = getshort(fp);
+  biBitCount      = getshort(fp);
+  biCompression   = getint(fp);
+  biSizeImage     = getint(fp);
+  biXPelsPerMeter = getint(fp);
+  biYPelsPerMeter = getint(fp);
+  biClrUsed       = getint(fp);
+  biClrImportant  = getint(fp);
+
+  *Width = (int)biWidth;
+  *Height = (int)biHeight;
+  *Planes = (int)biPlanes;
+  *BitsPerPixel = (int)biBitCount;
+
+//  fseek(fp, bfOffBits, SEEK_SET);
+  
+  return TRUE;
+}
+
+static int scanLineWidth = 0;
+
+bool OutputBitmapHeader(FILE *fd, bool isWinHelp = FALSE)
+{
+  int Width, Height, Planes, BitsPerPixel;
+  if (!GetBMPHeader(fd, &Width, &Height, &Planes, &BitsPerPixel))
+    return FALSE;
+
+  scanLineWidth = (int)((float)Width/(8.0/(float)BitsPerPixel));
+  if ((float)((int)(scanLineWidth/2.0)) != (float)(scanLineWidth/2.0))
+    scanLineWidth ++;
+    
+  int goalW = 15*Width;
+  int goalH = 15*Height;
+
+  TexOutput("{\\pict");
+  if (isWinHelp) TexOutput("\\wbitmap0");
+  else TexOutput("\\dibitmap");
+
+  char buf[50];
+  TexOutput("\\picw"); sprintf(buf, "%d", Width); TexOutput(buf);
+  TexOutput("\\pich"); sprintf(buf, "%d", Height); TexOutput(buf);
+  TexOutput("\\wbmbitspixel"); sprintf(buf, "%d", BitsPerPixel); TexOutput(buf);
+  TexOutput("\\wbmplanes"); sprintf(buf, "%d", Planes); TexOutput(buf);
+  TexOutput("\\wbmwidthbytes"); sprintf(buf, "%d", scanLineWidth); TexOutput(buf);
+  TexOutput("\\picwgoal"); sprintf(buf, "%d", goalW); TexOutput(buf);
+  TexOutput("\\pichgoal"); sprintf(buf, "%d", goalH); TexOutput(buf);
+  TexOutput("\n");
+  return TRUE;
+}
+
+
+bool OutputBitmapData(FILE *fd)
+{
+  fseek(fd, 14, SEEK_SET);
+  int bytesSoFar = 0;
+  int ch = getc(fd);
+  char hexBuf[3];
+  while (ch != EOF)
+  {
+    if (bytesSoFar == scanLineWidth)
+    {
+      bytesSoFar = 0;
+      TexOutput("\n");
+    }
+    DecToHex(ch, hexBuf);
+    TexOutput(hexBuf);
+    bytesSoFar ++;
+    ch = getc(fd);
+  }
+  TexOutput("\n}\n");
+  return TRUE;
+}
+
+#ifdef __WXMSW__
+struct mfPLACEABLEHEADER {
+       DWORD   key;
+       HANDLE  hmf;
+       RECT    bbox;
+       WORD    inch;
+       DWORD   reserved;
+       WORD    checksum;
+};
+
+// Returns size in TWIPS
+bool GetMetafileHeader(FILE *handle, int *width, int *height)
+{
+  char buffer[40];
+  mfPLACEABLEHEADER *theHeader = (mfPLACEABLEHEADER *)&buffer;
+  fread((void *)theHeader, sizeof(char), sizeof(mfPLACEABLEHEADER), handle);
+  if (theHeader->key != 0x9AC6CDD7)
+  {
+    return FALSE;
+  }
+
+  float widthInUnits = (float)theHeader->bbox.right - theHeader->bbox.left;
+  float heightInUnits = (float)theHeader->bbox.bottom - theHeader->bbox.top;
+  *width = (int)((widthInUnits*1440.0)/theHeader->inch);
+  *height = (int)((heightInUnits*1440.0)/theHeader->inch);
+  return TRUE;
+}
+
+bool OutputMetafileHeader(FILE *handle, bool isWinHelp, int userWidth, int userHeight)
+{
+  int Width, Height;
+  if (!GetMetafileHeader(handle, &Width, &Height))
+    return FALSE;
+
+  scanLineWidth = 64;
+  int goalW = Width;
+  int goalH = Height;
+
+  // Scale to user's dimensions if we have the information
+  if (userWidth > 0 && userHeight == 0)
+  {
+    double scaleFactor = ((double)userWidth/(double)goalW);
+    goalW = userWidth;
+    goalH = (int)((goalH * scaleFactor) + 0.5);
+  }
+  else if (userWidth == 0 && userHeight > 0)
+  {
+    double scaleFactor = ((double)userHeight/(double)goalH);
+    goalH = userHeight;
+    goalW = (int)((goalW * scaleFactor) + 0.5);
+  }
+  else if (userWidth > 0 && userHeight > 0)
+  {
+    goalW = userWidth;
+    goalH = userHeight;
+  }
+
+  TexOutput("{\\pict");
+  TexOutput("\\wmetafile8");
+
+  char buf[50];
+  TexOutput("\\picw"); sprintf(buf, "%d", Width); TexOutput(buf);
+  TexOutput("\\pich"); sprintf(buf, "%d", Height); TexOutput(buf);
+  TexOutput("\\picwgoal"); sprintf(buf, "%d", goalW); TexOutput(buf);
+  TexOutput("\\pichgoal"); sprintf(buf, "%d", goalH); TexOutput(buf);
+  TexOutput("\n");
+  return TRUE;
+}
+
+bool OutputMetafileData(FILE *handle)
+{
+  int bytesSoFar = 0;
+  char hexBuf[3];
+  int ch;
+  do
+  {
+    ch = getc(handle);  
+    if (bytesSoFar == scanLineWidth)
+    {
+      bytesSoFar = 0;
+      TexOutput("\n");
+    }
+    if (ch != EOF)
+    {
+      DecToHex(ch, hexBuf);
+      TexOutput(hexBuf);
+      bytesSoFar ++;
+    }
+  } while (ch != EOF);
+  TexOutput("\n}\n");
+  return TRUE;
+}
+
+#endif
+
diff --git a/utils/tex2rtf/src/books.bmp b/utils/tex2rtf/src/books.bmp
new file mode 100644 (file)
index 0000000..cf1e148
Binary files /dev/null and b/utils/tex2rtf/src/books.bmp differ
diff --git a/utils/tex2rtf/src/dos.def b/utils/tex2rtf/src/dos.def
new file mode 100644 (file)
index 0000000..00b503b
--- /dev/null
@@ -0,0 +1,10 @@
+NAME         TEX2RTF
+DESCRIPTION  'Tex2Rtf'
+;
+EXETYPE      DOS
+;
+CODE         PRELOAD MOVEABLE DISCARDABLE
+DATA         PRELOAD MOVEABLE MULTIPLE
+;
+HEAPSIZE     1024
+STACKSIZE    8192
diff --git a/utils/tex2rtf/src/htmlutil.cpp b/utils/tex2rtf/src/htmlutil.cpp
new file mode 100644 (file)
index 0000000..a67bc10
--- /dev/null
@@ -0,0 +1,2982 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        htmlutil.cpp
+// Purpose:     Converts Latex to HTML
+// Author:      Julian Smart
+// Modified by:
+// Created:     7.9.93
+// RCS-ID:      $Id$
+// Copyright:   (c) Julian Smart
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+#include "tex2any.h"
+#include "tex2rtf.h"
+#include "table.h"
+
+extern void DecToHex(int, char *);
+void GenerateHTMLIndexFile(char *fname);
+void OutputContentsFrame(void);
+
+#include "readshg.h" // Segmented hypergraphics parsing
+
+char *ChaptersName = NULL;
+char *SectionsName = NULL;
+char *SubsectionsName = NULL;
+char *SubsubsectionsName = NULL;
+char *TitlepageName = NULL;
+char *lastFileName = NULL;
+char *lastTopic = NULL;
+char *currentFileName = NULL;
+char *contentsFrameName = NULL;
+
+static TexChunk *descriptionItemArg = NULL;
+static TexChunk *helpRefFilename = NULL;
+static TexChunk *helpRefText = NULL;
+static int indentLevel = 0;
+static int citeCount = 1;
+extern FILE *Contents;
+FILE *FrameContents = NULL;
+FILE *Titlepage = NULL;
+// FILE *FrameTitlepage = NULL;
+int fileId = 0;
+bool subsectionStarted = FALSE;
+
+// Which column of a row are we in? (Assumes no nested tables, of course)
+int currentColumn = 0;
+
+// Are we in verbatim mode? If so, format differently.
+static bool inVerbatim = FALSE;
+
+// Need to know whether we're in a table or figure for benefit
+// of listoffigures/listoftables
+static bool inFigure = FALSE;
+static bool inTable = FALSE;
+
+// This is defined in the Tex2Any library.
+extern char *BigBuffer;
+
+class HyperReference: public wxObject
+{
+ public:
+  char *refName;
+  char *refFile;
+  HyperReference(char *name, char *file)
+  {
+    if (name) refName = copystring(name);
+    if (file) refFile = copystring(file);
+  }
+};
+
+class TexNextPage: public wxObject
+{
+ public:
+  char *label;
+  char *filename;
+  TexNextPage(char *theLabel, char *theFile)
+  {
+    label = copystring(theLabel);
+    filename = copystring(theFile);
+  }
+  ~TexNextPage(void)
+  {
+    delete[] label;
+    delete[] filename;
+  }
+};
+
+wxHashTable TexNextPages(wxKEY_STRING);
+
+static char *CurrentChapterName = NULL;
+static char *CurrentChapterFile = NULL;
+static char *CurrentSectionName = NULL;
+static char *CurrentSectionFile = NULL;
+static char *CurrentSubsectionName = NULL;
+static char *CurrentSubsectionFile = NULL;
+static char *CurrentSubsubsectionName = NULL;
+static char *CurrentSubsubsectionFile = NULL;
+static char *CurrentTopic = NULL;
+
+static void SetCurrentTopic(char *s)
+{
+  if (CurrentTopic) delete[] CurrentTopic;
+  CurrentTopic = copystring(s);
+}
+
+void SetCurrentChapterName(char *s, char *file)
+{
+  if (CurrentChapterName) delete[] CurrentChapterName;
+  CurrentChapterName = copystring(s);
+  if (CurrentChapterFile) delete[] CurrentChapterFile;
+  CurrentChapterFile = copystring(file);
+
+  currentFileName = CurrentChapterFile;
+  
+  SetCurrentTopic(s);
+}
+void SetCurrentSectionName(char *s, char *file)
+{
+  if (CurrentSectionName) delete[] CurrentSectionName;
+  CurrentSectionName = copystring(s);
+  if (CurrentSectionFile) delete[] CurrentSectionFile;
+  CurrentSectionFile = copystring(file);
+
+  currentFileName = CurrentSectionFile;
+  SetCurrentTopic(s);
+}
+void SetCurrentSubsectionName(char *s, char *file)
+{
+  if (CurrentSubsectionName) delete[] CurrentSubsectionName;
+  CurrentSubsectionName = copystring(s);
+  if (CurrentSubsectionFile) delete[] CurrentSubsectionFile;
+  CurrentSubsectionFile = copystring(file);
+  currentFileName = CurrentSubsectionFile;
+  SetCurrentTopic(s);
+}
+void SetCurrentSubsubsectionName(char *s, char *file)
+{
+  if (CurrentSubsubsectionName) delete[] CurrentSubsubsectionName;
+  CurrentSubsubsectionName = copystring(s);
+  if (CurrentSubsubsectionFile) delete[] CurrentSubsubsectionFile;
+  CurrentSubsubsectionFile = copystring(file);
+  currentFileName = CurrentSubsubsectionFile;
+  SetCurrentTopic(s);
+}
+
+/*
+ * Close former filedescriptor and reopen using another filename.
+ *
+ */
+
+void ReopenFile(FILE **fd, char **fileName)
+{
+  if (*fd)
+  {
+    fprintf(*fd, "\n</BODY></HTML>\n");
+    fclose(*fd);
+  }
+  fileId ++;
+  char buf[400];
+  if (truncateFilenames)
+    sprintf(buf, "%s%d.htm", FileRoot, fileId);
+  else
+    sprintf(buf, "%s%d.html", FileRoot, fileId);
+  if (*fileName) delete[] *fileName;
+  *fileName = copystring(FileNameFromPath(buf));
+  *fd = fopen(buf, "w");
+  fprintf(*fd, "<HTML>\n");
+}
+
+/*
+ * Reopen section contents file, i.e. the index appended to each section
+ * in subsectionCombine mode
+ */
+
+static char *SectionContentsFilename = NULL;
+static FILE *SectionContentsFD = NULL;
+
+void ReopenSectionContentsFile(void)
+{
+    if ( SectionContentsFD )
+    {
+        fclose(SectionContentsFD);
+    }
+    if ( SectionContentsFilename )
+        delete[] SectionContentsFilename;
+    SectionContentsFD = NULL;
+    SectionContentsFilename = NULL;
+
+    // Create the name from the current section filename
+    if ( CurrentSectionFile )
+    {
+        char buf[256];
+        strcpy(buf, CurrentSectionFile);
+        wxStripExtension(buf);
+        strcat(buf, ".con");
+        SectionContentsFilename = copystring(buf);
+
+        SectionContentsFD = fopen(SectionContentsFilename, "w");
+    }
+}
+
+
+/*
+ * Given a TexChunk with a string value, scans through the string
+ * converting Latex-isms into HTML-isms, such as 2 newlines -> <P>.
+ *
+ */
+void ProcessText2HTML(TexChunk *chunk)
+{
+  bool changed = FALSE;
+  int ptr = 0;
+  int i = 0;
+  char ch = 1;
+  int len = strlen(chunk->value);
+  while (ch != 0)
+  {
+    ch = chunk->value[i];
+
+    // 2 newlines means \par
+    if (!inVerbatim && chunk->value[i] == 10 && ((len > i+1 && chunk->value[i+1] == 10) ||
+                        ((len > i+1 && chunk->value[i+1] == 13) &&
+                        (len > i+2 && chunk->value[i+2] == 10))))
+    {
+      BigBuffer[ptr] = 0; strcat(BigBuffer, "<P>\n\n"); ptr += 5;
+      i += 2;
+      changed = TRUE;
+    }
+    else if (!inVerbatim && ch == '`' && (len >= i+1 && chunk->value[i+1] == '`'))
+    {
+      BigBuffer[ptr] = '"'; ptr ++;
+      i += 2;
+      changed = TRUE;
+    }
+    else if (!inVerbatim && ch == '`') // Change ` to '
+    {
+      BigBuffer[ptr] = 39; ptr ++;
+      i += 1;
+      changed = TRUE;
+    }
+    else if (ch == '<') // Change < to &lt
+    {
+      BigBuffer[ptr] = 0;
+      strcat(BigBuffer, "&lt;");
+      ptr += 4;
+      i += 1;
+      changed = TRUE;
+    }
+    else if (ch == '>') // Change > to &gt
+    {
+      BigBuffer[ptr] = 0;
+      strcat(BigBuffer, "&gt;");
+      ptr += 4;
+      i += 1;
+      changed = TRUE;
+    }
+    else
+    {
+      BigBuffer[ptr] = ch;
+      i ++;
+      ptr ++;
+    }
+  }
+  BigBuffer[ptr] = 0;
+
+  if (changed)
+  {
+    delete chunk->value;
+    chunk->value = copystring(BigBuffer);
+  }
+}
+
+/*
+ * Scan through all chunks starting from the given one,
+ * calling ProcessText2HTML to convert Latex-isms to RTF-isms.
+ * This should be called after Tex2Any has parsed the file,
+ * and before TraverseDocument is called.
+ *
+ */
+void Text2HTML(TexChunk *chunk)
+{
+  Tex2RTFYield();
+  if (stopRunning) return;
+
+  switch (chunk->type)
+  {
+    case CHUNK_TYPE_MACRO:
+    {
+      TexMacroDef *def = chunk->def;
+
+      if (def && def->ignore)
+        return;
+
+      if (def && (def->macroId == ltVERBATIM || def->macroId == ltVERB || def->macroId == ltSPECIAL))
+        inVerbatim = TRUE;
+
+      wxNode *node = chunk->children.First();
+      while (node)
+      {
+        TexChunk *child_chunk = (TexChunk *)node->Data();
+        Text2HTML(child_chunk);
+        node = node->Next();
+      }
+
+      if (def && (def->macroId == ltVERBATIM || def->macroId == ltVERB || def->macroId == ltSPECIAL))
+        inVerbatim = FALSE;
+
+      break;
+    }
+    case CHUNK_TYPE_ARG:
+    {
+      wxNode *node = chunk->children.First();
+      while (node)
+      {
+        TexChunk *child_chunk = (TexChunk *)node->Data();
+        Text2HTML(child_chunk);
+        node = node->Next();
+      }
+
+      break;
+    }
+    case CHUNK_TYPE_STRING:
+    {
+      if (chunk->value)
+        ProcessText2HTML(chunk);
+      break;
+    }
+  }
+}
+
+/*
+ * Add appropriate browse buttons to this page.
+ *
+ */
+
+void AddBrowseButtons(char *upLabel, char *upFilename,
+  char *previousLabel, char *previousFilename,
+  char *thisLabel, char *thisFilename)
+{
+  char contentsReferenceBuf[80];
+  char upReferenceBuf[80];
+  char backReferenceBuf[80];
+  char forwardReferenceBuf[80];
+  if (htmlBrowseButtons == HTML_BUTTONS_NONE)
+    return;
+
+  char *contentsReference = NULL;
+  if (htmlBrowseButtons == HTML_BUTTONS_TEXT)
+    contentsReference = ContentsNameString;
+  else
+  {
+//    contentsReference = "<img align=center src=\"contents.gif\" BORDER=0 ALT=\"Contents\">";
+    contentsReference = contentsReferenceBuf;
+    sprintf(contentsReference, "<img align=center src=\"%s\" BORDER=0 ALT=\"Contents\">", ConvertCase("contents.gif"));
+  }
+  
+  char *upReference = NULL;
+  if (htmlBrowseButtons == HTML_BUTTONS_TEXT)
+    upReference = UpNameString;
+  else
+  {
+//    upReference = "<img align=center src=\"up.gif\" ALT=\"Up\">";
+    upReference = upReferenceBuf;
+    sprintf(upReference, "<img align=center src=\"%s\" BORDER=0 ALT=\"Up\">", ConvertCase("up.gif"));
+  }
+  
+  char *backReference = NULL;
+  if (htmlBrowseButtons == HTML_BUTTONS_TEXT)
+    backReference = "&lt;&lt;";
+  else
+  {
+//    backReference = "<img align=center src=\"back.gif\" ALT=\"Previous\">";
+    backReference = backReferenceBuf;
+    sprintf(backReference, "<img align=center src=\"%s\" BORDER=0 ALT=\"Previous\">", ConvertCase("back.gif"));
+  }
+  
+  char *forwardReference = NULL;
+  if (htmlBrowseButtons == HTML_BUTTONS_TEXT)
+    forwardReference = "&gt;&gt;";
+  else
+  {
+//    forwardReference = "<img align=center src=\"forward.gif\" ALT=\"Next\">";
+    forwardReference = forwardReferenceBuf;
+    sprintf(forwardReference, "<img align=center src=\"%s\" BORDER=0 ALT=\"Next\">", ConvertCase("forward.gif"));
+  }
+  
+  TexOutput("<CENTER>");
+  
+  char buf[200];
+
+  /*
+   * Contents button
+   *
+   */
+
+  if (truncateFilenames)
+  {
+    char buf1[80];
+    strcpy(buf1, ConvertCase(FileNameFromPath(FileRoot)));
+    sprintf(buf, "\n<A HREF=\"%s.%s\">%s</A> ", buf1, ConvertCase("htm"), contentsReference);
+  }
+  else
+  {
+    char buf1[80];
+    strcpy(buf1, ConvertCase(FileNameFromPath(FileRoot)));
+    sprintf(buf, "\n<A HREF=\"%s%s\">%s</A> ", buf1, ConvertCase("_contents.html"), contentsReference);
+  }
+//  TexOutput("<NOFRAMES>");
+  TexOutput(buf);
+//  TexOutput("</NOFRAMES>");
+
+  /*
+   * Up button
+   *
+   */
+
+  if (upLabel && upFilename)
+  {
+    if (strlen(upLabel) > 0)
+      sprintf(buf, "<A HREF=\"%s#%s\">%s</A> ", ConvertCase(upFilename), upLabel, upReference);
+    else
+      sprintf(buf, "<A HREF=\"%s\">%s</A> ", ConvertCase(upFilename), upReference);
+    if (strcmp(upLabel, "contents") == 0)
+    {
+//      TexOutput("<NOFRAMES>");
+      TexOutput(buf);
+//      TexOutput("</NOFRAMES>");
+    }
+    else
+     TexOutput(buf);
+  }
+
+  /*
+   * << button
+   *
+   */
+
+  if (previousLabel && previousFilename)
+  {
+    sprintf(buf, "<A HREF=\"%s#%s\">%s</A> ", ConvertCase(previousFilename), previousLabel, backReference);
+    if (strcmp(previousLabel, "contents") == 0)
+    {
+//      TexOutput("<NOFRAMES>");
+      TexOutput(buf);
+//      TexOutput("</NOFRAMES>");
+    }
+    else
+      TexOutput(buf);
+  }
+  else
+  {
+    // A placeholder so the buttons don't keep moving position
+    sprintf(buf, "%s ", backReference);
+    TexOutput(buf);
+  }
+
+  char *nextLabel = NULL;
+  char *nextFilename = NULL;
+
+  // Get the next page, and record the previous page's 'next' page
+  // (i.e. this page)
+  TexNextPage *nextPage = (TexNextPage *)TexNextPages.Get(thisLabel);
+  if (nextPage)
+  {
+    nextLabel = nextPage->label;
+    nextFilename = nextPage->filename;
+  }
+  if (previousLabel && previousFilename)
+  {
+    TexNextPage *oldNextPage = (TexNextPage *)TexNextPages.Get(previousLabel);
+    if (oldNextPage)
+    {
+      delete oldNextPage;
+      TexNextPages.Delete(previousLabel);
+    }
+    TexNextPage *newNextPage = new TexNextPage(thisLabel, thisFilename);
+    TexNextPages.Put(previousLabel, newNextPage);
+  }
+
+  /*
+   * >> button
+   *
+   */
+
+  if (nextLabel && nextFilename)
+  {
+    sprintf(buf, "<A HREF=\"%s#%s\">%s</A> ", ConvertCase(nextFilename), nextLabel, forwardReference);
+    TexOutput(buf);
+  }
+  else
+  {
+    // A placeholder so the buttons don't keep moving position
+    sprintf(buf, "%s ", forwardReference);
+    TexOutput(buf);
+  }
+
+  /*
+   * Horizontal rule to finish it off nicely.
+   *
+   */
+  TexOutput("</CENTER>");
+  TexOutput("<HR>\n");
+
+  // Update last topic/filename
+  if (lastFileName)
+    delete[] lastFileName;
+  lastFileName = copystring(thisFilename);
+  if (lastTopic)
+    delete[] lastTopic;
+  lastTopic = copystring(thisLabel);
+}
+
+// A colour string is either 3 numbers separated by semicolons (RGB),
+// or a reference to a GIF. Return the filename or a hex string like #934CE8
+char *ParseColourString(char *bkStr, bool *isPicture)
+{
+  static char resStr[300];
+  strcpy(resStr, bkStr);
+  char *tok1 = strtok(resStr, ";");
+  char *tok2 = strtok(NULL, ";");
+  if (tok1)
+  {
+    if (!tok2)
+    {
+      *isPicture = TRUE;
+      return resStr;
+    }
+    else
+    {
+      *isPicture = FALSE;
+      char *tok3 = strtok(NULL, ";");
+      if (tok3)
+      {
+        // Now convert 3 strings into decimal numbers, and then hex numbers.
+        int red = atoi(tok1);
+        int green = atoi(tok2);
+        int blue = atoi(tok3);
+        
+        strcpy(resStr, "#");
+        
+        char buf[3];
+        DecToHex(red, buf);
+        strcat(resStr, buf);
+        DecToHex(green, buf);
+        strcat(resStr, buf);
+        DecToHex(blue, buf);
+        strcat(resStr, buf);
+        return resStr;
+      }
+      else return NULL;
+    }
+  }
+  else return NULL;
+}
+
+// Output start of <BODY> block
+void OutputBodyStart(void)
+{
+  TexOutput("\n<BODY");
+  if (backgroundImageString)
+  {
+    bool isPicture = FALSE;
+    char *s = ParseColourString(backgroundImageString, &isPicture);
+    if (s)
+    {
+      TexOutput(" BACKGROUND=\""); TexOutput(s); TexOutput("\"");
+    }
+  }
+  if (backgroundColourString)
+  {
+    bool isPicture = FALSE;
+    char *s = ParseColourString(backgroundColourString, &isPicture);
+    if (s)
+    {
+      TexOutput(" BGCOLOR="); TexOutput(s);
+    }
+  }
+    
+  // Set foreground text colour, if one is specified
+  if (textColourString)
+  {
+    bool isPicture = FALSE;
+    char *s = ParseColourString(textColourString, &isPicture);
+    if (s)
+    {
+      TexOutput(" TEXT="); TexOutput(s);
+    }
+  }
+  // Set link text colour, if one is specified
+  if (linkColourString)
+  {
+    bool isPicture = FALSE;
+    char *s = ParseColourString(linkColourString, &isPicture);
+    if (s)
+    {
+      TexOutput(" LINK="); TexOutput(s);
+    }
+  }
+  // Set followed link text colour, if one is specified
+  if (followedLinkColourString)
+  {
+    bool isPicture = FALSE;
+    char *s = ParseColourString(followedLinkColourString, &isPicture);
+    if (s)
+    {
+      TexOutput(" VLINK="); TexOutput(s);
+    }
+  }
+  TexOutput(">\n");
+}
+
+// Called on start/end of macro examination
+void HTMLOnMacro(int macroId, int no_args, bool start)
+{
+  switch (macroId)
+  {
+  case ltCHAPTER:
+  case ltCHAPTERSTAR:
+  case ltCHAPTERHEADING:
+  {
+    if (!start)
+    {
+      sectionNo = 0;
+      figureNo = 0;
+      subsectionNo = 0;
+      subsubsectionNo = 0;
+      if (macroId != ltCHAPTERSTAR)
+        chapterNo ++;
+
+      SetCurrentOutput(NULL);
+      startedSections = TRUE;
+
+      char *topicName = FindTopicName(GetNextChunk());
+      ReopenFile(&Chapters, &ChaptersName);
+      AddTexRef(topicName, ChaptersName, ChapterNameString);
+
+      SetCurrentChapterName(topicName, ChaptersName);
+
+      SetCurrentOutput(Chapters);
+
+      TexOutput("<head><title>");
+      OutputCurrentSection(); // Repeat section header
+      TexOutput("</title></head>\n");
+      OutputBodyStart();
+
+      char titleBuf[200];
+      if (truncateFilenames)
+        sprintf(titleBuf, "%s.htm", FileNameFromPath(FileRoot));
+      else
+        sprintf(titleBuf, "%s_contents.html", FileNameFromPath(FileRoot));
+
+      fprintf(Chapters, "<A NAME=\"%s\"></A>", topicName);
+      
+      AddBrowseButtons("", titleBuf, // Up
+                       lastTopic, lastFileName,  // Last topic
+                       topicName, ChaptersName); // This topic
+
+      fprintf(Contents, "\n<LI><A HREF=\"%s#%s\">", ConvertCase(ChaptersName), topicName);
+
+      if (htmlFrameContents && FrameContents)
+      {
+        SetCurrentOutput(FrameContents);
+        fprintf(FrameContents, "\n<LI><A HREF=\"%s#%s\" TARGET=\"mainwindow\">", ConvertCase(ChaptersName), topicName);
+        OutputCurrentSection();
+        fprintf(FrameContents, "</A>\n");
+      }
+
+      SetCurrentOutputs(Contents, Chapters);
+      fprintf(Chapters, "\n<H2>");
+      OutputCurrentSection();
+      fprintf(Contents, "</A>\n");
+      fprintf(Chapters, "</H2>\n");
+
+      SetCurrentOutput(Chapters);
+
+      // Add this section title to the list of keywords
+      if (htmlIndex)
+      {
+        OutputCurrentSectionToString(wxBuffer);
+        AddKeyWordForTopic(topicName, wxBuffer, ConvertCase(currentFileName));
+      }
+    }
+    break;
+  }
+  case ltSECTION:
+  case ltSECTIONSTAR:
+  case ltSECTIONHEADING:
+  case ltGLOSS:
+  {
+    if (!start)
+    {
+      subsectionNo = 0;
+      subsubsectionNo = 0;
+      subsectionStarted = FALSE;
+
+      if (macroId != ltSECTIONSTAR)
+        sectionNo ++;
+        
+      SetCurrentOutput(NULL);
+      startedSections = TRUE;
+
+      char *topicName = FindTopicName(GetNextChunk());
+      ReopenFile(&Sections, &SectionsName);
+      AddTexRef(topicName, SectionsName, SectionNameString);
+
+      SetCurrentSectionName(topicName, SectionsName);
+
+      SetCurrentOutput(Sections);
+      TexOutput("<head><title>");
+      OutputCurrentSection();
+      TexOutput("</title></head>\n");
+      OutputBodyStart();
+
+      fprintf(Sections, "<A NAME=\"%s\"></A>", topicName);
+      AddBrowseButtons(CurrentChapterName, CurrentChapterFile, // Up
+                       lastTopic, lastFileName,  // Last topic
+                       topicName, SectionsName); // This topic
+
+      FILE *jumpFrom = ((DocumentStyle == LATEX_ARTICLE) ? Contents : Chapters);
+
+      SetCurrentOutputs(jumpFrom, Sections);
+      if (DocumentStyle == LATEX_ARTICLE)
+        fprintf(jumpFrom, "\n<LI><A HREF=\"%s#%s\">", ConvertCase(SectionsName), topicName);
+      else
+        fprintf(jumpFrom, "\n<A HREF=\"%s#%s\"><B>", ConvertCase(SectionsName), topicName);
+
+      fprintf(Sections, "\n<H2>");
+      OutputCurrentSection();
+
+      if (DocumentStyle == LATEX_ARTICLE)
+        fprintf(jumpFrom, "</A>\n");
+      else
+        fprintf(jumpFrom, "</B></A><BR>\n");
+      fprintf(Sections, "</H2>\n");
+
+      SetCurrentOutput(Sections);
+      // Add this section title to the list of keywords
+      if (htmlIndex)
+      {
+        OutputCurrentSectionToString(wxBuffer);
+        AddKeyWordForTopic(topicName, wxBuffer, currentFileName);
+      }
+    }
+    break;
+  }
+  case ltSUBSECTION:
+  case ltSUBSECTIONSTAR:
+  case ltMEMBERSECTION:
+  case ltFUNCTIONSECTION:
+  {
+    if (!start)
+    {
+      if (!Sections)
+      {
+        OnError("You cannot have a subsection before a section!");
+      }
+      else
+      {
+          subsubsectionNo = 0;
+
+          if (macroId != ltSUBSECTIONSTAR)
+            subsectionNo ++;
+
+          if ( combineSubSections && !subsectionStarted )
+          {
+            // Read old .con file in at this point
+            char buf[256];
+            strcpy(buf, CurrentSectionFile);
+            wxStripExtension(buf);
+            strcat(buf, ".con");
+            FILE *fd = fopen(buf, "r");
+            if ( fd )
+            {
+                int ch = getc(fd);
+                while (ch != EOF)
+                {
+                    putc(ch, Sections);
+                    ch = getc(fd);
+                }
+                fclose(fd);
+            }
+            fprintf(Sections, "<P>\n");
+
+            // Close old file, create a new file for the sub(sub)section contents entries
+            ReopenSectionContentsFile();
+          }
+
+          startedSections = TRUE;
+          subsectionStarted = TRUE;
+
+          char *topicName = FindTopicName(GetNextChunk());
+
+          if ( !combineSubSections )
+          {
+            SetCurrentOutput(NULL);
+            ReopenFile(&Subsections, &SubsectionsName);
+            AddTexRef(topicName, SubsectionsName, SubsectionNameString);
+            SetCurrentSubsectionName(topicName, SubsectionsName);
+            SetCurrentOutput(Subsections);
+
+            TexOutput("<head><title>");
+            OutputCurrentSection();
+            TexOutput("</title></head>\n");
+            OutputBodyStart();
+
+            fprintf(Subsections, "<A NAME=\"%s\"></A>", topicName);
+            AddBrowseButtons(CurrentSectionName, CurrentSectionFile, // Up
+                           lastTopic, lastFileName,  // Last topic
+                           topicName, SubsectionsName); // This topic
+
+            SetCurrentOutputs(Sections, Subsections);
+            fprintf(Sections, "\n<A HREF=\"%s#%s\"><B>", ConvertCase(SubsectionsName), topicName);
+
+            fprintf(Subsections, "\n<H3>");
+            OutputCurrentSection();
+            fprintf(Sections, "</B></A><BR>\n");
+            fprintf(Subsections, "</H3>\n");
+
+            SetCurrentOutput(Subsections);
+          }
+          else
+          {
+            AddTexRef(topicName, SectionsName, SubsectionNameString);
+            SetCurrentSubsectionName(topicName, SectionsName);
+//            if ( subsectionNo != 0 )
+            fprintf(Sections, "\n<HR>\n");
+
+            // We're putting everything into the section file
+            fprintf(Sections, "<A NAME=\"%s\"></A>", topicName);
+            fprintf(Sections, "\n<H3>");
+            OutputCurrentSection();
+            fprintf(Sections, "</H3>\n");
+
+            SetCurrentOutput(SectionContentsFD);
+            fprintf(SectionContentsFD, "<A HREF=\"#%s\">", topicName);
+            OutputCurrentSection();
+            TexOutput("</A><BR>\n");
+
+            SetCurrentOutput(Sections);
+          }
+          // Add this section title to the list of keywords
+          if (htmlIndex)
+          {
+            OutputCurrentSectionToString(wxBuffer);
+            AddKeyWordForTopic(topicName, wxBuffer, currentFileName);
+          }
+
+      }
+    }
+    break;
+  }
+  case ltSUBSUBSECTION:
+  case ltSUBSUBSECTIONSTAR:
+  {
+    if (!start)
+    {
+      if (!Subsections && !combineSubSections)
+      {
+        OnError("You cannot have a subsubsection before a subsection!");
+      }
+      else
+      {
+        if (macroId != ltSUBSUBSECTIONSTAR)
+          subsubsectionNo ++;
+
+        startedSections = TRUE;
+
+        char *topicName = FindTopicName(GetNextChunk());
+
+        if ( !combineSubSections )
+        {
+            SetCurrentOutput(NULL);
+            ReopenFile(&Subsubsections, &SubsubsectionsName);
+            AddTexRef(topicName, SubsubsectionsName, SubsubsectionNameString);
+            SetCurrentSubsubsectionName(topicName, SubsubsectionsName);
+
+            SetCurrentOutput(Subsubsections);
+            TexOutput("<head><title>");
+            OutputCurrentSection();
+            TexOutput("</title></head>\n");
+            OutputBodyStart();
+
+            fprintf(Subsubsections, "<A NAME=\"%s\"></A>", topicName);
+
+            AddBrowseButtons(CurrentSubsectionName, CurrentSubsectionFile, // Up
+                         lastTopic, lastFileName,  // Last topic
+                         topicName, SubsubsectionsName); // This topic
+
+            SetCurrentOutputs(Subsections, Subsubsections);
+            fprintf(Subsections, "\n<A HREF=\"%s#%s\"><B>", ConvertCase(SubsubsectionsName), topicName);
+
+            fprintf(Subsubsections, "\n<H3>");
+            OutputCurrentSection();
+            fprintf(Subsections, "</B></A><BR>\n");
+            fprintf(Subsubsections, "</H3>\n");
+        }
+        else
+        {
+            AddTexRef(topicName, SectionsName, SubsubsectionNameString);
+            SetCurrentSubsectionName(topicName, SectionsName);
+            fprintf(Sections, "\n<HR>\n");
+
+            // We're putting everything into the section file
+            fprintf(Sections, "<A NAME=\"%s\"></A>", topicName);
+            fprintf(Sections, "\n<H3>");
+            OutputCurrentSection();
+            fprintf(Sections, "</H3>\n");
+/* TODO: where do we put subsubsection contents entry - indented, with subsection entries?
+            SetCurrentOutput(SectionContentsFD);
+            fprintf(SectionContentsFD, "<A HREF=\"#%s\">", topicName);
+            OutputCurrentSection();
+            TexOutput("</A><BR>");
+*/
+            SetCurrentOutput(Sections);
+        }
+
+        // Add this section title to the list of keywords
+        if (htmlIndex)
+        {
+          OutputCurrentSectionToString(wxBuffer);
+          AddKeyWordForTopic(topicName, wxBuffer, currentFileName);
+        }
+      }
+    }
+    break;
+  }
+  case ltFUNC:
+  case ltPFUNC:
+  {
+    if ( !combineSubSections )
+        SetCurrentOutput(Subsections);
+    else
+        SetCurrentOutput(Sections);
+    if (start)
+    {
+    }
+    else
+    {
+    }
+    break;
+  }
+  case ltCLIPSFUNC:
+  {
+    if ( !combineSubSections )
+        SetCurrentOutput(Subsections);
+    else
+        SetCurrentOutput(Sections);
+    if (start)
+    {
+    }
+    else
+    {
+    }
+    break;
+  }
+  case ltMEMBER:
+  {
+    if ( !combineSubSections )
+        SetCurrentOutput(Subsections);
+    else
+        SetCurrentOutput(Sections);
+    if (start)
+    {
+    }
+    else
+    {
+    }
+    break;
+  }
+  case ltVOID:
+//    if (start)
+//      TexOutput("<B>void</B>");
+    break;
+  case ltHARDY:
+    if (start)
+      TexOutput("HARDY");
+    break;
+  case ltWXCLIPS:
+    if (start)
+      TexOutput("wxCLIPS");
+    break;
+  case ltAMPERSAND:
+    if (start)
+      TexOutput("&amp;");
+    break;
+  case ltSPECIALAMPERSAND:
+  {
+    if (start)
+    {
+      if (inTabular)
+      {
+        // End cell, start cell
+        TexOutput("</TD>");
+        
+        // Start new row and cell, setting alignment for the first cell.
+        if (currentColumn < noColumns)
+          currentColumn ++;
+
+        char buf[100];
+        if (TableData[currentColumn].justification == 'c')
+          sprintf(buf, "\n<TD ALIGN=CENTER>");
+        else if (TableData[currentColumn].justification == 'r')
+          sprintf(buf, "\n<TD ALIGN=RIGHT>");
+        else if (TableData[currentColumn].absWidth)
+        {
+          // Convert from points * 20 into pixels.
+          int points = TableData[currentColumn].width / 20;
+        
+          // Say the display is 100 DPI (dots/pixels per inch).
+          // There are 72 pts to the inch. So 1pt = 1/72 inch, or 100 * 1/72 dots.
+          int pixels = (int)(points * 100.0 / 72.0);
+          sprintf(buf, "<TD ALIGN=CENTER WIDTH=%d>", pixels);
+        }
+        else
+          sprintf(buf, "\n<TD ALIGN=LEFT>");
+        TexOutput(buf);
+      }
+      else
+        TexOutput("&amp;");
+    }
+    break;
+  }
+  case ltBACKSLASHCHAR:
+  {
+    if (start)
+    {
+      if (inTabular)
+      {
+        // End row. In fact, tables without use of \row or \ruledrow isn't supported for
+        // HTML: the syntax is too different (e.g. how do we know where to put the first </TH>
+        // if we've ended the last row?). So normally you wouldn't use \\ to end a row.
+        TexOutput("</TR>\n");
+      }
+      else
+        TexOutput("<BR>\n");
+    }
+    break;
+  }
+  case ltROW:
+  case ltRULEDROW:
+  {
+    if (start)
+    {
+      currentColumn = 0;
+      
+      // Start new row and cell, setting alignment for the first cell.
+      char buf[100];
+      if (TableData[currentColumn].justification == 'c')
+        sprintf(buf, "<TR>\n<TD ALIGN=CENTER>");
+      else if (TableData[currentColumn].justification == 'r')
+        sprintf(buf, "<TR>\n<TD ALIGN=RIGHT>");
+      else if (TableData[currentColumn].absWidth)
+      {
+        // Convert from points * 20 into pixels.
+        int points = TableData[currentColumn].width / 20;
+        
+        // Say the display is 100 DPI (dots/pixels per inch).
+        // There are 72 pts to the inch. So 1pt = 1/72 inch, or 100 * 1/72 dots.
+        int pixels = (int)(points * 100.0 / 72.0);
+        sprintf(buf, "<TR>\n<TD ALIGN=CENTER WIDTH=%d>", pixels);
+      }
+      else
+        sprintf(buf, "<TR>\n<TD ALIGN=LEFT>");
+      TexOutput(buf);
+    }
+    else
+    {
+      // End cell and row
+      // Start new row and cell
+      TexOutput("</TD>\n</TR>\n");
+    }
+    break;
+  }
+  // HTML-only: break until the end of the picture (both margins are clear).
+  case ltBRCLEAR:
+  {
+    if (start)
+      TexOutput("<BR CLEAR=ALL>");
+    break;
+  }
+  case ltRTFSP:  // Explicit space, RTF only
+    break;
+  case ltSPECIALTILDE:
+  {
+    if (start)
+    {
+      if (inVerbatim)
+        TexOutput("~");
+      else
+        TexOutput(" ");
+    }
+    break;
+  }
+  case ltINDENTED :
+  {
+    if ( start )
+        TexOutput("<UL><UL>\n");
+    else
+        TexOutput("</UL></UL>\n");
+    break;
+  }
+  case ltITEMIZE:
+  case ltENUMERATE:
+  case ltDESCRIPTION:
+//  case ltTWOCOLLIST:
+  {
+    if (start)
+    {
+      indentLevel ++;
+
+      int listType;
+      if (macroId == ltENUMERATE)
+        listType = LATEX_ENUMERATE;
+      else if (macroId == ltITEMIZE)
+        listType = LATEX_ITEMIZE;
+      else
+        listType = LATEX_DESCRIPTION;
+
+      itemizeStack.Insert(new ItemizeStruc(listType));
+      switch (listType)
+      {
+        case LATEX_ITEMIZE:
+          TexOutput("<UL>\n");
+          break;
+        case LATEX_ENUMERATE:
+          TexOutput("<OL>\n");
+          break;
+        case LATEX_DESCRIPTION:
+        default:
+          TexOutput("<DL>\n");
+          break;
+      }
+    }
+    else
+    {
+      indentLevel --;
+      if (itemizeStack.First())
+      {
+        ItemizeStruc *struc = (ItemizeStruc *)itemizeStack.First()->Data();
+        switch (struc->listType)
+        {
+          case LATEX_ITEMIZE:
+            TexOutput("</UL>\n");
+            break;
+          case LATEX_ENUMERATE:
+            TexOutput("</OL>\n");
+            break;
+          case LATEX_DESCRIPTION:
+          default:
+            TexOutput("</DL>\n");
+            break;
+        }
+
+        delete struc;
+        delete itemizeStack.First();
+      }
+    }
+    break;
+  }
+  case ltTWOCOLLIST :
+  {
+    if ( start )
+        TexOutput("\n<TABLE>\n");
+    else
+        TexOutput("\n</TABLE>\n");
+    break;
+  }
+  case ltPAR:
+  {
+    if (start)
+      TexOutput("<P>\n");
+    break;
+  }
+/* For footnotes we need to output the text at the bottom of the page and
+ * insert a reference to it. Is it worth the trouble...
+  case ltFOOTNOTE:
+  case ltFOOTNOTEPOPUP:
+  {
+    if (start)
+    {
+      TexOutput("<FN>);
+    }
+    else TexOutput("</FN>");
+    break;
+  }
+*/
+  case ltVERB:
+  {
+    if (start)
+      TexOutput("<TT>");
+    else TexOutput("</TT>");
+    break;
+  }
+  case ltVERBATIM:
+  {
+    if (start)
+    {
+      char buf[100];
+      sprintf(buf, "<PRE>\n");
+      TexOutput(buf);
+    }
+    else TexOutput("</PRE>\n");
+    break;
+  }
+  case ltCENTERLINE:
+  case ltCENTER:
+  {
+    if (start)
+    {
+      TexOutput("<CENTER>");
+    }
+    else TexOutput("</CENTER>");
+    break;
+  }
+  case ltFLUSHLEFT:
+  {
+/*
+    if (start)
+    {
+      TexOutput("{\\ql ");
+    }
+    else TexOutput("}\\par\\pard\n");
+*/
+    break;
+  }
+  case ltFLUSHRIGHT:
+  {
+/*
+    if (start)
+    {
+      TexOutput("{\\qr ");
+    }
+    else TexOutput("}\\par\\pard\n");
+*/
+    break;
+  }
+  case ltSMALL:
+  {
+    if (start)
+    {
+      // Netscape extension
+      TexOutput("<FONT SIZE=2>");
+    }
+    else TexOutput("</FONT>");
+    break;
+  }
+  case ltTINY:
+  {
+    if (start)
+    {
+      // Netscape extension
+      TexOutput("<FONT SIZE=1>");
+    }
+    else TexOutput("</FONT>");
+    break;
+  }
+  case ltNORMALSIZE:
+  {
+    if (start)
+    {
+      // Netscape extension
+      TexOutput("<FONT SIZE=3>");
+    }
+    else TexOutput("</FONT>");
+    break;
+  }
+  case ltlarge:
+  {
+    if (start)
+    {
+      // Netscape extension
+      TexOutput("<FONT SIZE=4>");
+    }
+    else TexOutput("</FONT>");
+    break;
+  }
+  case ltLarge:
+  {
+    if (start)
+    {
+      // Netscape extension
+      TexOutput("<FONT SIZE=5>");
+    }
+    else TexOutput("</FONT>");
+    break;
+  }
+  case ltLARGE:
+  {
+    if (start)
+    {
+      // Netscape extension
+      TexOutput("<FONT SIZE=6>");
+    }
+    else TexOutput("</FONT>");
+    break;
+  }
+  case ltBFSERIES:
+  case ltTEXTBF:
+  case ltBF:
+  {
+    if (start)
+    {
+      TexOutput("<B>");
+    }
+    else TexOutput("</B>");
+    break;
+  }
+  case ltITSHAPE:
+  case ltTEXTIT:
+  case ltIT:
+  {
+    if (start)
+    {
+      TexOutput("<I>");
+    }
+    else TexOutput("</I>");
+    break;
+  }
+  case ltEMPH:
+  case ltEM:
+  {
+    if (start)
+    {
+      TexOutput("<EM>");
+    }
+    else TexOutput("</EM>");
+    break;
+  }
+  case ltUNDERLINE:
+  {
+    if (start)
+    {
+      TexOutput("<UL>");
+    }
+    else TexOutput("</UL>");
+    break;
+  }
+  case ltTTFAMILY:
+  case ltTEXTTT:
+  case ltTT:
+  {
+    if (start)
+    {
+      TexOutput("<TT>");
+    }
+    else TexOutput("</TT>");
+    break;
+  }
+  case ltCOPYRIGHT:
+  {
+    if (start)
+      TexOutput("&copy;", TRUE);
+    break;
+  }
+  case ltREGISTERED:
+  {
+    if (start)
+      TexOutput("&reg;", TRUE);
+    break;
+  }
+  // Arrows
+  case ltLEFTARROW:
+  {
+    if (start) TexOutput("&lt;--");
+    break;
+  }
+  case ltLEFTARROW2:
+  {
+    if (start) TexOutput("&lt;==");
+    break;
+  }
+  case ltRIGHTARROW:
+  {
+      if (start) TexOutput("--&gt;");
+      break;
+  }
+  case ltRIGHTARROW2:
+  {
+    if (start) TexOutput("==&gt;");
+    break;
+  }
+  case ltLEFTRIGHTARROW:
+  {
+    if (start) TexOutput("&lt;--&gt;");
+    break;
+  }
+  case ltLEFTRIGHTARROW2:
+  {
+    if (start) TexOutput("&lt;==&gt;");
+    break;
+  }
+/*
+  case ltSC:
+  {
+    break;
+  }
+*/
+  case ltITEM:
+  {
+    if (!start)
+    {
+      wxNode *node = itemizeStack.First();
+      if (node)
+      {
+        ItemizeStruc *struc = (ItemizeStruc *)node->Data();
+        struc->currentItem += 1;
+        if (struc->listType == LATEX_DESCRIPTION)
+        {
+          if (descriptionItemArg)
+          {
+            TexOutput("<DT> ");
+            TraverseChildrenFromChunk(descriptionItemArg);
+            TexOutput("\n");
+            descriptionItemArg = NULL;
+          }
+          TexOutput("<DD>");
+        }
+        else
+          TexOutput("<LI>");
+      }
+    }
+    break;
+  }
+  case ltMAKETITLE:
+  {
+    if (start && DocumentTitle && DocumentAuthor)
+    {
+      // Add a special label for the contents page.
+//      TexOutput("<CENTER>\n");
+      TexOutput("<A NAME=\"contents\">");
+      TexOutput("<H2 ALIGN=CENTER>\n");
+      TraverseChildrenFromChunk(DocumentTitle);
+      TexOutput("</H2>");
+      TexOutput("<P>");
+      TexOutput("</A>\n");
+      TexOutput("<P>\n\n");
+      TexOutput("<H3 ALIGN=CENTER>");
+      TraverseChildrenFromChunk(DocumentAuthor);
+      TexOutput("</H3><P>\n\n");
+      if (DocumentDate)
+      {
+        TexOutput("<H3 ALIGN=CENTER>");
+        TraverseChildrenFromChunk(DocumentDate);
+        TexOutput("</H3><P>\n\n");
+      }
+//      TexOutput("\n</CENTER>\n");
+      TexOutput("\n<P><HR><P>\n");
+
+/*
+      // Now do optional frame contents page
+      if (htmlFrameContents && FrameContents)
+      {
+        SetCurrentOutput(FrameContents);
+        
+        // Add a special label for the contents page.
+        TexOutput("<CENTER>\n");
+        TexOutput("<H3>\n");
+        TraverseChildrenFromChunk(DocumentTitle);
+        TexOutput("</H3>");
+        TexOutput("<P>");
+        TexOutput("</A>\n");
+        TexOutput("<P>\n\n");
+        TexOutput("<H3>");
+        TraverseChildrenFromChunk(DocumentAuthor);
+        TexOutput("</H3><P>\n\n");
+        if (DocumentDate)
+        {
+          TexOutput("<H4>");
+          TraverseChildrenFromChunk(DocumentDate);
+          TexOutput("</H4><P>\n\n");
+        }
+        TexOutput("\n</CENTER>\n");
+        TexOutput("<P><HR><P>\n");
+        
+        SetCurrentOutput(Titlepage);
+      }
+*/
+    }
+    break;
+  }
+  case ltHELPREF:
+  case ltHELPREFN:
+  case ltPOPREF:
+  case ltURLREF:
+  {
+    if (start)
+    {
+      helpRefFilename = NULL;
+      helpRefText = NULL;
+    }
+    break;
+  }
+  case ltBIBLIOGRAPHY:
+  {
+    if (start)
+    {
+      DefaultOnMacro(macroId, no_args, start);
+    }
+    else
+    {
+      DefaultOnMacro(macroId, no_args, start);
+      TexOutput("</DL>\n");
+    }
+    break;
+  }
+  case ltHRULE:
+  {
+    if (start)
+    {
+      TexOutput("<HR>\n");
+    }
+    break;
+  }
+  case ltRULE:
+  {
+    if (start)
+    {
+      TexOutput("<HR>\n");
+    }
+    break;
+  }
+  case ltTABLEOFCONTENTS:
+  {
+    if (start)
+    {
+      FILE *fd = fopen(ContentsName, "r");
+      if (fd)
+      {
+        int ch = getc(fd);
+        while (ch != EOF)
+        {
+          putc(ch, Titlepage);
+          ch = getc(fd);
+        }
+        fclose(fd);
+      }
+      else
+      {
+        TexOutput("RUN TEX2RTF AGAIN FOR CONTENTS PAGE\n");
+        OnInform("Run Tex2RTF again to include contents page.");
+      }
+    }
+    break;
+  }
+  case ltLANGLEBRA:
+  {
+    if (start)
+      TexOutput("&lt;");
+    break;
+  }
+  case ltRANGLEBRA:
+  {
+    if (start)
+      TexOutput("&gt;");
+    break;
+  }
+  case ltQUOTE:
+  case ltQUOTATION:
+  {
+    if (start)
+      TexOutput("<BLOCKQUOTE>");
+    else
+      TexOutput("</BLOCKQUOTE>");
+    break;
+  }
+  case ltCAPTION:
+  case ltCAPTIONSTAR:
+  {
+    if (start)
+    {
+      if (inTabular)
+        TexOutput("\n<CAPTION>");
+
+      char figBuf[40];
+
+      if ( inFigure )
+      {
+          figureNo ++;
+
+          if (DocumentStyle != LATEX_ARTICLE)
+            sprintf(figBuf, "%s %d.%d: ", FigureNameString, chapterNo, figureNo);
+          else
+            sprintf(figBuf, "%s %d: ", FigureNameString, figureNo);
+      }
+      else
+      {
+          tableNo ++;
+
+          if (DocumentStyle != LATEX_ARTICLE)
+            sprintf(figBuf, "%s %d.%d: ", TableNameString, chapterNo, tableNo);
+          else
+            sprintf(figBuf, "%s %d: ", TableNameString, tableNo);
+      }
+
+      TexOutput(figBuf);
+    }
+    else
+    {
+      if (inTabular)
+        TexOutput("\n</CAPTION>\n");
+
+      char *topicName = FindTopicName(GetNextChunk());
+
+      int n = inFigure ? figureNo : tableNo;
+
+      AddTexRef(topicName, NULL, NULL,
+           ((DocumentStyle != LATEX_ARTICLE) ? chapterNo : n),
+            ((DocumentStyle != LATEX_ARTICLE) ? n : 0));
+    }
+    break;
+  }
+  case ltSS:
+  {
+    if (start) TexOutput("&szlig;");
+    break;
+  }
+  case ltFIGURE:
+  {
+    if (start) inFigure = TRUE;
+    else inFigure = FALSE;
+    break;
+  }
+  case ltTABLE:
+  {
+    if (start) inTable = TRUE;
+    else inTable = FALSE;
+    break;
+  }
+  default:
+    DefaultOnMacro(macroId, no_args, start);
+    break;
+  }
+}
+
+// Called on start/end of argument examination
+bool HTMLOnArgument(int macroId, int arg_no, bool start)
+{
+  switch (macroId)
+  {
+  case ltCHAPTER:
+  case ltCHAPTERSTAR:
+  case ltCHAPTERHEADING:
+  case ltSECTION:
+  case ltSECTIONSTAR:
+  case ltSECTIONHEADING:
+  case ltSUBSECTION:
+  case ltSUBSECTIONSTAR:
+  case ltSUBSUBSECTION:
+  case ltSUBSUBSECTIONSTAR:
+  case ltGLOSS:
+  case ltMEMBERSECTION:
+  case ltFUNCTIONSECTION:
+  {
+    if (!start && (arg_no == 1))
+      currentSection = GetArgChunk();
+    return FALSE;
+    break;
+  }
+  case ltFUNC:
+  {
+    if (start && (arg_no == 1))
+      TexOutput("<B>");
+
+    if (!start && (arg_no == 1))
+      TexOutput("</B> ");
+
+    if (start && (arg_no == 2))
+    {
+      if (!suppressNameDecoration) TexOutput("<B>");
+      currentMember = GetArgChunk();
+    }
+    if (!start && (arg_no == 2))
+    {
+      if (!suppressNameDecoration) TexOutput("</B>");
+    }
+    
+    if (start && (arg_no == 3))
+      TexOutput("(");
+    if (!start && (arg_no == 3))
+     TexOutput(")");
+   break;
+  }
+  case ltCLIPSFUNC:
+  {
+    if (start && (arg_no == 1))
+      TexOutput("<B>");
+    if (!start && (arg_no == 1))
+      TexOutput("</B> ");
+
+    if (start && (arg_no == 2))
+    {
+      if (!suppressNameDecoration) TexOutput("( ");
+      currentMember = GetArgChunk();
+    }
+    if (!start && (arg_no == 2))
+    {
+    }
+
+    if (!start && (arg_no == 3))
+     TexOutput(")");
+    break;
+  }
+  case ltPFUNC:
+  {
+    if (!start && (arg_no == 1))
+      TexOutput(" ");
+
+    if (start && (arg_no == 2))
+      TexOutput("(*");
+    if (!start && (arg_no == 2))
+      TexOutput(")");
+
+    if (start && (arg_no == 2))
+      currentMember = GetArgChunk();
+
+    if (start && (arg_no == 3))
+      TexOutput("(");
+    if (!start && (arg_no == 3))
+      TexOutput(")");
+    break;
+  }
+  case ltPARAM:
+  {
+    if (start && (arg_no == 1))
+      TexOutput("<B>");
+    if (!start && (arg_no == 1))
+      TexOutput("</B>");
+    if (start && (arg_no == 2))
+    {
+      TexOutput("<I>");
+    }
+    if (!start && (arg_no == 2))
+    {
+      TexOutput("</I>");
+    }
+    break;
+  }
+  case ltCPARAM:
+  {
+    if (start && (arg_no == 1))
+      TexOutput("<B>");
+    if (!start && (arg_no == 1))
+      TexOutput("</B> ");  // This is the difference from param - one space!
+    if (start && (arg_no == 2))
+    {
+      TexOutput("<I>");
+    }
+    if (!start && (arg_no == 2))
+    {
+      TexOutput("</I>");
+    }
+    break;
+  }
+  case ltMEMBER:
+  {
+    if (!start && (arg_no == 1))
+      TexOutput(" ");
+
+    if (start && (arg_no == 2))
+      currentMember = GetArgChunk();
+    break;
+  }
+  case ltREF:
+  {
+    if (start)
+    {
+      char *sec = NULL;
+      
+      char *refName = GetArgData();
+      if (refName)
+      {
+        TexRef *texRef = FindReference(refName);
+        if (texRef)
+        {
+          sec = texRef->sectionNumber;
+        }
+      }
+      if (sec)
+      {
+        TexOutput(sec);
+      }
+      return FALSE;
+    }
+    break;
+  }
+  case ltURLREF:
+  {
+    if (IsArgOptional())
+      return FALSE;
+    else if ((GetNoArgs() - arg_no) == 1)
+    {
+      if (start)
+        helpRefText = GetArgChunk();
+      return FALSE;
+    }
+    else if ((GetNoArgs() - arg_no) == 0) // Arg = 2, or 3 if first is optional
+    {
+      if (start)
+      {
+        TexChunk *ref = GetArgChunk();
+        TexOutput("<A HREF=\"");
+        inVerbatim = TRUE;
+        TraverseChildrenFromChunk(ref);
+        inVerbatim = FALSE;
+        TexOutput("\">");
+        if (helpRefText)
+          TraverseChildrenFromChunk(helpRefText);
+        TexOutput("</A>");
+      }
+      return FALSE;
+    }
+    break;
+  }
+  case ltHELPREF:
+  case ltHELPREFN:
+  case ltPOPREF:
+  {
+    if (IsArgOptional())
+    {
+      if (start)
+        helpRefFilename = GetArgChunk();
+      return FALSE;
+    }
+    if ((GetNoArgs() - arg_no) == 1)
+    {
+      if (start)
+        helpRefText = GetArgChunk();
+      return FALSE;
+    }
+    else if ((GetNoArgs() - arg_no) == 0) // Arg = 2, or 3 if first is optional
+    {
+      if (start)
+      {
+        char *refName = GetArgData();
+        char *refFilename = NULL;
+
+        if (refName)
+        {
+          TexRef *texRef = FindReference(refName);
+          if (texRef)
+          {
+            if (texRef->refFile && strcmp(texRef->refFile, "??") != 0)
+              refFilename = texRef->refFile;
+
+            TexOutput("<A HREF=\"");
+            // If a filename is supplied, use it, otherwise try to
+            // use the filename associated with the reference (from this document).
+            if (helpRefFilename)
+               {
+              TraverseChildrenFromChunk(helpRefFilename);
+              TexOutput("#");
+               }
+            else if (refFilename)
+               {
+              TexOutput(ConvertCase(refFilename));
+              TexOutput("#");
+               }
+            TexOutput(refName);
+            TexOutput("\">");
+            if (helpRefText)
+              TraverseChildrenFromChunk(helpRefText);
+            TexOutput("</A>");
+          }
+          else
+          {
+            if (helpRefText)
+              TraverseChildrenFromChunk(helpRefText);
+            TexOutput(" (REF NOT FOUND)");
+          }
+        }
+        else TexOutput("??");
+      }
+      return FALSE;
+    }
+    break;
+  }
+  case ltIMAGE:
+  case ltIMAGEL:
+  case ltIMAGER:
+  case ltPSBOXTO:
+  {
+    if (arg_no == 2)
+    {
+      if (start)
+      {
+        char *alignment = "";
+        if (macroId == ltIMAGEL)
+          alignment = " align=left";
+        else if  (macroId == ltIMAGER)
+          alignment = " align=right";
+        
+        // Try to find an XBM or GIF image first.
+        char *filename = copystring(GetArgData());
+        char buf[500];
+        
+        strcpy(buf, filename);
+        StripExtension(buf);
+        strcat(buf, ".xbm");
+        wxString f = TexPathList.FindValidPath(buf);
+
+        if (f == "") // Try for a GIF instead
+        {
+          strcpy(buf, filename);
+          StripExtension(buf);
+          strcat(buf, ".gif");
+          f = TexPathList.FindValidPath(buf);
+        }
+        if (f != "")
+        {
+          char *inlineFilename = copystring(f);
+#if 0
+          char *originalFilename = TexPathList.FindValidPath(filename);
+          // If we have found the existing filename, make the inline
+          // image point to the original file (could be PS, for example)
+          if (originalFilename && (strcmp(inlineFilename, originalFilename) != 0))
+         {
+            TexOutput("<A HREF=\"");
+            TexOutput(ConvertCase(originalFilename));
+            TexOutput("\">");
+            TexOutput("<img src=\"");
+            TexOutput(ConvertCase(wxFileNameFromPath(inlineFilename)));
+            TexOutput("\""); TexOutput(alignment); TexOutput("></A>");
+         }
+          else
+#endif
+         {
+            TexOutput("<img src=\"");
+            TexOutput(ConvertCase(wxFileNameFromPath(inlineFilename)));
+            TexOutput("\""); TexOutput(alignment); TexOutput("></A>");
+            delete[] inlineFilename;
+         }
+        }
+        else
+        {
+          // Last resort - a link to a PS file.
+          TexOutput("<A HREF=\"");
+          TexOutput(ConvertCase(wxFileNameFromPath(filename)));
+          TexOutput("\">Picture</A>\n");
+          sprintf(buf, "Warning: could not find an inline XBM/GIF for %s.", filename);
+          OnInform(buf);
+        }
+      }
+    }
+    return FALSE;
+    break;
+  }
+  // First arg is PSBOX spec (ignored), second is image file, third is map name.
+  case ltIMAGEMAP:
+  {
+    static char *imageFile = NULL;
+    if (start && (arg_no == 2))
+    {
+      // Try to find an XBM or GIF image first.
+      char *filename = copystring(GetArgData());
+      char buf[500];
+        
+      strcpy(buf, filename);
+      StripExtension(buf);
+      strcat(buf, ".xbm");
+      wxString f = TexPathList.FindValidPath(buf);
+
+      if (f == "") // Try for a GIF instead
+      {
+        strcpy(buf, filename);
+        StripExtension(buf);
+        strcat(buf, ".gif");
+        f = TexPathList.FindValidPath(buf);
+      }
+      if (f == "")
+      {
+        char buf[300];
+        sprintf(buf, "Warning: could not find an inline XBM/GIF for %s.", filename);
+        OnInform(buf);
+      }
+      delete[] filename;
+      if (imageFile)
+        delete[] imageFile;
+      imageFile = NULL;
+      if (f)
+      {
+        imageFile = copystring(f);
+      }
+    }
+    else if (start && (arg_no == 3))
+    {
+      if (imageFile)
+      {
+        // First, try to find a .shg (segmented hypergraphics file)
+        // that we can convert to a map file
+        char buf[256];
+        strcpy(buf, imageFile);
+        StripExtension(buf);
+        strcat(buf, ".shg");
+        wxString f = TexPathList.FindValidPath(buf);
+
+        if (f != "")
+        {
+          // The default HTML file to go to is THIS file (so a no-op)
+          SHGToMap((char*) (const char*) f, currentFileName);
+        }
+
+        char *mapName = GetArgData();
+        TexOutput("<A HREF=\"/cgi-bin/imagemap/");
+        if (mapName)
+          TexOutput(mapName);
+        else
+          TexOutput("unknown");
+        TexOutput("\">");
+        TexOutput("<img src=\"");
+        TexOutput(ConvertCase(wxFileNameFromPath(imageFile)));
+        TexOutput("\" ISMAP></A><P>");
+        delete[] imageFile;
+        imageFile = NULL;
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltINDENTED :
+  {
+    if ( arg_no == 1 )
+        return FALSE;
+    else
+    {
+        return TRUE;
+    }
+  }
+  case ltITEM:
+  {
+    if (start)
+    {
+      descriptionItemArg = GetArgChunk();
+      return FALSE;
+    }
+  }
+  case ltTWOCOLITEM:
+  case ltTWOCOLITEMRULED:
+  {
+/*
+    if (start && (arg_no == 1))
+      TexOutput("\n<DT> ");
+    if (start && (arg_no == 2))
+      TexOutput("<DD> ");
+*/
+    if (arg_no == 1)
+    {
+        if ( start )
+            TexOutput("\n<TR><TD VALIGN=TOP>\n");
+        else
+            TexOutput("\n</TD>\n");
+    }
+    if (arg_no == 2)
+    {
+        if ( start )
+            TexOutput("\n<TD VALIGN=TOP>\n");
+        else
+            TexOutput("\n</TD></TR>\n");
+    }
+    return TRUE;
+    break;
+  }
+  case ltNUMBEREDBIBITEM:
+  {
+    if (arg_no == 1 && start)
+    {
+      TexOutput("\n<DT> ");
+    }
+    if (arg_no == 2 && !start)
+      TexOutput("<P>\n");
+    break;
+  }
+  case ltBIBITEM:
+  {
+    char buf[100];
+    if (arg_no == 1 && start)
+    {
+      char *citeKey = GetArgData();
+      TexRef *ref = (TexRef *)TexReferences.Get(citeKey);
+      if (ref)
+      {
+        if (ref->sectionNumber) delete[] ref->sectionNumber;
+        sprintf(buf, "[%d]", citeCount);
+        ref->sectionNumber = copystring(buf);
+      }
+
+      sprintf(buf, "\n<DT> [%d] ", citeCount);
+      TexOutput(buf);
+      citeCount ++;
+      return FALSE;
+    }
+    if (arg_no == 2 && !start)
+      TexOutput("<P>\n");
+    return TRUE;
+    break;
+  }
+  case ltMARGINPAR:
+  case ltMARGINPARODD:
+  case ltMARGINPAREVEN:
+  case ltNORMALBOX:
+  case ltNORMALBOXD:
+  {
+    if (start)
+    {
+      TexOutput("<HR>\n");
+      return TRUE;
+    }
+    else
+      TexOutput("<HR><P>\n");
+    break;
+  }
+  /*
+   * Accents
+   *
+   */
+  case ltACCENT_GRAVE:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        switch (val[0])
+        {
+          case 'a':
+           TexOutput("&agrave;");
+           break;
+          case 'e':
+           TexOutput("&egrave;");
+           break;
+          case 'i':
+           TexOutput("&igrave;");
+           break;
+          case 'o':
+           TexOutput("&ograve;");
+           break;
+          case 'u':
+           TexOutput("&ugrave;");
+           break;
+          case 'A':
+           TexOutput("&Agrave;");
+           break;
+          case 'E':
+           TexOutput("&Egrave;");
+           break;
+          case 'I':
+           TexOutput("&Igrave;");
+           break;
+          case 'O':
+           TexOutput("&Ograve;");
+           break;
+          case 'U':
+           TexOutput("&Igrave;");
+           break;
+          default:
+           break;
+        }
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltACCENT_ACUTE:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        switch (val[0])
+        {
+          case 'a':
+           TexOutput("&aacute;");
+           break;
+          case 'e':
+           TexOutput("&eacute;");
+           break;
+          case 'i':
+           TexOutput("&iacute;");
+           break;
+          case 'o':
+           TexOutput("&oacute;");
+           break;
+          case 'u':
+           TexOutput("&uacute;");
+           break;
+          case 'y':
+           TexOutput("&yacute;");
+           break;
+          case 'A':
+           TexOutput("&Aacute;");
+           break;
+          case 'E':
+           TexOutput("&Eacute;");
+           break;
+          case 'I':
+           TexOutput("&Iacute;");
+           break;
+          case 'O':
+           TexOutput("&Oacute;");
+           break;
+          case 'U':
+           TexOutput("&Uacute;");
+           break;
+          case 'Y':
+           TexOutput("&Yacute;");
+           break;
+          default:
+           break;
+        }
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltACCENT_CARET:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        switch (val[0])
+        {
+          case 'a':
+           TexOutput("&acirc;");
+           break;
+          case 'e':
+           TexOutput("&ecirc;");
+           break;
+          case 'i':
+           TexOutput("&icirc;");
+           break;
+          case 'o':
+           TexOutput("&ocirc;");
+           break;
+          case 'u':
+           TexOutput("&ucirc;");
+           break;
+          case 'A':
+           TexOutput("&Acirc;");
+           break;
+          case 'E':
+           TexOutput("&Ecirc;");
+           break;
+          case 'I':
+           TexOutput("&Icirc;");
+           break;
+          case 'O':
+           TexOutput("&Ocirc;");
+           break;
+          case 'U':
+           TexOutput("&Icirc;");
+           break;
+          default:
+           break;
+        }
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltACCENT_TILDE:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        switch (val[0])
+        {
+          case ' ':
+           TexOutput("~");
+           break;
+          case 'a':
+           TexOutput("&atilde;");
+           break;
+          case 'n':
+           TexOutput("&ntilde;");
+           break;
+          case 'o':
+           TexOutput("&otilde;");
+           break;
+          case 'A':
+           TexOutput("&Atilde;");
+           break;
+          case 'N':
+           TexOutput("&Ntilde;");
+           break;
+          case 'O':
+           TexOutput("&Otilde;");
+           break;
+          default:
+           break;
+        }
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltACCENT_UMLAUT:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        switch (val[0])
+        {
+          case 'a':
+           TexOutput("&auml;");
+           break;
+          case 'e':
+           TexOutput("&euml;");
+           break;
+          case 'i':
+           TexOutput("&iuml;");
+           break;
+          case 'o':
+           TexOutput("&ouml;");
+           break;
+          case 'u':
+           TexOutput("&uuml;");
+           break;
+          case 'y':
+           TexOutput("&yuml;");
+           break;
+          case 'A':
+           TexOutput("&Auml;");
+           break;
+          case 'E':
+           TexOutput("&Euml;");
+           break;
+          case 'I':
+           TexOutput("&Iuml;");
+           break;
+          case 'O':
+           TexOutput("&Ouml;");
+           break;
+          case 'U':
+           TexOutput("&Uuml;");
+           break;
+          case 'Y':
+           TexOutput("&Yuml;");
+           break;
+          default:
+           break;
+        }
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltACCENT_DOT:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        switch (val[0])
+        {
+          case 'a':
+           TexOutput("&aring;");
+           break;
+          case 'A':
+           TexOutput("&Aring;");
+           break;
+          default:
+           break;
+        }
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltBACKGROUND:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        bool isPicture = FALSE;
+        char *s = ParseColourString(val, &isPicture);
+        if (isPicture)
+        {
+          if (backgroundImageString)
+            delete[] backgroundImageString;
+          backgroundImageString = copystring(val);
+        }
+        else
+        {
+          if (backgroundColourString)
+            delete[] backgroundColourString;
+          backgroundColourString = copystring(val);
+        }
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltBACKGROUNDIMAGE:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        if (backgroundImageString)
+          delete[] backgroundImageString;
+        backgroundImageString = copystring(val);
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltBACKGROUNDCOLOUR:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        if (backgroundColourString)
+          delete[] backgroundColourString;
+        backgroundColourString = copystring(val);
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltTEXTCOLOUR:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        if (textColourString)
+          delete[] textColourString;
+        textColourString = copystring(val);
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltLINKCOLOUR:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        if (linkColourString)
+          delete[] linkColourString;
+        linkColourString = copystring(val);
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltFOLLOWEDLINKCOLOUR:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        if (followedLinkColourString)
+          delete[] followedLinkColourString;
+        followedLinkColourString = copystring(val);
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltACCENT_CADILLA:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        switch (val[0])
+        {
+          case 'c':
+           TexOutput("&ccedil;");
+           break;
+          case 'C':
+           TexOutput("&Ccedil;");
+           break;
+          default:
+           break;
+        }
+      }
+    }
+    return FALSE;
+    break;
+  }
+/*
+  case ltFOOTNOTE:
+  case ltFOOTNOTEPOPUP:
+  {
+    if (arg_no == 1)
+      return TRUE;
+    else
+      return FALSE;
+    break;
+  }
+*/  
+  case ltTABULAR:
+  case ltSUPERTABULAR:
+  {
+    if (arg_no == 1)
+    {
+      if (start)
+      {
+        currentRowNumber = 0;
+        inTabular = TRUE;
+        startRows = TRUE;
+        tableVerticalLineLeft = FALSE;
+        tableVerticalLineRight = FALSE;
+        int currentWidth = 0;
+
+        char *alignString = copystring(GetArgData());
+        ParseTableArgument(alignString);
+
+        TexOutput("<TABLE BORDER>\n");
+
+        // Write the first row formatting for compatibility
+        // with standard Latex
+        if (compatibilityMode)
+        {
+          TexOutput("<TR>\n<TD>");
+/*
+          for (int i = 0; i < noColumns; i++)
+          {
+            currentWidth += TableData[i].width;
+            sprintf(buf, "\\cellx%d", currentWidth);
+            TexOutput(buf);
+          }
+          TexOutput("\\pard\\intbl\n");
+*/
+        }
+        delete[] alignString;
+
+        return FALSE;
+      }
+    }
+    else if (arg_no == 2 && !start)
+    {
+      TexOutput("</TABLE>\n");
+      inTabular = FALSE;
+    }
+    break;
+  }
+  case ltTHEBIBLIOGRAPHY:
+  {
+    if (start && (arg_no == 1))
+    {
+      ReopenFile(&Chapters, &ChaptersName);
+      AddTexRef("bibliography", ChaptersName, "bibliography");
+      SetCurrentSubsectionName("bibliography", ChaptersName);
+
+      citeCount = 1;
+
+      SetCurrentOutput(Chapters);
+
+      char titleBuf[150];
+      if (truncateFilenames)
+        sprintf(titleBuf, "%s.htm", FileNameFromPath(FileRoot));
+      else
+        sprintf(titleBuf, "%s_contents.html", FileNameFromPath(FileRoot));
+
+      TexOutput("<head><title>");
+      TexOutput(ReferencesNameString);
+      TexOutput("</title></head>\n");
+      OutputBodyStart();
+
+      fprintf(Chapters, "<A NAME=\"%s\">\n<H2>%s", "bibliography", ReferencesNameString);
+      AddBrowseButtons("contents", titleBuf, // Up
+                       lastTopic, lastFileName,  // Last topic
+                       "bibliography", ChaptersName); // This topic
+
+      SetCurrentOutputs(Contents, Chapters);
+      fprintf(Contents, "\n<LI><A HREF=\"%s#%s\">", ConvertCase(ChaptersName), "bibliography");
+
+      fprintf(Contents, "%s</A>\n", ReferencesNameString);
+      fprintf(Chapters, "</H2>\n</A>\n");
+
+      SetCurrentOutput(Chapters);
+      return FALSE;
+    }
+    if (!start && (arg_no == 2))
+    {
+    }
+    return TRUE;
+    break;
+  }
+  case ltINDEX:
+  {
+    /* Build up list of keywords associated with topics */
+    if (start)
+    {
+//      char *entry = GetArgData();
+      char buf[300];
+      OutputChunkToString(GetArgChunk(), buf);
+      if (CurrentTopic)
+      {
+        AddKeyWordForTopic(CurrentTopic, buf, currentFileName);
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltFCOL:
+//  case ltBCOL:
+  {
+    if (start)
+    {
+      switch (arg_no)
+      {
+        case 1:
+        {
+          char *name = GetArgData();
+          char buf2[10];
+          if (!FindColourHTMLString(name, buf2))
+          {
+            strcpy(buf2, "#000000");
+            char buf[100];
+                       sprintf(buf, "Could not find colour name %s", name);
+            OnError(buf);
+          }
+          TexOutput("<FONT COLOR=\"");
+          TexOutput(buf2);
+          TexOutput("\">");
+          break;
+        }
+        case 2:
+        {
+          return TRUE;
+          break;
+        }
+        default:
+          break;
+      }
+    }
+    else
+    {
+      if (arg_no == 2) TexOutput("</FONT>");
+    }
+    return FALSE;
+    break;
+  }
+  case ltINSERTATLEVEL:
+  {
+    // This macro allows you to insert text at a different level
+    // from the current level, e.g. into the Sections from within a subsubsection.
+    if (useWord)
+        return FALSE;
+    static int currentLevelNo = 1;
+    static FILE* oldLevelFile = Chapters;
+    if (start)
+    {
+      switch (arg_no)
+      {
+        case 1:
+        {
+          oldLevelFile = CurrentOutput1;
+
+          char *str = GetArgData();
+          currentLevelNo = atoi(str);
+          FILE* outputFile;
+          // TODO: cope with article style (no chapters)
+          switch (currentLevelNo)
+          {
+            case 1:
+            {
+                outputFile = Chapters;
+                break;
+            }
+            case 2:
+            {
+                outputFile = Sections;
+                break;
+            }
+            case 3:
+            {
+                outputFile = Subsections;
+                break;
+            }
+            case 4:
+            {
+                outputFile = Subsubsections;
+                break;
+            }
+            default:
+            {
+                outputFile = NULL;
+                break;
+            }
+          }
+          if (outputFile)
+            CurrentOutput1 = outputFile;
+          return FALSE;
+          break;
+        }
+        case 2:
+        {
+          return TRUE;
+          break;
+        }
+        default:
+          break;
+      }
+      return TRUE;
+    }
+    else
+    {
+        if (arg_no == 2)
+        {
+            CurrentOutput1 = oldLevelFile;
+        }
+        return TRUE;
+    }
+  }
+  default:
+    return DefaultOnArgument(macroId, arg_no, start);
+    break;
+  }
+  return TRUE;
+}
+
+bool HTMLGo(void)
+{
+  fileId = 0;
+  inVerbatim = FALSE;
+  indentLevel = 0;
+  inTabular = FALSE;
+  startRows = FALSE;
+  tableVerticalLineLeft = FALSE;
+  tableVerticalLineRight = FALSE;
+  noColumns = 0;
+
+  if (InputFile && OutputFile)
+  {
+    // Do some HTML-specific transformations on all the strings,
+    // recursively
+    Text2HTML(GetTopLevelChunk());
+
+    char buf[300];
+    if (truncateFilenames)
+      sprintf(buf, "%s.htm", FileRoot);
+    else
+      sprintf(buf, "%s_contents.html", FileRoot);
+    if (TitlepageName) delete[] TitlepageName;
+    TitlepageName = copystring(buf);
+    Titlepage = fopen(buf, "w");
+    
+    if (truncateFilenames)
+      sprintf(buf, "%s_fc.htm", FileRoot);
+    else
+      sprintf(buf, "%s_fcontents.html", FileRoot);
+
+    contentsFrameName = copystring(buf);
+
+    Contents = fopen(TmpContentsName, "w");
+
+    if (htmlFrameContents)
+    {
+//      FrameContents = fopen(TmpFrameContentsName, "w");
+      FrameContents = fopen(contentsFrameName, "w");
+      fprintf(FrameContents, "<HTML>\n<UL>\n");
+    }
+
+    if (!Titlepage || !Contents)
+    {
+      OnError("Cannot open output file!");
+      return FALSE;
+    }
+    AddTexRef("contents", FileNameFromPath(TitlepageName), ContentsNameString);
+
+    fprintf(Contents, "<P><P><H2>%s</H2><P><P>\n", ContentsNameString);
+
+    fprintf(Contents, "<UL>\n");
+
+    SetCurrentOutput(Titlepage);
+    OnInform("Converting...");
+
+    TraverseDocument();
+    fprintf(Contents, "</UL>\n\n");
+
+//    SetCurrentOutput(Titlepage);
+    fclose(Titlepage);
+
+    if (Contents)
+    {
+//      fprintf(Titlepage, "\n</BODY></HTML>\n");
+      fclose(Contents);
+      Contents = NULL;
+    }
+
+    if (FrameContents)
+    {
+      fprintf(FrameContents, "\n</UL>\n");
+      fprintf(FrameContents, "</HTML>\n");
+      fclose(FrameContents);
+      FrameContents = NULL;
+    }
+
+    if (Chapters)
+    {
+      fprintf(Chapters, "\n</BODY></HTML>\n");
+      fclose(Chapters);
+      Chapters = NULL;
+    }
+    if (Sections)
+    {
+      fprintf(Sections, "\n</BODY></HTML>\n");
+      fclose(Sections);
+      Sections = NULL;
+    }
+    if (Subsections && !combineSubSections)
+    {
+      fprintf(Subsections, "\n</BODY></HTML>\n");
+      fclose(Subsections);
+      Subsections = NULL;
+    }
+    if (Subsubsections && !combineSubSections)
+    {
+      fprintf(Subsubsections, "\n</BODY></HTML>\n");
+      fclose(Subsubsections);
+      Subsubsections = NULL;
+    }
+    if ( SectionContentsFD )
+    {
+        fclose(SectionContentsFD);
+        SectionContentsFD = NULL;
+    }
+
+    // Create a temporary file for the title page header, add some info,
+    // and concat the titlepage just generated.
+    // This is necessary in order to put the title of the document
+    // at the TOP of the file within <HEAD>, even though we only find out
+    // what it is later on.
+    FILE *tmpTitle = fopen("title.tmp", "w");
+    if (tmpTitle)
+    {
+      if (DocumentTitle)
+      {
+        SetCurrentOutput(tmpTitle);
+        TexOutput("\n<HTML>\n<HEAD><TITLE>");
+        TraverseChildrenFromChunk(DocumentTitle);
+        TexOutput("</TITLE></HEAD>\n");
+      }
+      else
+      {
+        SetCurrentOutput(tmpTitle);
+        if (contentsString)
+          fprintf(tmpTitle, "<HEAD><TITLE>%s</TITLE></HEAD>\n\n", contentsString);
+        else
+          fprintf(tmpTitle, "<HEAD><TITLE>%s</TITLE></HEAD>\n\n", FileNameFromPath(FileRoot));
+      }
+      
+      // Output frame information
+      if (htmlFrameContents)
+      {
+        char firstFileName[300];
+        if (truncateFilenames)
+          sprintf(firstFileName, "%s1.htm", FileRoot);
+        else
+          sprintf(firstFileName, "%s1.html", FileRoot);
+
+        fprintf(tmpTitle, "<FRAMESET COLS=\"30%%,70%%\">\n");
+
+        fprintf(tmpTitle, "<FRAME SRC=\"%s\">\n", ConvertCase(FileNameFromPath(contentsFrameName)));
+        fprintf(tmpTitle, "<FRAME SRC=\"%s\" NAME=\"mainwindow\">\n", ConvertCase(FileNameFromPath(firstFileName)));
+        fprintf(tmpTitle, "</FRAMESET>\n");
+        
+        fprintf(tmpTitle, "<NOFRAMES>\n");
+      }
+
+      // Output <BODY...> to temporary title page
+      OutputBodyStart();
+      
+      // Concat titlepage
+      FILE *fd = fopen(TitlepageName, "r");
+      if (fd)
+      {
+        int ch = getc(fd);
+        while (ch != EOF)
+        {
+          putc(ch, tmpTitle);
+          ch = getc(fd);
+        }
+        fclose(fd);
+      }
+
+      fprintf(tmpTitle, "\n</BODY>\n");
+
+      if (htmlFrameContents)
+      {
+        fprintf(tmpTitle, "\n</NOFRAMES>\n");
+      }
+      fprintf(tmpTitle, "\n</HTML>\n");
+
+      fclose(tmpTitle);
+      if (FileExists(TitlepageName)) wxRemoveFile(TitlepageName);
+      if (!wxRenameFile("title.tmp", TitlepageName))
+      {
+        wxCopyFile("title.tmp", TitlepageName);
+        wxRemoveFile("title.tmp");
+      }
+    }
+
+    if (lastFileName) delete[] lastFileName;
+    lastFileName = NULL;
+    if (lastTopic) delete[] lastTopic;
+    lastTopic = NULL;
+
+    if (FileExists(ContentsName)) wxRemoveFile(ContentsName);
+
+    if (!wxRenameFile(TmpContentsName, ContentsName))
+    {
+      wxCopyFile(TmpContentsName, ContentsName);
+      wxRemoveFile(TmpContentsName);
+    }
+
+    // Generate .htx file if requested
+    if (htmlIndex)
+    {
+      char htmlIndexName[300];
+      sprintf(htmlIndexName, "%s.htx", FileRoot);
+      GenerateHTMLIndexFile(htmlIndexName);
+    }
+
+    return TRUE;
+  }
+  return FALSE;
+}
+
+// Output .htx index file
+void GenerateHTMLIndexFile(char *fname)
+{
+  FILE *fd = fopen(fname, "w");
+  if (!fd)
+    return;
+
+  TopicTable.BeginFind();
+  wxNode *node = NULL;
+  while ((node = TopicTable.Next()))
+  {
+    TexTopic *texTopic = (TexTopic *)node->Data();
+    const char *topicName = node->GetKeyString();
+    if (texTopic->filename && texTopic->keywords)
+    {
+      wxNode *node1 = texTopic->keywords->First();
+      while (node1)
+      {
+        char *s = (char *)node1->Data();
+        fprintf(fd, "%s|%s|%s\n", topicName, texTopic->filename, s);
+        node1 = node1->Next();
+      }
+    }
+  }
+  fclose(fd);
+}
diff --git a/utils/tex2rtf/src/makefile.b32 b/utils/tex2rtf/src/makefile.b32
new file mode 100644 (file)
index 0000000..e22b134
--- /dev/null
@@ -0,0 +1,62 @@
+#
+# File:                makefile.b32
+# Author:      Julian Smart
+# Created:     1993
+# Updated:     
+# Copyright:
+#
+# "%W% %G%"
+#
+# Makefile : Builds tex2rtf
+
+# WXWIN and BCCDIR are set by parent make
+
+WXDIR = $(WXWIN)
+!include $(WXDIR)\src\makeb32.env
+
+WXLIBDIR = $(WXDIR)\lib
+WXINC = $(WXDIR)\include\msw
+WXLIB = $(WXLIBDIR)\wx32.lib
+LIBS=$(WXLIB) cw32 import32 ole2w32
+
+TARGET=tex2rtf
+
+!if "$(FINAL)" == "0"
+LINKFLAGS=/v /Tpe /L$(WXLIBDIR);$(BCCDIR)\lib
+OPT = -Od
+DEBUG_FLAGS= -v
+!else
+LINKFLAGS=/Tpe /L$(WXLIBDIR);$(BCCDIR)\lib
+OPT = -Od
+DEBUG_FLAGS =
+!endif
+CPPFLAGS=$(DEBUG_FLAGS) $(OPT) @$(CFG)
+
+OBJECTS = tex2rtf.obj tex2any.obj texutils.obj rtfutils.obj xlputils.obj htmlutil.obj readshg.obj table.obj
+
+$(TARGET).exe: $(OBJECTS) $(TARGET).res
+  tlink32 $(LINKFLAGS) @&&!
+c0w32.obj $(OBJECTS)
+$(TARGET)
+nul
+$(LIBS)
+$(TARGET).def
+$(TARGET).res
+!
+
+.$(SRCSUFF).obj:
+       bcc32 $(CPPFLAGS) -c {$< }
+
+.c.obj:
+       bcc32 $(CPPFLAGS) -P- -c {$< }
+
+$(TARGET).res :      $(TARGET).rc $(WXDIR)\include\wx\msw\wx.rc
+    brc32 -r /i$(BCCDIR)\include /i$(WXDIR)\include $(TARGET)
+
+clean:
+        -erase *.obj
+        -erase *.exe
+        -erase *.res
+        -erase *.map
+        -erase *.rws
+
diff --git a/utils/tex2rtf/src/makefile.bcc b/utils/tex2rtf/src/makefile.bcc
new file mode 100644 (file)
index 0000000..c2dc7a4
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# File:                makefile.bcc
+# Author:      Julian Smart
+# Created:     1998
+# Updated:     
+#
+# Builds a BC++ 16-bit sample
+
+!if "$(WXWIN)" == ""
+!error You must define the WXWIN variable in autoexec.bat, e.g. WXWIN=c:\wx
+!endif
+
+WXDIR = $(WXWIN)
+
+TARGET=tex2rtf
+OBJECTS = tex2rtf.obj tex2any.obj texutils.obj rtfutils.obj xlputils.obj htmlutil.obj readshg.obj table.obj
+
+!include $(WXDIR)\src\makeprog.bcc
+
diff --git a/utils/tex2rtf/src/makefile.dos b/utils/tex2rtf/src/makefile.dos
new file mode 100644 (file)
index 0000000..3cf9947
--- /dev/null
@@ -0,0 +1,17 @@
+#
+# File:                makefile.dos
+# Author:      Julian Smart
+# Created:     1998
+# Updated:     
+#
+# Makefile : Builds 16-bit sample, VC++ 1.5
+# Use FINAL=1 argument to nmake to build final version with no debugging
+# info
+
+WXDIR = $(WXWIN)
+
+TARGET=tex2rtf
+OBJECTS = tex2rtf.obj tex2any.obj texutils.obj rtfutils.obj xlputils.obj htmlutil.obj readshg.obj table.obj
+
+!include $(WXDIR)\src\makeprog.msc
+
diff --git a/utils/tex2rtf/src/makefile.g95 b/utils/tex2rtf/src/makefile.g95
new file mode 100644 (file)
index 0000000..d5a033d
--- /dev/null
@@ -0,0 +1,61 @@
+#
+# File:                makefile.g95
+# Author:      Julian Smart
+# Created:     1996
+# Updated:     
+#
+# "%W% %G%"
+#
+# Makefile for Tex2RTF (GNU-WIN32)
+
+WXDIR = ../../..
+
+# All common UNIX compiler flags and options are now in
+# this central makefile.
+include $(WXDIR)/src/makeg95.env
+
+OBJECTS = $(OBJDIR)/tex2rtf.$(OBJSUFF) $(OBJDIR)/texutils.$(OBJSUFF) $(OBJDIR)/tex2any.$(OBJSUFF)\
+ $(OBJDIR)/htmlutil.$(OBJSUFF) $(OBJDIR)/rtfutils.$(OBJSUFF) $(OBJDIR)/xlputils.$(OBJSUFF)\
+ $(OBJDIR)/table.$(OBJSUFF) $(OBJDIR)/readshg.$(OBJSUFF)\
+ $(OBJDIR)/tex2rtf_resources.$(OBJSUFF)
+
+all:    $(OBJDIR) tex2rtf$(GUISUFFIX)$(EXESUFF)
+
+INC = $(COMPPATHS) -I$(WXDIR)/include/msw -I$(WXDIR)/include/base -I../../wxhelp/src
+CPPFLAGS = $(XINCLUDE) $(INC) $(OPTIONS) $(GUI) -DDEBUG='$(DEBUG)' $(DEBUGFLAGS) $(WARN) $(OPT)
+
+$(OBJDIR):
+       mkdir $(OBJDIR)
+
+tex2rtf$(GUISUFFIX)$(EXESUFF): $(OBJECTS) $(WXLIB)
+       $(CC) $(LDFLAGS) -o tex2rtf$(GUISUFFIX)$(EXESUFF) $(OBJECTS) $(LDLIBS)
+
+$(OBJDIR)/tex2rtf.$(OBJSUFF):  tex2rtf.$(SRCSUFF) tex2rtf.h tex2any.h
+       $(CC) -c $(CPPFLAGS) -o $@ tex2rtf.$(SRCSUFF)
+
+$(OBJDIR)/texutils.$(OBJSUFF): texutils.$(SRCSUFF) tex2rtf.h tex2any.h
+       $(CC) -c $(CPPFLAGS) -o $@ texutils.$(SRCSUFF)
+
+$(OBJDIR)/tex2any.$(OBJSUFF):  tex2any.$(SRCSUFF) tex2any.h
+       $(CC) -c $(CPPFLAGS) -o $@ tex2any.$(SRCSUFF)
+
+$(OBJDIR)/htmlutil.$(OBJSUFF): htmlutil.$(SRCSUFF) tex2any.h
+       $(CC) -c $(CPPFLAGS) -o $@ htmlutil.$(SRCSUFF)
+
+$(OBJDIR)/rtfutils.$(OBJSUFF): rtfutils.$(SRCSUFF) tex2any.h
+       $(CC) -c $(CPPFLAGS) -o $@ rtfutils.$(SRCSUFF)
+
+$(OBJDIR)/xlputils.$(OBJSUFF): xlputils.$(SRCSUFF) tex2any.h
+       $(CC) -c $(CPPFLAGS) -o $@ xlputils.$(SRCSUFF)
+
+$(OBJDIR)/table.$(OBJSUFF):    table.$(SRCSUFF) tex2any.h
+       $(CC) -c $(CPPFLAGS) -o $@ table.$(SRCSUFF)
+
+$(OBJDIR)/readshg.$(OBJSUFF):  readshg.$(SRCSUFF) readshg.h
+       $(CC) -c $(CPPFLAGS) -o $@ readshg.$(SRCSUFF)
+
+$(OBJDIR)/tex2rtf_resources.o:  tex2rtf.rc
+       $(RESCOMP) -i tex2rtf.rc -o $(OBJDIR)/tex2rtf_resources.o $(RESFLAGS)
+
+clean:
+       rm -f $(OBJECTS) tex2rtf$(GUISUFFIX).exe core *.rsc *.res
diff --git a/utils/tex2rtf/src/makefile.nt b/utils/tex2rtf/src/makefile.nt
new file mode 100644 (file)
index 0000000..03e71be
--- /dev/null
@@ -0,0 +1,141 @@
+#
+# File:                makefile.nt
+# Author:      Julian Smart
+# Created:     1993
+# Copyright:   (c) 1993, AIAI, University of Edinburgh
+#
+# "%W% %G%"
+#
+# Makefile : Builds Tex2RTF on Windows Windows 95/NT
+#
+!include <..\..\..\src\ntwxwin.mak>
+
+TEX2RTFDIR = $(WXDIR)\utils\tex2rtf
+TEX2RTFINC = $(TEX2RTFDIR)\src
+PROGRAM=tex2rtf
+DOCDIR=$(WXDIR)\docs
+LOCALDOCDIR=$(WXDIR)\utils\tex2rtf\docs
+THISDIR=$(TEX2RTFDIR)\src
+
+OBJECTS = tex2rtf.obj tex2any.obj texutils.obj rtfutils.obj xlputils.obj htmlutil.obj readshg.obj table.obj
+
+all:    tex2rtf.exe
+
+wx:
+        cd $(WXDIR)\src\msw
+        nmake -f makefile.nt
+        cd $(TEX2RTFDIR)\src
+
+$(PROGRAM).exe:      $(WXLIB) $(OBJECTS) $(PROGRAM).res
+       $(link) @<<
+-out:$(PROGRAM).exe
+$(LINKFLAGS)
+$(DUMMYOBJ) $(OBJECTS) $(PROGRAM).res
+$(LIBS)
+<<
+
+$(PROGRAM).res :      $(PROGRAM).rc $(WXDIR)\include\wx\msw\wx.rc
+    $(rc) -r /i$(WXDIR)\include -fo$@ $(PROGRAM).rc
+
+tex2any.obj: tex2any.$(SRCSUFF) tex2any.h
+       cl @<<
+$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
+<<
+
+texutils.obj: texutils.$(SRCSUFF) tex2any.h
+       cl @<<
+$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
+<<
+
+tex2rtf.obj: tex2rtf.$(SRCSUFF) bmputils.h tex2rtf.h tex2any.h
+       cl @<<
+$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
+<<
+
+rtfutils.obj: rtfutils.$(SRCSUFF) tex2rtf.h bmputils.h tex2any.h readshg.h table.h
+       cl @<<
+$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
+<<
+
+table.obj: table.$(SRCSUFF) table.h
+       cl @<<
+$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
+<<
+
+readshg.obj: readshg.$(SRCSUFF) readshg.h
+       cl @<<
+$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
+<<
+
+xlputils.obj: xlputils.$(SRCSUFF) tex2rtf.h rtfutils.h tex2any.h
+       cl @<<
+$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
+<<
+
+htmlutil.obj: htmlutil.$(SRCSUFF) tex2rtf.h tex2any.h table.h
+       cl @<<
+$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
+<<
+
+clean:
+        -erase *.obj
+        -erase *.sbr
+        -erase *.exe
+        -erase *.res
+        -erase *.map
+        -erase *.pdb
+
+cleanall:
+        erase *.exe *.obj *.pch *.res
+
+DOCSOURCES=$(LOCALDOCDIR)\tex2rtf.tex
+
+html: $(DOCDIR)\html\tex2rtf\t2rtf.htm
+hlp: $(DOCDIR)\winhelp\tex2rtf.hlp
+pdfrtf: $(DOCDIR)\pdf\tex2rtf.rtf
+ps: $(WXDIR)\docs\ps\tex2rtf.ps
+
+$(DOCDIR)\winhelp\tex2rtf.hlp:         $(LOCALDOCDIR)\tex2rtf.rtf $(LOCALDOCDIR)\tex2rtf.hpj
+        cd $(LOCALDOCDIR)
+        -erase tex2rtf.ph
+        hc tex2rtf
+        copy tex2rtf.hlp $(DOCDIR)\winhelp\tex2rtf.hlp
+        copy tex2rtf.cnt $(DOCDIR)\winhelp\tex2rtf.cnt
+        cd $(THISDIR)
+
+$(LOCALDOCDIR)\tex2rtf.rtf: $(DOCSOURCES)
+        cd $(LOCALDOCDIR)
+        -start /w tex2rtf $(LOCALDOCDIR)\tex2rtf.tex $(LOCALDOCDIR)\tex2rtf.rtf -twice -winhelp
+        cd $(THISDIR)
+
+$(DOCDIR)\pdf\tex2rtf.rtf: $(DOCSOURCES)
+        cd $(LOCALDOCDIR)
+        -copy *.bmp *.wmf $(DOCDIR)\pdf
+        -start /w tex2rtf $(LOCALDOCDIR)\tex2rtf.tex $(DOCDIR)\pdf\tex2rtf.rtf -twice -rtf
+        cd $(THISDIR)
+
+$(DOCDIR)\html\tex2rtf\t2rtf.htm:         $(DOCSOURCES)
+        cd $(LOCALDOCDIR)
+        -mkdir $(DOCDIR)\html\tex2rtf
+        -start /w tex2rtf $(LOCALDOCDIR)\tex2rtf.tex $(DOCDIR)\html\tex2rtf\t2rtf.htm -twice -html
+        -erase $(DOCDIR)\html\tex2rtf\*.con
+        -erase $(DOCDIR)\html\tex2rtf\*.ref
+        cd $(THISDIR)
+
+$(LOCALDOCDIR)\tex2rtf.dvi:    $(DOCSOURCES)
+       cd $(LOCALDOCDIR)
+        -latex tex2rtf
+        -latex tex2rtf
+        -makeindx tex2rtf
+        -bibtex tex2rtf
+        -latex tex2rtf
+        -latex tex2rtf
+        cd $(THISDIR)
+
+$(WXDIR)\docs\ps\tex2rtf.ps:   $(LOCALDOCDIR)\tex2rtf.dvi
+       cd $(LOCALDOCDIR)
+        -dvips32 -o tex2rtf.ps tex2rtf
+        copy tex2rtf.ps $(WXDIR)\docs\ps\tex2rtf.ps
+        cd $(THISDIR)
+
+
diff --git a/utils/tex2rtf/src/makefile.unx b/utils/tex2rtf/src/makefile.unx
new file mode 100644 (file)
index 0000000..082f482
--- /dev/null
@@ -0,0 +1,17 @@
+#
+# File:                makefile.unx
+# Author:      Julian Smart
+# Created:     1998
+# Updated:     
+# Copyright:   (c) 1998 Julian Smart
+#
+# "%W% %G%"
+#
+# Makefile for Tex2RTF (Unix)
+
+PROGRAM=tex2rtf
+
+OBJECTS = tex2rtf.o tex2any.o texutils.o rtfutils.o xlputils.o htmlutil.o readshg.o table.o
+
+include ../../../src/makeprog.env
+
diff --git a/utils/tex2rtf/src/makefile.wat b/utils/tex2rtf/src/makefile.wat
new file mode 100644 (file)
index 0000000..053db94
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# Makefile for WATCOM
+#
+# 8 Nov 1994
+#
+
+WXDIR = $(%WXWIN)
+
+PROGRAM = tex2rtf
+OBJECTS = tex2rtf.obj tex2any.obj texutils.obj rtfutils.obj xlputils.obj htmlutil.obj readshg.obj table.obj
+
+!include $(WXDIR)\src\makeprog.wat
+
+
diff --git a/utils/tex2rtf/src/makengui.nt b/utils/tex2rtf/src/makengui.nt
new file mode 100644 (file)
index 0000000..a4de8c2
--- /dev/null
@@ -0,0 +1,98 @@
+# From:        Juan Altmayer Pizzorno[SMTP:juan@vms.gmd.de]
+# Sent:        31 May 1996 10:11
+# To:  J.Smart@ed.ac.uk
+# Subject:     Changes to Tex2RTF
+#
+# Hello,
+#
+# Recently I've been looking for a way to create and maintain documentation on
+# multiple platforms out of a single source -- specifically, something that
+# prints nicely and can be converted to WinHelp and HTML.  I liked the approach
+# of Tex2RTF, so I set off to give it a try...  I found out it would crash
+# when submitted to a certain LaTeX file I created.  I wanted to find out why,
+# so I went on and worked on compiling on my PC:  Windows NT 4.0 beta, Visual
+# C++ 4.1a.  Since all I was interested on was the convertion utility, I tried
+# to make it work without a GUI.  It didn't compile immediately, but after a
+# few small changes it now works like a charm.  Unfortunately it doesn't crash
+# anymore, so I can't tell why it used to...  Anyway, I wanted to contribute
+# the changes back:  I'm appending two files to this message, the first a
+# description of the changes, and the second a quick-and-dirty makefile that
+# doesn't require wxWindows to run.  Please do write to me if you have any
+# questions or anything.
+# 
+# Last but not least, it's great that you took the time and wrote Tex2RTF!!
+#
+# Quick-and-dirty makefile for building Tex2RTF without the wx
+# libraries on a Windows NT machine.  If you want to use it for
+# "real", please update the dependancies between object and include
+# files.  Created for Windows NT 4.0 and Visual C++ 4.1.
+#
+# Juan Altmayer Pizzorno, May 1996
+#
+
+syslibs=kernel32.lib advapi32.lib
+
+cxxflags=/nologo /MD /W0 /O2 /Zi /D "WIN32" /D "_WIN32" /D "_DEBUG" /c
+linkflags=$(syslibs) /out:$@ /nologo /debug
+
+!if "$(PROCESSOR_ARCHITECTURE)" == "x86"
+cxxflags=$(cxxflags) /G5 # optimize for pentium
+!endif
+
+cxx=cl
+link=link
+remove=del
+cxxflags=$(cxxflags) /I wxwin /D wx_msw /D WINVER=0x0400 /D WIN95=0
+cxxflags=$(cxxflags) /D "NO_GUI" 
+
+objects=tex2any.obj texutils.obj tex2rtf.obj rtfutils.obj table.obj readshg.obj xlputils.obj htmlutil.obj
+objects=$(objects) wb_hash.obj wb_list.obj wb_obj.obj wb_utils.obj
+
+all : tex2rtf.exe
+
+clean :
+    -$(remove) *.obj
+
+cleanall : clean
+    -$(remove) *.exe *.pdb *.ilk
+
+tex2rtf.exe : $(objects)
+    $(link) $(linkflags) $(objects)
+
+tex2any.obj : tex2any.cpp tex2any.h
+    $(cxx) $(cxxflags) tex2any.cpp
+
+texutils.obj : texutils.cpp tex2any.h
+    $(cxx) $(cxxflags) texutils.cpp
+
+tex2rtf.obj : tex2rtf.cpp bmputils.h tex2rtf.h tex2any.h
+    $(cxx) $(cxxflags) tex2rtf.cpp
+
+rtfutils.obj : rtfutils.cpp tex2rtf.h bmputils.h tex2any.h readshg.h table.h
+    $(cxx) $(cxxflags) rtfutils.cpp
+
+table.obj : table.cpp table.h
+    $(cxx) $(cxxflags) table.cpp
+
+readshg.obj : readshg.cpp readshg.h
+    $(cxx) $(cxxflags) readshg.cpp
+
+xlputils.obj : xlputils.cpp tex2rtf.h rtfutils.h tex2any.h
+    $(cxx) $(cxxflags) xlputils.cpp
+
+htmlutil.obj : htmlutil.cpp tex2rtf.h tex2any.h table.h
+    $(cxx) $(cxxflags) htmlutil.cpp
+
+wb_hash.obj : wxwin\wb_hash.cpp
+    $(cxx) $(cxxflags) wxwin\wb_hash.cpp
+
+wb_list.obj : wxwin\wb_list.cpp
+    $(cxx) $(cxxflags) wxwin\wb_list.cpp
+
+wb_obj.obj : wxwin\wb_obj.cpp
+    $(cxx) $(cxxflags) wxwin\wb_obj.cpp
+
+wb_utils.obj : wxwin\wb_utils.cpp
+    $(cxx) $(cxxflags) wxwin\wb_utils.cpp
+
+
diff --git a/utils/tex2rtf/src/maths.cpp b/utils/tex2rtf/src/maths.cpp
new file mode 100644 (file)
index 0000000..e951fea
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * File:     maths.cc
+ * Purpose:  Beginnings of a maths parser for LaTeX.
+ *           NOT IMPLEMENTED. I'm still thinking how best to do this...
+ *
+ */
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx_prec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include <wx.h>
+#endif
+
+#include <ctype.h>
+#include "tex2any.h"
+#include <stdlib.h>
+#include <time.h>
+
diff --git a/utils/tex2rtf/src/readshg.cpp b/utils/tex2rtf/src/readshg.cpp
new file mode 100644 (file)
index 0000000..2a62d48
--- /dev/null
@@ -0,0 +1,163 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        readshg.cpp
+// Purpose:     Petr Smilauer's .SHG (Segmented Hypergraphics file) reading
+//              code.
+//              Note: .SHG is undocumented (anywhere!) so this is
+//              reverse-engineering
+//              and guesswork at its best.
+// Author:      Petr Smilauer
+// Modified by:
+// Created:     01/01/99
+// RCS-ID:      $Id$
+// Copyright:   (c) Petr Smilauer
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "readshg.h"
+#include "tex2any.h"
+
+// Returns the number of hotspots, and the array of hotspots.
+// E.g.
+// HotSpots *array;
+// int n = ParseSHG("thing.shg", &array);
+
+int   ParseSHG( const char* fileName, HotSpot **hotspots)
+{ FILE*   fSHG = fopen( fileName, "rb");
+  long    offset;
+  int nHotspots = 0;
+
+  if(fSHG == 0)
+    return 0;
+  nHotspots = 0;
+  //first, look at offset OFF_OFFSET to get another offset :-)
+  fseek( fSHG, OFF_OFFSET, SEEK_SET);
+  offset = 0L;                  // init whole 4-byte variable
+  fread( &offset, 2, 1, fSHG);  // get the offset in first two bytes..
+  if(offset == 0)               // if zero, used next DWORD field
+    fread( &offset, 4, 1, fSHG);// this is our offset for very long DIB
+  offset += 9;                  // don't know hot this delta comes-about
+  if(fseek( fSHG, offset, SEEK_SET) != 0)
+  {
+    fclose( fSHG);
+    return -1;    // this is probably because incorrect offset calculation.
+  }
+  fread( &nHotspots, 2, 1, fSHG);
+
+  *hotspots = new HotSpot[nHotspots];
+
+  int nMacroStrings = 0;
+
+  fread( &nMacroStrings, 2, 1, fSHG); // we can ignore the macros, as this is
+                         // repeated later, but we need to know how much to skip
+  fseek( fSHG, 2, SEEK_CUR);  // skip another 2 bytes I do not understand ;-)
+
+  ShgInfoBlock  sib;
+  int           i;
+
+  int sizeOf = sizeof( ShgInfoBlock);
+
+  for( i = 0 ; i < nHotspots ; ++i)
+  {
+    fread( &sib, sizeOf, 1, fSHG); // read one hotspot' info
+    // analyse it:
+    (*hotspots)[i].type    = (HotspotType)(sib.hotspotType & 0xFB);
+    (*hotspots)[i].left    = sib.left;
+    (*hotspots)[i].top     = sib.top;
+    (*hotspots)[i].right   = sib.left + sib.width;
+    (*hotspots)[i].bottom  = sib.top  + sib.height;
+    (*hotspots)[i].IsVisible = ((sib.hotspotType & 4) == 0);
+    (*hotspots)[i].szHlpTopic_Macro[0] = '\0';
+  }
+  // we have it...now read-off the macro-string block
+  if(nMacroStrings > 0)
+    fseek( fSHG, nMacroStrings, SEEK_CUR);  //nMacroStrings is byte offset...
+  // and, at the last, read through the strings: hotspot-id[ignored], then topic/macro
+  int  c;
+  for( i = 0 ; i < nHotspots ; ++i)
+  {
+    while( (c = fgetc( fSHG)) != 0)
+      ;
+    // now read it:
+    int j = 0;
+    while( (c = fgetc( fSHG)) != 0)
+    {
+      (*hotspots)[i].szHlpTopic_Macro[j] = c;
+      ++j;
+    }
+    (*hotspots)[i].szHlpTopic_Macro[j] = 0;
+  }
+  fclose( fSHG);
+  return nHotspots;
+}
+
+
+// Convert Windows .SHG file to HTML map file
+
+bool SHGToMap(char *filename, char *defaultFile)
+{
+  // Test the SHG parser
+  HotSpot *hotspots = NULL;
+  int n = ParseSHG(filename, &hotspots);
+  if (n == 0)
+    return FALSE;
+
+  char buf[100];
+  sprintf(buf, "Converting .SHG file to HTML map file: there are %d hotspots in %s.", n, filename);
+  OnInform(buf);
+
+  char outBuf[256];
+  strcpy(outBuf, filename);
+  StripExtension(outBuf);
+  strcat(outBuf, ".map");
+
+  FILE *fd = fopen(outBuf, "w");
+  if (!fd)
+  {
+    OnError("Could not open .map file for writing.");
+    delete[] hotspots;
+    return FALSE;
+  }
+
+  fprintf(fd, "default %s\n", defaultFile);
+  for (int i = 0; i < n; i++)
+  {
+    char *refFilename = "??";
+    
+    TexRef *texRef = FindReference(hotspots[i].szHlpTopic_Macro);
+    if (texRef)
+      refFilename = texRef->refFile;
+    else
+    {
+      char buf[300];
+      sprintf(buf, "Warning: could not find hotspot reference %s", hotspots[i].szHlpTopic_Macro);
+      OnInform(buf);
+    }
+    fprintf(fd, "rect %s %d %d %d %d\n", refFilename, (int)hotspots[i].left, (int)hotspots[i].top,
+      (int)hotspots[i].right, (int)hotspots[i].bottom);
+  }
+  fprintf(fd, "\n");
+
+  fclose(fd);
+
+  delete[] hotspots;
+  return TRUE;
+}
+
diff --git a/utils/tex2rtf/src/readshg.h b/utils/tex2rtf/src/readshg.h
new file mode 100644 (file)
index 0000000..b26d4fe
--- /dev/null
@@ -0,0 +1,64 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        readshg.h
+// Purpose:     Petr Smilauer's .SHG (Segmented Hypergraphics file) reading
+//              code.
+//              Note: .SHG is undocumented (anywhere!) so this is
+//              reverse-engineering
+//              and guesswork at its best.
+// Author:      Petr Smilauer
+// Modified by:
+// Created:     01/01/99
+// RCS-ID:      $Id$
+// Copyright:   (c) Petr Smilauer
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef readshgh
+#define readshgh
+
+#include  <stdio.h>
+#include <stdlib.h>
+
+typedef enum { TypePopup = 0xE2, TypeJump = 0xE3, TypeMacro = 0xC8} HotspotType;
+
+#define NOT_VISIBLE  0x04
+
+typedef struct
+{
+  unsigned char   hotspotType;// combines HotspotType /w NOT_VISIBLE if appropriate
+  unsigned char   flag;       // NOT_VISIBLE or 0 ??
+  unsigned char   skip;       // 0, always??
+  unsigned short  left,
+                  top,
+                  width,      // left+width/top+height give right/bottom,
+                  height;     // =>right and bottom edge are not 'included'
+  unsigned char   magic[4];   // wonderful numbers: for macros, this seems
+    // (at least first 2 bytes) to represent offset into macro-strings block.
+} ShgInfoBlock;   // whole block is just 15 bytes long. How weird!
+
+#define OFF_OFFSET    0x20    // this is offset, where WORD (?) lies
+#define OFFSET_DELTA  9       // we must add this to get real offset from file beginning
+
+struct HotSpot
+{
+          HotspotType type;
+          unsigned int left,
+                      top,
+                      right,
+                      bottom;
+          char        szHlpTopic_Macro[65];
+          bool        IsVisible;
+};
+
+// Returns the number of hotspots, and the array of hotspots.
+// E.g.
+// HotSpots *array;
+// int n = ParseSHG("thing.shg", &array);
+
+extern int ParseSHG( const char* fileName, HotSpot **hotspots);
+
+// Converts Windows .SHG file to HTML map file
+extern bool SHGToMap(char *filename, char *defaultFile);
+
+#endif
+
diff --git a/utils/tex2rtf/src/rtfutils.cpp b/utils/tex2rtf/src/rtfutils.cpp
new file mode 100644 (file)
index 0000000..d58191a
--- /dev/null
@@ -0,0 +1,5250 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        rtfutils.cpp
+// Purpose:     Converts Latex to Word RTF/WinHelp RTF
+// Author:      Julian Smart
+// Modified by:
+// Created:     7.9.93
+// RCS-ID:      $Id$
+// Copyright:   (c) Julian Smart
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+#include "tex2any.h"
+#include "tex2rtf.h"
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifdef __WIN32__
+#include <windows.h>
+#endif
+
+#include "bmputils.h"
+#include "table.h"
+
+wxList itemizeStack;
+static int indentLevel = 0;
+static int forbidParindent = 0; // if > 0, no parindent (e.g. in center environment)
+int forbidResetPar = 0; // If > 0, don't reset memory of having output a new par
+
+static char *contentsLineSection = NULL;
+static char *contentsLineValue = NULL;
+static TexChunk *descriptionItemArg = NULL;
+static wxStringList environmentStack; // Stack of paragraph styles we need to remember
+static int footnoteCount = 0;
+static int citeCount = 1;
+extern char *FileRoot;
+extern bool winHelp;
+extern bool startedSections;
+extern FILE *Contents;
+extern FILE *Chapters;
+extern FILE *Popups;
+extern FILE *WinHelpContentsFile;
+extern char *RTFCharset;
+// This is defined in the Tex2Any library and isn't in use after parsing
+extern char *BigBuffer;
+// Are we in verbatim mode? If so, format differently.
+static bool inVerbatim = FALSE;
+
+// We're in a series of PopRef topics, so don't output section headings
+bool inPopRefSection = FALSE;
+
+// Green colour?
+static bool hotSpotColour = TRUE;
+static bool hotSpotUnderline = TRUE;
+
+// Transparency (WHITE = transparent)
+static bool bitmapTransparency = TRUE;
+
+// Linear RTF requires us to set the style per section.
+static char *currentNumberStyle = NULL;
+static int currentItemSep = 8;
+static int CurrentTextWidth = 8640; // Say, six inches
+static int CurrentLeftMarginOdd = 400;
+static int CurrentLeftMarginEven = 1440;
+static int CurrentRightMarginOdd = 1440;
+static int CurrentRightMarginEven = 400;
+static int CurrentMarginParWidth = 2000;
+static int CurrentMarginParSep = 400;  // Gap between marginpar and text
+static int CurrentMarginParX = CurrentLeftMarginOdd + CurrentTextWidth + CurrentMarginParSep;
+static int GutterWidth = 2300;
+
+// Two-column table dimensions, in twips
+static int TwoColWidthA = 1500;
+static int TwoColWidthB = 3000;
+
+const int PageWidth = 12242; // 8.25 inches wide for A4
+
+
+/*
+ * Flag to say we've just issued a \par\pard command, so don't
+ * repeat this unnecessarily.
+ *
+ */
+
+int issuedNewParagraph = 0;
+
+// Need to know whether we're in a table or figure for benefit
+// of listoffigures/listoftables
+static bool inFigure = FALSE;
+static bool inTable = FALSE;
+
+/*
+ * Current topics
+ *
+ */
+static char *CurrentChapterName = NULL;
+static char *CurrentSectionName = NULL;
+static char *CurrentSubsectionName = NULL;
+static char *CurrentTopic = NULL;
+
+static bool InPopups()
+{
+  if (CurrentChapterName && (strcmp(CurrentChapterName, "popups") == 0))
+    return TRUE;
+  if (CurrentSectionName && (strcmp(CurrentSectionName, "popups") == 0))
+    return TRUE;
+  return FALSE;
+}
+
+static void SetCurrentTopic(char *s)
+{
+  if (CurrentTopic) delete[] CurrentTopic;
+  CurrentTopic = copystring(s);
+}
+
+void SetCurrentChapterName(char *s)
+{
+  if (CurrentChapterName) delete[] CurrentChapterName;
+  CurrentChapterName = copystring(s);
+  SetCurrentTopic(s);
+}
+void SetCurrentSectionName(char *s)
+{
+  if (CurrentSectionName) delete[] CurrentSectionName;
+  CurrentSectionName = copystring(s);
+  SetCurrentTopic(s);
+}
+void SetCurrentSubsectionName(char *s)
+{
+  if (CurrentSubsectionName) delete[] CurrentSubsectionName;
+  CurrentSubsectionName = copystring(s);
+  SetCurrentTopic(s);
+}
+
+// Indicate that a parent topic at level 'level' has children.
+// Level 1 is a chapter, 2 is a section, etc.
+void NotifyParentHasChildren(int parentLevel)
+{
+  char *parentTopic = NULL;
+  switch (parentLevel)
+  {
+    case 1:
+    {
+      parentTopic = CurrentChapterName;
+      break;
+    }
+    case 2:
+    {
+      parentTopic = CurrentSectionName;
+      break;
+    }
+    case 3:
+    {
+      parentTopic = CurrentSubsectionName;
+      break;
+    }
+    default:
+    {
+      break;
+    }
+  }
+  if (parentTopic)
+  {
+    TexTopic *texTopic = (TexTopic *)TopicTable.Get(parentTopic);
+    if (!texTopic)
+    {
+      texTopic = new TexTopic;
+      TopicTable.Put(parentTopic, texTopic);
+    }
+    texTopic->hasChildren = TRUE;
+  }
+}
+
+// Have to keep a count of what levels are books, what are pages,
+// in order to correct for a Win95 bug which means that if you
+// have a book at level n, and then a page at level n, the page
+// ends up on level n + 1.
+
+bool ContentsLevels[5];
+
+// Reset below this level (starts from 1)
+void ResetContentsLevels(int l)
+{
+  int i;
+  for (i = l; i < 5; i++)
+    ContentsLevels[i] = FALSE;
+    
+  // There are always books on the top level
+  ContentsLevels[0] = TRUE;
+}
+
+// Output a WinHelp section as a keyword, substituting
+// : for space.
+void OutputSectionKeyword(FILE *fd)
+{
+  OutputCurrentSectionToString(wxBuffer);
+  
+  int i;
+  for (i = 0; i < strlen(wxBuffer); i++)
+    if (wxBuffer[i] == ':')
+      wxBuffer[i] = ' ';
+    // Don't write to index if there's some RTF in the string
+    else if ( wxBuffer[i] == '{' )
+        return;
+
+  fprintf(fd, "K{\\footnote {K} ");
+  fprintf(fd, "%s", wxBuffer);
+  
+  fprintf(fd, "}\n");
+}
+
+// Write a line for the .cnt file, if we're doing this.
+void WriteWinHelpContentsFileLine(char *topicName, char *xitle, int level)
+{
+  // First, convert any RTF characters to ASCII
+  char title[255];
+  int s=0;
+  int d=0;
+  while ( (xitle[s]!=0)&&(d<255) )
+  {
+         char ch=xitle[s]&0xff;
+         if (ch==0x5c) {
+                 char ch1=xitle[s+1]&0xff;
+                 char ch2=xitle[s+2]&0xff;
+                 char ch3=xitle[s+3]&0xff;
+                 char ch4=xitle[s+4]&0xff;
+                 s+=4; // next character                 
+                 char a=0;
+                 if ((ch1==0x27)&&(ch2==0x66)&&(ch3==0x36)) { title[d++]='ö';  a=1; }
+                 if ((ch1==0x27)&&(ch2==0x65)&&(ch3==0x34)) { title[d++]='ä';  a=1; }
+                 if ((ch1==0x27)&&(ch2==0x66)&&(ch3==0x63)) { title[d++]='ü';  a=1; }
+                 if ((ch1==0x27)&&(ch2==0x64)&&(ch3==0x36)) { title[d++]='Ö';  a=1; }
+                 if ((ch1==0x27)&&(ch2==0x63)&&(ch3==0x34)) { title[d++]='Ä';  a=1; }
+                 if ((ch1==0x27)&&(ch2==0x64)&&(ch3==0x63)) { title[d++]='Ãœ';  a=1; }
+//               if (a==0)
+//                       printf("!!!!! %04X %04X %04X %04X! \n",ch1,ch2,ch3,ch4);
+         } else {
+               title[d++]=ch;
+               s++;
+         }       
+  }
+  title[d]=0;
+
+  // Section (2) becomes level 1 if it's an article.
+  if (DocumentStyle == LATEX_ARTICLE)
+    level --;
+
+  if (level == 0) // Means we had a Chapter in an article, oops.
+    return;
+    
+  ResetContentsLevels(level);
+  
+  if (!title)
+    return;
+    
+  if (winHelp && winHelpContents && WinHelpContentsFile)
+  {
+    TexTopic *texTopic = (TexTopic *)TopicTable.Get(topicName);
+    if (texTopic)
+    {
+      // If a previous section at this level was a book, we *have* to have a
+      // book not a page, because of a bug in WHC (or WinHelp 4).
+      if (texTopic->hasChildren || level == 1 || ContentsLevels[level-1])
+      {
+        // At this level, we have a pointer to a further hierarchy.
+        // So we need a 'book' consisting of (say) Chapter 1.
+        fprintf(WinHelpContentsFile, "%d %s\n", level, title);
+
+        // Then we have a 'page' consisting of the text for this chapter
+        fprintf(WinHelpContentsFile, "%d %s=%s\n", level+1, title, topicName);
+
+        // Then we'll be writing out further pages or books at level + 1...
+
+        // Remember that at this level, we had a book and *must* for the
+        // remainder of sections at this level.
+        ContentsLevels[level-1] = TRUE;
+      }
+      else
+      {
+        fprintf(WinHelpContentsFile, "%d %s=%s\n", level, title, topicName);
+      }
+    }
+    else
+    {
+      if (level == 1 || ContentsLevels[level-1])
+      {
+        // Always have a book at level 1
+        fprintf(WinHelpContentsFile, "%d %s\n", level, title);
+        fprintf(WinHelpContentsFile, "%d %s=%s\n", level+1, title, topicName);
+        ContentsLevels[level-1] = TRUE;
+      }
+      else
+        // Probably doesn't have children if it hasn't been added to the topic table
+        fprintf(WinHelpContentsFile, "%d %s=%s\n", level, title, topicName);
+    }
+  }
+}
+
+void SplitIndexEntry(char *entry, char *buf1, char *buf2)
+{
+  int len = strlen(entry); int i = 0;
+  while ((i < len) && entry[i] != '!')
+  { buf1[i] = entry[i]; i ++; }
+  buf1[i] = 0; buf2[0] = 0; int j = 0;
+
+  if (entry[i] == '!')
+  {
+    i ++;
+    while (i < len) { buf2[j] = entry[i]; i ++; j++; }
+    buf2[j] = 0;
+  }
+}
+
+/*
+ * Output topic index entries in WinHelp RTF
+ *
+ */
+void GenerateKeywordsForTopic(char *topic)
+{
+  TexTopic *texTopic = (TexTopic *)TopicTable.Get(topic);
+  if (!texTopic)
+    return;
+
+  wxStringList *list = texTopic->keywords;
+  if (list)
+  {
+    wxNode *node = list->First();
+    while (node)
+    {
+      char *s = (char *)node->Data();
+
+      // Must separate out main entry form subentry (only 1 subentry allowed)
+      char buf1[100]; char buf2[100];
+      SplitIndexEntry(s, buf1, buf2);
+      
+      // Check for ':' which messes up index
+      int i;
+      for (i = 0; i < strlen(buf1) ; i++)
+        if (buf1[i] == ':')
+          buf1[i] = ' ';
+      for (i = 0; i < strlen(buf2) ; i++)
+        if (buf2[i] == ':')
+          buf2[i] = ' ';
+
+      // {K} is a strange fix to prevent words beginning with K not
+      // being indexed properly
+      TexOutput("K{\\footnote {K} ");
+      TexOutput(buf1);
+      if (strlen(buf2) > 0)
+      {
+        // Output subentry
+        TexOutput(", ");
+        TexOutput(buf2);
+      }
+      TexOutput("}\n");
+      node = node->Next();
+    }
+  }
+}
+
+/*
+ * Output index entry in linear RTF
+ *
+ */
+void GenerateIndexEntry(char *entry)
+{
+  if (useWord)
+  {
+    char buf1[100]; char buf2[100];
+    SplitIndexEntry(entry, buf1, buf2);
+
+    TexOutput("{\\xe\\v {");
+    TexOutput(buf1);
+    if (strlen(buf2) > 0)
+    {
+      TexOutput("\\:");
+      TexOutput(buf2);
+    }
+    TexOutput("}}");
+  }
+}
+
+ /*
+  * Write a suitable RTF header.
+  *
+  */
+  
+void WriteColourTable(FILE *fd)
+{
+  fprintf(fd, "{\\colortbl");
+  wxNode *node = ColourTable.First();
+  while (node)
+  {
+    ColourTableEntry *entry = (ColourTableEntry *)node->Data();
+    fprintf(fd, "\\red%d\\green%d\\blue%d;\n", entry->red, entry->green, entry->blue);
+    node = node->Next();
+  }
+  fprintf(fd, "}");
+}
+
+/*
+ * Write heading style
+ *
+ */
+
+void WriteHeadingStyle(FILE *fd, int heading)
+{
+  switch (heading)
+  {
+    case 1:
+    {
+      fprintf(fd, "\\b\\fs%d", chapterFont*2);
+      break;
+    }
+    case 2:
+    {
+      fprintf(fd, "\\b\\fs%d", sectionFont*2);
+      break;
+    }
+    case 3:
+    {
+      fprintf(fd, "\\b\\fs%d", subsectionFont*2);
+      break;
+    }
+    case 4:
+    {
+      fprintf(fd, "\\b\\fs%d", subsectionFont*2);
+      break;
+    }
+    default:
+      break;
+  }
+}
+
+void WriteRTFHeader(FILE *fd)
+{
+  fprintf(fd, "{\\rtf1\\%s \\deff0\n", RTFCharset);
+  fprintf(fd, "{\\fonttbl{\\f0\\froman Times New Roman;}{\\f1\\ftech Symbol;}{\\f2\\fswiss Arial;}\n");
+  fprintf(fd, "{\\f3\\fmodern Courier;}{\\f4\\ftech Wingdings;}{\\f5\\ftech Monotype Sorts;}\n}");
+  /*
+   * Style sheet
+   */
+  fprintf(fd, "{\\stylesheet{\\f2\\fs20 \\snext0 Normal;}\n");
+  // Headings
+  fprintf(fd, "{\\s1 "); WriteHeadingStyle(fd, 1); fprintf(fd, "\\sbasedon0\\snext0 heading 1;}\n");
+  fprintf(fd, "{\\s2 "); WriteHeadingStyle(fd, 2); fprintf(fd, "\\sbasedon0\\snext0 heading 2;}\n");
+  fprintf(fd, "{\\s3 "); WriteHeadingStyle(fd, 3); fprintf(fd, "\\sbasedon0\\snext0 heading 3;}\n");
+  fprintf(fd, "{\\s4 "); WriteHeadingStyle(fd, 4); fprintf(fd, "\\sbasedon0\\snext0 heading 4;}\n");
+  // Table of contents styles
+  fprintf(fd, "{\\s20\\sb300\\tqr\\tldot\\tx8640 \\b\\f2 \\sbasedon0\\snext0 toc 1;}\n");
+  
+  fprintf(fd, "{\\s21\\sb90\\tqr\\tldot\\li400\\tqr\\tx8640 \\f2\\fs20\\sbasedon0\\snext0 toc 2;}\n");
+  fprintf(fd, "{\\s22\\sb90\\tqr\\tldot\\li800\\tx8640 \\f2\\fs20 \\sbasedon0\\snext0 toc 3;}\n");
+  fprintf(fd, "{\\s23\\sb90\\tqr\\tldot\\li1200\\tx8640 \\f2\\fs20 \\sbasedon0\\snext0 toc 4;}\n");
+
+  // Index styles
+  fprintf(fd, "{\\s30\\fi-200\\li200\\tqr\\tx3960 \\f2\\fs18 \\sbasedon0\\snext0 index 1;}\n");
+  fprintf(fd, "{\\s31\\fi-200\\li400\\tqr\\tx3960 \\f2\\fs18 \\sbasedon0\\snext0 index 2;}\n");
+  fprintf(fd, "{\\s32\\fi-200\\li600\\tqr\\tx3960 \\f2\\fs18 \\sbasedon0\\snext0 index 3;}\n");
+  fprintf(fd, "{\\s33\\fi-200\\li800\\tqr\\tx3960 \\f2\\fs18 \\sbasedon0\\snext0 index 4;}\n");
+  fprintf(fd, "{\\s35\\qc\\sb240\\sa120 \\b\\f2\\fs26 \\sbasedon0\\snext30 index heading;}\n");
+  fprintf(fd, "}\n");
+
+  WriteColourTable(fd);
+  fprintf(fd, "\n\\ftnbj\\ftnrestart"); // Latex default is footnotes at bottom of page, not section.
+  fprintf(fd, "\n");
+}
+
+void OutputNumberStyle(char *numberStyle)
+{
+  if (numberStyle)
+  {
+    if (strcmp(numberStyle, "arabic") == 0)
+    {
+      TexOutput("\\pgndec");
+    }
+    else if (strcmp(numberStyle, "roman") == 0)
+    {
+      TexOutput("\\pgnlcrm");
+    }
+    else if (strcmp(numberStyle, "Roman") == 0)
+    {
+      TexOutput("\\pgnucrm");
+    }
+    else if (strcmp(numberStyle, "alph") == 0)
+    {
+      TexOutput("\\pgnlcltr");
+    }
+    else if (strcmp(numberStyle, "Alph") == 0)
+    {
+      TexOutput("\\pgnucltr");
+    }
+  }
+}
+
+/*
+ * Write a Windows help project file
+ */
+bool WriteHPJ(char *filename)
+{
+  char hpjFilename[256];
+  char helpFile[50];
+  char rtfFile[50];
+  strcpy(hpjFilename, filename);
+  StripExtension(hpjFilename);
+  strcat(hpjFilename, ".hpj");
+
+  strcpy(helpFile, FileNameFromPath(filename));
+  StripExtension(helpFile);
+  strcpy(rtfFile, helpFile);
+  strcat(helpFile, ".hlp");
+  strcat(rtfFile, ".rtf");
+  
+  FILE *fd = fopen(hpjFilename, "w");
+  if (!fd)
+    return FALSE;
+
+  char *helpTitle = winHelpTitle;
+  if (!helpTitle)
+    helpTitle = "Untitled";
+    
+  char *thePath = wxPathOnly(InputFile);
+  if (!thePath)
+    thePath = ".";
+  fprintf(fd, "[OPTIONS]\n");
+  fprintf(fd, "BMROOT=%s ; Assume that bitmaps are where the source is\n", thePath);
+  fprintf(fd, "TITLE=%s\n", helpTitle);
+  fprintf(fd, "CONTENTS=Contents\n");
+
+  if (winHelpVersion > 3)
+  {
+    fprintf(fd, "; COMPRESS=12 Hall Zeck ; Max compression, but needs lots of memory\n");
+    fprintf(fd, "COMPRESS=8 Zeck\n");
+    fprintf(fd, "LCID=0x809 0x0 0x0 ;English (British)\n");
+    fprintf(fd, "HLP=.\\%s.hlp\n", wxFileNameFromPath(FileRoot));
+  }
+  else
+  {
+    fprintf(fd, "COMPRESS=HIGH\n");
+  }
+  fprintf(fd, "\n");
+
+  if (winHelpVersion > 3)
+  {
+    fprintf(fd, "[WINDOWS]\n");
+    fprintf(fd, "Main=\"\",(553,102,400,600),20736,(r14876671),(r12632256),f3\n");
+    fprintf(fd, "\n");
+  }
+
+  fprintf(fd, "[FILES]\n%s\n\n", rtfFile);
+  fprintf(fd, "[CONFIG]\n");
+  if (useUpButton)
+    fprintf(fd, "CreateButton(\"Up\", \"&Up\", \"JumpId(`%s', `Contents')\")\n", helpFile);
+  fprintf(fd, "BrowseButtons()\n\n");
+  fprintf(fd, "[MAP]\n\n[BITMAPS]\n\n");
+  fclose(fd);
+  return TRUE;
+}
+
+
+/*
+ * Given a TexChunk with a string value, scans through the string
+ * converting Latex-isms into RTF-isms, such as 2 newlines -> \par,
+ * and inserting spaces at the start of lines since in Latex, a newline
+ * implies a space, but not in RTF.
+ *
+ */
+
+void ProcessText2RTF(TexChunk *chunk)
+{
+  bool changed = FALSE;
+  int ptr = 0;
+  int i = 0;
+  char ch = 1;
+  int len = strlen(chunk->value);
+  while (ch != 0)
+  {
+    ch = chunk->value[i];
+
+    if (ch == 10)
+    {
+      if (inVerbatim)
+      {
+        BigBuffer[ptr] = 0; strcat(BigBuffer, "\\par\n"); ptr += 5;
+        i ++;
+        changed = TRUE;
+      }
+      else
+      {
+        // If the first character of the next line is ASCII,
+        // put a space in. Implicit in Latex, not in RTF.
+        /*
+          The reason this is difficult is that you don't really know
+          where a space would be appropriate. If you always put in a space
+          when you find a newline, unwanted spaces appear in the text.
+         */
+        if ((i > 0) && (len > i+1 && isascii(chunk->value[i+1]) &&
+                  !isspace(chunk->value[i+1])) ||
+            ((len > i+1 && chunk->value[i+1] == 13) &&
+             (len > i+2 && isascii(chunk->value[i+2]) &&
+              !isspace(chunk->value[i+2]))))
+//        if (TRUE)
+        {
+          // DOS files have a 13 after the 10
+          BigBuffer[ptr] = 10;
+          ptr ++;
+          i ++;
+          if (chunk->value[i] == 13)
+          {
+            BigBuffer[ptr] = 13;
+            ptr ++;
+            i ++;
+          }
+
+          BigBuffer[ptr] = ' ';
+          ptr ++;
+
+          // Note that the actual ASCII character seen is dealt with in the next
+          // iteration
+          changed = TRUE;
+        }
+        else
+        {
+          BigBuffer[ptr] = ch;
+          i ++;
+        }
+      }
+    }
+    else if (!inVerbatim && ch == '`' && (len >= i+1 && chunk->value[i+1] == '`'))
+    {
+      BigBuffer[ptr] = '"'; ptr ++;
+      i += 2;
+      changed = TRUE;
+    }
+    else if (!inVerbatim && ch == '`') // Change ` to '
+    {
+      BigBuffer[ptr] = 39; ptr ++;
+      i += 1;
+      changed = TRUE;
+    }
+    else if (inVerbatim && ch == '\\') // Change backslash to two backslashes
+    {
+      BigBuffer[ptr] = '\\'; ptr ++;
+      BigBuffer[ptr] = '\\'; ptr ++;
+      i += 1;
+      changed = TRUE;
+    }
+    else if (inVerbatim && (ch == '{' || ch == '}')) // Escape the curly bracket
+    {
+      BigBuffer[ptr] = '\\'; ptr ++;
+      BigBuffer[ptr] = ch; ptr ++;
+      i += 1;
+      changed = TRUE;
+    }
+    else
+    {
+      BigBuffer[ptr] = ch;
+      i ++;
+      ptr ++;
+    }
+  }
+  BigBuffer[ptr] = 0;
+
+  if (changed)
+  {
+    delete[] chunk->value;
+    chunk->value = copystring(BigBuffer);
+  }
+}
+
+/*
+ * Scan through all chunks starting from the given one,
+ * calling ProcessText2RTF to convert Latex-isms to RTF-isms.
+ * This should be called after Tex2Any has parsed the file,
+ * and before TraverseDocument is called.
+ *
+ */
+void Text2RTF(TexChunk *chunk)
+{
+  Tex2RTFYield();
+  if (stopRunning) return;
+
+  switch (chunk->type)
+  {
+    case CHUNK_TYPE_MACRO:
+    {
+      TexMacroDef *def = chunk->def;
+      if (def && def->ignore)
+        return;
+
+      if (def && (def->macroId == ltVERBATIM || def->macroId == ltVERB))
+        inVerbatim = TRUE;
+
+      wxNode *node = chunk->children.First();
+      while (node)
+      {
+        TexChunk *child_chunk = (TexChunk *)node->Data();
+        Text2RTF(child_chunk);
+        node = node->Next();
+      }
+
+      if (def && (def->macroId == ltVERBATIM || def->macroId == ltVERB))
+        inVerbatim = FALSE;
+
+      break;
+    }
+    case CHUNK_TYPE_ARG:
+    {
+      wxNode *node = chunk->children.First();
+      while (node)
+      {
+        TexChunk *child_chunk = (TexChunk *)node->Data();
+        Text2RTF(child_chunk);
+        node = node->Next();
+      }
+
+      break;
+    }
+    case CHUNK_TYPE_STRING:
+    {
+      if (chunk->value)
+        ProcessText2RTF(chunk);
+      break;
+    }
+  }
+}
+
+/*
+ * Not used yet
+ *
+ */
+char browseBuf[10];
+static long browseId = 0;
+char *GetBrowseString(void)
+{
+  char buf[10];
+  browseId ++;
+  sprintf(buf, "%ld", browseId);
+  int noZeroes = 5-strlen(buf);
+  strcpy(browseBuf, "browse");
+  for (int i = 0; i < noZeroes; i++)
+    strcat(browseBuf, "0");
+  strcat(browseBuf, buf);
+  return browseBuf;
+}
+
+/*
+ * Keeping track of environments to restore the styles after \pard.
+ * Push strings like "\qc" onto stack.
+ *
+ */
+
+void PushEnvironmentStyle(char *style)
+{
+  environmentStack.Add(style);
+}
+
+void PopEnvironmentStyle(void)
+{
+  wxNode *node = environmentStack.Last();
+  if (node)
+  {
+    char *val = (char *)node->Data();
+    delete[] val;
+    delete node;
+  }
+}
+
+// Write out the styles, most recent first.
+void WriteEnvironmentStyles(void)
+{
+  wxNode *node = environmentStack.Last();
+  while (node)
+  {
+    char *val = (char *)node->Data();
+    TexOutput(val);
+    node = node->Next();
+  }
+  if (!inTabular && (ParIndent > 0) && (forbidParindent == 0))
+  {
+    char buf[15];
+    sprintf(buf, "\\fi%d", ParIndent*20); // Convert points to TWIPS
+    TexOutput(buf);
+  }
+  if (environmentStack.Number() > 0 || (ParIndent > 0))
+    TexOutput("\n");
+}
+
+
+/*
+ * Output a header
+ *
+ */
+
+void OutputRTFHeaderCommands(void)
+{
+  char buf[300];
+  if (PageStyle && strcmp(PageStyle, "plain") == 0)
+  {
+    TexOutput("{\\headerl }{\\headerr }");
+  }
+  else if (PageStyle && strcmp(PageStyle, "empty") == 0)
+  {
+    TexOutput("{\\headerl }{\\headerr }");
+  }
+  else if (PageStyle && strcmp(PageStyle, "headings") == 0)
+  {
+    // Left header
+    TexOutput("{\\headerl\\fi0 ");
+
+    if (headerRule)
+      TexOutput("\\brdrb\\brdrs\\brdrw15\\brsp20 ");
+
+    TexOutput("{\\i \\qr ");
+    if (DocumentStyle == LATEX_ARTICLE)
+    {
+      sprintf(buf, "SECTION %d", sectionNo);
+      TexOutput(buf);
+    }
+    else
+    {
+      sprintf(buf, "CHAPTER %d: ", chapterNo);
+      TexOutput(buf);
+    }
+    TexOutput("{\\field{\\*\\fldinst PAGE \\\\* MERGEFORMAT }{\\fldrslt 1}}");
+    TexOutput("}\\par\\pard}");
+
+    // Right header
+    TexOutput("{\\headerr\\fi0 ");
+
+    if (headerRule)
+      TexOutput("\\brdrb\\brdrs\\brdrw15\\brsp20 ");
+
+    TexOutput("{\\i \\qc ");
+    if (DocumentStyle == LATEX_ARTICLE)
+    {
+      sprintf(buf, "SECTION %d", sectionNo);
+      TexOutput(buf);
+    }
+    else
+    {
+      sprintf(buf, "CHAPTER %d", chapterNo);
+      TexOutput(buf);
+    }
+    TexOutput("{\\field{\\*\\fldinst PAGE \\\\* MERGEFORMAT }{\\fldrslt 1}}");
+    TexOutput("}\\par\\pard}");
+  }
+  else
+  {
+    int oldForbidResetPar = forbidResetPar;
+    forbidResetPar = 0;
+    
+    if (LeftHeaderEven || CentreHeaderEven || RightHeaderEven)
+    {
+      TexOutput("{\\headerl\\fi0 ");
+
+      if (headerRule)
+        TexOutput("\\brdrb\\brdrs\\brdrw15\\brsp20 ");
+
+      if (LeftHeaderEven)
+      {
+        if (!CentreHeaderEven && !RightHeaderEven)
+          TexOutput("\\ql ");
+        TraverseChildrenFromChunk(LeftHeaderEven);
+      }
+      if (CentreHeaderEven)
+      {
+        if (!LeftHeaderEven && !RightHeaderEven)
+          TexOutput("\\qc ");
+        else
+          TexOutput("\\tab\\tab\\tab ");
+        TraverseChildrenFromChunk(CentreHeaderEven);
+      }
+      if (RightHeaderEven)
+      {
+        if (!LeftHeaderEven && !CentreHeaderEven)
+          TexOutput("\\qr ");
+        else
+          TexOutput("\\tab\\tab\\tab\\tab\\tab\\tab ");
+        TraverseChildrenFromChunk(RightHeaderEven);
+      }
+      TexOutput("\\par\\pard}");
+    }
+
+    if (LeftHeaderOdd || CentreHeaderOdd || RightHeaderOdd)
+    {
+      TexOutput("{\\headerr\\fi0 ");
+
+      if (headerRule)
+        TexOutput("\\brdrb\\brdrs\\brdrw15\\brsp20 ");
+
+      if (LeftHeaderOdd)
+      {
+        if (!CentreHeaderOdd && !RightHeaderOdd)
+          TexOutput("\\ql ");
+        TraverseChildrenFromChunk(LeftHeaderOdd);
+      }
+      if (CentreHeaderOdd)
+      {
+        if (!LeftHeaderOdd && !RightHeaderOdd)
+          TexOutput("\\qc ");
+        else
+          TexOutput("\\tab\\tab\\tab ");
+        TraverseChildrenFromChunk(CentreHeaderOdd);
+      }
+      if (RightHeaderOdd)
+      {
+        if (!LeftHeaderOdd && !CentreHeaderOdd)
+          TexOutput("\\qr ");
+        else
+          TexOutput("\\tab\\tab\\tab\\tab\\tab\\tab ");
+        TraverseChildrenFromChunk(RightHeaderOdd);
+      }
+      TexOutput("\\par\\pard}");
+    }
+    // As an approximation, don't put a header on the first page of a section.
+    // This may not always be desired, but it's a reasonable guess.
+    TexOutput("{\\headerf }");
+
+    forbidResetPar = oldForbidResetPar;
+  }
+}
+
+void OutputRTFFooterCommands(void)
+{
+  if (PageStyle && strcmp(PageStyle, "plain") == 0)
+  {
+    TexOutput("{\\footerl\\fi0 ");
+    if (footerRule)
+      TexOutput("\\brdrt\\brdrs\\brdrw15\\brsp20 ");
+    TexOutput("{\\qc ");
+    TexOutput("{\\field{\\*\\fldinst PAGE \\\\* MERGEFORMAT }{\\fldrslt 1}}");
+    TexOutput("}\\par\\pard}");
+
+    TexOutput("{\\footerr\\fi0 ");
+    if (footerRule)
+      TexOutput("\\brdrt\\brdrs\\brdrw15\\brsp20 ");
+    TexOutput("{\\qc ");
+    TexOutput("{\\field{\\*\\fldinst PAGE \\\\* MERGEFORMAT }{\\fldrslt 1}}");
+    TexOutput("}\\par\\pard}");
+  }
+  else if (PageStyle && strcmp(PageStyle, "empty") == 0)
+  {
+    TexOutput("{\\footerl }{\\footerr }");
+  }
+  else if (PageStyle && strcmp(PageStyle, "headings") == 0)
+  {
+    TexOutput("{\\footerl }{\\footerr }");
+  }
+  else
+  {
+    if (LeftFooterEven || CentreFooterEven || RightFooterEven)
+    {
+      TexOutput("{\\footerl\\fi0 ");
+      if (footerRule)
+        TexOutput("\\brdrt\\brdrs\\brdrw15\\brsp20 ");
+      if (LeftFooterEven)
+      {
+        if (!CentreFooterEven && !RightFooterEven)
+          TexOutput("\\ql ");
+        TraverseChildrenFromChunk(LeftFooterEven);
+      }
+      if (CentreFooterEven)
+      {
+        if (!LeftFooterEven && !RightFooterEven)
+          TexOutput("\\qc ");
+        else
+          TexOutput("\\tab\\tab\\tab ");
+        TraverseChildrenFromChunk(CentreFooterEven);
+      }
+      if (RightFooterEven)
+      {
+        if (!LeftFooterEven && !CentreFooterEven)
+          TexOutput("\\qr ");
+        else
+          TexOutput("\\tab\\tab\\tab\\tab\\tab\\tab ");
+        TraverseChildrenFromChunk(RightFooterEven);
+      }
+      TexOutput("\\par\\pard}");
+    }
+
+    if (LeftFooterOdd || CentreFooterOdd || RightFooterOdd)
+    {
+      TexOutput("{\\footerr\\fi0 ");
+      if (footerRule)
+        TexOutput("\\brdrt\\brdrs\\brdrw15\\brsp20 ");
+      if (LeftFooterOdd)
+      {
+        if (!CentreFooterOdd && !RightFooterOdd)
+          TexOutput("\\ql ");
+        TraverseChildrenFromChunk(LeftFooterOdd);
+      }
+      if (CentreFooterOdd)
+      {
+        if (!LeftFooterOdd && !RightFooterOdd)
+          TexOutput("\\qc ");
+        else
+          TexOutput("\\tab\\tab\\tab ");
+        TraverseChildrenFromChunk(CentreFooterOdd);
+      }
+      if (RightFooterOdd)
+      {
+        if (!LeftFooterOdd && !CentreFooterOdd)
+          TexOutput("\\qr ");
+        else
+          TexOutput("\\tab\\tab\\tab\\tab\\tab\\tab ");
+        TraverseChildrenFromChunk(RightFooterOdd);
+      }
+      TexOutput("\\par\\pard}");
+    }
+
+    // As an approximation, put a footer on the first page of a section.
+    // This may not always be desired, but it's a reasonable guess.
+    if (LeftFooterOdd || CentreFooterOdd || RightFooterOdd)
+    {
+      TexOutput("{\\footerf\\fi0 ");
+      if (LeftFooterOdd)
+      {
+        if (!CentreFooterOdd && !RightFooterOdd)
+          TexOutput("\\ql ");
+        TraverseChildrenFromChunk(LeftFooterOdd);
+      }
+      if (CentreFooterOdd)
+      {
+        if (!LeftFooterOdd && !RightFooterOdd)
+          TexOutput("\\qc ");
+        else
+          TexOutput("\\tab\\tab\\tab ");
+        TraverseChildrenFromChunk(CentreFooterOdd);
+      }
+      if (RightFooterOdd)
+      {
+        if (!LeftFooterOdd && !CentreFooterOdd)
+          TexOutput("\\qr ");
+        else
+          TexOutput("\\tab\\tab\\tab\\tab\\tab\\tab ");
+        TraverseChildrenFromChunk(RightFooterOdd);
+      }
+      TexOutput("\\par\\pard}");
+    }
+  }
+}
+
+// Called on start/end of macro examination
+void RTFOnMacro(int macroId, int no_args, bool start)
+{
+/*
+  char tmpBuf[40];
+  sprintf(tmpBuf, "%d (%d)", macroId, (int)start);
+  OutputDebugString("RTFOnMacro Start "); OutputDebugString(tmpBuf);
+  OutputDebugString("\n"); wxYield();
+*/
+
+  // ltLABEL is included here because after a section but BEFORE
+  // the label is seen, a new paragraph is issued. Don't upset this by
+  // immediately forgetting we've done it.
+  if (start && (macroId != ltPAR && macroId != ltITEMIZE &&
+                        macroId != ltENUMERATE && macroId != ltDESCRIPTION &&
+                        macroId != ltVERBATIM && macroId != ltLABEL &&
+                        macroId != ltSETHEADER && macroId != ltSETFOOTER &&
+                        macroId != ltPAGENUMBERING &&
+                        (forbidResetPar == 0)))
+  {
+    issuedNewParagraph = 0;
+  }
+
+  char buf[300];
+  switch (macroId)
+  {
+  case ltCHAPTER:
+  case ltCHAPTERSTAR:
+  case ltCHAPTERHEADING:
+  case ltCHAPTERHEADINGSTAR:
+  {
+    if (!start)
+    {
+      sectionNo = 0;
+      figureNo = 0;
+      tableNo = 0;
+      subsectionNo = 0;
+      subsubsectionNo = 0;
+      footnoteCount = 0;
+
+      if (macroId != ltCHAPTERSTAR && macroId != ltCHAPTERHEADINGSTAR)
+        chapterNo ++;
+
+      char *topicName = FindTopicName(GetNextChunk());
+      SetCurrentChapterName(topicName);
+
+      if (winHelpContents && winHelp && !InPopups())
+      {
+        OutputCurrentSectionToString(wxBuffer);
+        WriteWinHelpContentsFileLine(topicName, wxBuffer, 1);
+      }
+      AddTexRef(topicName, NULL, ChapterNameString, chapterNo);
+
+      if (winHelp)
+      {
+        if (!InPopups())
+          fprintf(Contents, "\n{\\uldb ");
+        fprintf(Chapters, "\\page");
+        fprintf(Chapters, "\n${\\footnote ");
+        if (!InPopups())
+          SetCurrentOutputs(Contents, Chapters);
+        else
+          SetCurrentOutput(Chapters);
+      }
+      else
+      {
+        fprintf(Chapters, "\\sect\\pgncont\\titlepg\n");
+
+        // If a non-custom page style, we generate the header now.
+        if (PageStyle && (strcmp(PageStyle, "plain") == 0 ||
+                          strcmp(PageStyle, "empty") == 0 ||
+                          strcmp(PageStyle, "headings") == 0))
+        {
+          OutputRTFHeaderCommands();
+          OutputRTFFooterCommands();
+        }
+        
+        // Need to reset the current numbering style, or RTF forgets it.
+        SetCurrentOutput(Chapters);
+        OutputNumberStyle(currentNumberStyle);
+
+        SetCurrentOutput(Contents);
+
+        if (!InPopups())
+        {
+          if (macroId == ltCHAPTER)
+          {
+            // Section
+            fprintf(Contents, "\\par\n\\pard{\\b %d\\tab ", chapterNo);
+          }
+          else if (macroId == ltCHAPTERHEADING)
+          {
+            fprintf(Contents, "\\par\n\\pard{\\b ");
+          }
+          else SetCurrentOutput(NULL); // No entry in table of contents
+        }
+      }
+  
+      startedSections = TRUE;
+
+      // Output heading to contents page
+      if (!InPopups())
+      {
+        OutputCurrentSection();
+      
+        if (winHelp)
+          fprintf(Contents, "}{\\v %s}\\par\\pard\n", topicName);
+        else if ((macroId == ltCHAPTER) || (macroId == ltCHAPTERHEADING))
+          fprintf(Contents, "}\\par\\par\\pard\n");
+
+        // From here, just output to chapter
+        SetCurrentOutput(Chapters);
+      }
+     
+      if (winHelp)
+      {
+        fprintf(Chapters, "}\n#{\\footnote %s}\n", topicName);
+        fprintf(Chapters, "+{\\footnote %s}\n", GetBrowseString());
+        
+        OutputSectionKeyword(Chapters);
+
+        GenerateKeywordsForTopic(topicName);
+        if (useUpButton)
+        {
+          // If we're generating a .cnt file, we don't want to be able
+          // jump up to the old-style contents page, so disable it.
+          if (winHelpContents)
+            fprintf(Chapters, "!{\\footnote DisableButton(\"Up\")}\n");
+          else
+            fprintf(Chapters, "!{\\footnote EnableButton(\"Up\");ChangeButtonBinding(\"Up\", \"JumpId(`%s.hlp', `%s')\")}\n",
+               FileNameFromPath(FileRoot), "Contents");
+        }
+      }
+
+      if (!InPopups())
+      {
+      char *styleCommand = "";
+      if (!winHelp && useHeadingStyles && (macroId == ltCHAPTER || macroId == ltCHAPTERHEADING || macroId == ltCHAPTERHEADINGSTAR))
+        styleCommand = "\\s1";
+      fprintf(Chapters, "\\pard{%s", ((winHelp && !InPopups()) ? "\\keepn\\sa140\\sb140" : styleCommand));
+      WriteHeadingStyle(Chapters, 1);  fprintf(Chapters, " ");
+      if (!winHelp)
+      {
+        if (macroId == ltCHAPTER)
+        {
+          if (useWord)
+//            fprintf(Chapters, "{\\bkmkstart %s}%d{\\bkmkend %s}. ", topicName, chapterNo,
+            fprintf(Chapters, "{\\bkmkstart %s}{\\bkmkend %s}", topicName, topicName);
+          else
+            fprintf(Chapters, "%d. ", chapterNo);
+        }
+        else if ( useWord )
+        {
+              fprintf(Chapters, "{\\bkmkstart %s}{\\bkmkend %s}", topicName, topicName);
+        }
+      }
+      OutputCurrentSection();
+      TexOutput("\\par\\pard}\\par\n");
+      }
+      issuedNewParagraph = 2;
+    }
+    break;
+  }
+  case ltSECTION:
+  case ltSECTIONSTAR:
+  case ltSECTIONHEADING:
+  case ltSECTIONHEADINGSTAR:
+  case ltGLOSS:
+  {
+    FILE *jumpFrom;
+    if (DocumentStyle == LATEX_ARTICLE)
+      jumpFrom = Contents;
+    else
+      jumpFrom = Chapters;
+
+    if (!start)
+    {
+      subsectionNo = 0;
+      subsubsectionNo = 0;
+      if (DocumentStyle == LATEX_ARTICLE)
+        footnoteCount = 0;
+
+      if (macroId != ltSECTIONSTAR && macroId != ltSECTIONHEADINGSTAR)
+        sectionNo ++;
+
+      char *topicName = FindTopicName(GetNextChunk());
+      SetCurrentSectionName(topicName);
+      NotifyParentHasChildren(1);
+      if (winHelpContents && winHelp && !InPopups())
+      {
+        OutputCurrentSectionToString(wxBuffer);
+        WriteWinHelpContentsFileLine(topicName, wxBuffer, 2);
+      }
+      AddTexRef(topicName, NULL, SectionNameString, chapterNo, sectionNo);
+
+      if (winHelp)
+      {
+        SetCurrentOutputs(jumpFrom, Sections);
+        // Newline for a new section if this is an article
+        if ((DocumentStyle == LATEX_ARTICLE) &&
+            ((macroId == ltSECTION) || (macroId == ltSECTIONSTAR) || (macroId == ltSECTIONHEADINGSTAR)))
+          fprintf(Sections, "\\page\n");
+
+        if (!InPopups())
+          fprintf(jumpFrom, "\n{\\uldb ");
+      }
+      else
+      {
+        if (DocumentStyle == LATEX_ARTICLE)
+        {
+          TexOutput("\\sect\\pgncont\n");
+          // If a non-custom page style, we generate the header now.
+          if (PageStyle && (strcmp(PageStyle, "plain") == 0 ||
+                            strcmp(PageStyle, "empty") == 0 ||
+                            strcmp(PageStyle, "headings") == 0))
+          {
+            OutputRTFHeaderCommands();
+            OutputRTFFooterCommands();
+          }
+        }
+        SetCurrentOutput(Contents);
+
+        if (macroId == ltSECTION)
+        {
+          if (!InPopups())
+          {
+            if (DocumentStyle == LATEX_REPORT)
+              fprintf(Contents, "\n\\pard{\\tab %d.%d\\tab ", chapterNo, sectionNo);
+            else
+              fprintf(Contents, "\\par\n\\pard{\\b %d\\tab ", sectionNo);
+          }
+        }
+        else if (macroId == ltSECTIONHEADING)
+        {
+          if (!InPopups())
+          {
+            if (DocumentStyle == LATEX_REPORT)
+              fprintf(Contents, "\n\\pard{\\tab "); //, chapterNo, sectionNo);
+            else
+              fprintf(Contents, "\\par\n\\pard{\\b "); //, sectionNo);
+          }
+        }
+        else SetCurrentOutput(NULL);
+      } 
+
+      if (startedSections)
+      {
+        if (winHelp)
+          fprintf(Sections, "\\page\n");
+      }
+      startedSections = TRUE;
+
+      if (winHelp)
+        fprintf(Sections, "\n${\\footnote ");
+
+      // Output heading to contents page
+      if (!InPopups())
+        OutputCurrentSection();
+
+      if (winHelp)
+      {
+        if (!InPopups())
+          fprintf(jumpFrom, "}{\\v %s}\\par\\pard\n", topicName);
+      }
+      else if ((macroId != ltSECTIONSTAR) && (macroId != ltGLOSS))
+      {
+        if (DocumentStyle == LATEX_REPORT)
+          fprintf(Contents, "}\\par\\pard\n");
+        else
+          fprintf(Contents, "}\\par\\par\\pard\n");
+      }
+        
+      SetCurrentOutput(winHelp ? Sections : Chapters);
+
+      if (winHelp)
+      {
+        fprintf(Sections, "}\n#{\\footnote %s}\n", topicName);
+        fprintf(Sections, "+{\\footnote %s}\n", GetBrowseString());
+        OutputSectionKeyword(Sections);
+        GenerateKeywordsForTopic(topicName);
+        if (useUpButton)
+        {
+          if (DocumentStyle == LATEX_ARTICLE)
+          {
+            fprintf(Sections, "!{\\footnote EnableButton(\"Up\");ChangeButtonBinding(\"Up\", \"JumpId(`%s.hlp', `%s')\")}\n",
+               FileNameFromPath(FileRoot), "Contents");
+          }
+          else if (CurrentChapterName)
+          {
+            fprintf(Sections, "!{\\footnote EnableButton(\"Up\");ChangeButtonBinding(\"Up\", \"JumpId(`%s.hlp', `%s')\")}\n",
+               FileNameFromPath(FileRoot), CurrentChapterName);
+          }
+        }
+      }
+
+      if (!InPopups())
+      {
+      char *styleCommand = "";
+      if (!winHelp && useHeadingStyles && (macroId != ltSECTIONSTAR))
+      {
+        if (DocumentStyle == LATEX_ARTICLE)
+          styleCommand = "\\s1";
+        else
+          styleCommand = "\\s2";
+      }
+      char *keep = "";
+      if (winHelp && (macroId != ltGLOSS) && !InPopups())
+        keep = "\\keepn\\sa140\\sb140";
+        
+      fprintf(winHelp ? Sections : Chapters, "\\pard{%s%s",
+         keep, styleCommand);
+
+      WriteHeadingStyle((winHelp ? Sections : Chapters),
+                        (DocumentStyle == LATEX_ARTICLE ? 1 : 2));
+      fprintf(winHelp ? Sections : Chapters, " ");
+
+      if (!winHelp)
+      {
+        if ((macroId != ltSECTIONSTAR) && (macroId != ltSECTIONHEADINGSTAR) && (macroId != ltGLOSS))
+        {
+          if (DocumentStyle == LATEX_REPORT)
+          {
+            if (useWord)
+//              fprintf(Chapters, "{\\bkmkstart %s}%d.%d{\\bkmkend %s}. ", topicName, chapterNo, sectionNo,
+              fprintf(Chapters, "{\\bkmkstart %s}{\\bkmkend %s}", topicName,
+                  topicName);
+            else
+              fprintf(Chapters, "%d.%d. ", chapterNo, sectionNo);
+          }
+          else
+          {
+            if (useWord)
+//              fprintf(Chapters, "{\\bkmkstart %s}%d{\\bkmkend %s}. ", topicName, sectionNo,
+              fprintf(Chapters, "{\\bkmkstart %s}{\\bkmkend %s}", topicName,
+                 topicName);
+            else
+              fprintf(Chapters, "%d. ", sectionNo);
+          }
+        }
+        else if ( useWord )
+        {
+              fprintf(Chapters, "{\\bkmkstart %s}{\\bkmkend %s}", topicName, topicName);
+        }
+      }
+      OutputCurrentSection();
+      TexOutput("\\par\\pard}\\par\n");
+      }
+      issuedNewParagraph = 2;
+    }
+    break;
+  }
+  case ltSUBSECTION:
+  case ltSUBSECTIONSTAR:
+  case ltMEMBERSECTION:
+  case ltFUNCTIONSECTION:
+  {
+    if (!start)
+    {
+      if (winHelp && !Sections)
+      {
+        OnError("You cannot have a subsection before a section!");
+      }
+      else
+      {
+      subsubsectionNo = 0;
+
+      if (macroId != ltSUBSECTIONSTAR)
+        subsectionNo ++;
+
+      char *topicName = FindTopicName(GetNextChunk());
+      SetCurrentSubsectionName(topicName);
+      NotifyParentHasChildren(2);
+      if (winHelpContents && winHelp && !InPopups())
+      {
+        OutputCurrentSectionToString(wxBuffer);
+        WriteWinHelpContentsFileLine(topicName, wxBuffer, 3);
+      }
+      AddTexRef(topicName, NULL, SectionNameString, chapterNo, sectionNo, subsectionNo);
+
+      if (winHelp)
+      {
+        SetCurrentOutputs(Sections, Subsections);
+        SetCurrentOutputs(Sections, Subsections);
+        if (!InPopups())
+          fprintf(Sections, "\n{\\uldb ");
+      }
+      else
+      {
+        if ((macroId != ltSUBSECTIONSTAR) && (macroId != ltMEMBERSECTION) &&
+            (macroId != ltFUNCTIONSECTION))
+        {
+          SetCurrentOutput(Contents);
+          if (DocumentStyle == LATEX_REPORT)
+            fprintf(Contents, "\n\\pard\\tab\\tab %d.%d.%d\\tab ", chapterNo, sectionNo, subsectionNo);
+          else
+            fprintf(Contents, "\n\\pard\\tab %d.%d\\tab ", sectionNo, subsectionNo);
+        } else SetCurrentOutput(NULL);
+      }
+      if (startedSections)
+      {
+        if (winHelp)
+        {
+          if (!InPopups())
+            fprintf(Subsections, "\\page\n");
+        }
+        else
+          fprintf(Chapters, "\\par\n");
+      }
+      startedSections = TRUE;
+
+      if (winHelp)
+        fprintf(Subsections, "\n${\\footnote ");
+
+      // Output to contents page
+      if (!InPopups())
+        OutputCurrentSection();
+
+      if (winHelp)
+      {
+        if (!InPopups())
+          fprintf(Sections, "}{\\v %s}\\par\\pard\n", topicName);
+      }
+      else if ((macroId != ltSUBSECTIONSTAR) && (macroId != ltMEMBERSECTION) &&
+         (macroId != ltFUNCTIONSECTION))
+        fprintf(Contents, "\\par\\pard\n");
+
+      SetCurrentOutput(winHelp ? Subsections : Chapters);
+      if (winHelp)
+      {
+        fprintf(Subsections, "}\n#{\\footnote %s}\n", topicName);
+        fprintf(Subsections, "+{\\footnote %s}\n", GetBrowseString());
+        OutputSectionKeyword(Subsections);
+        GenerateKeywordsForTopic(topicName);
+        if (useUpButton && CurrentSectionName)
+        {
+          fprintf(Subsections, "!{\\footnote EnableButton(\"Up\");ChangeButtonBinding(\"Up\", \"JumpId(`%s.hlp', `%s')\")}\n",
+             FileNameFromPath(FileRoot), CurrentSectionName);
+        }
+      }
+      if (!winHelp && indexSubsections && useWord)
+      {
+        // Insert index entry for this subsection
+        TexOutput("{\\xe\\v {");
+        OutputCurrentSection();
+        TexOutput("}}");
+      }
+
+      if (!InPopups())
+      {
+      char *styleCommand = "";
+      if (!winHelp && useHeadingStyles && (macroId != ltSUBSECTIONSTAR))
+      {
+        if (DocumentStyle == LATEX_ARTICLE)
+          styleCommand = "\\s2";
+        else
+          styleCommand = "\\s3";
+      }
+      char *keep = "";
+      if (winHelp && !InPopups())
+        keep = "\\keepn\\sa140\\sb140";
+
+      fprintf(winHelp ? Subsections : Chapters, "\\pard{%s%s",
+         keep, styleCommand);
+
+      WriteHeadingStyle((winHelp ? Subsections : Chapters),
+                        (DocumentStyle == LATEX_ARTICLE ? 2 : 3));
+      fprintf(winHelp ? Subsections : Chapters, " ");
+
+      if (!winHelp)
+      {
+        if ((macroId != ltSUBSECTIONSTAR) && (macroId != ltMEMBERSECTION) &&
+         (macroId != ltFUNCTIONSECTION))
+        {
+          if (DocumentStyle == LATEX_REPORT)
+          {
+            if (useWord)
+//              fprintf(Chapters, "{\\bkmkstart %s}%d.%d.%d{\\bkmkend %s}. ", topicName, chapterNo, sectionNo, subsectionNo,
+              fprintf(Chapters, "{\\bkmkstart %s}{\\bkmkend %s}", topicName,
+                       topicName);
+            else
+              fprintf(Chapters, "%d.%d.%d. ", chapterNo, sectionNo, subsectionNo);
+          }
+          else
+          {
+            if (useWord)
+//              fprintf(Chapters, "{\\bkmkstart %s}%d.%d{\\bkmkend %s}. ", topicName, sectionNo, subsectionNo,
+              fprintf(Chapters, "{\\bkmkstart %s}{\\bkmkend %s}", topicName,
+                       topicName);
+            else
+              fprintf(Chapters, "%d.%d. ", sectionNo, subsectionNo);
+          }
+        }
+        else if ( useWord )
+        {
+              fprintf(Chapters, "{\\bkmkstart %s}{\\bkmkend %s}", topicName, topicName);
+        }
+      }
+      OutputCurrentSection(); // Repeat section header
+      TexOutput("\\par\\pard}\\par\n");
+      }
+      issuedNewParagraph = 2;
+    }
+    }
+    break;
+  }
+  case ltSUBSUBSECTION:
+  case ltSUBSUBSECTIONSTAR:
+  {
+    if (!start)
+    {
+      if (winHelp && !Subsections)
+      {
+        OnError("You cannot have a subsubsection before a subsection!");
+      }
+      else
+      {
+      if (macroId != ltSUBSUBSECTIONSTAR)
+        subsubsectionNo ++;
+
+      char *topicName = FindTopicName(GetNextChunk());
+      SetCurrentTopic(topicName);
+      NotifyParentHasChildren(3);
+      if (winHelpContents && winHelp)
+      {
+        OutputCurrentSectionToString(wxBuffer);
+        WriteWinHelpContentsFileLine(topicName, wxBuffer, 4);
+      }
+      AddTexRef(topicName, NULL, SectionNameString, chapterNo, sectionNo, subsectionNo, subsubsectionNo);
+
+      if (winHelp)
+      {
+        SetCurrentOutputs(Subsections, Subsubsections);
+        fprintf(Subsections, "\n{\\uldb ");
+      }
+      else
+      {
+        if (macroId != ltSUBSUBSECTIONSTAR)
+        {
+          if (DocumentStyle == LATEX_ARTICLE)
+          {
+            SetCurrentOutput(Contents);
+            fprintf(Contents, "\n\\tab\\tab %d.%d.%d\\tab ",
+                               sectionNo, subsectionNo, subsubsectionNo);
+          }
+          else
+            SetCurrentOutput(NULL); // Don't write it into the contents, or anywhere else
+       }
+        else
+          SetCurrentOutput(NULL); // Don't write it into the contents, or anywhere else
+      }
+      
+      if (startedSections)
+      {
+        if (winHelp)
+          fprintf(Subsubsections, "\\page\n");
+        else
+          fprintf(Chapters, "\\par\n");
+      }
+
+      startedSections = TRUE;
+
+      if (winHelp)
+        fprintf(Subsubsections, "\n${\\footnote ");
+
+      // Output header to contents page
+      OutputCurrentSection();
+
+      if (winHelp)
+        fprintf(Subsections, "}{\\v %s}\\par\\pard\n", topicName);
+      else if ((DocumentStyle == LATEX_ARTICLE) && (macroId != ltSUBSUBSECTIONSTAR))
+        fprintf(Contents, "\\par\\pard\n");
+        
+      SetCurrentOutput(winHelp ? Subsubsections : Chapters);
+      if (winHelp)
+      {
+        fprintf(Subsubsections, "}\n#{\\footnote %s}\n", topicName);
+        fprintf(Subsubsections, "+{\\footnote %s}\n", GetBrowseString());
+        OutputSectionKeyword(Subsubsections);
+        GenerateKeywordsForTopic(topicName);
+        if (useUpButton && CurrentSubsectionName)
+        {
+          fprintf(Subsubsections, "!{\\footnote EnableButton(\"Up\");ChangeButtonBinding(\"Up\", \"JumpId(`%s.hlp', `%s')\")}\n",
+             FileNameFromPath(FileRoot), CurrentSubsectionName);
+        }
+      }
+      if (!winHelp && indexSubsections && useWord)
+      {
+        // Insert index entry for this subsubsection
+        TexOutput("{\\xe\\v {");
+        OutputCurrentSection();
+        TexOutput("}}");
+      }
+
+      char *styleCommand = "";
+      if (!winHelp && useHeadingStyles && (macroId != ltSUBSUBSECTIONSTAR))
+      {
+        if (DocumentStyle == LATEX_ARTICLE)
+          styleCommand = "\\s3";
+        else
+          styleCommand = "\\s4";
+      }
+      char *keep = "";
+      if (winHelp)
+        keep = "\\keepn\\sa140\\sb140";
+
+      fprintf(winHelp ? Subsubsections : Chapters, "\\pard{%s%s",
+         keep, styleCommand);
+
+      WriteHeadingStyle((winHelp ? Subsubsections : Chapters),
+                        (DocumentStyle == LATEX_ARTICLE ? 3 : 4));
+      fprintf(winHelp ? Subsubsections : Chapters, " ");
+         
+      if (!winHelp)
+      {
+        if ((macroId != ltSUBSUBSECTIONSTAR))
+        {
+          if (DocumentStyle == LATEX_ARTICLE)
+          {
+            if (useWord)
+//              fprintf(Chapters, "{\\bkmkstart %s}%d.%d.%d{\\bkmkend %s}. ", topicName, sectionNo, subsectionNo, subsubsectionNo,
+              fprintf(Chapters, "{\\bkmkstart %s}{\\bkmkend %s}", topicName,
+                     topicName);
+            else
+              fprintf(Chapters, "%d.%d.%d. ", sectionNo, subsectionNo, subsubsectionNo);
+          }
+          else
+          {
+            if (useWord)
+//              fprintf(Chapters, "{\\bkmkstart %s}%d.%d.%d.%d{\\bkmkend %s}. ", topicName, chapterNo, sectionNo, subsectionNo, subsubsectionNo,
+              fprintf(Chapters, "{\\bkmkstart %s}{\\bkmkend %s}", topicName,
+                      topicName);
+            else
+              fprintf(Chapters, "%d.%d.%d.%d. ", chapterNo, sectionNo, subsectionNo, subsubsectionNo);
+          }
+        }
+        else if ( useWord )
+        {
+              fprintf(Chapters, "{\\bkmkstart %s}{\\bkmkend %s}", topicName, topicName);
+        }
+      }
+      OutputCurrentSection(); // Repeat section header
+      TexOutput("\\par\\pard}\\par\n");
+      issuedNewParagraph = 2;
+//      if (winHelp) TexOutput("\\pard");
+    }
+    }
+    break;
+  }
+  case ltCAPTION:
+  case ltCAPTIONSTAR:
+  {
+    if (!start)
+    {
+      char *topicName = FindTopicName(GetNextChunk());
+      SetCurrentTopic(topicName);
+
+      TexOutput("\\pard\\par");
+      char figBuf[200];
+
+      if (inFigure)
+      {
+        figureNo ++;
+
+        if (winHelp || !useWord)
+        {
+          if (DocumentStyle != LATEX_ARTICLE)
+            sprintf(figBuf, "%s %d.%d: ", FigureNameString, chapterNo, figureNo);
+          else
+            sprintf(figBuf, "%s %d: ", FigureNameString, figureNo);
+        }
+        else
+        {
+          sprintf(figBuf, "%s {\\field\\flddirty{\\*\\fldinst  SEQ Figure \\\\* ARABIC }{\\fldrslt {\\bkmkstart %s}??{\\bkmkend %s}}}: ",
+               FigureNameString, topicName, topicName);
+        }
+      }
+      else
+      {
+        tableNo ++;
+
+        if (winHelp || !useWord)
+        {
+          if (DocumentStyle != LATEX_ARTICLE)
+            sprintf(figBuf, "%s %d.%d: ", TableNameString, chapterNo, tableNo);
+          else
+            sprintf(figBuf, "%s %d: ", TableNameString, tableNo);
+        }
+        else
+        {
+          sprintf(figBuf, "%s {\\field\\flddirty{\\*\\fldinst  SEQ Table \\\\* ARABIC }{\\fldrslt {\\bkmkstart %s}??{\\bkmkend %s}}}: ",
+               TableNameString, topicName, topicName);
+        }
+      }
+
+      int n = (inTable ? tableNo : figureNo);
+      AddTexRef(topicName, NULL, NULL,
+           ((DocumentStyle != LATEX_ARTICLE) ? chapterNo : n),
+            ((DocumentStyle != LATEX_ARTICLE) ? n : 0));
+
+      if (winHelp)
+        TexOutput("\\qc{\\b ");
+      else
+        TexOutput("\\ql{\\b ");
+      TexOutput(figBuf);
+
+      OutputCurrentSection();
+
+      TexOutput("}\\par\\pard\n");
+      WriteEnvironmentStyles();
+    }
+    break;
+  }
+  case ltFUNC:
+  case ltPFUNC:
+  {
+//    SetCurrentOutput(winHelp ? Subsections : Chapters);
+    if (start)
+    {
+      TexOutput("{");
+    }
+    else
+    {
+      TexOutput("}\n");
+      if (winHelp)
+      {
+        TexOutput("K{\\footnote {K} ");
+        suppressNameDecoration = TRUE;
+        TraverseChildrenFromChunk(currentMember);
+        suppressNameDecoration = FALSE;
+        TexOutput("}\n");
+      }
+      if (!winHelp && useWord)
+      {
+        // Insert index entry for this function
+        TexOutput("{\\xe\\v {");
+        suppressNameDecoration = TRUE;  // Necessary so don't print "(\\bf" etc.
+        TraverseChildrenFromChunk(currentMember);
+        suppressNameDecoration = FALSE;
+        TexOutput("}}");
+      }
+    }
+    break;
+  }
+  case ltCLIPSFUNC:
+  {
+//    SetCurrentOutput(winHelp ? Subsections : Chapters);
+    if (start)
+    {
+      TexOutput("{");
+    }
+    else
+    {
+      TexOutput("}\n");
+      if (winHelp)
+      {
+        TexOutput("K{\\footnote {K} ");
+        suppressNameDecoration = TRUE;  // Necessary so don't print "(\\bf" etc.
+        TraverseChildrenFromChunk(currentMember);
+        suppressNameDecoration = FALSE;
+        TexOutput("}\n");
+      }
+      if (!winHelp && useWord)
+      {
+        // Insert index entry for this function
+        TexOutput("{\\xe\\v {");
+        suppressNameDecoration = TRUE;  // Necessary so don't print "(\\bf" etc.
+        TraverseChildrenFromChunk(currentMember);
+        suppressNameDecoration = FALSE;
+        TexOutput("}}");
+      }
+    }
+    break;
+  }
+  case ltMEMBER:
+  {
+//    SetCurrentOutput(winHelp ? Subsections : Chapters);
+    if (start)
+    {
+      TexOutput("{\\b ");
+    }
+    else
+    {
+      TexOutput("}\n");
+      if (winHelp)
+      {
+        TexOutput("K{\\footnote {K} ");
+        TraverseChildrenFromChunk(currentMember);
+        TexOutput("}\n");
+      }
+      if (!winHelp && useWord)
+      {
+        // Insert index entry for this function
+        TexOutput("{\\xe\\v {");
+        suppressNameDecoration = TRUE;  // Necessary so don't print "(\\bf" etc.
+        TraverseChildrenFromChunk(currentMember);
+        suppressNameDecoration = FALSE;
+        TexOutput("}}");
+      }
+    }
+    break;
+  }
+  case ltDOCUMENT:
+  {
+    if (start)
+      SetCurrentOutput(Chapters);
+    break;
+  }
+  case ltTABLEOFCONTENTS:
+  {
+    if (start)
+    {
+      if (!winHelp && useWord)
+      {
+        // Insert Word for Windows table of contents
+        TexOutput("\\par\\pard\\pgnrestart\\sect\\titlepg");
+
+       // In linear RTF, same as chapter headings.
+        sprintf(buf, "{\\b\\fs%d %s}\\par\\par\\pard\n\n", chapterFont*2, ContentsNameString);
+
+        TexOutput(buf);
+        sprintf(buf, "{\\field{\\*\\fldinst TOC \\\\o \"1-%d\" }{\\fldrslt PRESS F9 TO REFORMAT CONTENTS}}\n", contentsDepth);
+        TexOutput(buf);
+//        TexOutput("\\sect\\sectd");
+      }
+      else
+      {
+        FILE *fd = fopen(ContentsName, "r");
+        if (fd)
+        {
+          int ch = getc(fd);
+          while (ch != EOF)
+          {
+            putc(ch, Chapters);
+            ch = getc(fd);
+          }
+          fclose(fd);
+        }
+        else
+        {
+          TexOutput("{\\i RUN TEX2RTF AGAIN FOR CONTENTS PAGE}\\par\n");
+          OnInform("Run Tex2RTF again to include contents page.");
+        }
+      }
+    }
+    break;
+  }
+  case ltVOID:
+  {
+//    if (start)
+//      TexOutput("{\\b void}");
+    break;
+  }
+  case ltHARDY:
+  {
+    if (start)
+      TexOutput("{\\scaps HARDY}");
+    break;
+  }
+  case ltWXCLIPS:
+  {
+    if (start)
+      TexOutput("wxCLIPS");
+    break;
+  }
+  case ltSPECIALAMPERSAND:
+  {
+    if (start)
+    {
+      if (inTabular)
+        TexOutput("\\cell ");
+      else
+        TexOutput("&");
+    }
+    break;
+  }
+  case ltSPECIALTILDE:
+  {
+    if (start)
+    {
+      if (inVerbatim)
+        TexOutput("~");
+      else
+        TexOutput(" ");
+    }
+    break;
+  }
+  case ltBACKSLASHCHAR:
+  {
+    if (start)
+    {
+      if (inTabular)
+      {
+//        TexOutput("\\cell\\row\\trowd\\trgaph108\\trleft-108\n");
+        TexOutput("\\cell\\row\\trowd\\trgaph108\n");
+        int currentWidth = 0;
+        for (int i = 0; i < noColumns; i++)
+        {
+          currentWidth += TableData[i].width;
+          if (TableData[i].rightBorder)
+            TexOutput("\\clbrdrr\\brdrs\\brdrw15");
+
+          if (TableData[i].leftBorder)
+            TexOutput("\\clbrdrl\\brdrs\\brdrw15");
+          
+          sprintf(buf, "\\cellx%d", currentWidth);
+          TexOutput(buf);
+        }
+        TexOutput("\\pard\\intbl\n");
+      }
+      else
+        TexOutput("\\line\n");
+    }
+    break;
+  }
+  case ltRANGLEBRA:
+  {
+    if (start)
+      TexOutput("\tab ");
+    break;
+  }
+  case ltRTFSP:  // Explicit space, RTF only
+  {
+    if (start)
+      TexOutput(" ");
+   break;
+  }
+  case ltITEMIZE:
+  case ltENUMERATE:
+  case ltDESCRIPTION:
+  {
+    if (start)
+    {
+      if (indentLevel > 0)
+      {
+        TexOutput("\\par\\par\n");
+        issuedNewParagraph = 2;
+      }
+      else
+      {
+        // Top-level list: issue a new paragraph if we haven't
+        // just done so
+        if (!issuedNewParagraph)
+        {
+          TexOutput("\\par\\pard");
+          WriteEnvironmentStyles();
+          issuedNewParagraph = 1;
+        }
+        else issuedNewParagraph = 0;
+      }
+      indentLevel ++;
+      TexOutput("\\fi0\n");
+      int listType;
+      if (macroId == ltENUMERATE)
+        listType = LATEX_ENUMERATE;
+      else if (macroId == ltITEMIZE)
+        listType = LATEX_ITEMIZE;
+      else
+        listType = LATEX_DESCRIPTION;
+
+      int oldIndent = 0;
+      wxNode *node = itemizeStack.First();
+      if (node)
+        oldIndent = ((ItemizeStruc *)node->Data())->indentation;
+
+      int indentSize1 = oldIndent + 20*labelIndentTab;
+      int indentSize2 = oldIndent + 20*itemIndentTab;
+
+      ItemizeStruc *struc = new ItemizeStruc(listType, indentSize2, indentSize1);
+      itemizeStack.Insert(struc);
+      
+      sprintf(buf, "\\tx%d\\tx%d\\li%d", indentSize1, indentSize2, indentSize2);
+      PushEnvironmentStyle(buf);
+    }
+    else
+    {
+      currentItemSep = 8; // Reset to the default
+      indentLevel --;
+      PopEnvironmentStyle();
+
+      if (itemizeStack.First())
+      {
+        ItemizeStruc *struc = (ItemizeStruc *)itemizeStack.First()->Data();
+        delete struc;
+        delete itemizeStack.First();
+      }
+/* Change 18/7/97 - don't know why we wish to do this
+      if (itemizeStack.Number() == 0)
+      {
+        OnMacro(ltPAR, 0, TRUE);
+        OnMacro(ltPAR, 0, FALSE);
+        issuedNewParagraph = 2;
+      }
+*/
+    }
+    break;
+  }
+  case ltTWOCOLLIST:
+  {
+    if (start)
+    {
+      indentLevel ++;
+      int oldIndent = 0;
+      wxNode *node = itemizeStack.First();
+      if (node)
+        oldIndent = ((ItemizeStruc *)node->Data())->indentation;
+
+      int indentSize = oldIndent + TwoColWidthA;
+
+      ItemizeStruc *struc = new ItemizeStruc(LATEX_TWOCOL, indentSize);
+      itemizeStack.Insert(struc);
+      
+//      sprintf(buf, "\\tx%d\\li%d\\ri%d", indentSize, indentSize, TwoColWidthA+TwoColWidthB+oldIndent);
+      sprintf(buf, "\\tx%d\\li%d", indentSize, indentSize);
+      PushEnvironmentStyle(buf);
+    }
+    else
+    {
+      indentLevel --;
+      PopEnvironmentStyle();
+      if (itemizeStack.First())
+      {
+        ItemizeStruc *struc = (ItemizeStruc *)itemizeStack.First()->Data();
+        delete struc;
+        delete itemizeStack.First();
+      }
+/*
+      // JACS June 1997
+      TexOutput("\\pard\n");
+      WriteEnvironmentStyles();
+*/
+/* why do we need this? */
+      if (itemizeStack.Number() == 0)
+      {
+        issuedNewParagraph = 0;
+        OnMacro(ltPAR, 0, TRUE);
+        OnMacro(ltPAR, 0, FALSE);
+      }
+    }
+    break;
+  }
+  case ltITEM:
+  {
+    wxNode *node = itemizeStack.First();
+    if (node)
+    {
+      ItemizeStruc *struc = (ItemizeStruc *)node->Data();
+      if (!start)
+      {
+        struc->currentItem += 1;
+        char indentBuf[60];
+
+        int indentSize1 = struc->labelIndentation;
+        int indentSize2 = struc->indentation;
+
+        TexOutput("\n");
+        if (struc->currentItem > 1)
+        {
+          if (currentItemSep > 0)
+            TexOutput("\\par");
+
+          TexOutput("\\par");
+//          WriteEnvironmentStyles();
+        }
+
+        sprintf(buf, "\\tx%d\\tx%d\\li%d\\fi-%d\n", indentSize1, indentSize2,
+                  indentSize2, 20*itemIndentTab);
+        TexOutput(buf);
+
+        switch (struc->listType)
+        {
+          case LATEX_ENUMERATE:
+          {
+            if (descriptionItemArg)
+            {
+              TexOutput("\\tab{ ");
+              TraverseChildrenFromChunk(descriptionItemArg);
+              TexOutput("}\\tab");
+              descriptionItemArg = NULL;
+           }
+           else
+           {
+              sprintf(indentBuf, "\\tab{\\b %d.}\\tab", struc->currentItem);
+              TexOutput(indentBuf);
+            }
+            break;
+          }
+          case LATEX_ITEMIZE:
+          {
+            if (descriptionItemArg)
+            {
+              TexOutput("\\tab{ ");
+              TraverseChildrenFromChunk(descriptionItemArg);
+              TexOutput("}\\tab");
+              descriptionItemArg = NULL;
+           }
+           else
+           {
+              if (bulletFile && winHelp)
+              {
+                if (winHelpVersion > 3) // Transparent bitmap
+                  sprintf(indentBuf, "\\tab\\{bmct %s\\}\\tab", bulletFile);
+                else
+                  sprintf(indentBuf, "\\tab\\{bmc %s\\}\\tab", bulletFile);
+              }
+              else if (winHelp)
+                sprintf(indentBuf, "\\tab{\\b o}\\tab");
+              else
+                sprintf(indentBuf, "\\tab{\\f1\\'b7}\\tab");
+              TexOutput(indentBuf);
+            }
+            break;
+          }
+          default:
+          case LATEX_DESCRIPTION:
+          {
+            if (descriptionItemArg)
+            {
+              TexOutput("\\tab{\\b ");
+              TraverseChildrenFromChunk(descriptionItemArg);
+              TexOutput("}  ");
+              descriptionItemArg = NULL;
+            }
+            break;
+          }
+       }
+      }
+    }
+    break;
+  }
+  case ltTWOCOLITEM:
+  case ltTWOCOLITEMRULED:
+  {
+    wxNode *node = itemizeStack.First();
+    if (node)
+    {
+      ItemizeStruc *struc = (ItemizeStruc *)node->Data();
+      if (start)
+      {
+        struc->currentItem += 1;
+
+        int indentSize = struc->indentation;
+        int oldIndent = 0;
+        wxNode *node2 = NULL;
+        if (itemizeStack.Number() > 1) // TODO: do I actually mean Nth(0) here??
+            node2 = itemizeStack.Nth(1);
+        if (node2)
+          oldIndent = ((ItemizeStruc *)node2->Data())->indentation;
+
+        TexOutput("\n");
+        if (struc->currentItem > 1)
+        {
+          if (currentItemSep > 0)
+            TexOutput("\\par");
+
+//          WriteEnvironmentStyles();
+        }
+
+//        sprintf(buf, "\\tx%d\\li%d\\fi-%d\\ri%d\n", TwoColWidthA,
+//             TwoColWidthA, TwoColWidthA, TwoColWidthA+TwoColWidthB+oldIndent);
+/*
+        sprintf(buf, "\\tx%d\\li%d\\fi-%d\n", TwoColWidthA,
+             TwoColWidthA, TwoColWidthA);
+*/
+        sprintf(buf, "\\tx%d\\li%d\\fi-%d\n", TwoColWidthA + oldIndent,
+             TwoColWidthA + oldIndent, TwoColWidthA);
+        TexOutput(buf);
+      }
+    }
+    break;
+  }
+  case ltVERBATIM:
+  case ltVERB:
+  {
+    if (start)
+    {
+      if (macroId == ltVERBATIM)
+      {
+        if (!issuedNewParagraph)
+        {
+          TexOutput("\\par\\pard");
+          WriteEnvironmentStyles();
+          issuedNewParagraph = 1;
+        }
+        else issuedNewParagraph = 0;
+      }
+      sprintf(buf, "{\\f3\\fs20 ");
+      TexOutput(buf);
+    }
+    else
+    {
+      TexOutput("}");
+      if (macroId == ltVERBATIM)
+      {
+        TexOutput("\\pard\n");
+//        issuedNewParagraph = 1;
+        WriteEnvironmentStyles();
+      }
+    }
+    break;
+  }
+  case ltCENTERLINE:
+  case ltCENTER:
+  {
+    if (start)
+    {
+      TexOutput("\\fi0\\qc ");
+      forbidParindent ++;
+      PushEnvironmentStyle("\\qc");
+    }
+    else
+    {
+      TexOutput("\\par\\pard\n");
+      issuedNewParagraph = 1;
+      forbidParindent --;
+      PopEnvironmentStyle();
+      WriteEnvironmentStyles();
+    }
+    break;
+  }
+  case ltFLUSHLEFT:
+  {
+    if (start)
+    {
+      TexOutput("\\fi0\\ql ");
+      forbidParindent ++;
+      PushEnvironmentStyle("\\ql");
+    }
+    else
+    {
+      TexOutput("\\par\\pard\n");
+      issuedNewParagraph = 1;
+      forbidParindent --;
+      PopEnvironmentStyle();
+      WriteEnvironmentStyles();
+    }
+    break;
+  }
+  case ltFLUSHRIGHT:
+  {
+    if (start)
+    {
+      TexOutput("\\fi0\\qr ");
+      forbidParindent ++;
+      PushEnvironmentStyle("\\qr");
+    }
+    else
+    {
+      TexOutput("\\par\\pard\n");
+      issuedNewParagraph = 1;
+      forbidParindent --;
+      PopEnvironmentStyle();
+      WriteEnvironmentStyles();
+    }
+    break;
+  }
+  case ltSMALL:
+  case ltFOOTNOTESIZE:
+  {
+    if (start)
+    {
+      sprintf(buf, "{\\fs%d\n", smallFont*2);
+      TexOutput(buf);
+    }
+    else TexOutput("}\n");
+    break;
+  }
+  case ltTINY:
+  case ltSCRIPTSIZE:
+  {
+    if (start)
+    {
+      sprintf(buf, "{\\fs%d\n", tinyFont*2);
+      TexOutput(buf);
+    }
+    else TexOutput("}\n");
+    break;
+  }
+  case ltNORMALSIZE:
+  {
+    if (start)
+    {
+      sprintf(buf, "{\\fs%d\n", normalFont*2);
+      TexOutput(buf);
+    }
+    else TexOutput("}\n");
+    break;
+  }
+  case ltlarge:
+  {
+    if (start)
+    {
+      sprintf(buf, "{\\fs%d\n", largeFont1*2);
+      TexOutput(buf);
+    }
+    else TexOutput("}\n");
+    break;
+  }
+  case ltLarge:
+  {
+    if (start)
+    {
+      sprintf(buf, "{\\fs%d\n", LargeFont2*2);
+      TexOutput(buf);
+    }
+    else TexOutput("}\n");
+    break;
+  }
+  case ltLARGE:
+  {
+    if (start)
+    {
+      sprintf(buf, "{\\fs%d\n", LARGEFont3*2);
+      TexOutput(buf);
+    }
+    else TexOutput("}\n");
+    break;
+  }
+  case lthuge:
+  {
+    if (start)
+    {
+      sprintf(buf, "{\\fs%d\n", hugeFont1*2);
+      TexOutput(buf);
+    }
+    else TexOutput("}\n");
+    break;
+  }
+  case ltHuge:
+  {
+    if (start)
+    {
+      sprintf(buf, "{\\fs%d\n", HugeFont2*2);
+      TexOutput(buf);
+    }
+    else TexOutput("}\n");
+    break;
+  }
+  case ltHUGE:
+  {
+    if (start)
+    {
+      sprintf(buf, "{\\fs%d\n", HUGEFont3*2);
+      TexOutput(buf);
+    }
+    else TexOutput("}\n");
+    break;
+  }
+  case ltTEXTBF:
+  case ltBFSERIES:
+  case ltBF:
+  {
+    if (start)
+    {
+      TexOutput("{\\b ");
+    }
+    else TexOutput("}");
+    break;
+  }
+  case ltUNDERLINE:
+  {
+    if (start)
+    {
+      TexOutput("{\\ul ");
+    }
+    else TexOutput("}");
+    break;
+  }
+  case ltTEXTIT:
+  case ltITSHAPE:
+  case ltIT:
+  case ltEMPH:
+  case ltEM:
+  {
+    if (start)
+    {
+      TexOutput("{\\i ");
+    }
+    else TexOutput("}");
+    break;
+  }
+  // Roman font: do nothing. Should really switch between
+  // fonts.
+  case ltTEXTRM:
+  case ltRMFAMILY:
+  case ltRM:
+  {
+/*    
+    if (start)
+    {
+      TexOutput("{\\plain ");
+    }
+    else TexOutput("}");
+ */
+    break;
+  }
+  // Medium-weight font. Unbolden...
+  case ltMDSERIES:
+  {
+    if (start)
+    {
+      TexOutput("{\\b0 ");
+    }
+    else TexOutput("}");
+    break;
+  }
+  // Upright (un-italic or slant)
+  case ltUPSHAPE:
+  {
+    if (start)
+    {
+      TexOutput("{\\i0 ");
+    }
+    else TexOutput("}");
+    break;
+  }
+  case ltTEXTSC:
+  case ltSCSHAPE:
+  case ltSC:
+  {
+    if (start)
+    {
+      TexOutput("{\\scaps ");
+    }
+    else TexOutput("}");
+    break;
+  }
+  case ltTEXTTT:
+  case ltTTFAMILY:
+  case ltTT:
+  {
+    if (start)
+    {
+      TexOutput("{\\f3 ");
+    }
+    else TexOutput("}");
+    break;
+  }
+  case ltLBRACE:
+  {
+    if (start)
+      TexOutput("\\{");
+    break;
+  }
+  case ltRBRACE:
+  {
+    if (start)
+      TexOutput("\\}");
+    break;
+  }
+  case ltBACKSLASH:
+  {
+    if (start)
+      TexOutput("\\\\");
+    break;
+  }
+  case ltPAR:
+  {
+    if (start)
+    {
+               if ( issuedNewParagraph == 0 )
+               {
+          TexOutput("\\par\\pard");
+          issuedNewParagraph ++;
+
+          // Extra par if parskip is more than zero (usually looks best.)
+          if (!inTabular && (ParSkip > 0))
+                 {
+            TexOutput("\\par");
+            issuedNewParagraph ++;
+                 }
+          WriteEnvironmentStyles();
+               }
+               // 1 is a whole paragraph if ParSkip == 0,
+               // half a paragraph if ParSkip > 0
+               else if ( issuedNewParagraph == 1 )
+               {
+                 // Don't need a par at all if we've already had one,
+                 // and ParSkip == 0.
+
+          // Extra par if parskip is more than zero (usually looks best.)
+          if (!inTabular && (ParSkip > 0))
+                 {
+            TexOutput("\\par");
+            issuedNewParagraph ++;
+                 }
+          WriteEnvironmentStyles();
+               }
+/*
+      if (!issuedNewParagraph || (issuedNewParagraph > 1))
+      {
+        TexOutput("\\par\\pard");
+
+        // Extra par if parskip is more than zero (usually looks best.)
+        if (!inTabular && (ParSkip > 0))
+          TexOutput("\\par");
+        WriteEnvironmentStyles();
+      }
+*/
+
+      TexOutput("\n");
+    }
+    break;
+  }
+  case ltNEWPAGE:
+  {
+    // In Windows Help, no newpages until we've started some chapters or sections
+    if (!(winHelp && !startedSections))
+      if (start)
+        TexOutput("\\page\n");
+    break;
+  }
+  case ltMAKETITLE:
+  {
+    if (start && DocumentTitle)
+    {
+      TexOutput("\\par\\pard");
+      if (!winHelp)
+        TexOutput("\\par");
+      sprintf(buf, "\\qc{\\fs%d\\b ", titleFont*2);
+      TexOutput(buf);
+      TraverseChildrenFromChunk(DocumentTitle);
+      TexOutput("}\\par\\pard\n");
+
+      if (DocumentAuthor)
+      {
+        if (!winHelp)
+          TexOutput("\\par");
+        sprintf(buf, "\\par\\qc{\\fs%d ", authorFont*2);
+        TexOutput(buf);
+        TraverseChildrenFromChunk(DocumentAuthor);
+        TexOutput("}");
+        TexOutput("\\par\\pard\n");
+      }
+      if (DocumentDate)
+      {
+        TexOutput("\\par");
+        sprintf(buf, "\\qc{\\fs%d ", authorFont*2);
+        TexOutput(buf);
+        TraverseChildrenFromChunk(DocumentDate);
+        TexOutput("}\\par\\pard\n");
+      }
+      // If linear RTF, we want this titlepage to be in a separate
+      // section with its own (blank) header and footer
+      if (!winHelp && (DocumentStyle != LATEX_ARTICLE))
+      {
+        TexOutput("{\\header }{\\footer }\n");
+        // Not sure about this: we get too many sections.
+//        TexOutput("\\sect");
+      }
+    }
+    break;
+  }
+  case ltADDCONTENTSLINE:
+  {
+    if (!start)
+    {
+    if (contentsLineSection && contentsLineValue)
+    {
+      if (strcmp(contentsLineSection, "chapter") == 0)
+      {
+        fprintf(Contents, "\\par\n{\\b %s}\\par\n", contentsLineValue);
+      }
+      else if (strcmp(contentsLineSection, "section") == 0)
+      {
+        if (DocumentStyle != LATEX_ARTICLE)
+          fprintf(Contents, "\n\\tab%s\\par\n", contentsLineValue);
+        else
+          fprintf(Contents, "\\par\n{\\b %s}\\par\n", contentsLineValue);
+      }
+    }
+    }
+    break;
+  }
+  case ltHRULE:
+  {
+    if (start)
+    {
+      TexOutput("\\brdrb\\brdrs\\par\\pard\n");
+      issuedNewParagraph = 1;
+      WriteEnvironmentStyles();
+    }
+    break;
+  }
+  case ltRULE:
+  {
+    if (start)
+    {
+      TexOutput("\\brdrb\\brdrs\\par\\pard\n");
+      issuedNewParagraph = 1;
+      WriteEnvironmentStyles();
+    }
+    break;
+  }
+  case ltHLINE:
+  {
+    if (start)
+      ruleTop ++;
+    break;
+  }
+  case ltNUMBEREDBIBITEM:
+  {
+    if (start)
+      TexOutput("\\li260\\fi-260 "); // Indent from 2nd line
+    else
+      TexOutput("\\par\\pard\\par\n\n");
+    break;
+  }
+  case ltTHEPAGE:
+  {
+    if (start)
+    {
+      TexOutput("{\\field{\\*\\fldinst PAGE \\\\* MERGEFORMAT }{\\fldrslt 1}}");
+    }
+    break;
+  }
+  case ltTHECHAPTER:
+  {
+    if (start)
+    {
+//      TexOutput("{\\field{\\*\\fldinst SECTION \\\\* MERGEFORMAT }{\\fldrslt 1}}");
+      sprintf(buf, "%d", chapterNo);
+      TexOutput(buf);
+    }
+    break;
+  }
+  case ltTHESECTION:
+  {
+    if (start)
+    {
+//      TexOutput("{\\field{\\*\\fldinst SECTION \\\\* MERGEFORMAT }{\\fldrslt 1}}");
+      sprintf(buf, "%d", sectionNo);
+      TexOutput(buf);
+    }
+    break;
+  }
+  case ltTWOCOLUMN:
+  {
+    if (!start && !winHelp)
+    {
+      TexOutput("\\cols2\n");
+    }
+    break;
+  }
+  case ltONECOLUMN:
+  {
+    if (!start && !winHelp)
+    {
+      TexOutput("\\cols1\n");
+    }
+    break;
+  }
+  case ltPRINTINDEX:
+  {
+    if (start && useWord && !winHelp)
+    {
+      FakeCurrentSection("Index");
+      OnMacro(ltPAR, 0, TRUE);
+      OnMacro(ltPAR, 0, FALSE);
+      TexOutput("\\par{\\field{\\*\\fldinst INDEX \\\\h \"\\emdash A\\emdash \"\\\\c \"2\"}{\\fldrslt PRESS F9 TO REFORMAT INDEX}}\n");
+    }
+    break;
+  }
+  case ltLISTOFFIGURES:
+  {
+    if (start && useWord && !winHelp)
+    {
+      FakeCurrentSection(FiguresNameString, FALSE);
+      OnMacro(ltPAR, 0, TRUE);
+      OnMacro(ltPAR, 0, FALSE);
+      OnMacro(ltPAR, 0, TRUE);
+      OnMacro(ltPAR, 0, FALSE);
+      char buf[200];
+      sprintf(buf, "{\\field\\fldedit{\\*\\fldinst  TOC \\\\c \"%s\" }{\\fldrslt PRESS F9 TO REFORMAT LIST OF FIGURES}}\n",
+               FigureNameString);
+      TexOutput(buf);
+    }
+    break;
+  }
+  case ltLISTOFTABLES:
+  {
+    if (start && useWord && !winHelp)
+    {
+      FakeCurrentSection(TablesNameString, FALSE);
+      OnMacro(ltPAR, 0, TRUE);
+      OnMacro(ltPAR, 0, FALSE);
+      OnMacro(ltPAR, 0, TRUE);
+      OnMacro(ltPAR, 0, FALSE);
+      char buf[200];
+      sprintf(buf, "{\\field\\fldedit{\\*\\fldinst  TOC \\\\c \"%s\" }{\\fldrslt PRESS F9 TO REFORMAT LIST OF TABLES}}\n",
+                TablesNameString);
+      TexOutput(buf);
+    }
+    break;
+  }
+  // Symbols
+  case ltALPHA:
+    if (start) TexOutput("{\\f1\\'61}");
+    break;
+  case ltBETA:
+    if (start) TexOutput("{\\f1\\'62}");
+    break;
+  case ltGAMMA:
+    if (start) TexOutput("{\\f1\\'63}");
+    break;
+  case ltDELTA:
+    if (start) TexOutput("{\\f1\\'64}");
+    break;
+  case ltEPSILON:
+  case ltVAREPSILON:
+    if (start) TexOutput("{\\f1\\'65}");
+    break;
+  case ltZETA:
+    if (start) TexOutput("{\\f1\\'7A}");
+    break;
+  case ltETA:
+    if (start) TexOutput("{\\f1\\'68}");
+    break;
+  case ltTHETA:
+  case ltVARTHETA:
+    if (start) TexOutput("{\\f1\\'71}");
+    break;
+  case ltIOTA:
+    if (start) TexOutput("{\\f1\\'69}");
+    break;
+  case ltKAPPA:
+    if (start) TexOutput("{\\f1\\'6B}");
+    break;
+  case ltLAMBDA:
+    if (start) TexOutput("{\\f1\\'6C}");
+    break;
+  case ltMU:
+    if (start) TexOutput("{\\f1\\'6D}");
+    break;
+  case ltNU:
+    if (start) TexOutput("{\\f1\\'6E}");
+    break;
+  case ltXI:
+    if (start) TexOutput("{\\f1\\'78}");
+    break;
+  case ltPI:
+    if (start) TexOutput("{\\f1\\'70}");
+    break;
+  case ltVARPI:
+    if (start) TexOutput("{\\f1\\'76}");
+    break;
+  case ltRHO:
+  case ltVARRHO:
+    if (start) TexOutput("{\\f1\\'72}");
+    break;
+  case ltSIGMA:
+    if (start) TexOutput("{\\f1\\'73}");
+    break;
+  case ltVARSIGMA:
+    if (start) TexOutput("{\\f1\\'56}");
+    break;
+  case ltTAU:
+    if (start) TexOutput("{\\f1\\'74}");
+    break;
+  case ltUPSILON:
+    if (start) TexOutput("{\\f1\\'75}");
+    break;
+  case ltPHI:
+  case ltVARPHI:
+    if (start) TexOutput("{\\f1\\'66}");
+    break;
+  case ltCHI:
+    if (start) TexOutput("{\\f1\\'63}");
+    break;
+  case ltPSI:
+    if (start) TexOutput("{\\f1\\'79}");
+    break;
+  case ltOMEGA:
+    if (start) TexOutput("{\\f1\\'77}");
+    break;
+  case ltCAP_GAMMA:
+    if (start) TexOutput("{\\f1\\'47}");
+    break;
+  case ltCAP_DELTA:
+    if (start) TexOutput("{\\f1\\'44}");
+    break;
+  case ltCAP_THETA:
+    if (start) TexOutput("{\\f1\\'51}");
+    break;
+  case ltCAP_LAMBDA:
+    if (start) TexOutput("{\\f1\\'4C}");
+    break;
+  case ltCAP_XI:
+    if (start) TexOutput("{\\f1\\'58}");
+    break;
+  case ltCAP_PI:
+    if (start) TexOutput("{\\f1\\'50}");
+    break;
+  case ltCAP_SIGMA:
+    if (start) TexOutput("{\\f1\\'53}");
+    break;
+  case ltCAP_UPSILON:
+    if (start) TexOutput("{\\f1\\'54}");
+    break;
+  case ltCAP_PHI:
+    if (start) TexOutput("{\\f1\\'46}");
+    break;
+  case ltCAP_PSI:
+    if (start) TexOutput("{\\f1\\'59}");
+    break;
+  case ltCAP_OMEGA:
+    if (start) TexOutput("{\\f1\\'57}");
+    break;
+  // Binary operation symbols
+  case ltLE:
+  case ltLEQ:
+    if (start) TexOutput("{\\f1\\'A3}");
+    break;
+  case ltLL:
+    if (start) TexOutput("<<");
+    break;
+  case ltSUBSET:
+    if (start) TexOutput("{\\f1\\'CC}");
+    break;
+  case ltSUBSETEQ:
+    if (start) TexOutput("{\\f1\\'CD}");
+    break;
+  case ltIN:
+    if (start) TexOutput("{\\f1\\'CE}");
+    break;
+  case ltGE:
+  case ltGEQ:
+    if (start) TexOutput("{\\f1\\'B3}");
+    break;
+  case ltGG:
+    if (start) TexOutput(">>");
+    break;
+  case ltSUPSET:
+    if (start) TexOutput("{\\f1\\'C9}");
+    break;
+  case ltSUPSETEQ:
+    if (start) TexOutput("{\\f1\\'CD}");
+    break;
+  case ltNI:
+    if (start) TexOutput("{\\f1\\'27}");
+    break;
+  case ltPERP:
+    if (start) TexOutput("{\\f1\\'5E}");
+    break;
+  case ltNEQ:
+    if (start) TexOutput("{\\f1\\'B9}");
+    break;
+  case ltAPPROX:
+    if (start) TexOutput("{\\f1\\'BB}");
+    break;
+  case ltCONG:
+    if (start) TexOutput("{\\f1\\'40}");
+    break;
+  case ltEQUIV:
+    if (start) TexOutput("{\\f1\\'BA}");
+    break;
+  case ltPROPTO:
+    if (start) TexOutput("{\\f1\\'B5}");
+    break;
+  case ltSIM:
+    if (start) TexOutput("{\\f1\\'7E}");
+    break;
+  case ltSMILE:
+    if (start) TexOutput("{\\f4\\'4A}");
+    break;
+  case ltFROWN:
+    if (start) TexOutput("{\\f4\\'4C}");
+    break;
+  case ltMID:
+    if (start) TexOutput("|");
+    break;
+
+  // Negated relation symbols
+  case ltNOTEQ:
+    if (start) TexOutput("{\\f1\\'B9}");
+    break;
+  case ltNOTIN:
+    if (start) TexOutput("{\\f1\\'CF}");
+    break;
+  case ltNOTSUBSET:
+    if (start) TexOutput("{\\f1\\'CB}");
+    break;
+
+  // Arrows
+  case ltLEFTARROW:
+     if (start) TexOutput("{\\f1\\'AC}");
+    break;
+  case ltLEFTARROW2:
+    if (start) TexOutput("{\\f1\\'DC}");
+    break;
+  case ltRIGHTARROW:
+    if (start) TexOutput("{\\f1\\'AE}");
+    break;
+  case ltRIGHTARROW2:
+    if (start) TexOutput("{\\f1\\'DE}");
+    break;
+  case ltLEFTRIGHTARROW:
+    if (start) TexOutput("{\\f1\\'AB}");
+    break;
+  case ltLEFTRIGHTARROW2:
+    if (start) TexOutput("{\\f1\\'DB}");
+    break;
+  case ltUPARROW:
+    if (start) TexOutput("{\\f1\\'AD}");
+    break;
+  case ltUPARROW2:
+    if (start) TexOutput("{\\f1\\'DD}");
+    break;
+  case ltDOWNARROW:
+    if (start) TexOutput("{\\f1\\'AF}");
+    break;
+  case ltDOWNARROW2:
+    if (start) TexOutput("{\\f1\\'DF}");
+    break;
+
+  // Miscellaneous symbols
+  case ltALEPH:
+    if (start) TexOutput("{\\f1\\'CO}");
+    break;
+  case ltWP:
+    if (start) TexOutput("{\\f1\\'C3}");
+    break;
+  case ltRE:
+    if (start) TexOutput("{\\f1\\'C2}");
+    break;
+  case ltIM:
+    if (start) TexOutput("{\\f1\\'C1}");
+    break;
+  case ltEMPTYSET:
+    if (start) TexOutput("{\\f1\\'C6}");
+    break;
+  case ltNABLA:
+    if (start) TexOutput("{\\f1\\'D1}");
+    break;
+  case ltSURD:
+    if (start) TexOutput("{\\f1\\'D6}");
+    break;
+  case ltPARTIAL:
+    if (start) TexOutput("{\\f1\\'B6}");
+    break;
+  case ltBOT:
+    if (start) TexOutput("{\\f1\\'5E}");
+    break;
+  case ltFORALL:
+    if (start) TexOutput("{\\f1\\'22}");
+    break;
+  case ltEXISTS:
+    if (start) TexOutput("{\\f1\\'24}");
+    break;
+  case ltNEG:
+    if (start) TexOutput("{\\f1\\'D8}");
+    break;
+  case ltSHARP:
+    if (start) TexOutput("{\\f1\\'23}");
+    break;
+  case ltANGLE:
+    if (start) TexOutput("{\\f1\\'D0}");
+    break;
+  case ltTRIANGLE:
+    if (start) TexOutput("{\\f5\\'73}");
+    break;
+  case ltCLUBSUIT:
+    if (start) TexOutput("{\\f5\\'A8}");
+    break;
+  case ltDIAMONDSUIT:
+    if (start) TexOutput("{\\f5\\'A9}");
+    break;
+  case ltHEARTSUIT:
+    if (start) TexOutput("{\\f5\\'AA}");
+    break;
+  case ltSPADESUIT:
+    if (start) TexOutput("{\\f5\\'AB}");
+    break;
+  case ltINFTY:
+    if (start) TexOutput("{\\f1\\'A5}");
+    break;
+  case ltCOPYRIGHT:
+    if (start) TexOutput("{\\f0\\'A9}");
+    break;
+  case ltREGISTERED:
+    if (start) TexOutput("{\\f0\\'AE}");
+    break;
+  case ltPM:
+    if (start) TexOutput("{\\f1\\'B1}");
+    break;
+  case ltMP:
+    if (start) TexOutput("{\\f1\\'B1}");
+    break;
+  case ltTIMES:
+    if (start) TexOutput("{\\f1\\'B4}");
+    break;
+  case ltDIV:
+    if (start) TexOutput("{\\f1\\'B8}");
+    break;
+  case ltCDOT:
+    if (start) TexOutput("{\\f1\\'D7}");
+    break;
+  case ltAST:
+    if (start) TexOutput("{\\f1\\'2A}");
+    break;
+  case ltSTAR:
+    if (start) TexOutput("{\\f5\\'AB}");
+    break;
+  case ltCAP:
+    if (start) TexOutput("{\\f1\\'C7}");
+    break;
+  case ltCUP:
+    if (start) TexOutput("{\\f1\\'C8}");
+    break;
+  case ltVEE:
+    if (start) TexOutput("{\\f1\\'DA}");
+    break;
+  case ltWEDGE:
+    if (start) TexOutput("{\\f1\\'D9}");
+    break;
+  case ltCIRC:
+    if (start) TexOutput("{\\f1\\'B0}");
+    break;
+  case ltBULLET:
+    if (start) TexOutput("{\\f1\\'B7}");
+    break;
+  case ltDIAMOND:
+    if (start) TexOutput("{\\f1\\'E0}");
+    break;
+  case ltBOX:
+    if (start) TexOutput("{\\f1\\'C6}");
+    break;
+  case ltDIAMOND2:
+    if (start) TexOutput("{\\f1\\'E0}");
+    break;
+  case ltBIGTRIANGLEDOWN:
+    if (start) TexOutput("{\\f1\\'D1}");
+    break;
+  case ltOPLUS:
+    if (start) TexOutput("{\\f1\\'C5}");
+    break;
+  case ltOTIMES:
+    if (start) TexOutput("{\\f1\\'C4}");
+    break;
+  case ltSS:
+    if (start) TexOutput("{\\'DF}");
+    break;
+  case ltFIGURE:
+  {
+    if (start) inFigure = TRUE;
+    else inFigure = FALSE;
+    break;
+  }
+  case ltTABLE:
+  {
+    if (start) inTable = TRUE;
+    else inTable = FALSE;
+    break;
+  }
+  default:
+  {
+    DefaultOnMacro(macroId, no_args, start);
+    break;
+  }
+  }
+}
+
+// Called on start/end of argument examination
+bool RTFOnArgument(int macroId, int arg_no, bool start)
+{
+  char buf[300];
+  switch (macroId)
+  {
+  case ltCHAPTER:
+  case ltCHAPTERSTAR:
+  case ltCHAPTERHEADING:
+  case ltSECTION:
+  case ltSECTIONSTAR:
+  case ltSECTIONHEADING:
+  case ltSUBSECTION:
+  case ltSUBSECTIONSTAR:
+  case ltSUBSUBSECTION:
+  case ltSUBSUBSECTIONSTAR:
+  case ltGLOSS:
+  case ltMEMBERSECTION:
+  case ltFUNCTIONSECTION:
+  case ltCAPTION:
+  case ltCAPTIONSTAR:
+  {
+    if (!start && (arg_no == 1))
+      currentSection = GetArgChunk();
+    return FALSE;
+    break;
+  }
+  case ltFUNC:
+  {
+    if (start && (arg_no == 1))
+      TexOutput("\\pard\\li600\\fi-600{\\b ");
+
+    if (!start && (arg_no == 1))
+      TexOutput("} ");
+
+    if (start && (arg_no == 2))
+    {
+      if (!suppressNameDecoration) TexOutput("{\\b ");
+      currentMember = GetArgChunk();
+    }
+    if (!start && (arg_no == 2))
+    {
+      if (!suppressNameDecoration) TexOutput("}");
+    }
+    
+    if (start && (arg_no == 3))
+      TexOutput("(");
+    if (!start && (arg_no == 3))
+    {
+//      TexOutput(")\\li0\\fi0");
+//      TexOutput(")\\par\\pard\\li0\\fi0");
+//      issuedNewParagraph = 1;
+      TexOutput(")");
+      WriteEnvironmentStyles();
+    }
+    break;
+  }
+  case ltCLIPSFUNC:
+  {
+    if (start && (arg_no == 1))
+      TexOutput("\\pard\\li260\\fi-260{\\b ");
+    if (!start && (arg_no == 1))
+      TexOutput("} ");
+
+    if (start && (arg_no == 2))
+    {
+      if (!suppressNameDecoration) TexOutput("({\\b ");
+      currentMember = GetArgChunk();
+    }
+    if (!start && (arg_no == 2))
+    {
+      if (!suppressNameDecoration) TexOutput("}");
+    }
+
+    if (!start && (arg_no == 3))
+    {
+      TexOutput(")\\li0\\fi0");
+      WriteEnvironmentStyles();
+    }
+    break;
+  }
+  case ltPFUNC:
+  {
+    if (start && (arg_no == 1))
+      TexOutput("\\pard\\li260\\fi-260");
+
+    if (!start && (arg_no == 1))
+      TexOutput(" ");
+
+    if (start && (arg_no == 2))
+      TexOutput("(*");
+    if (!start && (arg_no == 2))
+      TexOutput(")");
+
+    if (start && (arg_no == 2))
+      currentMember = GetArgChunk();
+
+    if (start && (arg_no == 3))
+      TexOutput("(");
+    if (!start && (arg_no == 3))
+    {
+      TexOutput(")\\li0\\fi0");
+      WriteEnvironmentStyles();
+    }
+    break;
+  }
+  case ltPARAM:
+  {
+    if (start && (arg_no == 1))
+      TexOutput("{\\b ");
+    if (!start && (arg_no == 1))
+      TexOutput("}");
+    if (start && (arg_no == 2))
+    {
+      TexOutput("{\\i ");
+    }
+    if (!start && (arg_no == 2))
+    {
+      TexOutput("}");
+    }
+    break;
+  }
+  case ltCPARAM:
+  {
+    if (start && (arg_no == 1))
+      TexOutput("{\\b ");
+    if (!start && (arg_no == 1))
+      TexOutput("} ");  // This is the difference from param - one space!
+    if (start && (arg_no == 2))
+    {
+      TexOutput("{\\i ");
+    }
+    if (!start && (arg_no == 2))
+    {
+      TexOutput("}");
+    }
+    break;
+  }
+  case ltMEMBER:
+  {
+    if (!start && (arg_no == 1))
+      TexOutput(" ");
+
+    if (start && (arg_no == 2))
+      currentMember = GetArgChunk();
+    break;
+  }
+  case ltREF:
+  {
+    if (start)
+    {
+      char *sec = NULL;
+      char *secName = NULL;
+      
+      char *refName = GetArgData();
+      if (winHelp || !useWord)
+      {
+        if (refName)
+        {
+          TexRef *texRef = FindReference(refName);
+          if (texRef)
+          {
+            sec = texRef->sectionNumber;
+            secName = texRef->sectionName;
+          }
+        }
+        if (sec)
+        {
+          TexOutput(sec);
+        }
+      }
+      else
+      {
+        fprintf(Chapters, "{\\field{\\*\\fldinst  REF %s \\\\* MERGEFORMAT }{\\fldrslt ??}}",
+                refName);
+      }
+      return FALSE;
+    }
+    break;
+  }
+  case ltHELPREF:
+  case ltHELPREFN:
+  {
+    if (winHelp)
+    {
+        if ((GetNoArgs() - arg_no) == 1)
+        {
+          if (start)
+            TexOutput("{\\uldb ");
+          else
+            TexOutput("}");
+        }
+        if ((GetNoArgs() - arg_no) == 0) // Arg = 2, or 3 if first is optional
+        {
+          if (start)
+          {
+            TexOutput("{\\v ");
+
+            // Remove green colour/underlining if specified
+            if (!hotSpotUnderline && !hotSpotColour)
+              TexOutput("%");
+            else if (!hotSpotColour)
+              TexOutput("*");
+          }
+          else TexOutput("}");
+        }
+    }
+    else // If a linear document, must resolve the references ourselves
+    {
+      if ((GetNoArgs() - arg_no) == 1)
+      {
+        // In a linear document we display the anchor text in italic plus
+        // the page number.
+        if (start)
+          TexOutput("{\\i ");
+        else
+          TexOutput("}");
+        return TRUE;
+      }
+      else if ((GetNoArgs() - arg_no) == 0) // Arg = 2, or 3 if first is optional
+      {
+        if (macroId != ltHELPREFN)
+        {
+          if (start)
+          {
+            TexOutput(" (");
+            char *refName = GetArgData();
+            if (refName)
+            {
+                if (useWord)
+                {
+                    char *s = GetArgData();
+                    TexOutput("p. ");
+                    TexOutput("{\\field{\\*\\fldinst  PAGEREF ");
+                    TexOutput(refName);
+                    TexOutput(" \\\\* MERGEFORMAT }{\\fldrslt ??}}");
+                }
+                else
+                {
+                  // Only print section name if we're not in Word mode,
+                  // so can't do page references
+                  TexRef *texRef = FindReference(refName);
+                  if (texRef)
+                  {
+                    TexOutput(texRef->sectionName) ; TexOutput(" "); TexOutput(texRef->sectionNumber);
+                  }
+                  else
+                  {
+                    TexOutput("??");
+                    sprintf(buf, "Warning: unresolved reference %s.", refName);
+                    OnInform(buf);
+                  }
+                }
+            }
+            else TexOutput("??");
+          }
+          else TexOutput(")");
+        }
+        return FALSE;
+      }
+    }
+    break;
+  }
+  case ltURLREF:
+  {
+    if (arg_no == 1)
+    {
+      return TRUE;
+    }
+    else if (arg_no == 2)
+    {
+      if (start)
+      {
+        inVerbatim = TRUE;
+        TexOutput(" ({\\f3 ");
+      }
+      else
+      {
+        TexOutput("})");
+        inVerbatim = FALSE;
+      }
+      return TRUE;
+    }
+    break;
+  }
+  case ltPOPREF:
+  {
+    if (winHelp)
+    {
+      if ((GetNoArgs() - arg_no) == 1)
+      {
+        if (start)
+          TexOutput("{\\ul ");
+        else
+          TexOutput("}");
+      }
+      if ((GetNoArgs() - arg_no) == 0) // Arg = 2, or 3 if first is optional
+      {
+        if (start)
+        {
+          TexOutput("{\\v ");
+
+          // Remove green colour/underlining if specified
+          if (!hotSpotUnderline && !hotSpotColour)
+            TexOutput("%");
+          else if (!hotSpotColour)
+            TexOutput("*");
+        }
+        else TexOutput("}");
+      }
+    }
+    else // A linear document...
+    {
+      if ((GetNoArgs() - arg_no) == 1)
+      {
+        // In a linear document we just display the anchor text in italic
+        if (start)
+          TexOutput("{\\i ");
+        else
+          TexOutput("}");
+        return TRUE;
+      }
+      else return FALSE;
+    }
+    break;
+  }
+  case ltADDCONTENTSLINE:
+  {
+    if (start && !winHelp)
+    {
+      if (arg_no == 2)
+        contentsLineSection = copystring(GetArgData());
+      else if (arg_no == 3)
+        contentsLineValue = copystring(GetArgData());
+      return FALSE;
+    }
+    else return FALSE;
+    break;
+  }
+  case ltIMAGE:
+  case ltIMAGEL:
+  case ltIMAGER:
+  case ltIMAGEMAP:
+  case ltPSBOXTO:
+  {
+    if (arg_no == 3)
+      return FALSE;
+      
+    static int imageWidth = 0;
+    static int imageHeight = 0;
+    
+    if (start && (arg_no == 1))
+    {
+      char *imageDimensions = copystring(GetArgData());
+      char buf1[50];
+      strcpy(buf1, imageDimensions);
+      char *tok1 = strtok(buf1, ";:");
+      char *tok2 = strtok(NULL, ";:");
+      // Convert points to TWIPS (1 twip = 1/20th of point)
+      imageWidth = (int)(20*(tok1 ? ParseUnitArgument(tok1) : 0));
+      imageHeight = (int)(20*(tok2 ? ParseUnitArgument(tok2) : 0));
+      return FALSE;
+    }  
+    else if (start && (arg_no == 2 ))
+    {
+      char *filename = copystring(GetArgData());
+      wxString f = "";
+      if ((winHelp || (strcmp(bitmapMethod, "includepicture") == 0)  || (strcmp(bitmapMethod, "import") == 0)) && useWord)
+      {
+        if (f == "") // Try for a .shg (segmented hypergraphics file)
+        {
+          strcpy(buf, filename);
+          StripExtension(buf);
+          strcat(buf, ".shg");
+          f = TexPathList.FindValidPath(buf);
+        }
+        if (f == "") // Try for a .bmp
+        {
+          strcpy(buf, filename);
+          StripExtension(buf);
+          strcat(buf, ".bmp");
+          f = TexPathList.FindValidPath(buf);
+        }
+        if (f == "") // Try for a metafile instead
+        {
+          strcpy(buf, filename);
+          StripExtension(buf);
+          strcat(buf, ".wmf");
+          f = TexPathList.FindValidPath(buf);
+        }
+        if (f != "")
+        {
+          if (winHelp)
+          {
+            if (bitmapTransparency && (winHelpVersion > 3))
+              TexOutput("\\{bmct ");
+            else
+              TexOutput("\\{bmc ");
+            wxString str = wxFileNameFromPath(f);
+            TexOutput((char*) (const char*) str);
+            TexOutput("\\}");
+          }
+          else
+          {
+            // Microsoft Word method
+            if (strcmp(bitmapMethod, "import") == 0)
+              TexOutput("{\\field{\\*\\fldinst IMPORT ");
+            else
+              TexOutput("{\\field{\\*\\fldinst INCLUDEPICTURE ");
+
+            // Full path appears not to be valid!
+            wxString str = wxFileNameFromPath(f);
+            TexOutput((char*)(const char*) str);
+/*
+            int len = strlen(f);
+            char smallBuf[2]; smallBuf[1] = 0;
+            for (int i = 0; i < len; i++)
+            {
+              smallBuf[0] = f[i];
+              TexOutput(smallBuf);
+              if (smallBuf[0] == '\\')
+                TexOutput(smallBuf);
+            }
+*/
+            TexOutput("}{\\fldrslt PRESS F9 TO FORMAT PICTURE}}");
+          }
+        }
+        else
+        {
+          TexOutput("[No BMP or WMF for image file ");
+          TexOutput(filename);
+          TexOutput("]");
+          sprintf(buf, "Warning: could not find a BMP or WMF equivalent for %s.", filename);
+          OnInform(buf);
+        }
+      }
+      else // linear RTF
+      {
+          if (f == "") // Try for a .bmp
+          {
+            strcpy(buf, filename);
+            StripExtension(buf);
+            strcat(buf, ".bmp");
+            f = TexPathList.FindValidPath(buf);
+          }
+          if (f != "")
+          {
+            FILE *fd = fopen(f, "rb");
+            if (OutputBitmapHeader(fd, winHelp))
+              OutputBitmapData(fd);
+            else
+            {
+              sprintf(buf, "Could not read bitmap %s.\nMay be in wrong format (needs RGB-encoded Windows BMP).", (const char*) f);
+              OnError(buf);
+            }
+            fclose(fd);
+          }
+          else // Try for a metafile instead
+          {
+#ifdef __WXMSW__
+            strcpy(buf, filename);
+            StripExtension(buf);
+            strcat(buf, ".wmf");
+            f = TexPathList.FindValidPath(buf);
+            if (f != "")
+            {
+  //            HFILE handle = _lopen(f, READ);
+              FILE *fd = fopen(f, "rb");
+              if (OutputMetafileHeader(fd, winHelp, imageWidth, imageHeight))
+              {
+                OutputMetafileData(fd);
+              }
+              else
+              {
+                sprintf(buf, "Could not read metafile %s. Perhaps it's not a placeable metafile?", f);
+                OnError(buf);
+              }
+              fclose(fd);
+            }
+            else
+            {
+#endif            
+              TexOutput("[No BMP or WMF for image file ");
+              TexOutput(filename);
+              TexOutput("]");
+              sprintf(buf, "Warning: could not find a BMP or WMF equivalent for %s.", filename);
+              OnInform(buf);
+#ifdef __WXMSW__
+            }
+#endif
+        }
+      }
+      return FALSE;
+    }
+    else
+      return FALSE;
+    break;
+  }
+  case ltTABULAR:
+  case ltSUPERTABULAR:
+  {
+    if (arg_no == 1)
+    {
+      if (start)
+      {
+        currentRowNumber = 0;
+        inTabular = TRUE;
+        startRows = TRUE;
+        tableVerticalLineLeft = FALSE;
+        tableVerticalLineRight = FALSE;
+        int currentWidth = 0;
+
+        char *alignString = copystring(GetArgData());
+        ParseTableArgument(alignString);
+
+//        TexOutput("\\trowd\\trgaph108\\trleft-108");
+        TexOutput("\\trowd\\trgaph108");
+
+        // Write the first row formatting for compatibility
+        // with standard Latex
+        if (compatibilityMode)
+        {
+          for (int i = 0; i < noColumns; i++)
+          {
+            currentWidth += TableData[i].width;
+            sprintf(buf, "\\cellx%d", currentWidth);
+            TexOutput(buf);
+          }
+          TexOutput("\\pard\\intbl\n");
+        }
+        delete[] alignString;
+
+        return FALSE;
+      }
+    }
+    else if (arg_no == 2 && !start)
+    {
+      TexOutput("\\pard\n");
+      WriteEnvironmentStyles();
+      inTabular = FALSE;
+    }
+    break;
+  }
+
+  case ltQUOTE:
+  case ltVERSE:
+  {
+    if (start)
+    {
+      TexOutput("\\li360\n");
+      forbidParindent ++;
+      PushEnvironmentStyle("\\li360");
+    }
+    else
+    {
+      forbidParindent --;
+      PopEnvironmentStyle();
+      OnMacro(ltPAR, 0, TRUE);
+      OnMacro(ltPAR, 0, FALSE);
+    }
+    break;
+  }
+  case ltQUOTATION:
+  {
+    if (start)
+    {
+      TexOutput("\\li360\n");
+      PushEnvironmentStyle("\\li360");
+    }
+    else
+    {
+      PopEnvironmentStyle();
+      OnMacro(ltPAR, 0, TRUE);
+      OnMacro(ltPAR, 0, FALSE);
+    }
+    break;
+  }
+  case ltBOXIT:
+  case ltFRAMEBOX:
+  case ltFBOX:
+  case ltNORMALBOX:
+  case ltNORMALBOXD:
+  {
+    if (start)
+    {
+      sprintf(buf, "\\box\\trgaph108%s\n", ((macroId == ltNORMALBOXD) ? "\\brdrdb" : "\\brdrs"));
+      TexOutput(buf);
+      PushEnvironmentStyle(buf);
+    }
+    else
+    {
+      PopEnvironmentStyle();
+      OnMacro(ltPAR, 0, TRUE);
+      OnMacro(ltPAR, 0, FALSE);
+    }
+    break;
+  }
+  case ltHELPFONTSIZE:
+  {
+    if (start)
+    {
+      char *data = GetArgData();
+      if (strcmp(data, "10") == 0)
+        SetFontSizes(10);
+      else if (strcmp(data, "11") == 0)
+        SetFontSizes(11);
+      else if (strcmp(data, "12") == 0)
+        SetFontSizes(12);
+      sprintf(buf, "\\fs%d\n", normalFont*2);
+      TexOutput(buf);
+      TexOutput(buf);
+      return FALSE;
+    }
+    break;
+  }
+  case ltHELPFONTFAMILY:
+  {
+    if (start)
+    {
+      char *data = GetArgData();
+      if (strcmp(data, "Swiss") == 0)
+        TexOutput("\\f2\n");
+      else if (strcmp(data, "Symbol") == 0)
+        TexOutput("\\f1\n");
+      else if (strcmp(data, "Times") == 0)
+        TexOutput("\\f0\n");
+
+      return FALSE;
+    }
+    break;
+  }
+  case ltPARINDENT:
+  {
+    if (start && arg_no == 1)
+    {
+      char *data = GetArgData();
+      ParIndent = ParseUnitArgument(data);
+      if (ParIndent == 0 || forbidParindent == 0)
+      {
+        sprintf(buf, "\\fi%d\n", ParIndent*20);
+        TexOutput(buf);
+      }
+      return FALSE;
+    }
+    break;
+  }
+  case ltITEM:
+  {
+    if (start && IsArgOptional())
+    {
+      descriptionItemArg = GetArgChunk();
+      return FALSE;
+    }
+    break;
+  }
+  case ltTWOCOLITEM:
+  case ltTWOCOLITEMRULED:
+  {
+    switch (arg_no)
+    {
+      case 1:
+      {
+        if (!start)
+          TexOutput("\\tab ");
+        break;
+      }
+      case 2:
+      {
+        if (!start)
+        {
+          if (macroId == ltTWOCOLITEMRULED)
+            TexOutput("\\brdrb\\brdrs\\brdrw15\\brsp20 ");
+          TexOutput("\\par\\pard\n");
+          issuedNewParagraph = 1;
+          WriteEnvironmentStyles();
+        }
+        break;
+      }
+    }
+    return TRUE;
+    break;
+  }
+  /*
+   * Accents
+   *
+   */
+  case ltACCENT_GRAVE:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        switch (val[0])
+        {
+          case 'a':
+           TexOutput("\\'e0");
+           break;
+          case 'e':
+           TexOutput("\\'e8");
+           break;
+          case 'i':
+           TexOutput("\\'ec");
+           break;
+          case 'o':
+           TexOutput("\\'f2");
+           break;
+          case 'u':
+           TexOutput("\\'f9");
+           break;
+          case 'A':
+           TexOutput("\\'c0");
+           break;
+          case 'E':
+           TexOutput("\\'c8");
+           break;
+          case 'I':
+           TexOutput("\\'cc");
+           break;
+          case 'O':
+           TexOutput("\\'d2");
+           break;
+          case 'U':
+           TexOutput("\\'d9");
+           break;
+          default:
+           break;
+        }
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltACCENT_ACUTE:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        switch (val[0])
+        {
+          case 'a':
+           TexOutput("\\'e1");
+           break;
+          case 'e':
+           TexOutput("\\'e9");
+           break;
+          case 'i':
+           TexOutput("\\'ed");
+           break;
+          case 'o':
+           TexOutput("\\'f3");
+           break;
+          case 'u':
+           TexOutput("\\'fa");
+           break;
+          case 'y':
+           TexOutput("\\'fd");
+           break;
+          case 'A':
+           TexOutput("\\'c1");
+           break;
+          case 'E':
+           TexOutput("\\'c9");
+           break;
+          case 'I':
+           TexOutput("\\'cd");
+           break;
+          case 'O':
+           TexOutput("\\'d3");
+           break;
+          case 'U':
+           TexOutput("\\'da");
+           break;
+          case 'Y':
+           TexOutput("\\'dd");
+           break;
+          default:
+           break;
+        }
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltACCENT_CARET:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        switch (val[0])
+        {
+          case 'a':
+           TexOutput("\\'e2");
+           break;
+          case 'e':
+           TexOutput("\\'ea");
+           break;
+          case 'i':
+           TexOutput("\\'ee");
+           break;
+          case 'o':
+           TexOutput("\\'f4");
+           break;
+          case 'u':
+           TexOutput("\\'fb");
+           break;
+          case 'A':
+           TexOutput("\\'c2");
+           break;
+          case 'E':
+           TexOutput("\\'ca");
+           break;
+          case 'I':
+           TexOutput("\\'ce");
+           break;
+          case 'O':
+           TexOutput("\\'d4");
+           break;
+          case 'U':
+           TexOutput("\\'db");
+           break;
+          default:
+           break;
+        }
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltACCENT_TILDE:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        switch (val[0])
+        {
+          case 'a':
+           TexOutput("\\'e3");
+           break;
+          case ' ':
+           TexOutput("~");
+           break;
+          case 'n':
+           TexOutput("\\'f1");
+           break;
+          case 'o':
+           TexOutput("\\'f5");
+           break;
+          case 'A':
+           TexOutput("\\'c3");
+           break;
+          case 'N':
+           TexOutput("\\'d1");
+           break;
+          case 'O':
+           TexOutput("\\'d5");
+           break;
+          default:
+           break;
+        }
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltACCENT_UMLAUT:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        switch (val[0])
+        {
+          case 'a':
+           TexOutput("\\'e4");
+           break;
+          case 'e':
+           TexOutput("\\'eb");
+           break;
+          case 'i':
+           TexOutput("\\'ef");
+           break;
+          case 'o':
+           TexOutput("\\'f6");
+           break;
+          case 'u':
+           TexOutput("\\'fc");
+           break;
+          case 's':
+           TexOutput("\\'df");
+           break;
+          case 'y':
+           TexOutput("\\'ff");
+           break;
+          case 'A':
+           TexOutput("\\'c4");
+           break;
+          case 'E':
+           TexOutput("\\'cb");
+           break;
+          case 'I':
+           TexOutput("\\'cf");
+           break;
+          case 'O':
+           TexOutput("\\'d6");
+           break;
+          case 'U':
+           TexOutput("\\'dc");
+           break;
+          case 'Y':
+           TexOutput("\\'df");
+           break;
+          default:
+           break;
+        }
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltACCENT_DOT:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        switch (val[0])
+        {
+          case 'a':
+           TexOutput("\\'e5");
+           break;
+          case 'A':
+           TexOutput("\\'c5");
+           break;
+          default:
+           break;
+        }
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltACCENT_CADILLA:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        switch (val[0])
+        {
+          case 'c':
+           TexOutput("\\'e7");
+           break;
+          case 'C':
+           TexOutput("\\'c7");
+           break;
+          default:
+           break;
+        }
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltFOOTNOTE:
+  {
+    static char *helpTopic = NULL;
+    static FILE *savedOutput = NULL;
+    if (winHelp)
+    {
+      if (arg_no == 1)
+      {
+        if (start)
+        {
+          OnInform("Consider using \\footnotepopup instead of \\footnote.");
+          footnoteCount ++;
+          char footBuf[20];
+          sprintf(footBuf, "(%d)", footnoteCount);
+
+          TexOutput(" {\\ul ");
+          TexOutput(footBuf);
+          TexOutput("}");
+          helpTopic = FindTopicName(NULL);
+          TexOutput("{\\v ");
+
+          // Remove green colour/underlining if specified
+          if (!hotSpotUnderline && !hotSpotColour)
+            TexOutput("%");
+          else if (!hotSpotColour)
+            TexOutput("*");
+
+          TexOutput(helpTopic);
+          TexOutput("}");
+
+          fprintf(Popups, "\\page\n");
+//          fprintf(Popups, "\n${\\footnote }"); // No title
+          fprintf(Popups, "\n#{\\footnote %s}\n", helpTopic);
+          fprintf(Popups, "+{\\footnote %s}\n", GetBrowseString());
+          savedOutput = CurrentOutput1;
+          SetCurrentOutput(Popups);
+       }
+       else
+       {
+          SetCurrentOutput(savedOutput);
+       }
+       return TRUE;
+      }
+      return TRUE;
+    }
+    else
+    {
+      if (start)
+      {
+        TexOutput(" {\\super \\chftn{\\footnote \\fs20 {\\super \\chftn}", TRUE);
+      }
+      else
+      {
+        TexOutput("}}", TRUE);
+      }
+      return TRUE;
+    }
+    break;
+  }
+  case ltFOOTNOTEPOPUP:
+  {
+    static char *helpTopic = NULL;
+    static FILE *savedOutput = NULL;
+    if (winHelp)
+    {
+      if (arg_no == 1)
+      {
+        if (start)
+        {
+          TexOutput("{\\ul ");
+       }
+       else TexOutput("}");
+       return TRUE;
+      }
+      else if (arg_no == 2)
+      {
+        if (start)
+        {
+          helpTopic = FindTopicName(NULL);
+          TexOutput("{\\v ");
+
+          // Remove green colour/underlining if specified
+          if (!hotSpotUnderline && !hotSpotColour)
+            TexOutput("%");
+          else if (!hotSpotColour)
+            TexOutput("*");
+
+          TexOutput(helpTopic);
+          TexOutput("}");
+
+          fprintf(Popups, "\\page\n");
+//          fprintf(Popups, "\n${\\footnote }"); // No title
+          fprintf(Popups, "\n#{\\footnote %s}\n", helpTopic);
+          fprintf(Popups, "+{\\footnote %s}\n", GetBrowseString());
+          savedOutput = CurrentOutput1;
+          SetCurrentOutput(Popups);
+        }
+        else
+        {
+          SetCurrentOutput(savedOutput);
+        }
+        return TRUE;
+      }
+    }
+    else
+    {
+      if (arg_no == 1)
+        return TRUE;
+      if (start)
+      {
+        TexOutput(" {\\super \\chftn{\\footnote \\fs20 {\\super \\chftn}", TRUE);
+      }
+      else
+      {
+        TexOutput("}}", TRUE);
+      }
+      return TRUE;
+    }
+    break;
+  }
+  case ltFANCYPLAIN:
+  {
+    if (start && (arg_no == 1))
+      return FALSE;
+    else
+      return TRUE;
+    break;
+  }
+  case ltSETHEADER:
+  {
+    if (start)
+      forbidResetPar ++;
+    else
+      forbidResetPar --;
+
+    if (winHelp) return FALSE;
+    if (start)
+    {
+      switch (arg_no)
+      {
+        case 1:
+          LeftHeaderEven = GetArgChunk();
+          if (strlen(GetArgData(LeftHeaderEven)) == 0)
+            LeftHeaderEven = NULL;
+          break;
+        case 2:
+          CentreHeaderEven = GetArgChunk();
+          if (strlen(GetArgData(CentreHeaderEven)) == 0)
+            CentreHeaderEven = NULL;
+          break;
+        case 3:
+          RightHeaderEven = GetArgChunk();
+          if (strlen(GetArgData(RightHeaderEven)) == 0)
+            RightHeaderEven = NULL;
+          break;
+        case 4:
+          LeftHeaderOdd = GetArgChunk();
+          if (strlen(GetArgData(LeftHeaderOdd)) == 0)
+            LeftHeaderOdd = NULL;
+          break;
+        case 5:
+          CentreHeaderOdd = GetArgChunk();
+          if (strlen(GetArgData(CentreHeaderOdd)) == 0)
+            CentreHeaderOdd = NULL;
+          break;
+        case 6:
+          RightHeaderOdd = GetArgChunk();
+          if (strlen(GetArgData(RightHeaderOdd)) == 0)
+            RightHeaderOdd = NULL;
+          OutputRTFHeaderCommands();
+          break;
+        default:
+          break;
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltSETFOOTER:
+  {
+    if (start)
+      forbidResetPar ++;
+    else
+      forbidResetPar --;
+
+    if (winHelp) return FALSE;
+    if (start)
+    {
+      switch (arg_no)
+      {
+        case 1:
+          LeftFooterEven = GetArgChunk();
+          if (strlen(GetArgData(LeftFooterEven)) == 0)
+            LeftFooterEven = NULL;
+          break;
+        case 2:
+          CentreFooterEven = GetArgChunk();
+          if (strlen(GetArgData(CentreFooterEven)) == 0)
+            CentreFooterEven = NULL;
+          break;
+        case 3:
+          RightFooterEven = GetArgChunk();
+          if (strlen(GetArgData(RightFooterEven)) == 0)
+            RightFooterEven = NULL;
+          break;
+        case 4:
+          LeftFooterOdd = GetArgChunk();
+          if (strlen(GetArgData(LeftFooterOdd)) == 0)
+            LeftFooterOdd = NULL;
+          break;
+        case 5:
+          CentreFooterOdd = GetArgChunk();
+          if (strlen(GetArgData(CentreFooterOdd)) == 0)
+            CentreFooterOdd = NULL;
+          break;
+        case 6:
+          RightFooterOdd = GetArgChunk();
+          if (strlen(GetArgData(RightFooterOdd)) == 0)
+            RightFooterOdd = NULL;
+          OutputRTFFooterCommands();
+          break;
+        default:
+          break;
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltMARKRIGHT:
+  {
+    if (winHelp) return FALSE;
+    // Fake a SetHeader command
+    if (start)
+    {
+      LeftHeaderOdd = NULL;
+      CentreHeaderOdd = NULL;
+      RightHeaderOdd = NULL;
+      LeftHeaderEven = NULL;
+      CentreHeaderEven = NULL;
+      RightHeaderEven = NULL;
+      OnInform("Consider using setheader/setfooter rather than markright.");
+    }
+    RTFOnArgument(ltSETHEADER, 4, start);
+    if (!start)
+      OutputRTFHeaderCommands();
+    return FALSE;
+    break;
+  }
+  case ltMARKBOTH:
+  {
+    if (winHelp) return FALSE;
+    // Fake a SetHeader command
+    switch (arg_no)
+    {
+      case 1:
+      {
+        if (start)
+        {
+          LeftHeaderOdd = NULL;
+          CentreHeaderOdd = NULL;
+          RightHeaderOdd = NULL;
+          LeftHeaderEven = NULL;
+          CentreHeaderEven = NULL;
+          RightHeaderEven = NULL;
+          OnInform("Consider using setheader/setfooter rather than markboth.");
+        }
+        return RTFOnArgument(ltSETHEADER, 1, start);
+        break;
+      }
+      case 2:
+      {
+        RTFOnArgument(ltSETHEADER, 4, start);
+        if (!start)
+          OutputRTFHeaderCommands();
+        return FALSE;
+        break;
+      }
+    }
+    break;
+  }
+  case ltPAGENUMBERING:
+  {
+    if (start)
+      forbidResetPar ++;
+    else
+      forbidResetPar --;
+
+    if (winHelp) return FALSE;
+    if (start)
+    {
+      TexOutput("\\pgnrestart");
+      char *data = GetArgData();
+      if (currentNumberStyle) delete[] currentNumberStyle;
+      currentNumberStyle = copystring(data);
+      OutputNumberStyle(currentNumberStyle);
+      
+      TexOutput("\n");
+    }
+    return FALSE;
+    break;
+  }
+  case ltTWOCOLUMN:
+  {
+    if (winHelp) return FALSE;
+    if (start)
+      return TRUE;
+    break;
+  }
+  case ltITEMSEP:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      currentItemSep = ParseUnitArgument(val);
+      return FALSE;
+    }
+    break;
+  }
+  case ltEVENSIDEMARGIN:
+  {
+    return FALSE;
+    break;
+  }
+  case ltODDSIDEMARGIN:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      int twips = (int)(20*ParseUnitArgument(val));
+      // Add an inch since in LaTeX it's specified minus an inch
+      twips += 1440;
+      CurrentLeftMarginOdd = twips;
+      sprintf(buf, "\\margl%d\n", twips);
+      TexOutput(buf);
+
+      CurrentMarginParX = CurrentLeftMarginOdd + CurrentTextWidth + CurrentMarginParSep;
+    }
+    return FALSE;
+  }
+  case ltMARGINPARWIDTH:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      int twips = (int)(20*ParseUnitArgument(val));
+      CurrentMarginParWidth = twips;
+    }
+    return FALSE;
+  }
+  case ltMARGINPARSEP:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      int twips = (int)(20*ParseUnitArgument(val));
+      CurrentMarginParSep = twips;
+      CurrentMarginParX = CurrentLeftMarginOdd + CurrentTextWidth + CurrentMarginParSep;
+    }
+    return FALSE;
+  }
+  case ltTEXTWIDTH:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      int twips = (int)(20*ParseUnitArgument(val));
+      CurrentTextWidth = twips;
+
+      // Need to set an implicit right margin
+      CurrentRightMarginOdd = PageWidth - CurrentTextWidth - CurrentLeftMarginOdd;
+      CurrentRightMarginEven = PageWidth - CurrentTextWidth - CurrentLeftMarginEven;
+      CurrentMarginParX = CurrentLeftMarginOdd + CurrentTextWidth + CurrentMarginParSep;
+      sprintf(buf, "\\margr%d\n", CurrentRightMarginOdd);
+      TexOutput(buf);
+    }
+    return FALSE;
+  }
+  case ltMARGINPAR:
+  case ltMARGINPARODD:
+  {
+    if (start)
+    {
+      if (winHelp)
+      {
+        TexOutput("\\box\n");
+        PushEnvironmentStyle("\\box");
+      }
+      else
+      {
+        sprintf(buf, "\\phpg\\posx%d\\absw%d\n", CurrentMarginParX, CurrentMarginParWidth);
+        TexOutput(buf);
+      }
+      return TRUE;
+    }
+    else
+    {
+      if (winHelp)
+      {
+        TexOutput("\\par\\pard\n");
+        PopEnvironmentStyle();
+        WriteEnvironmentStyles();
+      }
+      else
+        TexOutput("\\par\\pard\n");
+      issuedNewParagraph = 1;
+    }
+    return FALSE;
+  }
+  case ltMARGINPAREVEN:
+  {
+    if (start)
+    {
+      if (winHelp)
+      {
+        TexOutput("\\box\n");
+        PushEnvironmentStyle("\\box");
+      }
+      else
+      {
+        if (mirrorMargins)
+        {
+          // Have to calculate what the margins are changed to in WfW margin
+          // mirror mode, on an even (left-hand) page.
+          int x = PageWidth - CurrentRightMarginOdd - CurrentMarginParWidth - CurrentMarginParSep
+                    - CurrentTextWidth + GutterWidth;
+          sprintf(buf, "\\phpg\\posx%d\\absw%d\n", x, CurrentMarginParWidth);
+          TexOutput(buf);
+        }
+        else
+        {
+          sprintf(buf, "\\phpg\\posx%d\\absw%d\n", CurrentMarginParX, CurrentMarginParWidth);
+          TexOutput(buf);
+        }
+      }
+      return TRUE;
+    }
+    else
+    {
+      if (winHelp)
+      {
+        TexOutput("\\par\\pard\n");
+        PopEnvironmentStyle();
+        WriteEnvironmentStyles();
+      }
+      else
+        issuedNewParagraph = 1;
+      TexOutput("\\par\\pard\n");
+    }
+    return FALSE;
+  }
+  case ltTWOCOLWIDTHA:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      int twips = (int)(20*ParseUnitArgument(val));
+      TwoColWidthA = twips;
+    }
+    return FALSE;
+    break;
+  }
+  case ltTWOCOLWIDTHB:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      int twips = (int)(20*ParseUnitArgument(val));
+      TwoColWidthB = twips;
+    }
+    return FALSE;
+    break;
+  }
+  case ltROW:
+  case ltRULEDROW:
+  {
+    if (start)
+    {
+      int currentWidth = 0;
+
+      if (!compatibilityMode || (currentRowNumber > 0))
+      {
+      TexOutput("\\pard\\intbl");
+
+      if (macroId == ltRULEDROW)
+        ruleBottom = 1;
+      for (int i = 0; i < noColumns; i++)
+      {
+        currentWidth += TableData[i].width;
+        if (ruleTop == 1)
+        {
+          TexOutput("\\clbrdrt\\brdrs\\brdrw15");
+        }
+        else if (ruleTop > 1)
+        {
+          TexOutput("\\clbrdrt\\brdrdb\\brdrw15");
+        }
+        if (ruleBottom == 1)
+        {
+          TexOutput("\\clbrdrb\\brdrs\\brdrw15");
+        }
+        else if (ruleBottom > 1)
+        {
+          TexOutput("\\clbrdrb\\brdrdb\\brdrw15");
+        }
+
+        if (TableData[i].rightBorder)
+          TexOutput("\\clbrdrr\\brdrs\\brdrw15");
+
+        if (TableData[i].leftBorder)
+          TexOutput("\\clbrdrl\\brdrs\\brdrw15");
+          
+        sprintf(buf, "\\cellx%d", currentWidth);
+        TexOutput(buf);
+      }
+      TexOutput("\\pard\\intbl\n");
+      }
+      ruleTop = 0;
+      ruleBottom = 0;
+      currentRowNumber ++;
+      return TRUE;
+    }
+    else
+    {
+//      TexOutput("\\cell\\row\\trowd\\trgaph108\\trleft-108\n");
+      TexOutput("\\cell\\row\\trowd\\trgaph108\n");
+    }
+    break;
+  }
+  case ltMULTICOLUMN:
+  {
+    static int noMultiColumns = 0;
+    if (start)
+    {
+      switch (arg_no)
+      {
+        case 1:
+        {
+          noMultiColumns = atoi(GetArgData());
+          return FALSE;
+          break;
+        }
+        case 2:
+        {
+          return FALSE;
+        }
+        case 3:
+        {
+          return TRUE;
+        }
+      }
+    }
+    else
+    {
+      if (arg_no == 3)
+      {
+        for (int i = 1; i < noMultiColumns; i ++)
+          TexOutput("\\cell");
+      }
+    }
+    break;
+  }
+  case ltINDENTED:
+  {
+    if (start && (arg_no == 1))
+    {
+//      indentLevel ++;
+//      TexOutput("\\fi0\n");
+      int oldIndent = 0;
+      wxNode *node = itemizeStack.First();
+      if (node)
+        oldIndent = ((ItemizeStruc *)node->Data())->indentation;
+
+      int indentValue = 20*ParseUnitArgument(GetArgData());
+      int indentSize = indentValue + oldIndent;
+
+      ItemizeStruc *struc = new ItemizeStruc(LATEX_INDENT, indentSize);
+      itemizeStack.Insert(struc);
+      
+      sprintf(buf, "\\tx%d\\li%d ", indentSize, indentSize);
+      PushEnvironmentStyle(buf);
+      TexOutput(buf);
+      return FALSE;
+    }
+    if (!start && (arg_no == 2))
+    {
+      PopEnvironmentStyle();
+      if (itemizeStack.First())
+      {
+        ItemizeStruc *struc = (ItemizeStruc *)itemizeStack.First()->Data();
+        delete struc;
+        delete itemizeStack.First();
+      }
+      if (itemizeStack.Number() == 0)
+      {
+        TexOutput("\\par\\pard\n");
+        issuedNewParagraph = 1;
+        WriteEnvironmentStyles();
+      }
+    }
+    return TRUE;
+    break;
+  }
+/*
+  case ltSIZEDBOX:
+  case ltSIZEDBOXD:
+  {
+    if (start && (arg_no == 1))
+    {
+      int oldIndent = 0;
+      wxNode *node = itemizeStack.First();
+      if (node)
+        oldIndent = ((ItemizeStruc *)node->Data())->indentation;
+
+      int boxWidth = 20*ParseUnitArgument(GetArgData());
+
+      int indentValue = (int)((CurrentTextWidth - oldIndent - boxWidth)/2.0);
+      int indentSize = indentValue + oldIndent;
+      int indentSizeRight = indentSize + boxWidth;
+
+      ItemizeStruc *struc = new ItemizeStruc(LATEX_INDENT, indentSize);
+      itemizeStack.Insert(struc);
+      
+      sprintf(buf, "\\tx%d\\li%d\\lr%d\\box%s ", indentSize, indentSize, indentSizeRight,
+        ((macroId == ltCENTEREDBOX) ? "\\brdrs" : "\\brdrdb"));
+      PushEnvironmentStyle(buf);
+      TexOutput(buf);
+      return FALSE;
+    }
+    if (!start && (arg_no == 2))
+    {
+      PopEnvironmentStyle();
+      if (itemizeStack.First())
+      {
+        ItemizeStruc *struc = (ItemizeStruc *)itemizeStack.First()->Data();
+        delete struc;
+        delete itemizeStack.First();
+      }
+      if (itemizeStack.Number() == 0)
+      {
+        TexOutput("\\par\\pard\n");
+        issuedNewParagraph = 1;
+        WriteEnvironmentStyles();
+      }
+    }
+    return TRUE;
+    break;
+  }
+*/
+  case ltDOCUMENTSTYLE:
+  {
+    DefaultOnArgument(macroId, arg_no, start);
+    if (!start && !IsArgOptional())
+    {
+      if (MinorDocumentStyleString)
+      {
+        if (StringMatch("twoside", MinorDocumentStyleString))
+          // Mirror margins, switch on odd/even headers & footers, and break sections at odd pages
+          TexOutput("\\margmirror\\facingp\\sbkodd");
+        if (StringMatch("twocolumn", MinorDocumentStyleString))
+          TexOutput("\\cols2");
+      }
+      TexOutput("\n");
+    }
+    return FALSE;
+  }
+  case ltSETHOTSPOTCOLOUR:
+  case ltSETHOTSPOTCOLOR:
+  {
+    if (!start)
+    {
+      char *text = GetArgData();
+      if (strcmp(text, "yes") == 0 || strcmp(text, "on") == 0 || strcmp(text, "ok") == 0)
+        hotSpotColour = TRUE;
+      else
+        hotSpotColour = FALSE;
+    }
+    return FALSE;
+  }
+  case ltSETTRANSPARENCY:
+  {
+    if (!start)
+    {
+      char *text = GetArgData();
+      if (strcmp(text, "yes") == 0 || strcmp(text, "on") == 0 || strcmp(text, "ok") == 0)
+        bitmapTransparency = TRUE;
+      else
+        bitmapTransparency = FALSE;
+    }
+    return FALSE;
+  }
+  case ltSETHOTSPOTUNDERLINE:
+  {
+    if (!start)
+    {
+      char *text = GetArgData();
+      if (strcmp(text, "yes") == 0 || strcmp(text, "on") == 0 || strcmp(text, "ok") == 0)
+        hotSpotUnderline = TRUE;
+      else
+        hotSpotUnderline = FALSE;
+    }
+    return FALSE;
+  }
+  case ltBIBITEM:
+  {
+    if (arg_no == 1 && start)
+    {
+      char *citeKey = GetArgData();
+      TexRef *ref = (TexRef *)TexReferences.Get(citeKey);
+      if (ref)
+      {
+        if (ref->sectionNumber) delete[] ref->sectionNumber;
+        sprintf(buf, "[%d]", citeCount);
+        ref->sectionNumber = copystring(buf);
+      }
+
+      TexOutput("\\li260\\fi-260 "); // Indent from 2nd line
+      sprintf(buf, "{\\b [%d]} ", citeCount);
+      TexOutput(buf);
+      citeCount ++;
+      return FALSE;
+    }
+    if (arg_no == 2 && !start)
+      TexOutput("\\par\\pard\\par\n\n");
+    return TRUE;
+    break;
+  }
+  case ltTHEBIBLIOGRAPHY:
+  {
+    if (start && (arg_no == 1))
+    {
+      citeCount = 1;
+      if (winHelp)
+        SetCurrentOutputs(Contents, Chapters);
+
+      if (!winHelp)
+      {
+        fprintf(Chapters, "\\sect\\pgncont\\titlepg\n");
+
+        // If a non-custom page style, we generate the header now.
+        if (PageStyle && (strcmp(PageStyle, "plain") == 0 ||
+                          strcmp(PageStyle, "empty") == 0 ||
+                          strcmp(PageStyle, "headings") == 0))
+        {
+          OutputRTFHeaderCommands();
+          OutputRTFFooterCommands();
+        }
+        
+        // Need to reset the current numbering style, or RTF forgets it.
+        OutputNumberStyle(currentNumberStyle);
+        SetCurrentOutput(Contents);
+      }
+      else
+        fprintf(Chapters, "\\page\n");
+
+      if (winHelp)
+        fprintf(Contents, "\n{\\uldb %s}", ReferencesNameString);
+      else
+        fprintf(Contents, "\\par\n\\pard{\\b %s}", ReferencesNameString);
+
+      startedSections = TRUE;
+
+      if (winHelp)
+        fprintf(Chapters, "\n${\\footnote %s}", ReferencesNameString);
+
+      char *topicName = "bibliography";
+
+      if (winHelp)
+        fprintf(Contents, "{\\v %s}\\par\\pard\n", topicName);
+      else
+        fprintf(Contents, "\\par\\par\\pard\n");
+
+      if (winHelp)
+      {
+        fprintf(Chapters, "\n#{\\footnote %s}\n", topicName);
+        fprintf(Chapters, "+{\\footnote %s}\n", GetBrowseString());
+        fprintf(Chapters, "K{\\footnote {K} %s}\n", ReferencesNameString);
+        GenerateKeywordsForTopic(topicName);
+        if (useUpButton)
+        {
+          fprintf(Chapters, "!{\\footnote EnableButton(\"Up\");ChangeButtonBinding(\"Up\", \"JumpId(`%s.hlp', `%s')\")}\n",
+               FileNameFromPath(FileRoot), "Contents");
+        }
+      }
+      
+      SetCurrentOutput(Chapters);
+      char *styleCommand = "";
+      if (!winHelp && useHeadingStyles)
+        styleCommand = "\\s1";
+      fprintf(Chapters, "\\pard{%s", (winHelp ? "\\keepn\\sa140\\sb140" : styleCommand));
+      WriteHeadingStyle(Chapters, 1);  fprintf(Chapters, " References\\par\\pard}\n");
+
+      return FALSE;
+    }
+    return TRUE;
+    break;
+  }
+  case ltINDEX:
+  {
+    /*
+     * In Windows help, all keywords should be at the start of the
+     * topic, but Latex \index commands can be anywhere in the text.
+     * So we're going to have to build up lists of keywords for a topic,
+     * and insert them on the second pass.
+     *
+     * In linear RTF, we can embed the index entry now.
+     *
+     */
+    if (start)
+    {
+//      char *entry = GetArgData();
+      char buf[300];
+      OutputChunkToString(GetArgChunk(), buf);
+      if (winHelp)
+      {
+        if (CurrentTopic)
+        {
+          AddKeyWordForTopic(CurrentTopic, buf);
+        }
+      }
+      else GenerateIndexEntry(buf);
+    }
+    return FALSE;
+    break;
+  }
+  case ltFCOL:
+  case ltBCOL:
+  {
+    if (start)
+    {
+      switch (arg_no)
+      {
+        case 1:
+        {
+          char *name = GetArgData();
+          int pos = FindColourPosition(name);
+          if (pos > -1)
+          {
+            sprintf(buf, "{%s%d ", ((macroId == ltFCOL) ? "\\cf" : "\\cb"), pos);
+            TexOutput(buf);
+          }
+                 else
+                 {
+                       sprintf(buf, "Could not find colour name %s", name);
+            OnError(buf);
+                 }
+          break;
+        }
+        case 2:
+        {
+          return TRUE;
+          break;
+        }
+        default:
+          break;
+      }
+    }
+    else
+    {
+      if (arg_no == 2) TexOutput("}");
+    }
+    return FALSE;
+    break;
+  }
+  case ltLABEL:
+  {
+    if (start && !winHelp && useWord)
+    {
+      char *s = GetArgData();
+      // Only insert a bookmark here if it's not just been inserted
+      // in a section heading.
+      if ( !CurrentTopic || !(strcmp(CurrentTopic, s) == 0) )
+/*
+      if ( (!CurrentChapterName || !(CurrentChapterName && (strcmp(CurrentChapterName, s) == 0))) &&
+           (!CurrentSectionName || !(CurrentSectionName && (strcmp(CurrentSectionName, s) == 0))) &&
+           (!CurrentSubsectionName || !(CurrentSubsectionName && (strcmp(CurrentSubsectionName, s) == 0)))
+         )
+*/
+      {
+          fprintf(Chapters, "{\\bkmkstart %s}{\\bkmkend %s}", s,s);
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltPAGEREF:
+  {
+    if (start && useWord && !winHelp)
+    {
+      char *s = GetArgData();
+      fprintf(Chapters, "{\\field{\\*\\fldinst  PAGEREF %s \\\\* MERGEFORMAT }{\\fldrslt ??}}",
+              s);
+    }
+    return FALSE;
+    break;
+  }
+  case ltPOPREFONLY:
+  {
+    if (start)
+      inPopRefSection = TRUE;
+    else
+      inPopRefSection = FALSE;
+    break;
+  }
+  case ltINSERTATLEVEL:
+  {
+    // This macro allows you to insert text at a different level
+    // from the current level, e.g. into the Sections from within a subsubsection.
+    if (!winHelp & useWord)
+        return FALSE;
+    static int currentLevelNo = 1;
+    static FILE* oldLevelFile = Chapters;
+    if (start)
+    {
+      switch (arg_no)
+      {
+        case 1:
+        {
+          oldLevelFile = CurrentOutput1;
+
+          char *str = GetArgData();
+          currentLevelNo = atoi(str);
+          FILE* outputFile;
+          // TODO: cope with article style (no chapters)
+          switch (currentLevelNo)
+          {
+            case 1:
+            {
+                outputFile = Chapters;
+                break;
+            }
+            case 2:
+            {
+                outputFile = Sections;
+                break;
+            }
+            case 3:
+            {
+                outputFile = Subsections;
+                break;
+            }
+            case 4:
+            {
+                outputFile = Subsubsections;
+                break;
+            }
+            default:
+            {
+                outputFile = NULL;
+                break;
+            }
+          }
+          if (outputFile)
+            CurrentOutput1 = outputFile;
+          return FALSE;
+          break;
+        }
+        case 2:
+        {
+          return TRUE;
+          break;
+        }
+        default:
+          break;
+      }
+      return TRUE;
+    }
+    else
+    {
+        if (arg_no == 2)
+        {
+            CurrentOutput1 = oldLevelFile;
+        }
+        return TRUE;
+    }
+    break;
+  }
+  default:
+  {
+    return DefaultOnArgument(macroId, arg_no, start);
+    break;
+  }
+  }
+  return TRUE;
+}
+
+bool RTFGo(void)
+{
+  // Reset variables
+  indentLevel = 0;
+  forbidParindent = 0;
+  contentsLineSection = NULL;
+  contentsLineValue = NULL;
+  descriptionItemArg = NULL;
+  inTabular = FALSE;
+  inTable = FALSE;
+  inFigure = FALSE;
+  startRows = FALSE;
+  tableVerticalLineLeft = FALSE;
+  tableVerticalLineRight = FALSE;
+  noColumns = 0;
+  startedSections = FALSE;
+  inVerbatim = FALSE;
+  browseId = 0;
+  
+  if (InputFile && OutputFile)
+  {
+    // Do some RTF-specific transformations on all the strings,
+    // recursively
+    Text2RTF(GetTopLevelChunk());
+
+    Contents = fopen(TmpContentsName, "w");
+    Chapters = fopen("chapters.rtf", "w");
+    if (winHelp)
+    {
+      Sections = fopen("sections.rtf", "w");
+      Subsections = fopen("subsections.rtf", "w");
+      Subsubsections = fopen("subsubsections.rtf", "w");
+      Popups = fopen("popups.rtf", "w");
+      if (winHelpContents)
+      {
+        WinHelpContentsFile = fopen(WinHelpContentsFileName, "w");
+        if (WinHelpContentsFile)
+          fprintf(WinHelpContentsFile, ":Base %s.hlp\n", wxFileNameFromPath(FileRoot));
+      }
+
+      if (!Sections || !Subsections || !Subsubsections || !Popups || (winHelpContents && !WinHelpContentsFile))
+      {
+        OnError("Ouch! Could not open temporary file(s) for writing.");
+        return FALSE;
+      }
+    }
+    if (!Contents || !Chapters)
+    {
+      OnError("Ouch! Could not open temporary file(s) for writing.");
+      return FALSE;
+    }
+
+    if (winHelp)
+    {
+      fprintf(Chapters, "\n#{\\footnote Contents}\n");
+      fprintf(Chapters, "${\\footnote Contents}\n");
+      fprintf(Chapters, "+{\\footnote %s}\n", GetBrowseString());
+      fprintf(Chapters, "K{\\footnote {K} %s}\n", ContentsNameString);
+      fprintf(Chapters, "!{\\footnote DisableButton(\"Up\")}\n");
+    }
+    if (!winHelp)
+    {
+      fprintf(Chapters, "\\titlepg\n");
+      fprintf(Contents, "\\par\\pard\\pgnrestart\\sect\\titlepg");
+    }
+    
+    // In WinHelp, Contents title takes font of title.
+    // In linear RTF, same as chapter headings.
+    fprintf(Contents, "{\\b\\fs%d %s}\\par\\par\\pard\n\n",
+      (winHelp ? titleFont : chapterFont)*2, ContentsNameString);
+
+    // By default, Swiss, 10 point.
+    fprintf(Chapters, "\\f2\\fs20\n");
+
+    SetCurrentOutput(Chapters);
+
+    OnInform("Converting...");
+
+    TraverseDocument();
+
+    FILE *Header = fopen("header.rtf", "w");
+    if (!Header)
+    {
+      OnError("Ouch! Could not open temporary file header.rtf for writing.");
+      return FALSE;
+    }
+    WriteRTFHeader(Header);
+    fclose(Header); Header = NULL;
+    
+    Tex2RTFYield(TRUE);
+    if (winHelp)
+    {
+//      fprintf(Contents, "\\page\n");
+      fprintf(Chapters, "\\page\n");
+      fprintf(Sections, "\\page\n");
+      fprintf(Subsections, "\\page\n");
+      fprintf(Subsubsections, "\\page\n\n");
+      fprintf(Popups, "\\page\n}\n");
+    }
+
+//    TexOutput("\n\\info{\\doccomm Document created by Julian Smart's Tex2RTF.}\n");
+    if (!winHelp)
+      TexOutput("}\n");
+    fclose(Contents); Contents = NULL;
+    fclose(Chapters); Chapters = NULL;
+    if (winHelp)
+    {
+      fclose(Sections); Sections = NULL;
+      fclose(Subsections); Subsections = NULL;
+      fclose(Subsubsections); Subsubsections = NULL;
+      fclose(Popups); Popups = NULL;
+      if (winHelpContents)
+      {
+        fclose(WinHelpContentsFile); WinHelpContentsFile = NULL;
+      }
+    }
+
+    if (winHelp)
+    {
+      wxConcatFiles("header.rtf", "chapters.rtf", "tmp1.rtf");
+      Tex2RTFYield(TRUE);
+      wxConcatFiles("tmp1.rtf", "sections.rtf", "tmp2.rtf");
+      Tex2RTFYield(TRUE);
+      wxConcatFiles("tmp2.rtf", "subsections.rtf", "tmp3.rtf");
+      Tex2RTFYield(TRUE);
+      wxConcatFiles("tmp3.rtf", "subsubsections.rtf", "tmp4.rtf");
+      Tex2RTFYield(TRUE);
+      wxConcatFiles("tmp4.rtf", "popups.rtf", OutputFile);
+      Tex2RTFYield(TRUE);
+
+      wxRemoveFile("tmp1.rtf");
+      wxRemoveFile("tmp2.rtf");
+      wxRemoveFile("tmp3.rtf");
+      wxRemoveFile("tmp4.rtf");
+    }
+    else
+    {
+      wxConcatFiles("header.rtf", "chapters.rtf", "tmp1.rtf");
+      Tex2RTFYield(TRUE);
+      if (FileExists(OutputFile)) wxRemoveFile(OutputFile);
+      wxCopyFile("tmp1.rtf", OutputFile);
+      Tex2RTFYield(TRUE);
+      wxRemoveFile("tmp1.rtf");
+    }
+    
+    if (FileExists(ContentsName)) wxRemoveFile(ContentsName);
+
+    if (!wxRenameFile(TmpContentsName, ContentsName))
+    {
+      wxCopyFile(TmpContentsName, ContentsName);
+      wxRemoveFile(TmpContentsName);
+    }
+
+    wxRemoveFile("chapters.rtf");
+    wxRemoveFile("header.rtf");
+      
+    if (winHelp)
+    {
+      wxRemoveFile("sections.rtf");
+      wxRemoveFile("subsections.rtf");
+      wxRemoveFile("subsubsections.rtf");
+      wxRemoveFile("popups.rtf");
+    }
+    if (winHelp && generateHPJ)
+      WriteHPJ(OutputFile);
+    return TRUE;
+  }
+  return FALSE;
+}
diff --git a/utils/tex2rtf/src/rtfutils.h b/utils/tex2rtf/src/rtfutils.h
new file mode 100644 (file)
index 0000000..9f2cf95
--- /dev/null
@@ -0,0 +1,60 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        rtfutils.h
+// Purpose:     RTF-specific code
+// Author:      Julian Smart
+// Modified by:
+// Created:     7.9.93
+// RCS-ID:      $Id$
+// Copyright:   (c) Julian Smart
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+ /*
+  * Write a suitable RTF header.
+  *
+  */
+  
+void WriteRTFHeader(FILE *fd);
+
+/*
+ * Given a TexChunk with a string value, scans through the string
+ * converting Latex-isms into RTF-isms, such as 2 newlines -> \par,
+ * and inserting spaces at the start of lines since in Latex, a newline
+ * implies a space, but not in RTF.
+ *
+ */
+void ProcessText2RTF(TexChunk *chunk);
+
+/*
+ * Scan through all chunks starting from the given one,
+ * calling ProcessText2RTF to convert Latex-isms to RTF-isms.
+ * This should be called after Tex2Any has parsed the file,
+ * and before TraverseDocument is called.
+ *
+ */
+void Text2RTF(TexChunk *chunk);
+
+
+/*
+ * Keeping track of environments to restore the styles after \pard.
+ * Push strings like "\qc" onto stack.
+ *
+ */
+
+void PushEnvironmentStyle(char *style);
+
+void PopEnvironmentStyle(void);
+
+// Write out the styles, most recent first.
+void WriteEnvironmentStyles(void);
+
+// Called on start/end of macro examination
+void DefaultRtfOnMacro(char *name, int no_args, bool start);
+
+// Called on start/end of argument examination
+bool DefaultRtfOnArgument(char *macro_name, int arg_no, bool start);
+
+// Reset memory of which levels have 'books' (for WinHelp 4 contents file)
+void ResetContentsLevels(int level);
diff --git a/utils/tex2rtf/src/table.cpp b/utils/tex2rtf/src/table.cpp
new file mode 100644 (file)
index 0000000..4dc88ee
--- /dev/null
@@ -0,0 +1,156 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        table.cpp
+// Purpose:     Utilities for manipulating tables
+// Author:      Julian Smart
+// Modified by:
+// Created:     01/01/99
+// RCS-ID:      $Id$
+// Copyright:   (c) Julian Smart
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+
+#include <wx/hash.h>
+
+#if wxUSE_IOSTREAMH
+#include <iostream.h>
+#include <fstream.h>
+#else
+#include <iostream>
+#include <fstream>
+#endif
+
+#include <ctype.h>
+#include "tex2any.h"
+#include "table.h"
+
+ColumnData TableData[40];
+bool inTabular = FALSE;
+
+bool startRows = FALSE;
+bool tableVerticalLineLeft = FALSE;
+bool tableVerticalLineRight = FALSE;
+int noColumns = 0;   // Current number of columns in table
+int ruleTop = 0;
+int ruleBottom = 0;
+int currentRowNumber = 0;
+
+/*
+ * Parse table argument
+ *
+ */
+
+bool ParseTableArgument(char *value)
+{
+  noColumns = 0;
+  int i = 0;
+  int len = strlen(value);
+  bool isBorder = FALSE;
+  while (i < len)
+  {
+    int ch = value[i];
+    if (ch == '|')
+    {
+      i ++;
+      isBorder = TRUE;
+    }
+    else if (ch == 'l')
+    {
+      TableData[noColumns].leftBorder = isBorder;
+      TableData[noColumns].rightBorder = FALSE;
+      TableData[noColumns].justification = 'l';
+      TableData[noColumns].width = 2000; // Estimate
+      TableData[noColumns].absWidth = FALSE;
+//      TableData[noColumns].spacing = ??
+      noColumns ++;
+      i ++;
+      isBorder = FALSE;
+    }
+    else if (ch == 'c')
+    {
+      TableData[noColumns].leftBorder = isBorder;
+      TableData[noColumns].rightBorder = FALSE;
+      TableData[noColumns].justification = 'c';
+      TableData[noColumns].width = defaultTableColumnWidth; // Estimate
+      TableData[noColumns].absWidth = FALSE;
+//      TableData[noColumns].spacing = ??
+      noColumns ++;
+      i ++;
+      isBorder = FALSE;
+    }
+    else if (ch == 'r')
+    {
+      TableData[noColumns].leftBorder = isBorder;
+      TableData[noColumns].rightBorder = FALSE;
+      TableData[noColumns].justification = 'r';
+      TableData[noColumns].width = 2000; // Estimate
+      TableData[noColumns].absWidth = FALSE;
+//      TableData[noColumns].spacing = ??
+      noColumns ++;
+      i ++;
+      isBorder = FALSE;
+    }
+    else if (ch == 'p')
+    {
+      i ++;
+      int j = 0;
+      char numberBuf[50];
+      ch = value[i];
+      if (ch == '{')
+      {
+        i++;
+        ch = value[i];
+      }
+        
+      while ((i < len) && (isdigit(ch) || ch == '.'))
+      {
+        numberBuf[j] = ch;
+        j ++;
+        i ++;
+        ch = value[i];
+      }
+      // Assume we have 2 characters for units
+      numberBuf[j] = value[i];
+      j ++; i++;
+      numberBuf[j] = value[i];
+      j ++; i++;
+      numberBuf[j] = 0;
+      if (value[i] == '}') i++;
+      
+      TableData[noColumns].leftBorder = isBorder;
+      TableData[noColumns].rightBorder = FALSE;
+      TableData[noColumns].justification = 'l';
+      TableData[noColumns].width = 20*ParseUnitArgument(numberBuf);
+      TableData[noColumns].absWidth = TRUE;
+//      TableData[noColumns].spacing = ??
+      noColumns ++;
+      isBorder = FALSE;
+    }
+    else
+    {
+      char *buf = new char[strlen(value) + 80];
+      sprintf(buf, "Tabular first argument \"%s\" too complex!", value);
+      OnError(buf);
+      delete[] buf;
+      return FALSE;
+    }
+  }
+  if (isBorder)
+    TableData[noColumns-1].rightBorder = TRUE;
+  return TRUE;
+}
diff --git a/utils/tex2rtf/src/table.h b/utils/tex2rtf/src/table.h
new file mode 100644 (file)
index 0000000..d2235f2
--- /dev/null
@@ -0,0 +1,36 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        table.h
+// Purpose:     Table utilities
+// Author:      Julian Smart
+// Modified by:
+// Created:     7.9.93
+// RCS-ID:      $Id$
+// Copyright:   (c) Julian Smart
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+/*
+ * Table dimensions
+ *
+ */
+
+struct ColumnData
+{
+  char justification; // l, r, c
+  int width;          // -1 or a width in twips
+  int spacing;        // Space between columns in twips
+  bool leftBorder;
+  bool rightBorder;
+  bool absWidth;      // If FALSE (the default), don't use an absolute width if you can help it.
+};
+
+extern ColumnData TableData[];
+extern bool inTabular;
+extern bool startRows;
+extern bool tableVerticalLineLeft;
+extern bool tableVerticalLineRight;
+extern int noColumns;   // Current number of columns in table
+extern int ruleTop;
+extern int ruleBottom;
+extern int currentRowNumber;
+extern bool ParseTableArgument(char *value);
diff --git a/utils/tex2rtf/src/tex2any.cpp b/utils/tex2rtf/src/tex2any.cpp
new file mode 100644 (file)
index 0000000..40e159e
--- /dev/null
@@ -0,0 +1,3482 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        tex2any.cpp
+// Purpose:     Utilities for Latex conversion.
+// Author:      Julian Smart
+// Modified by:
+// Created:     01/01/99
+// RCS-ID:      $Id$
+// Copyright:   (c) Julian Smart
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+#include <ctype.h>
+#include "tex2any.h"
+#include <stdlib.h>
+#include <time.h>
+
+/*
+ * Variables accessible from clients
+ *
+ */
+TexChunk *      DocumentTitle = NULL;
+TexChunk *      DocumentAuthor = NULL;
+TexChunk *      DocumentDate = NULL;
+
+// Header/footers/pagestyle
+TexChunk *      LeftHeaderEven = NULL;
+TexChunk *      LeftFooterEven = NULL;
+TexChunk *      CentreHeaderEven = NULL;
+TexChunk *      CentreFooterEven = NULL;
+TexChunk *      RightHeaderEven = NULL;
+TexChunk *      RightFooterEven = NULL;
+TexChunk *      LeftHeaderOdd = NULL;
+TexChunk *      LeftFooterOdd = NULL;
+TexChunk *      CentreHeaderOdd = NULL;
+TexChunk *      CentreFooterOdd = NULL;
+TexChunk *      RightHeaderOdd = NULL;
+TexChunk *      RightFooterOdd = NULL;
+char *          PageStyle = copystring("plain");
+
+int             DocumentStyle = LATEX_REPORT;
+int             MinorDocumentStyle = 0;
+wxPathList      TexPathList;
+char *          BibliographyStyleString = copystring("plain");
+char *          DocumentStyleString = copystring("report");
+char *          MinorDocumentStyleString = NULL;
+int             ParSkip = 0;
+int             ParIndent = 0;
+
+int             normalFont = 10;
+int             smallFont = 8;
+int             tinyFont = 6;
+int             largeFont1 = 12;
+int             LargeFont2 = 14;
+int             LARGEFont3 = 18;
+int             hugeFont1 = 20;
+int             HugeFont2 = 24;
+int             HUGEFont3 = 28;
+
+/*
+ * USER-ADJUSTABLE SETTINGS
+ *
+ */
+
+// Section font sizes
+int             chapterFont =    12; // LARGEFont3;
+int             sectionFont =    12; // LargeFont2;
+int             subsectionFont = 12; // largeFont1;
+int             titleFont = LARGEFont3;
+int             authorFont = LargeFont2;
+int             mirrorMargins = TRUE;
+bool            winHelp = FALSE;  // Output in Windows Help format if TRUE, linear otherwise
+bool            isInteractive = FALSE;
+bool            runTwice = FALSE;
+int             convertMode = TEX_RTF;
+bool            headerRule = FALSE;
+bool            footerRule = FALSE;
+bool            compatibilityMode = FALSE; // If TRUE, maximum Latex compatibility
+                                // (Quality of RTF generation deteriorate)
+bool            generateHPJ; // Generate WinHelp Help Project file
+char            *winHelpTitle = NULL; // Windows Help title
+int             defaultTableColumnWidth = 2000;
+
+int             labelIndentTab = 18;  // From left indent to item label (points)
+int             itemIndentTab = 40;   // From left indent to item (points)
+
+bool            useUpButton = TRUE;
+int             htmlBrowseButtons = HTML_BUTTONS_TEXT;
+
+bool            truncateFilenames = FALSE; // Truncate for DOS
+int             winHelpVersion = 3; // WinHelp Version (3 for Windows 3.1, 4 for Win95)
+bool            winHelpContents = FALSE; // Generate .cnt file for WinHelp 4
+bool            htmlIndex = FALSE; // Generate .htx file for HTML
+bool            htmlFrameContents = FALSE; // Use frames for HTML contents page
+bool            useHeadingStyles = TRUE; // Insert \s1, s2 etc.
+bool            useWord = TRUE; // Insert proper Word table of contents, etc etc
+int             contentsDepth = 4; // Depth of Word table of contents
+bool            indexSubsections = TRUE; // Index subsections in linear RTF
+// Linear RTF method of including bitmaps. Can be "includepicture", "hex"
+char            *bitmapMethod = copystring("includepicture");
+bool            upperCaseNames = FALSE;
+// HTML background and text colours
+char            *backgroundImageString = NULL;
+char            *backgroundColourString = copystring("255;255;255");
+char            *textColourString = NULL;
+char            *linkColourString = NULL;
+char            *followedLinkColourString = NULL;
+bool            combineSubSections = FALSE;
+
+/*
+ * International support
+ */
+
+// Names to help with internationalisation
+char *ContentsNameString = copystring("Contents");
+char *AbstractNameString = copystring("Abstract");
+char *GlossaryNameString = copystring("Glossary");
+char *ReferencesNameString = copystring("References");
+char *FiguresNameString = copystring("List of Figures");
+char *TablesNameString = copystring("List of Tables");
+char *FigureNameString = copystring("Figure");
+char *TableNameString = copystring("Table");
+char *IndexNameString = copystring("Index");
+char *ChapterNameString = copystring("chapter");
+char *SectionNameString = copystring("section");
+char *SubsectionNameString = copystring("subsection");
+char *SubsubsectionNameString = copystring("subsubsection");
+char *UpNameString = copystring("Up");
+
+/*
+ * Section numbering
+ *
+ */
+int             chapterNo = 0;
+int             sectionNo = 0;
+int             subsectionNo = 0;
+int             subsubsectionNo = 0;
+int             figureNo = 0;
+int             tableNo = 0;
+
+/*
+ * Other variables
+ *
+ */
+FILE *CurrentOutput1 = NULL;
+FILE *CurrentOutput2 = NULL;
+FILE *Inputs[15];
+int LineNumbers[15];
+char *FileNames[15];
+int CurrentInputIndex = 0;
+
+char *TexFileRoot = NULL;
+char *TexBibName = NULL;         // Bibliography output file name
+char *TexTmpBibName = NULL;      // Temporary bibliography output file name
+bool isSync = FALSE;             // If TRUE, should not yield to other processes.
+bool stopRunning = FALSE;        // If TRUE, should abort.
+
+static int currentColumn = 0;
+char *currentArgData = NULL;
+bool haveArgData = FALSE; // If TRUE, we're simulating the data.
+TexChunk *currentArgument = NULL;
+TexChunk *nextChunk = NULL;
+bool isArgOptional = FALSE;
+bool noArgs = 0;
+
+TexChunk *TopLevel = NULL;
+// wxList MacroDefs(wxKEY_STRING);
+wxHashTable MacroDefs(wxKEY_STRING);
+wxStringList IgnorableInputFiles; // Ignorable \input files, e.g. psbox.tex
+char *BigBuffer = NULL;  // For reading in large chunks of text
+TexMacroDef *SoloBlockDef = NULL;
+TexMacroDef *VerbatimMacroDef = NULL;
+
+#define IncrementLineNumber() LineNumbers[CurrentInputIndex] ++
+
+void TexOutput(char *s, bool ordinaryText)
+{
+  int len = strlen(s);
+
+  // Update current column, but only if we're guaranteed to
+  // be ordinary text (not mark-up stuff)
+  int i;
+  if (ordinaryText)
+    for (i = 0; i < len; i++)
+    {
+      if (s[i] == 13 || s[i] == 10)
+        currentColumn = 0;
+      else
+        currentColumn ++;
+    }
+
+  if (CurrentOutput1)
+    fprintf(CurrentOutput1, "%s", s);
+  if (CurrentOutput2)
+    fprintf(CurrentOutput2, "%s", s);
+}
+
+/*
+ * Try to find a Latex macro, in one of the following forms:
+ * (1) \begin{} ... \end{}
+ * (2) \macroname{arg1}...{argn}
+ * (3) {\bf arg1}
+ */
+
+void ForbidWarning(TexMacroDef *def)
+{
+  char buf[100];
+  switch (def->forbidden)
+  {
+    case FORBID_WARN:
+    {
+      sprintf(buf, "Warning: it is recommended that command %s is not used.", def->name);
+      OnInform(buf);
+      break;
+    }
+    case FORBID_ABSOLUTELY:
+    {
+      sprintf(buf, "Error: command %s cannot be used and will lead to errors.", def->name);
+      OnInform(buf);
+      break;
+    }
+    default:
+      break;
+  }
+}
+TexMacroDef *MatchMacro(char *buffer, int *pos, char **env, bool *parseToBrace)
+{
+  *parseToBrace = TRUE;
+  int i = (*pos);
+  TexMacroDef *def = NULL;
+  char macroBuf[40];
+
+  // First, try to find begin{thing}
+  if (strncmp(buffer+i, "begin{", 6) == 0)
+  {
+    i += 6;
+
+    int j = i;
+    while ((isalpha(buffer[j]) || buffer[j] == '*') && ((j - i) < 39))
+    {
+      macroBuf[j-i] = buffer[j];
+      j ++;
+    }
+    macroBuf[j-i] = 0;
+    def = (TexMacroDef *)MacroDefs.Get(macroBuf);
+
+    if (def)
+    {
+      *pos = j + 1;  // BUGBUG Should this be + 1???
+      *env = def->name;
+      ForbidWarning(def);
+      return def;
+    }
+    else return NULL;
+  }
+
+  // Failed, so try to find macro from definition list
+  int j = i;
+
+  // First try getting a one-character macro, but ONLY
+  // if these TWO characters are not both alphabetical (could
+  // be a longer macro)
+  if (!(isalpha(buffer[i]) && isalpha(buffer[i+1])))
+  {
+    macroBuf[0] = buffer[i];
+    macroBuf[1] = 0;
+
+    def = (TexMacroDef *)MacroDefs.Get(macroBuf);
+    if (def) j ++;
+  }
+
+  if (!def)
+  {
+    while ((isalpha(buffer[j]) || buffer[j] == '*') && ((j - i) < 39))
+    {
+      macroBuf[j-i] = buffer[j];
+      j ++;
+    }
+    macroBuf[j-i] = 0;
+    def = (TexMacroDef *)MacroDefs.Get(macroBuf);
+  }
+    
+  if (def)
+  {
+    i = j;
+    
+    // We want to check whether this is a space-consuming macro
+    // (e.g. {\bf word})
+    // No brace, e.g. \input thing.tex instead of \input{thing};
+    // or a numeric argument, such as \parindent0pt
+    if ((def->no_args > 0) && ((buffer[i] == 32) || (buffer[i] == '=') || (isdigit(buffer[i]))))
+    {
+      if ((buffer[i] == 32) || (buffer[i] == '='))
+        i ++;
+
+      *parseToBrace = FALSE;
+    }
+    *pos = i;
+    ForbidWarning(def);
+    return def;
+  }
+  return NULL;
+}
+
+void EatWhiteSpace(char *buffer, int *pos)
+{
+  int len = strlen(buffer);
+  int j = *pos;
+  bool keepGoing = TRUE;
+  bool moreLines = TRUE;
+  while ((j < len) && keepGoing &&
+         (buffer[j] == 10 || buffer[j] == 13 || buffer[j] == ' ' || buffer[j] == 9))
+  {
+    j ++;
+    if (j >= len)
+    {
+      if (moreLines)
+      {
+        moreLines = read_a_line(buffer);
+        len = strlen(buffer);
+        j = 0;
+      }
+      else
+        keepGoing = FALSE;
+    }
+  }
+  *pos = j;
+}
+
+bool FindEndEnvironment(char *buffer, int *pos, char *env)
+{
+  int i = (*pos);
+
+  // Try to find end{thing}
+  if ((strncmp(buffer+i, "end{", 4) == 0) &&
+      (strncmp(buffer+i+4, env, strlen(env)) == 0))
+  {
+    *pos = i + 5 + strlen(env);
+    return TRUE;
+  }
+  else return FALSE;
+}
+
+bool readingVerbatim = FALSE;
+bool readInVerbatim = FALSE;  // Within a verbatim, but not nec. verbatiminput
+
+bool read_a_line(char *buf)
+{
+  if (CurrentInputIndex < 0)
+  {
+    buf[0] = 0;
+    return FALSE;
+  }
+  
+  int ch = -2;
+  int i = 0;
+  buf[0] = 0;
+  while (ch != EOF && ch != 10)
+  {
+    if (((i == 14) && (strncmp(buf, "\\end{verbatim}", 14) == 0)) ||
+         ((i == 16) && (strncmp(buf, "\\end{toocomplex}", 16) == 0)))
+      readInVerbatim = FALSE;
+
+    ch = getc(Inputs[CurrentInputIndex]);
+    if (ch != EOF)
+    {
+      // Check for 2 consecutive newlines and replace with \par
+      if (ch == 10 && !readInVerbatim)
+      {
+        int ch1 = getc(Inputs[CurrentInputIndex]);
+        if ((ch1 == 10) || (ch1 == 13))
+        {
+          // Eliminate newline (10) following DOS linefeed
+          if (ch1 == 13) ch1 = getc(Inputs[CurrentInputIndex]);
+          buf[i] = 0;
+          IncrementLineNumber();
+//          strcat(buf, "\\par\n");
+//          i += 6;
+          strcat(buf, "\\par");
+          i += 5;
+        }
+        else
+        {
+          ungetc(ch1, Inputs[CurrentInputIndex]);
+          buf[i] = ch;
+          i ++;
+        }
+      }
+      else
+      {
+
+        // Convert embedded characters to RTF equivalents
+               switch(ch)
+               {
+               case 0xf6: // Ã¶
+               case 0xe4: // Ã¼
+               case 0xfc: // Ã¼
+               case 0xd6: // Ã–
+               case 0xc4: // Ã„
+               case 0xdc: // Ãœ         
+                               buf[i++]='\\';
+                               buf[i++]='"';
+                               buf[i++]='{';
+                               switch(ch)
+                               {
+                                       case 0xf6:buf[i++]='o';break; // Ã¶
+                                       case 0xe4:buf[i++]='a';break; // Ã¤
+                                       case 0xfc:buf[i++]='u';break; // Ã¼
+                                       case 0xd6:buf[i++]='O';break; // Ã–
+                                       case 0xc4:buf[i++]='A';break; // Ã„
+                                       case 0xdc:buf[i++]='U';break; // Ãœ                                      
+                               }                               
+                               buf[i++]='}';
+                               break;
+               case 0xdf: // ÃŸ 
+                       buf[i++]='\\';
+                       buf[i++]='s';
+                       buf[i++]='s';
+            buf[i++]='\\';
+            buf[i++]='/';
+                       break;  
+               default:
+                       buf[i++] = ch;
+                       break;
+               }
+        
+      }
+    }
+    else
+    {
+      buf[i] = 0;
+      fclose(Inputs[CurrentInputIndex]);
+      Inputs[CurrentInputIndex] = NULL;
+      if (CurrentInputIndex > 0) ch = ' '; // No real end of file
+      CurrentInputIndex --;
+      if (readingVerbatim)
+      {
+        readingVerbatim = FALSE;
+        readInVerbatim = FALSE;
+        strcat(buf, "\\end{verbatim}\n");
+        return FALSE;
+      }
+    }
+    if (ch == 10)
+      IncrementLineNumber();
+  }
+  buf[i] = 0;
+
+  // Strip out comment environment
+  if (strncmp(buf, "\\begin{comment}", 15) == 0)
+  {
+    while (strncmp(buf, "\\end{comment}", 13) != 0)
+      read_a_line(buf);
+    return read_a_line(buf);
+  }
+  // Read a verbatim input file as if it were a verbatim environment
+  else if (strncmp(buf, "\\verbatiminput", 14) == 0)
+  {
+    int wordLen = 14;
+    char *fileName = buf + wordLen + 1;
+
+    int j = i - 1;
+    buf[j] = 0;
+
+    // thing}\par -- eliminate the \par!
+    if (strncmp((buf + strlen(buf)-5), "\\par", 4) == 0)
+    {
+      j -= 5;
+      buf[j] = 0;
+    }
+    
+    if (buf[j-1] == '}') buf[j-1] = 0; // Ignore final brace
+
+    wxString actualFile = TexPathList.FindValidPath(fileName);
+    if (actualFile == "")
+    {
+      char errBuf[300];
+      strcpy(errBuf, "Could not find file: ");
+      strncat(errBuf, fileName, 100);
+      OnError(errBuf);
+    }
+    else
+    {
+      CurrentInputIndex ++;
+      Inputs[CurrentInputIndex] = fopen(actualFile, "r");
+      LineNumbers[CurrentInputIndex] = 1;
+      if (FileNames[CurrentInputIndex])
+        delete[] FileNames[CurrentInputIndex];
+      FileNames[CurrentInputIndex] = copystring(actualFile);
+
+      if (!Inputs[CurrentInputIndex])
+      {
+        CurrentInputIndex --;
+        OnError("Could not open verbatiminput file.");
+      }
+      else
+      {
+        readingVerbatim = TRUE;
+        readInVerbatim = TRUE;
+        strcpy(buf, "\\begin{verbatim}\n");
+        return FALSE;
+      }
+    }
+    return FALSE;
+  }
+  else if (strncmp(buf, "\\input", 6) == 0 || strncmp(buf, "\\helpinput", 10) == 0 ||
+      strncmp(buf, "\\include", 8) == 0)
+  {
+    int wordLen;
+    if (strncmp(buf, "\\input", 6) == 0)
+      wordLen = 6;
+    else
+    if (strncmp(buf, "\\include", 8) == 0)
+      wordLen = 8;
+    else
+      wordLen = 10;
+
+    char *fileName = buf + wordLen + 1;
+
+    int j = i - 1;
+    buf[j] = 0;
+
+    // \input{thing}\par -- eliminate the \par!
+//    if (strncmp((buf + strlen(buf)-5), "\\par", 4) == 0)
+    if (strncmp((buf + strlen(buf)-4), "\\par", 4) == 0) // Bug fix 8/2/95 Ulrich Leodolter
+    {
+//      j -= 5;
+      j -= 4; // Ditto
+      buf[j] = 0;
+    }
+
+    if (buf[j-1] == '}') buf[j-1] = 0; // Ignore final brace
+
+    // Ignore some types of input files (e.g. macro definition files)
+    char *fileOnly = FileNameFromPath(fileName);
+    if (IgnorableInputFiles.Member(fileOnly))
+      return read_a_line(buf);
+
+    wxString actualFile = TexPathList.FindValidPath(fileName);
+    if (actualFile == "")
+    {
+      char buf2[400];
+      sprintf(buf2, "%s.tex", fileName);
+      actualFile = TexPathList.FindValidPath(buf2);
+    }
+    if (actualFile == "")
+    {
+      char errBuf[300];
+      strcpy(errBuf, "Could not find file: ");
+      strncat(errBuf, fileName, 100);
+      OnError(errBuf);
+    }
+    else
+    {
+      // Ensure that if this file includes another,
+      // then we look in the same directory as this one.
+      TexPathList.EnsureFileAccessible(actualFile);
+
+      CurrentInputIndex ++;
+      Inputs[CurrentInputIndex] = fopen(actualFile, "r");
+      LineNumbers[CurrentInputIndex] = 1;
+      if (FileNames[CurrentInputIndex])
+        delete[] FileNames[CurrentInputIndex];
+      FileNames[CurrentInputIndex] = copystring(actualFile);
+
+      if (!Inputs[CurrentInputIndex])
+      {
+        char errBuf[300];
+        sprintf(errBuf, "Could not open include file %s", (const char*) actualFile);
+        CurrentInputIndex --;
+        OnError(errBuf);
+      }
+    }
+    bool succ = read_a_line(buf);
+    return succ;
+  }
+  if (strncmp(buf, "\\begin{verbatim}", 16) == 0 ||
+      strncmp(buf, "\\begin{toocomplex}", 18) == 0)
+    readInVerbatim = TRUE;
+  else if (strncmp(buf, "\\end{verbatim}", 14) == 0 ||
+           strncmp(buf, "\\end{toocomplex}", 16) == 0)
+    readInVerbatim = FALSE;
+
+  return (ch == EOF);
+}
+
+/*
+ * Parse newcommand
+ *
+ */
+
+bool ParseNewCommand(char *buffer, int *pos)
+{
+  if ((strncmp((buffer+(*pos)), "newcommand", 10) == 0) ||
+      (strncmp((buffer+(*pos)), "renewcommand", 12) == 0))
+  {
+    if (strncmp((buffer+(*pos)), "newcommand", 10) == 0)
+      *pos = *pos + 12;
+    else
+      *pos = *pos + 14;
+
+    char commandName[100];
+    char commandValue[1000];
+    int noArgs = 0;
+    int i = 0;
+    while (buffer[*pos] != '}' && (buffer[*pos] != 0))
+    {
+      commandName[i] = buffer[*pos];
+      *pos += 1;
+      i ++;
+    }
+    commandName[i] = 0;
+    i = 0;
+    *pos += 1;
+    if (buffer[*pos] == '[')
+    {
+      *pos += 1;
+      noArgs = (int)(buffer[*pos]) - 48;
+      *pos += 2; // read past argument and '['
+    }
+    bool end = FALSE;
+    int braceCount = 0;
+    while (!end)
+    {
+      char ch = buffer[*pos];
+      if (ch == '{')
+        braceCount ++;
+      else if (ch == '}')
+      {
+        braceCount --;
+        if (braceCount == 0)
+          end = TRUE;
+      }
+      else if (ch == 0)
+      {
+        if (!read_a_line(buffer))
+          end = TRUE;
+        *pos = 0;
+        break;
+      }
+      commandValue[i] = ch;
+      i ++;
+      *pos += 1;
+    }
+    commandValue[i] = 0;
+
+    CustomMacro *macro = new CustomMacro(commandName, noArgs, NULL);
+    if (strlen(commandValue) > 0)
+      macro->macroBody = copystring(commandValue);
+    if (!CustomMacroList.Find(commandName))
+    {
+      CustomMacroList.Append(commandName, macro);
+      AddMacroDef(ltCUSTOM_MACRO, commandName, noArgs);
+    }
+    return TRUE;
+  }
+  else return FALSE;
+}
+
+void MacroError(char *buffer)
+{
+  char errBuf[300];
+  char macroBuf[200];
+  macroBuf[0] = '\\';
+  int i = 1;
+  char ch;
+  while (((ch = buffer[i-1]) != '\n') && (ch != 0))
+  {
+    macroBuf[i] = ch;
+    i ++;
+  }
+  macroBuf[i] = 0;
+  if (i > 20)
+    macroBuf[20] = 0;
+
+  sprintf(errBuf, "Could not find macro: %s at line %d, file %s",
+             macroBuf, (int)(LineNumbers[CurrentInputIndex]-1), FileNames[CurrentInputIndex]);
+  OnError(errBuf);
+}
+
+/*
+ * Parse an argument.
+ * 'environment' specifies the name of the macro IFF if we're looking for the end
+ * of an environment, e.g. \end{itemize}. Otherwise it's NULL.
+ * 'parseToBrace' is TRUE if the argument should extend to the next right brace,
+ * e.g. in {\bf an argument} as opposed to \vskip 30pt
+ *
+ */
+int ParseArg(TexChunk *thisArg, wxList& children, char *buffer, int pos, char *environment, bool parseToBrace, TexChunk *customMacroArgs)
+{
+  Tex2RTFYield();
+  if (stopRunning) return pos;
+  
+  bool eof = FALSE;
+  BigBuffer[0] = 0;
+  int buf_ptr = 0;
+  int len;
+
+/*
+
+  // Consume leading brace or square bracket, but ONLY if not following
+  // a space, because this could be e.g. {\large {\bf thing}} where {\bf thing}
+  // is the argument of \large AS WELL as being a block in its
+  // own right.
+  if (!environment)
+  {
+    if ((pos > 0) && (buffer[pos-1] != ' ') && buffer[pos] == '{')
+      pos ++;
+    else
+
+    if ((pos > 0) && (buffer[pos-1] != ' ') && (buffer[pos] == '[' || buffer[pos] == '('))
+    {
+      isOptional = TRUE;
+      pos ++;
+    }
+    else if ((pos > 1) && (buffer[pos-1] != ' ') && (buffer[pos+1] == '[' || buffer[pos+1] == '('))
+    {
+      isOptional = TRUE;
+      pos += 2;
+    }
+  }
+*/
+    
+  // If not parsing to brace, just read the next word
+  // (e.g. \vskip 20pt)
+  if (!parseToBrace)
+  {
+    int ch = buffer[pos];
+    while (!eof && ch != 13 && ch != 32 && ch != 10 &&
+           ch != 0 && ch != '{')
+    {
+      BigBuffer[buf_ptr] = ch;
+      buf_ptr ++;
+      pos ++;
+      ch = buffer[pos];
+    }
+    if (buf_ptr > 0)
+    {
+      TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
+      BigBuffer[buf_ptr] = 0;
+      buf_ptr = 0;
+      chunk->value = copystring(BigBuffer);
+      children.Append((wxObject *)chunk);
+    }
+    return pos;
+  }
+
+  while (!eof)
+  {
+    len = strlen(buffer);
+    if (pos >= len)
+    {
+      if (customMacroArgs) return 0;
+
+      eof = read_a_line(buffer);
+      pos = 0;
+      len = strlen(buffer);
+      // Check for verbatim (or toocomplex, which comes to the same thing)
+      if (strncmp(buffer, "\\begin{verbatim}", 16) == 0 ||
+          strncmp(buffer, "\\begin{toocomplex}", 18) == 0)
+      {
+        if (buf_ptr > 0)
+        {
+          TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
+          BigBuffer[buf_ptr] = 0;
+          buf_ptr = 0;
+          chunk->value = copystring(BigBuffer);
+          children.Append((wxObject *)chunk);
+        }
+        BigBuffer[0] = 0;
+        buf_ptr = 0;
+
+        eof = read_a_line(buffer);
+        while (!eof && (strncmp(buffer, "\\end{verbatim}", 14) != 0) &&
+                       (strncmp(buffer, "\\end{toocomplex}", 16) != 0)
+               )
+       {
+          strcat(BigBuffer, buffer);
+          buf_ptr += strlen(buffer);
+          eof = read_a_line(buffer);
+       }
+        eof = read_a_line(buffer);
+        buf_ptr = 0;
+
+        TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO, VerbatimMacroDef);
+        chunk->no_args = 1;
+        chunk->macroId = ltVERBATIM;
+        TexChunk *arg = new TexChunk(CHUNK_TYPE_ARG, VerbatimMacroDef);
+        arg->argn = 1;
+        arg->macroId = ltVERBATIM;
+        TexChunk *str = new TexChunk(CHUNK_TYPE_STRING);
+        str->value = copystring(BigBuffer);
+
+        children.Append((wxObject *)chunk);
+        chunk->children.Append((wxObject *)arg);
+        arg->children.Append((wxObject *)str);
+
+        // Also want to include the following newline (is always a newline
+        // after a verbatim): EXCEPT in HTML
+        if (convertMode != TEX_HTML)
+        {
+          TexMacroDef *parDef = (TexMacroDef *)MacroDefs.Get("\\");
+          TexChunk *parChunk = new TexChunk(CHUNK_TYPE_MACRO, parDef);
+          parChunk->no_args = 0;
+          parChunk->macroId = ltBACKSLASHCHAR;
+          children.Append((wxObject *)parChunk);
+        }
+      }
+    }
+
+    char ch = buffer[pos];
+    // End of optional argument -- pretend it's right brace for simplicity
+    if (thisArg->optional && (ch == ']'))
+      ch = '}';
+
+    switch (ch)
+    {
+      case 0:
+      case '}':  // End of argument
+      {
+        if (buf_ptr > 0)
+        {
+          TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
+          BigBuffer[buf_ptr] = 0;
+          buf_ptr = 0;
+          chunk->value = copystring(BigBuffer);
+          children.Append((wxObject *)chunk);
+        }
+        if (ch == '}') pos ++;
+        return pos;
+        break;
+      }
+      case '\\':
+      {
+        if (buf_ptr > 0)  // Finish off the string we've read so far
+        {
+          TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
+          BigBuffer[buf_ptr] = 0;
+          buf_ptr = 0;
+          chunk->value = copystring(BigBuffer);
+          children.Append((wxObject *)chunk);
+        }
+        pos ++;
+        
+
+        // Try matching \end{environment}
+        if (environment && FindEndEnvironment(buffer, &pos, environment))
+        {
+          // Eliminate newline after an \end{} if possible
+          if (buffer[pos] == 13)
+          {
+            pos ++;
+            if (buffer[pos] == 10)
+              pos ++;
+          }
+          return pos;
+        }
+
+        if (ParseNewCommand(buffer, &pos))
+          break;
+
+        if (strncmp(buffer+pos, "special", 7) == 0)
+        {
+          pos += 7;
+
+          // Discard {
+          pos ++;
+          int noBraces = 1;
+
+          wxBuffer[0] = 0;
+          int i = 0;
+          bool end = FALSE;
+          while (!end)
+          {
+            int ch = buffer[pos];
+            if (ch == '}')
+            {
+              noBraces --;
+              if (noBraces == 0)
+              {
+                wxBuffer[i] = 0;
+                end = TRUE;
+              }
+              else
+              {
+                wxBuffer[i] = '}';
+                i ++;
+              }
+              pos ++;
+            }
+            else if (ch == '{')
+            {
+              wxBuffer[i] = '{';
+              i ++;
+              pos ++;
+            }
+            else if (ch == '\\' && buffer[pos+1] == '}')
+            {
+              wxBuffer[i] = '}';
+              pos += 2;
+              i++;
+            }
+            else if (ch == '\\' && buffer[pos+1] == '{')
+            {
+              wxBuffer[i] = '{';
+              pos += 2;
+              i++;
+            }
+            else
+            {
+              wxBuffer[i] = ch;
+              pos ++;
+              i ++;
+              if (ch == 0)
+                end = TRUE;
+            }
+          }
+          TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
+          chunk->no_args = 1;
+          chunk->macroId = ltSPECIAL;
+          TexMacroDef *specialDef = (TexMacroDef *)MacroDefs.Get("special");
+          chunk->def = specialDef;
+          TexChunk *arg = new TexChunk(CHUNK_TYPE_ARG, specialDef);
+          chunk->children.Append((wxObject *)arg);
+          arg->argn = 1;
+          arg->macroId = chunk->macroId;
+
+          // The value in the first argument.
+          TexChunk *argValue = new TexChunk(CHUNK_TYPE_STRING);
+          arg->children.Append((wxObject *)argValue);
+          argValue->argn = 1;
+          argValue->value = copystring(wxBuffer);
+
+          children.Append((wxObject *)chunk);
+        }
+        else if (strncmp(buffer+pos, "verb", 4) == 0)
+        {
+          pos += 4;
+          if (buffer[pos] == '*')
+            pos ++;
+
+          // Find the delimiter character         
+          int ch = buffer[pos];
+          pos ++;
+          // Now at start of verbatim text
+          int j = pos;
+          while ((buffer[pos] != ch) && buffer[pos] != 0)
+            pos ++;
+          char *val = new char[pos - j + 1];
+          int i;
+          for (i = j; i < pos; i++)
+          {
+            val[i-j] = buffer[i];
+          }
+          val[i-j] = 0;
+
+          pos ++;
+
+          TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
+          chunk->no_args = 1;
+          chunk->macroId = ltVERB;
+          TexMacroDef *verbDef = (TexMacroDef *)MacroDefs.Get("verb");
+          chunk->def = verbDef;
+          TexChunk *arg = new TexChunk(CHUNK_TYPE_ARG, verbDef);
+          chunk->children.Append((wxObject *)arg);
+          arg->argn = 1;
+          arg->macroId = chunk->macroId;
+
+          // The value in the first argument.
+          TexChunk *argValue = new TexChunk(CHUNK_TYPE_STRING);
+          arg->children.Append((wxObject *)argValue);
+          argValue->argn = 1;
+          argValue->value = val;
+
+          children.Append((wxObject *)chunk);
+        }
+       else
+       {
+          char *env = NULL;
+          bool tmpParseToBrace = TRUE;
+          TexMacroDef *def = MatchMacro(buffer, &pos, &env, &tmpParseToBrace);
+          if (def)
+          {
+          CustomMacro *customMacro = FindCustomMacro(def->name);
+
+          TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO, def);
+          chunk->no_args = def->no_args;
+//          chunk->name = copystring(def->name);
+          chunk->macroId = def->macroId;
+
+          if  (!customMacro)
+            children.Append((wxObject *)chunk);
+
+          // Eliminate newline after a \begin{} or a \\ if possible
+          if (env || strcmp(def->name, "\\") == 0)
+            if (buffer[pos] == 13)
+            {
+              pos ++;
+              if (buffer[pos] == 10)
+                pos ++;
+            }
+
+          pos = ParseMacroBody(def->name, chunk, chunk->no_args,
+                     buffer, pos, env, tmpParseToBrace, customMacroArgs);
+
+          // If custom macro, parse the body substituting the above found args.
+          if (customMacro)
+          {
+            if (customMacro->macroBody)
+            {
+              char macroBuf[300];
+//              strcpy(macroBuf, "{");
+              strcpy(macroBuf, customMacro->macroBody);
+              strcat(macroBuf, "}");
+              ParseArg(thisArg, children, macroBuf, 0, NULL, TRUE, chunk);
+            }
+            
+//            delete chunk; // Might delete children
+          }
+        }
+        else
+        {
+          MacroError(buffer+pos);
+        }
+        }
+        break;
+      }
+      // Parse constructs like {\bf thing} as if they were
+      // \bf{thing}
+      case '{':
+      {
+        pos ++;
+        if (buffer[pos] == '\\')
+        {
+          if (buf_ptr > 0)
+          {
+            TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
+            BigBuffer[buf_ptr] = 0;
+            buf_ptr = 0;
+            chunk->value = copystring(BigBuffer);
+            children.Append((wxObject *)chunk);
+          }
+          pos ++;
+
+          char *env;
+          bool tmpParseToBrace;
+          TexMacroDef *def = MatchMacro(buffer, &pos, &env, &tmpParseToBrace);
+          if (def)
+          {
+            CustomMacro *customMacro = FindCustomMacro(def->name);
+
+            TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO, def);
+            chunk->no_args = def->no_args;
+//            chunk->name = copystring(def->name);
+            chunk->macroId = def->macroId;
+            if (!customMacro)
+              children.Append((wxObject *)chunk);
+
+            pos = ParseMacroBody(def->name, chunk, chunk->no_args,
+                       buffer, pos, NULL, TRUE, customMacroArgs);
+
+            // If custom macro, parse the body substituting the above found args.
+            if (customMacro)
+            {
+              if (customMacro->macroBody)
+              {
+                char macroBuf[300];
+//                strcpy(macroBuf, "{");
+                strcpy(macroBuf, customMacro->macroBody);
+                strcat(macroBuf, "}");
+                ParseArg(thisArg, children, macroBuf, 0, NULL, TRUE, chunk);
+              }
+            
+//            delete chunk; // Might delete children
+           }
+          }
+          else
+          {
+            MacroError(buffer+pos);
+          }
+        }
+        else
+       {
+         /*
+          * If all else fails, we assume that we have
+          * a pair of braces on their own, so return a `dummy' macro
+          * definition with just one argument to parse.
+          */
+          if (!SoloBlockDef)
+          {
+            SoloBlockDef = new TexMacroDef(ltSOLO_BLOCK, "solo block", 1, FALSE);
+          }
+          // Save text so far
+          if (buf_ptr > 0)
+          {
+            TexChunk *chunk1 = new TexChunk(CHUNK_TYPE_STRING);
+            BigBuffer[buf_ptr] = 0;
+            buf_ptr = 0;
+            chunk1->value = copystring(BigBuffer);
+            children.Append((wxObject *)chunk1);
+          }
+          TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO, SoloBlockDef);
+          chunk->no_args = SoloBlockDef->no_args;
+//          chunk->name = copystring(SoloBlockDef->name);
+          chunk->macroId = SoloBlockDef->macroId;
+          children.Append((wxObject *)chunk);
+
+          TexChunk *arg = new TexChunk(CHUNK_TYPE_ARG, SoloBlockDef);
+
+          chunk->children.Append((wxObject *)arg);
+//          arg->name = copystring(SoloBlockDef->name);
+          arg->argn = 1;
+          arg->macroId = chunk->macroId;
+
+          pos = ParseArg(arg, arg->children, buffer, pos, NULL, TRUE, customMacroArgs);
+       }
+        break;
+      }
+      case '$':
+      {
+        if (buf_ptr > 0)
+        {
+          TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
+          BigBuffer[buf_ptr] = 0;
+          buf_ptr = 0;
+          chunk->value = copystring(BigBuffer);
+          children.Append((wxObject *)chunk);
+        }
+
+        pos ++;
+
+        if (buffer[pos] == '$')
+        {
+          TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
+          chunk->no_args = 0;
+//          chunk->name = copystring("$$");
+          chunk->macroId = ltSPECIALDOUBLEDOLLAR;
+          children.Append((wxObject *)chunk);
+          pos ++;
+        }
+        else
+        {
+          TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
+          chunk->no_args = 0;
+//          chunk->name = copystring("_$");
+          chunk->macroId = ltSPECIALDOLLAR;
+          children.Append((wxObject *)chunk);
+        }
+        break;
+      }
+      case '~':
+      {
+        if (buf_ptr > 0)
+        {
+          TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
+          BigBuffer[buf_ptr] = 0;
+          buf_ptr = 0;
+          chunk->value = copystring(BigBuffer);
+          children.Append((wxObject *)chunk);
+        }
+
+        pos ++;
+        TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
+        chunk->no_args = 0;
+//        chunk->name = copystring("_~");
+        chunk->macroId = ltSPECIALTILDE;
+        children.Append((wxObject *)chunk);
+        break;
+      }
+      case '#': // Either treat as a special TeX character or as a macro arg
+      {
+        if (buf_ptr > 0)
+        {
+          TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
+          BigBuffer[buf_ptr] = 0;
+          buf_ptr = 0;
+          chunk->value = copystring(BigBuffer);
+          children.Append((wxObject *)chunk);
+        }
+
+        pos ++;
+        if (!customMacroArgs)
+        {
+          TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
+          chunk->no_args = 0;
+//          chunk->name = copystring("_#");
+          chunk->macroId = ltSPECIALHASH;
+          children.Append((wxObject *)chunk);
+        }
+        else
+        {
+          if (isdigit(buffer[pos]))
+          {
+            int n = buffer[pos] - 48;
+            pos ++;
+            wxNode *node = customMacroArgs->children.Nth(n-1);
+            if (node)
+            {
+              TexChunk *argChunk = (TexChunk *)node->Data();
+              children.Append((wxObject *)new TexChunk(*argChunk));
+            }
+          }
+        }
+        break;
+      }
+      case '&':
+      {
+        // Remove white space before and after the ampersand,
+        // since this is probably a table column separator with
+        // some convenient -- but useless -- white space in the text.
+        while ((buf_ptr > 0) && ((BigBuffer[buf_ptr-1] == ' ') || (BigBuffer[buf_ptr-1] == 9)))
+          buf_ptr --;
+
+        if (buf_ptr > 0)
+        {
+          TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
+          BigBuffer[buf_ptr] = 0;
+          buf_ptr = 0;
+          chunk->value = copystring(BigBuffer);
+          children.Append((wxObject *)chunk);
+        }
+
+        pos ++;
+
+        while (buffer[pos] == ' ' || buffer[pos] == 9)
+          pos ++;
+
+        TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
+        chunk->no_args = 0;
+//        chunk->name = copystring("_&");
+        chunk->macroId = ltSPECIALAMPERSAND;
+        children.Append((wxObject *)chunk);
+        break;
+      }
+      // Eliminate end-of-line comment
+      case '%':
+      {
+        ch = buffer[pos];
+        while (ch != 10 && ch != 13 && ch != 0)
+        {
+          pos ++;
+          ch = buffer[pos];
+        }
+        if (buffer[pos] == 10 || buffer[pos] == 13)
+        {
+          pos ++;
+          if (buffer[pos] == 10) pos ++; // Eliminate newline following DOS line feed
+        }
+        break;
+      }
+      // Eliminate tab
+      case 9:
+      {
+        BigBuffer[buf_ptr] = ' ';
+        BigBuffer[buf_ptr+1] = 0;
+        buf_ptr ++;
+        pos ++;
+        break;
+      }
+      default:
+      {
+        BigBuffer[buf_ptr] = ch;
+        BigBuffer[buf_ptr+1] = 0;
+        buf_ptr ++;
+        pos ++;
+        break;
+      }
+    }
+  }
+  return pos;
+}
+
+/*
+ * Consume as many arguments as the macro definition specifies
+ *
+ */
+int ParseMacroBody(char *macro_name, TexChunk *parent,
+                   int no_args, char *buffer, int pos,
+                   char *environment, bool parseToBrace,
+                   TexChunk *customMacroArgs)
+{
+  Tex2RTFYield();
+  if (stopRunning) return pos;
+
+  // Check for a first optional argument
+  if (buffer[pos] == ' ' && buffer[pos+1] == '[')
+  {
+    // Fool following code into thinking that this is definitely
+    // an optional first argument. (If a space before a non-first argument,
+    // [ is interpreted as a [, not an optional argument.)
+    buffer[pos] = '!';
+    pos ++;
+    no_args ++;
+  }
+  else
+    if (buffer[pos] == '[')
+      no_args ++;
+
+  int maxArgs = 0;
+
+  int i;
+  for (i = 0; i < no_args; i++)
+  {
+    maxArgs ++;
+    TexChunk *arg = new TexChunk(CHUNK_TYPE_ARG, parent->def);
+
+    parent->children.Append((wxObject *)arg);
+//    arg->name = copystring(macro_name);
+    arg->argn = maxArgs;
+    arg->macroId = parent->macroId;
+
+    // To parse the first arg of a 2 arg \begin{thing}{arg} ... \end{thing}
+    // have to fool parser into thinking this is a regular kind of block.
+    char *actualEnv;
+    if ((no_args == 2) && (i == 0))
+      actualEnv = NULL;
+    else
+      actualEnv = environment;
+
+    bool isOptional = FALSE;
+
+    // Remove the first { of the argument so it doesn't get recognized as { ... }
+//    EatWhiteSpace(buffer, &pos);
+    if (!actualEnv)
+    {
+      // The reason for these tests is to not consume braces that don't
+      // belong to this macro.
+      // E.g. {\bf {\small thing}}
+      if ((pos > 0) && (buffer[pos-1] != ' ') && buffer[pos] == '{')
+        pos ++;
+      else
+      if ((pos > 0) && (buffer[pos-1] != ' ') && (buffer[pos] == '['))
+      {
+        isOptional = TRUE;
+        pos ++;
+      }
+      else if ((pos > 1) && (buffer[pos-1] != ' ') && (buffer[pos+1] == '['))
+      {
+        isOptional = TRUE;
+        pos += 2;
+      }
+    }
+    arg->optional = isOptional;
+
+    pos = ParseArg(arg, arg->children, buffer, pos, actualEnv, parseToBrace, customMacroArgs);
+
+    // If we've encountered an OPTIONAL argument, go another time around
+    // the loop, because we've got more than we thought.
+    // Hopefully optional args don't occur at the end of a macro use
+    // or we might miss it.
+    // Don't increment no of times round loop if the first optional arg
+    // -- we already did it before the loop.
+    if (arg->optional && (i > 0))
+      i --;
+  }
+  parent->no_args = maxArgs;
+
+  // Tell each argument how many args there are (useful when processing an arg)
+  wxNode *node = parent->children.First();
+  while (node)
+  {
+    TexChunk *chunk = (TexChunk *)node->Data();
+    chunk->no_args = maxArgs;
+    node = node->Next();
+  }
+  return pos;
+}
+
+bool TexLoadFile(char *filename)
+{
+  stopRunning = FALSE;
+  strcpy(TexFileRoot, filename);
+  StripExtension(TexFileRoot);
+  sprintf(TexBibName, "%s.bb", TexFileRoot);
+  sprintf(TexTmpBibName, "%s.bb1", TexFileRoot);
+
+  TexPathList.EnsureFileAccessible(filename);
+
+#ifdef __WXMSW__
+  static char *line_buffer = new char[600];
+#else
+  static char *line_buffer = new char[11000];
+#endif
+  
+  Inputs[0] = fopen(filename, "r");
+  LineNumbers[0] = 1;
+  FileNames[0] = copystring(filename);
+  if (Inputs[0])
+  {
+    read_a_line(line_buffer);
+    ParseMacroBody("toplevel", TopLevel, 1, line_buffer, 0, NULL, TRUE);
+    if (Inputs[0]) fclose(Inputs[0]);
+    return TRUE;
+  }
+  else return FALSE;
+}
+
+TexMacroDef::TexMacroDef(int the_id, char *the_name, int n, bool ig, bool forbidLevel)
+{
+  name = copystring(the_name);
+  no_args = n;
+  ignore = ig;
+  macroId = the_id;
+  forbidden = forbidLevel;
+}
+
+TexMacroDef::~TexMacroDef(void)
+{
+  if (name) delete[] name;
+}
+
+TexChunk::TexChunk(int the_type, TexMacroDef *the_def)
+{
+  type = the_type;
+  no_args = 0;
+  argn = 0;
+//  name = NULL;
+  def = the_def;
+  macroId = 0;
+  value = NULL;
+  optional = FALSE;
+}
+
+TexChunk::TexChunk(TexChunk& toCopy)
+{
+  type = toCopy.type;
+  no_args = toCopy.no_args;
+  argn = toCopy.argn;
+  macroId = toCopy.macroId;
+  
+//  if (toCopy.name)
+//    name = copystring(toCopy.name);
+//  else
+//    name = NULL;
+  def = toCopy.def;
+
+  if (toCopy.value)
+    value = copystring(toCopy.value);
+  else
+    value = NULL;
+  
+  optional = toCopy.optional;
+  wxNode *node = toCopy.children.First();
+  while (node)
+  {
+    TexChunk *child = (TexChunk *)node->Data();
+    children.Append((wxObject *)new TexChunk(*child));
+    node = node->Next();
+  }
+}
+
+TexChunk::~TexChunk(void)
+{
+//  if (name) delete[] name;
+  if (value) delete[] value;
+  wxNode *node = children.First();
+  while (node)
+  {
+    TexChunk *child = (TexChunk *)node->Data();
+    delete child;
+    wxNode *next = node->Next();
+    delete node;
+    node = next;
+  }
+}
+
+bool IsArgOptional(void)  // Is this argument an optional argument?
+{
+  return isArgOptional;
+}
+
+int GetNoArgs(void) // Number of args for this macro
+{
+  return noArgs;
+}
+
+/* Gets the text of a chunk on request (must be for small arguments
+ * only!)
+ *
+ */
+void GetArgData1(TexChunk *chunk)
+{
+  switch (chunk->type)
+  {
+    case CHUNK_TYPE_MACRO:
+    {
+      TexMacroDef *def = chunk->def;
+      if (def && def->ignore)
+        return;
+
+      if (def && (strcmp(def->name, "solo block") != 0))
+      {
+        strcat(currentArgData, "\\");
+        strcat(currentArgData, def->name);
+      }
+
+      wxNode *node = chunk->children.First();
+      while (node)
+      {
+        TexChunk *child_chunk = (TexChunk *)node->Data();
+        strcat(currentArgData, "{");
+        GetArgData1(child_chunk);
+        strcat(currentArgData, "}");
+        node = node->Next();
+      }
+      break;
+    }
+    case CHUNK_TYPE_ARG:
+    {
+      wxNode *node = chunk->children.First();
+      while (node)
+      {
+        TexChunk *child_chunk = (TexChunk *)node->Data();
+        GetArgData1(child_chunk);
+        node = node->Next();
+      }
+      break;
+    }
+    case CHUNK_TYPE_STRING:
+    {
+      if (chunk->value)
+        strcat(currentArgData, chunk->value);
+      break;
+    }
+  }
+}
+
+char *GetArgData(TexChunk *chunk)
+{
+  currentArgData[0] = 0;
+  GetArgData1(currentArgument);
+  haveArgData = FALSE;
+  return currentArgData;
+}
+
+char *GetArgData(void)
+{
+  if (!haveArgData)
+  {
+    currentArgData[0] = 0;
+    GetArgData1(currentArgument);
+  }
+  return currentArgData;
+}
+
+TexChunk *GetArgChunk(void)
+{
+  return currentArgument;
+}
+
+TexChunk *GetNextChunk(void)     // Look ahead to the next chunk
+{
+  return nextChunk;
+}
+
+TexChunk *GetTopLevelChunk(void)
+{
+  return TopLevel;
+}
+
+int GetCurrentColumn(void)
+{
+  return currentColumn;
+}
+
+/*
+ * Traverses document calling functions to allow the client to
+ * write out the appropriate stuff
+ */
+
+
+void TraverseFromChunk(TexChunk *chunk, wxNode *thisNode, bool childrenOnly)
+{
+  Tex2RTFYield();
+  if (stopRunning) return;
+
+  switch (chunk->type)
+  {
+    case CHUNK_TYPE_MACRO:
+    {
+      TexMacroDef *def = chunk->def;
+      if (def && def->ignore)
+        return;
+
+      if (!childrenOnly)
+        OnMacro(chunk->macroId, chunk->no_args, TRUE);
+
+      wxNode *node = chunk->children.First();
+      while (node)
+      {
+        TexChunk *child_chunk = (TexChunk *)node->Data();
+        TraverseFromChunk(child_chunk, node);
+        node = node->Next();
+      }
+
+      if (thisNode && thisNode->Next()) nextChunk = (TexChunk *)thisNode->Next()->Data();
+
+      if (!childrenOnly)
+        OnMacro(chunk->macroId, chunk->no_args, FALSE);
+      break;
+    }
+    case CHUNK_TYPE_ARG:
+    {
+      currentArgument = chunk;
+
+      isArgOptional = chunk->optional;
+      noArgs = chunk->no_args;
+
+      // If OnArgument returns FALSE, don't output.
+
+      if (childrenOnly || OnArgument(chunk->macroId, chunk->argn, TRUE))
+      {
+        wxNode *node = chunk->children.First();
+        while (node)
+        {
+          TexChunk *child_chunk = (TexChunk *)node->Data();
+          TraverseFromChunk(child_chunk, node);
+          node = node->Next();
+        }
+      }
+
+      currentArgument = chunk;
+
+      if (thisNode && thisNode->Next()) nextChunk = (TexChunk *)thisNode->Next()->Data();
+
+      isArgOptional = chunk->optional;
+      noArgs = chunk->no_args;
+
+      if (!childrenOnly)
+        (void)OnArgument(chunk->macroId, chunk->argn, FALSE);
+      break;
+    }
+    case CHUNK_TYPE_STRING:
+    {
+      extern int issuedNewParagraph;
+      extern int forbidResetPar;
+      if (chunk->value && (forbidResetPar == 0))
+      {
+        // If non-whitespace text, we no longer have a new paragraph.
+        if (issuedNewParagraph && !((chunk->value[0] == 10 || chunk->value[0] == 13 || chunk->value[0] == 32)
+                                    && chunk->value[1] == 0))
+          issuedNewParagraph = FALSE;
+        TexOutput(chunk->value, TRUE);
+      }
+      break;
+    }
+  }
+}
+
+void TraverseDocument(void)
+{
+  TraverseFromChunk(TopLevel, NULL);
+}
+
+void SetCurrentOutput(FILE *fd)
+{
+  CurrentOutput1 = fd;
+  CurrentOutput2 = NULL;
+}
+
+void SetCurrentOutputs(FILE *fd1, FILE *fd2)
+{
+  CurrentOutput1 = fd1;
+  CurrentOutput2 = fd2;
+}
+
+void AddMacroDef(int the_id, char *name, int n, bool ignore, bool forbid)
+{
+  MacroDefs.Put(name, new TexMacroDef(the_id, name, n, ignore, forbid));
+}
+
+void TexInitialize(int bufSize)
+{
+  InitialiseColourTable();
+#ifdef __WXMSW__
+  TexPathList.AddEnvList("TEXINPUT");
+#endif
+#ifdef __UNIX__
+  TexPathList.AddEnvList("TEXINPUTS");
+#endif
+  int i;
+  for (i = 0; i < 15; i++)
+  {
+    Inputs[i] = NULL;
+    LineNumbers[i] = 1;
+    FileNames[i] = NULL;
+  }
+
+  IgnorableInputFiles.Add("psbox.tex");
+  BigBuffer = new char[(bufSize*1000)];
+  currentArgData = new char[2000];
+  TexFileRoot = new char[300];
+  TexBibName = new char[300];
+  TexTmpBibName = new char[300];
+  AddMacroDef(ltTOPLEVEL, "toplevel", 1);
+  TopLevel = new TexChunk(CHUNK_TYPE_MACRO);
+//  TopLevel->name = copystring("toplevel");
+  TopLevel->macroId = ltTOPLEVEL;
+  TopLevel->no_args = 1;
+  VerbatimMacroDef = (TexMacroDef *)MacroDefs.Get("verbatim");
+}
+
+void TexCleanUp(void)
+{
+  int i;
+  for (i = 0; i < 15; i++)
+    Inputs[i] = NULL;
+
+  chapterNo = 0;
+  sectionNo = 0;
+  subsectionNo = 0;
+  subsubsectionNo = 0;
+  figureNo = 0;
+
+  CurrentOutput1 = NULL;
+  CurrentOutput2 = NULL;
+  CurrentInputIndex = 0;
+  haveArgData = FALSE;
+  noArgs = 0;
+
+  if (TopLevel)
+    delete TopLevel;
+  TopLevel = new TexChunk(CHUNK_TYPE_MACRO);
+//  TopLevel->name = copystring("toplevel");
+  TopLevel->macroId = ltTOPLEVEL;
+  TopLevel->no_args = 1;
+
+  DocumentTitle = NULL;
+  DocumentAuthor = NULL;
+  DocumentDate = NULL;
+  DocumentStyle = LATEX_REPORT;
+  MinorDocumentStyle = 0;
+  BibliographyStyleString = copystring("plain");
+  DocumentStyleString = copystring("report");
+  MinorDocumentStyleString = NULL;
+/* Don't want to remove custom macros after each pass.
+  SetFontSizes(10);
+  wxNode *node = CustomMacroList.First();
+  while (node)
+  {
+    CustomMacro *macro = (CustomMacro *)node->Data();
+    delete macro;
+    delete node;
+    node = CustomMacroList.First();
+  }
+*/
+  TexReferences.BeginFind();
+  wxNode *node = TexReferences.Next();
+  while (node)
+  {
+    TexRef *ref = (TexRef *)node->Data();
+    delete ref;
+    node = TexReferences.Next();
+  }
+  TexReferences.Clear();
+  
+  node = BibList.First();
+  while (node)
+  {
+    BibEntry *entry = (BibEntry *)node->Data();
+    delete entry;
+    delete node;
+    node = BibList.First();
+  }
+  CitationList.Clear();
+  ResetTopicCounter();
+}
+
+// There is likely to be one set of macros used by all utilities.
+void DefineDefaultMacros(void)
+{
+  // Put names which subsume other names at the TOP
+  // so they get recognized first
+
+  AddMacroDef(ltACCENT_GRAVE,     "`", 1);
+  AddMacroDef(ltACCENT_ACUTE,     "'", 1);
+  AddMacroDef(ltACCENT_CARET,     "^", 1);
+  AddMacroDef(ltACCENT_UMLAUT,    "\"", 1);
+  AddMacroDef(ltACCENT_TILDE,     "~", 1);
+  AddMacroDef(ltACCENT_DOT,       ".", 1);
+  AddMacroDef(ltACCENT_CADILLA,   "c", 1);
+  AddMacroDef(ltSMALLSPACE1,      ",", 0);
+  AddMacroDef(ltSMALLSPACE2,      ";", 0);
+
+  AddMacroDef(ltABSTRACT,         "abstract", 1);
+  AddMacroDef(ltADDCONTENTSLINE,  "addcontentsline", 3);
+  AddMacroDef(ltADDTOCOUNTER,     "addtocounter", 2);
+  AddMacroDef(ltALEPH,            "aleph", 0);
+  AddMacroDef(ltALPHA,            "alpha", 0);
+  AddMacroDef(ltALPH1,            "alph", 1);
+  AddMacroDef(ltALPH2,            "Alph", 1);
+  AddMacroDef(ltANGLE,            "angle", 0);
+  AddMacroDef(ltAPPENDIX,         "appendix", 0);
+  AddMacroDef(ltAPPROX,           "approx", 0);
+  AddMacroDef(ltARABIC,           "arabic", 1);
+  AddMacroDef(ltARRAY,            "array", 1);
+  AddMacroDef(ltAST,              "ast", 0);
+  AddMacroDef(ltASYMP,            "asymp", 0);
+  AddMacroDef(ltAUTHOR,           "author", 1);
+
+  AddMacroDef(ltBACKGROUNDCOLOUR, "backgroundcolour", 1);
+  AddMacroDef(ltBACKGROUNDIMAGE,  "backgroundimage", 1);
+  AddMacroDef(ltBACKGROUND,       "background", 1);
+  AddMacroDef(ltBACKSLASHRAW,     "backslashraw", 0);
+  AddMacroDef(ltBACKSLASH,        "backslash", 0);
+  AddMacroDef(ltBASELINESKIP,     "baselineskip", 1);
+  AddMacroDef(ltBCOL,             "bcol", 2);
+  AddMacroDef(ltBETA,             "beta", 0);
+  AddMacroDef(ltBFSERIES,         "bfseries", 1);
+  AddMacroDef(ltBF,               "bf", 1);
+  AddMacroDef(ltBIBITEM,          "bibitem", 2);  // For convenience, bibitem has 2 args: label and item.
+                              // The Latex syntax permits writing as 2 args.
+  AddMacroDef(ltBIBLIOGRAPHYSTYLE,    "bibliographystyle", 1);
+  AddMacroDef(ltBIBLIOGRAPHY,     "bibliography", 1);
+  AddMacroDef(ltBIGTRIANGLEDOWN,  "bigtriangledown", 0);
+  AddMacroDef(ltBOT,              "bot", 0);
+  AddMacroDef(ltBOXIT,            "boxit", 1);
+  AddMacroDef(ltBOX,              "box", 0);
+  AddMacroDef(ltBRCLEAR,          "brclear", 0);
+  AddMacroDef(ltBULLET,           "bullet", 0);
+
+  AddMacroDef(ltCAPTIONSTAR,      "caption*", 1);
+  AddMacroDef(ltCAPTION,          "caption", 1);
+  AddMacroDef(ltCAP,              "cap", 0);
+  AddMacroDef(ltCDOTS,            "cdots", 0);
+  AddMacroDef(ltCDOT,             "cdot", 0);
+  AddMacroDef(ltCENTERLINE,       "centerline", 1);
+  AddMacroDef(ltCENTERING,        "centering", 0);
+  AddMacroDef(ltCENTER,           "center", 1);
+  AddMacroDef(ltCEXTRACT,         "cextract", 0);
+  AddMacroDef(ltCHAPTERHEADING,   "chapterheading", 1);
+  AddMacroDef(ltCHAPTERSTAR,      "chapter*", 1);
+  AddMacroDef(ltCHAPTER,          "chapter", 1);
+  AddMacroDef(ltCHI,              "chi", 0);
+  AddMacroDef(ltCINSERT,          "cinsert", 0);
+  AddMacroDef(ltCIRC,             "circ", 0);
+  AddMacroDef(ltCITE,             "cite", 1);
+  AddMacroDef(ltCLASS,            "class", 1);
+  AddMacroDef(ltCLEARDOUBLEPAGE,  "cleardoublepage", 0);
+  AddMacroDef(ltCLEARPAGE,        "clearpage", 0);
+  AddMacroDef(ltCLINE,            "cline", 1);
+  AddMacroDef(ltCLIPSFUNC,        "clipsfunc", 3);
+  AddMacroDef(ltCLUBSUIT,         "clubsuit", 0);
+  AddMacroDef(ltCOLUMNSEP,        "columnsep", 1);
+  AddMacroDef(ltCOMMENT,          "comment", 1, TRUE);
+  AddMacroDef(ltCONG,             "cong", 0);
+  AddMacroDef(ltCOPYRIGHT,        "copyright", 0);
+  AddMacroDef(ltCPARAM,           "cparam", 2);
+  AddMacroDef(ltCHEAD,            "chead", 1);
+  AddMacroDef(ltCFOOT,            "cfoot", 1);
+  AddMacroDef(ltCUP,              "cup", 0);
+
+  AddMacroDef(ltDASHV,            "dashv", 0);
+  AddMacroDef(ltDATE,             "date", 1);
+  AddMacroDef(ltDELTA,            "delta", 0);
+  AddMacroDef(ltCAP_DELTA,        "Delta", 0);
+  AddMacroDef(ltDEFINECOLOUR,     "definecolour", 4);
+  AddMacroDef(ltDEFINECOLOR,      "definecolor", 4);
+  AddMacroDef(ltDESCRIPTION,      "description", 1);
+  AddMacroDef(ltDESTRUCT,         "destruct", 1);
+  AddMacroDef(ltDIAMOND2,         "diamond2", 0);
+  AddMacroDef(ltDIAMOND,          "diamond", 0);
+  AddMacroDef(ltDIV,              "div", 0);
+  AddMacroDef(ltDOCUMENTCLASS,    "documentclass", 1);
+  AddMacroDef(ltDOCUMENTSTYLE,    "documentstyle", 1);
+  AddMacroDef(ltDOCUMENT,         "document", 1);
+  AddMacroDef(ltDOUBLESPACE,      "doublespace", 1);
+  AddMacroDef(ltDOTEQ,            "doteq", 0);
+  AddMacroDef(ltDOWNARROW,        "downarrow", 0);
+  AddMacroDef(ltDOWNARROW2,       "Downarrow", 0);
+
+  AddMacroDef(ltEMPTYSET,         "emptyset", 0);
+  AddMacroDef(ltEMPH,             "emph", 1);
+  AddMacroDef(ltEM,               "em", 1);
+  AddMacroDef(ltENUMERATE,        "enumerate", 1);
+  AddMacroDef(ltEPSILON,          "epsilon", 0);
+  AddMacroDef(ltEQUATION,         "equation", 1);
+  AddMacroDef(ltEQUIV,            "equiv", 0);
+  AddMacroDef(ltETA,              "eta", 0);
+  AddMacroDef(ltEVENSIDEMARGIN,   "evensidemargin", 1);
+  AddMacroDef(ltEXISTS,           "exists", 0);
+
+  AddMacroDef(ltFBOX,             "fbox", 1);
+  AddMacroDef(ltFCOL,             "fcol", 2);
+  AddMacroDef(ltFIGURE,           "figure", 1);
+  AddMacroDef(ltFIGURESTAR,       "figure*", 1);
+  AddMacroDef(ltFLUSHLEFT,        "flushleft", 1);
+  AddMacroDef(ltFLUSHRIGHT,       "flushright", 1);
+  AddMacroDef(ltFOLLOWEDLINKCOLOUR, "followedlinkcolour", 1);
+  AddMacroDef(ltFOOTHEIGHT,       "footheight", 1);
+  AddMacroDef(ltFOOTNOTEPOPUP,    "footnotepopup", 2);
+  AddMacroDef(ltFOOTNOTE,         "footnote", 1);
+  AddMacroDef(ltFOOTSKIP,         "footskip", 1);
+  AddMacroDef(ltFORALL,           "forall", 0);
+  AddMacroDef(ltFRAMEBOX,         "framebox", 1);
+  AddMacroDef(ltFROWN,            "frown", 0);
+  AddMacroDef(ltFUNCTIONSECTION,  "functionsection", 1);
+  AddMacroDef(ltFUNC,             "func", 3);
+  AddMacroDef(ltFOOTNOTESIZE,     "footnotesize", 0);
+  AddMacroDef(ltFANCYPLAIN,       "fancyplain", 2);
+
+  AddMacroDef(ltGAMMA,            "gamma", 0);
+  AddMacroDef(ltCAP_GAMMA,        "Gamma", 0);
+  AddMacroDef(ltGEQ,              "geq", 0);
+  AddMacroDef(ltGE,               "ge", 0);
+  AddMacroDef(ltGG,               "gg", 0);
+  AddMacroDef(ltGLOSSARY,         "glossary", 1);
+  AddMacroDef(ltGLOSS,            "gloss", 1);
+
+  AddMacroDef(ltHEADHEIGHT,       "headheight", 1);
+  AddMacroDef(ltHEARTSUIT,        "heartsuit", 0);
+  AddMacroDef(ltHELPGLOSSARY,     "helpglossary", 1);
+  AddMacroDef(ltHELPIGNORE,       "helpignore", 1, TRUE);
+  AddMacroDef(ltHELPONLY,         "helponly", 1);
+  AddMacroDef(ltHELPINPUT,        "helpinput", 1);
+  AddMacroDef(ltHELPFONTFAMILY,   "helpfontfamily", 1);
+  AddMacroDef(ltHELPFONTSIZE,     "helpfontsize", 1);
+  AddMacroDef(ltHELPREFN,         "helprefn", 2);
+  AddMacroDef(ltHELPREF,          "helpref", 2);
+  AddMacroDef(ltHFILL,            "hfill", 0);
+  AddMacroDef(ltHLINE,            "hline", 0);
+  AddMacroDef(ltHRULE,            "hrule", 0);
+  AddMacroDef(ltHSPACESTAR,       "hspace*", 1);
+  AddMacroDef(ltHSPACE,           "hspace", 1);
+  AddMacroDef(ltHSKIPSTAR,        "hskip*", 1);
+  AddMacroDef(ltHSKIP,            "hskip", 1);
+  AddMacroDef(lthuge,             "huge", 1);
+  AddMacroDef(ltHuge,             "Huge", 1);
+  AddMacroDef(ltHUGE,             "HUGE", 1);
+  AddMacroDef(ltHTMLIGNORE,       "htmlignore", 1);
+  AddMacroDef(ltHTMLONLY,         "htmlonly", 1);
+
+  AddMacroDef(ltIM,               "im", 0);
+  AddMacroDef(ltINCLUDEONLY,      "includeonly", 1);
+  AddMacroDef(ltINCLUDE,          "include", 1);
+  AddMacroDef(ltINDENTED,         "indented", 2);
+  AddMacroDef(ltINDEX,            "index", 1);
+  AddMacroDef(ltINPUT,            "input", 1, TRUE);
+  AddMacroDef(ltIOTA,             "iota", 0);
+  AddMacroDef(ltITEMIZE,          "itemize", 1);
+  AddMacroDef(ltITEM,             "item", 0);
+  AddMacroDef(ltIMAGEMAP,         "imagemap", 3);
+  AddMacroDef(ltIMAGEL,           "imagel", 2);
+  AddMacroDef(ltIMAGER,           "imager", 2);
+  AddMacroDef(ltIMAGE,            "image", 2);
+  AddMacroDef(ltIN,               "in", 0);
+  AddMacroDef(ltINFTY,            "infty", 0);
+  AddMacroDef(ltITSHAPE,          "itshape", 1);
+  AddMacroDef(ltIT,               "it", 1);
+  AddMacroDef(ltITEMSEP,          "itemsep", 1);
+  AddMacroDef(ltINSERTATLEVEL,    "insertatlevel", 2);
+
+  AddMacroDef(ltKAPPA,            "kappa", 0);
+  AddMacroDef(ltKILL,             "kill", 0);
+
+  AddMacroDef(ltLABEL,            "label", 1);
+  AddMacroDef(ltLAMBDA,           "lambda", 0);
+  AddMacroDef(ltCAP_LAMBDA,       "Lambda", 0);
+  AddMacroDef(ltlarge,            "large", 1);
+  AddMacroDef(ltLarge,            "Large", 1);
+  AddMacroDef(ltLARGE,            "LARGE", 1);
+  AddMacroDef(ltLATEXIGNORE,      "latexignore", 1);
+  AddMacroDef(ltLATEXONLY,        "latexonly", 1);
+  AddMacroDef(ltLATEX,            "LaTeX", 0);
+  AddMacroDef(ltLBOX,             "lbox", 1);
+  AddMacroDef(ltLBRACERAW,        "lbraceraw", 0);
+  AddMacroDef(ltLDOTS,            "ldots", 0);
+  AddMacroDef(ltLEQ,              "leq", 0);
+  AddMacroDef(ltLE,               "le", 0);
+  AddMacroDef(ltLEFTARROW,        "leftarrow", 0);
+  AddMacroDef(ltLEFTRIGHTARROW,   "leftrightarrow", 0);
+  AddMacroDef(ltLEFTARROW2,       "Leftarrow", 0);
+  AddMacroDef(ltLEFTRIGHTARROW2,  "Leftrightarrow", 0);
+  AddMacroDef(ltLINEBREAK,        "linebreak", 0);
+  AddMacroDef(ltLINKCOLOUR,       "linkcolour", 1);
+  AddMacroDef(ltLISTOFFIGURES,    "listoffigures", 0);
+  AddMacroDef(ltLISTOFTABLES,     "listoftables", 0);
+  AddMacroDef(ltLHEAD,            "lhead", 1);
+  AddMacroDef(ltLFOOT,            "lfoot", 1);
+  AddMacroDef(ltLOWERCASE,        "lowercase", 1);
+  AddMacroDef(ltLL,               "ll", 0);
+
+  AddMacroDef(ltMAKEGLOSSARY,     "makeglossary", 0);
+  AddMacroDef(ltMAKEINDEX,        "makeindex", 0);
+  AddMacroDef(ltMAKETITLE,        "maketitle", 0);
+  AddMacroDef(ltMARKRIGHT,        "markright", 1);
+  AddMacroDef(ltMARKBOTH,         "markboth", 2);
+  AddMacroDef(ltMARGINPARWIDTH,   "marginparwidth", 1);
+  AddMacroDef(ltMARGINPARSEP,     "marginparsep", 1);
+  AddMacroDef(ltMARGINPARODD,     "marginparodd", 1);
+  AddMacroDef(ltMARGINPAREVEN,    "marginpareven", 1);
+  AddMacroDef(ltMARGINPAR,        "marginpar", 1);
+  AddMacroDef(ltMBOX,             "mbox", 1);
+  AddMacroDef(ltMDSERIES,         "mdseries", 1);
+  AddMacroDef(ltMEMBERSECTION,    "membersection", 1);
+  AddMacroDef(ltMEMBER,           "member", 2);
+  AddMacroDef(ltMID,              "mid", 0);
+  AddMacroDef(ltMODELS,           "models", 0);
+  AddMacroDef(ltMP,               "mp", 0);
+  AddMacroDef(ltMULTICOLUMN,      "multicolumn", 3);
+  AddMacroDef(ltMU,               "mu", 0);
+
+  AddMacroDef(ltNABLA,            "nabla", 0);
+  AddMacroDef(ltNEG,              "neg", 0);
+  AddMacroDef(ltNEQ,              "neq", 0);
+  AddMacroDef(ltNEWCOUNTER,       "newcounter", 1, FALSE, FORBID_ABSOLUTELY);
+  AddMacroDef(ltNEWLINE,          "newline", 0);
+  AddMacroDef(ltNEWPAGE,          "newpage", 0);
+  AddMacroDef(ltNI,               "ni", 0);
+  AddMacroDef(ltNOCITE,           "nocite", 1);
+  AddMacroDef(ltNOINDENT,         "noindent", 0);
+  AddMacroDef(ltNOLINEBREAK,      "nolinebreak", 0);
+  AddMacroDef(ltNOPAGEBREAK,      "nopagebreak", 0);
+  AddMacroDef(ltNORMALSIZE,       "normalsize", 1);
+  AddMacroDef(ltNORMALBOX,        "normalbox", 1);
+  AddMacroDef(ltNORMALBOXD,       "normalboxd", 1);
+  AddMacroDef(ltNOTEQ,            "noteq", 0);
+  AddMacroDef(ltNOTIN,            "notin", 0);
+  AddMacroDef(ltNOTSUBSET,        "notsubset", 0);
+  AddMacroDef(ltNU,               "nu", 0);
+
+  AddMacroDef(ltODDSIDEMARGIN,    "oddsidemargin", 1);
+  AddMacroDef(ltOMEGA,            "omega", 0);
+  AddMacroDef(ltCAP_OMEGA,        "Omega", 0);
+  AddMacroDef(ltONECOLUMN,        "onecolumn", 0);
+  AddMacroDef(ltOPLUS,            "oplus", 0);
+  AddMacroDef(ltOSLASH,           "oslash", 0);
+  AddMacroDef(ltOTIMES,           "otimes", 0);
+
+  AddMacroDef(ltPAGEBREAK,        "pagebreak", 0);
+  AddMacroDef(ltPAGEREF,          "pageref", 1);
+  AddMacroDef(ltPAGESTYLE,        "pagestyle", 1);
+  AddMacroDef(ltPAGENUMBERING,    "pagenumbering", 1);
+  AddMacroDef(ltPARAGRAPHSTAR,    "paragraph*", 1);
+  AddMacroDef(ltPARAGRAPH,        "paragraph", 1);
+  AddMacroDef(ltPARALLEL,         "parallel", 0);
+  AddMacroDef(ltPARAM,            "param", 2);
+  AddMacroDef(ltPARINDENT,        "parindent", 1);
+  AddMacroDef(ltPARSKIP,          "parskip", 1);
+  AddMacroDef(ltPARTIAL,          "partial", 0);
+  AddMacroDef(ltPARTSTAR,         "part*", 1);
+  AddMacroDef(ltPART,             "part", 1);
+  AddMacroDef(ltPAR,              "par", 0);
+  AddMacroDef(ltPERP,             "perp", 0);
+  AddMacroDef(ltPHI,              "phi", 0);
+  AddMacroDef(ltCAP_PHI,          "Phi", 0);
+  AddMacroDef(ltPFUNC,            "pfunc", 3);
+  AddMacroDef(ltPICTURE,          "picture", 1);
+  AddMacroDef(ltPI,               "pi", 0);
+  AddMacroDef(ltCAP_PI,           "Pi", 0);
+  AddMacroDef(ltPM,               "pm", 0);
+  AddMacroDef(ltPOPREFONLY,       "poprefonly", 1);
+  AddMacroDef(ltPOPREF,           "popref", 2);
+  AddMacroDef(ltPOUNDS,           "pounds", 0);
+  AddMacroDef(ltPREC,             "prec", 0);
+  AddMacroDef(ltPRECEQ,           "preceq", 0);
+  AddMacroDef(ltPRINTINDEX,       "printindex", 0);
+  AddMacroDef(ltPROPTO,           "propto", 0);
+  AddMacroDef(ltPSBOXTO,          "psboxto", 1, FALSE, FORBID_ABSOLUTELY);
+  AddMacroDef(ltPSBOX,            "psbox", 1, FALSE, FORBID_ABSOLUTELY);
+  AddMacroDef(ltPSI,              "psi", 0);
+  AddMacroDef(ltCAP_PSI,          "Psi", 0);
+
+  AddMacroDef(ltQUOTE,            "quote", 1);
+  AddMacroDef(ltQUOTATION,        "quotation", 1);
+
+  AddMacroDef(ltRAGGEDBOTTOM,     "raggedbottom", 0);
+  AddMacroDef(ltRAGGEDLEFT,       "raggedleft", 0);
+  AddMacroDef(ltRAGGEDRIGHT,      "raggedright", 0);
+  AddMacroDef(ltRBRACERAW,        "rbraceraw", 0);
+  AddMacroDef(ltREF,              "ref", 1);
+  AddMacroDef(ltREGISTERED,       "registered", 0);
+  AddMacroDef(ltRE,               "we", 0);
+  AddMacroDef(ltRHO,              "rho", 0);
+  AddMacroDef(ltRIGHTARROW,       "rightarrow", 0);
+  AddMacroDef(ltRIGHTARROW2,      "rightarrow2", 0);
+  AddMacroDef(ltRMFAMILY,         "rmfamily", 1);
+  AddMacroDef(ltRM,               "rm", 1);
+  AddMacroDef(ltROMAN,            "roman", 1);
+  AddMacroDef(ltROMAN2,           "Roman", 1);
+//  AddMacroDef(lt"row", 1);
+  AddMacroDef(ltRTFSP,            "rtfsp", 0);
+  AddMacroDef(ltRTFIGNORE,        "rtfignore", 1);
+  AddMacroDef(ltRTFONLY,          "rtfonly", 1);
+  AddMacroDef(ltRULEDROW,         "ruledrow", 1);
+  AddMacroDef(ltDRULED,           "druled", 1);
+  AddMacroDef(ltRULE,             "rule", 2);
+  AddMacroDef(ltRHEAD,            "rhead", 1);
+  AddMacroDef(ltRFOOT,            "rfoot", 1);
+  AddMacroDef(ltROW,              "row", 1);
+
+  AddMacroDef(ltSCSHAPE,          "scshape", 1);
+  AddMacroDef(ltSC,               "sc", 1);
+  AddMacroDef(ltSECTIONHEADING,   "sectionheading", 1);
+  AddMacroDef(ltSECTIONSTAR,      "section*", 1);
+  AddMacroDef(ltSECTION,          "section", 1);
+  AddMacroDef(ltSETCOUNTER,       "setcounter", 2);
+  AddMacroDef(ltSFFAMILY,         "sffamily", 1);
+  AddMacroDef(ltSF,               "sf", 1);
+  AddMacroDef(ltSHARP,            "sharp", 0);
+  AddMacroDef(ltSHORTCITE,        "shortcite", 1);
+  AddMacroDef(ltSIGMA,            "sigma", 0);
+  AddMacroDef(ltCAP_SIGMA,        "Sigma", 0);
+  AddMacroDef(ltSIM,              "sim", 0);
+  AddMacroDef(ltSIMEQ,            "simeq", 0);
+  AddMacroDef(ltSINGLESPACE,      "singlespace", 1);
+  AddMacroDef(ltSIZEDBOX,         "sizedbox", 2);
+  AddMacroDef(ltSIZEDBOXD,        "sizedboxd", 2);
+  AddMacroDef(ltSLOPPYPAR,        "sloppypar", 1);
+  AddMacroDef(ltSLOPPY,           "sloppy", 0);
+  AddMacroDef(ltSLSHAPE,          "slshape", 1);
+  AddMacroDef(ltSL,               "sl", 1);
+  AddMacroDef(ltSMALL,            "small", 1);
+  AddMacroDef(ltSMILE,            "smile", 0);
+  AddMacroDef(ltSS,               "ss", 0);
+  AddMacroDef(ltSTAR,             "star", 0);
+  AddMacroDef(ltSUBITEM,          "subitem", 0);
+  AddMacroDef(ltSUBPARAGRAPHSTAR, "subparagraph*", 1);
+  AddMacroDef(ltSUBPARAGRAPH,     "subparagraph", 1);
+  AddMacroDef(ltSPECIAL,          "special", 1);
+  AddMacroDef(ltSUBSECTIONSTAR,   "subsection*", 1);
+  AddMacroDef(ltSUBSECTION,       "subsection", 1);
+  AddMacroDef(ltSUBSETEQ,         "subseteq", 0);
+  AddMacroDef(ltSUBSET,           "subset", 0);
+  AddMacroDef(ltSUCC,             "succ", 0);
+  AddMacroDef(ltSUCCEQ,           "succeq", 0);
+  AddMacroDef(ltSUPSETEQ,         "supseteq", 0);
+  AddMacroDef(ltSUPSET,           "supset", 0);
+  AddMacroDef(ltSUBSUBSECTIONSTAR,"subsubsection*", 1);
+  AddMacroDef(ltSUBSUBSECTION,    "subsubsection", 1);
+  AddMacroDef(ltSUPERTABULAR,     "supertabular", 2, FALSE);
+  AddMacroDef(ltSURD,             "surd", 0);
+  AddMacroDef(ltSCRIPTSIZE,       "scriptsize", 1);
+  AddMacroDef(ltSETHEADER,        "setheader", 6);
+  AddMacroDef(ltSETFOOTER,        "setfooter", 6);
+  AddMacroDef(ltSETHOTSPOTCOLOUR, "sethotspotcolour", 1);
+  AddMacroDef(ltSETHOTSPOTCOLOR,  "sethotspotcolor", 1);
+  AddMacroDef(ltSETHOTSPOTUNDERLINE, "sethotspotunderline", 1);
+  AddMacroDef(ltSETTRANSPARENCY,  "settransparency", 1);
+  AddMacroDef(ltSPADESUIT,        "spadesuit", 0);
+
+  AddMacroDef(ltTABBING,          "tabbing", 2);
+  AddMacroDef(ltTABLEOFCONTENTS,  "tableofcontents", 0);
+  AddMacroDef(ltTABLE,            "table", 1);
+  AddMacroDef(ltTABULAR,          "tabular", 2, FALSE);
+  AddMacroDef(ltTAB,              "tab", 0);
+  AddMacroDef(ltTAU,              "tau", 0);
+  AddMacroDef(ltTEXTRM,           "textrm", 1);
+  AddMacroDef(ltTEXTSF,           "textsf", 1);
+  AddMacroDef(ltTEXTTT,           "texttt", 1);
+  AddMacroDef(ltTEXTBF,           "textbf", 1);
+  AddMacroDef(ltTEXTIT,           "textit", 1);
+  AddMacroDef(ltTEXTSL,           "textsl", 1);
+  AddMacroDef(ltTEXTSC,           "textsc", 1);
+  AddMacroDef(ltTEXTWIDTH,        "textwidth", 1);
+  AddMacroDef(ltTEXTHEIGHT,       "textheight", 1);
+  AddMacroDef(ltTEXTCOLOUR,       "textcolour", 1);
+  AddMacroDef(ltTEX,              "TeX", 0);
+  AddMacroDef(ltTHEBIBLIOGRAPHY,  "thebibliography", 2);
+  AddMacroDef(ltTHETA,            "theta", 0);
+  AddMacroDef(ltTIMES,            "times", 0);
+  AddMacroDef(ltCAP_THETA,        "Theta", 0);
+  AddMacroDef(ltTITLEPAGE,        "titlepage", 1);
+  AddMacroDef(ltTITLE,            "title", 1);
+  AddMacroDef(ltTINY,             "tiny", 1);
+  AddMacroDef(ltTODAY,            "today", 0);
+  AddMacroDef(ltTOPMARGIN,        "topmargin", 1);
+  AddMacroDef(ltTOPSKIP,          "topskip", 1);
+  AddMacroDef(ltTRIANGLE,         "triangle", 0);
+  AddMacroDef(ltTTFAMILY,         "ttfamily", 1);
+  AddMacroDef(ltTT,               "tt", 1);
+  AddMacroDef(ltTYPEIN,           "typein", 1);
+  AddMacroDef(ltTYPEOUT,          "typeout", 1);
+  AddMacroDef(ltTWOCOLWIDTHA,     "twocolwidtha", 1);
+  AddMacroDef(ltTWOCOLWIDTHB,     "twocolwidthb", 1);
+  AddMacroDef(ltTWOCOLSPACING,    "twocolspacing", 1);
+  AddMacroDef(ltTWOCOLITEMRULED,  "twocolitemruled", 2);
+  AddMacroDef(ltTWOCOLITEM,       "twocolitem", 2);
+  AddMacroDef(ltTWOCOLLIST,       "twocollist", 1);
+  AddMacroDef(ltTWOCOLUMN,        "twocolumn", 0);
+  AddMacroDef(ltTHEPAGE,          "thepage", 0);
+  AddMacroDef(ltTHECHAPTER,       "thechapter", 0);
+  AddMacroDef(ltTHESECTION,       "thesection", 0);
+  AddMacroDef(ltTHISPAGESTYLE,    "thispagestyle", 1);
+
+  AddMacroDef(ltUNDERLINE,        "underline", 1);
+  AddMacroDef(ltUPSILON,          "upsilon", 0);
+  AddMacroDef(ltCAP_UPSILON,      "Upsilon", 0);
+  AddMacroDef(ltUPARROW,          "uparrow", 0);
+  AddMacroDef(ltUPARROW2,         "Uparrow", 0);
+  AddMacroDef(ltUPPERCASE,        "uppercase", 1);
+  AddMacroDef(ltUPSHAPE,          "upshape", 1);
+  AddMacroDef(ltURLREF,           "urlref", 2);
+  AddMacroDef(ltUSEPACKAGE,       "usepackage", 1);
+  
+  AddMacroDef(ltVAREPSILON,       "varepsilon", 0);
+  AddMacroDef(ltVARPHI,           "varphi", 0);
+  AddMacroDef(ltVARPI,            "varpi", 0);
+  AddMacroDef(ltVARRHO,           "varrho", 0);
+  AddMacroDef(ltVARSIGMA,         "varsigma", 0);
+  AddMacroDef(ltVARTHETA,         "vartheta", 0);
+  AddMacroDef(ltVDOTS,            "vdots", 0);
+  AddMacroDef(ltVEE,              "vee", 0);
+  AddMacroDef(ltVERBATIMINPUT,    "verbatiminput", 1);
+  AddMacroDef(ltVERBATIM,         "verbatim", 1);
+  AddMacroDef(ltVERBSTAR,         "verb*", 1);
+  AddMacroDef(ltVERB,             "verb", 1);
+  AddMacroDef(ltVERSE,            "verse", 1);
+  AddMacroDef(ltVFILL,            "vfill", 0);
+  AddMacroDef(ltVLINE,            "vline", 0);
+  AddMacroDef(ltVOID,             "void", 0);
+  AddMacroDef(ltVDASH,            "vdash", 0);
+  AddMacroDef(ltVRULE,            "vrule", 0);
+  AddMacroDef(ltVSPACESTAR,       "vspace*", 1);
+  AddMacroDef(ltVSKIPSTAR,        "vskip*", 1);
+  AddMacroDef(ltVSPACE,           "vspace", 1);
+  AddMacroDef(ltVSKIP,            "vskip", 1);
+
+  AddMacroDef(ltWEDGE,            "wedge", 0);
+  AddMacroDef(ltWXCLIPS,          "wxclips", 0);
+  AddMacroDef(ltWINHELPIGNORE,    "winhelpignore", 1);
+  AddMacroDef(ltWINHELPONLY,      "winhelponly", 1);
+  AddMacroDef(ltWP,               "wp", 0);
+
+  AddMacroDef(ltXI,               "xi", 0);
+  AddMacroDef(ltCAP_XI,           "Xi", 0);
+  AddMacroDef(ltXLPIGNORE,        "xlpignore", 1);
+  AddMacroDef(ltXLPONLY,          "xlponly", 1);
+
+  AddMacroDef(ltZETA,             "zeta", 0);
+
+  AddMacroDef(ltSPACE,            " ", 0);
+  AddMacroDef(ltBACKSLASHCHAR,    "\\", 0);
+  AddMacroDef(ltPIPE,             "|", 0);
+  AddMacroDef(ltFORWARDSLASH,     "/", 0);
+  AddMacroDef(ltUNDERSCORE,       "_", 0);
+  AddMacroDef(ltAMPERSAND,        "&", 0);
+  AddMacroDef(ltPERCENT,          "%", 0);
+  AddMacroDef(ltDOLLAR,           "$", 0);
+  AddMacroDef(ltHASH,             "#", 0);
+  AddMacroDef(ltLPARENTH,         "(", 0);
+  AddMacroDef(ltRPARENTH,         ")", 0);
+  AddMacroDef(ltLBRACE,           "{", 0);
+  AddMacroDef(ltRBRACE,           "}", 0);
+//  AddMacroDef(ltEQUALS,           "=", 0);
+  AddMacroDef(ltRANGLEBRA,        ">", 0);
+  AddMacroDef(ltLANGLEBRA,        "<", 0);
+  AddMacroDef(ltPLUS,             "+", 0);
+  AddMacroDef(ltDASH,             "-", 0);
+  AddMacroDef(ltAT_SYMBOL,        "@", 0);
+//  AddMacroDef(ltSINGLEQUOTE,      "'", 0);
+//  AddMacroDef(ltBACKQUOTE,        "`", 0);
+}
+
+/*
+ * Default behaviour, should be called by client if can't match locally.
+ *
+ */
+// Called on start/end of macro examination
+void DefaultOnMacro(int macroId, int no_args, bool start)
+{
+  switch (macroId)
+  {
+    // Default behaviour for abstract
+    case ltABSTRACT:
+    {
+      if (start)
+      {
+        // Write the heading
+        FakeCurrentSection(AbstractNameString);
+        OnMacro(ltPAR, 0, TRUE);
+        OnMacro(ltPAR, 0, FALSE);
+      }
+      else
+      {
+        if (DocumentStyle == LATEX_ARTICLE)
+          sectionNo --;
+        else
+          chapterNo --;
+      }
+      break;
+    }
+
+    // Default behaviour for glossary
+    case ltHELPGLOSSARY:
+    {
+      if (start)
+      {
+        // Write the heading
+        FakeCurrentSection(GlossaryNameString);
+        OnMacro(ltPAR, 0, TRUE);
+        OnMacro(ltPAR, 0, FALSE);
+        if ((convertMode == TEX_RTF) && !winHelp)
+        {
+          OnMacro(ltPAR, 0, TRUE);
+          OnMacro(ltPAR, 0, FALSE);
+        }
+      }
+      break;
+    }
+    case ltSPECIALAMPERSAND:
+      if (start)
+        TexOutput("  ");
+      break;
+
+    case ltCINSERT:
+      if (start)
+        TexOutput("<<", TRUE);
+      break;
+    case ltCEXTRACT:
+      if (start)
+        TexOutput(">>", TRUE);
+      break;
+    case ltDESTRUCT:
+      if (start)
+        TexOutput("~", TRUE);
+      break;
+    case ltTILDE:
+      if (start)
+        TexOutput("~", TRUE);
+      break;
+    case ltSPECIALTILDE:
+      if (start)
+        TexOutput(" ", TRUE);
+      break;
+    case ltUNDERSCORE:
+      if (start)
+        TexOutput("_", TRUE);
+      break;
+    case ltHASH:
+      if (start)
+        TexOutput("#", TRUE);
+      break;
+    case ltAMPERSAND:
+      if (start)
+        TexOutput("&", TRUE);
+      break;
+    case ltSPACE:
+      if (start)
+        TexOutput(" ", TRUE);
+      break;
+    case ltPIPE:
+      if (start)
+        TexOutput("|", TRUE);
+      break;
+    case ltPERCENT:
+      if (start)
+        TexOutput("%", TRUE);
+      break;
+    case ltDOLLAR:
+      if (start)
+        TexOutput("$", TRUE);
+      break;
+    case ltLPARENTH:
+      if (start)
+        TexOutput("", TRUE);
+      break;
+    case ltRPARENTH:
+      if (start)
+        TexOutput("", TRUE);
+      break;
+    case ltLBRACE:
+      if (start)
+        TexOutput("{", TRUE);
+      break;
+    case ltRBRACE:
+      if (start)
+        TexOutput("}", TRUE);
+      break;
+    case ltCOPYRIGHT:
+      if (start)
+        TexOutput("(c)", TRUE);
+      break;
+    case ltREGISTERED:
+      if (start)
+        TexOutput("(r)", TRUE);
+      break;
+    case ltBACKSLASH:
+      if (start)    
+        TexOutput("\\", TRUE);
+      break;
+    case ltLDOTS:
+    case ltCDOTS:
+      if (start)
+        TexOutput("...", TRUE);
+      break;
+    case ltVDOTS:
+      if (start)
+        TexOutput("|", TRUE);
+      break;
+    case ltLATEX:
+      if (start)
+        TexOutput("LaTeX", TRUE);
+      break;
+    case ltTEX:
+      if (start)
+        TexOutput("TeX", TRUE);
+      break;
+    case ltPOUNDS:
+      if (start)
+        TexOutput("£", TRUE);
+      break;
+    case ltSPECIALDOUBLEDOLLAR:  // Interpret as center
+      OnMacro(ltCENTER, no_args, start);
+      break;
+    case ltEMPH:
+    case ltTEXTSL:
+    case ltSLSHAPE:
+    case ltSL:
+      OnMacro(ltIT, no_args, start);
+      break;
+    case ltPARAGRAPH:
+    case ltPARAGRAPHSTAR:
+    case ltSUBPARAGRAPH:
+    case ltSUBPARAGRAPHSTAR:
+      OnMacro(ltSUBSUBSECTION, no_args, start);
+      break;
+    case ltTODAY:
+    {
+      if (start)
+      {
+        time_t when;
+        (void) time(&when);
+        TexOutput(ctime(&when), TRUE);
+      }
+      break;
+    }
+    case ltNOINDENT:
+      if (start)
+        ParIndent = 0;
+      break;
+
+    // Symbols
+    case ltALPHA:
+      if (start) TexOutput("alpha");
+      break;
+    case ltBETA:
+      if (start) TexOutput("beta");
+      break;
+    case ltGAMMA:
+      if (start) TexOutput("gamma");
+      break;
+    case ltDELTA:
+      if (start) TexOutput("delta");
+      break;
+    case ltEPSILON:
+    case ltVAREPSILON:
+      if (start) TexOutput("epsilon");
+      break;
+    case ltZETA:
+      if (start) TexOutput("zeta");
+      break;
+    case ltETA:
+      if (start) TexOutput("eta");
+      break;
+    case ltTHETA:
+    case ltVARTHETA:
+      if (start) TexOutput("theta");
+      break;
+    case ltIOTA:
+      if (start) TexOutput("iota");
+      break;
+    case ltKAPPA:
+      if (start) TexOutput("kappa");
+      break;
+    case ltLAMBDA:
+      if (start) TexOutput("lambda");
+      break;
+    case ltMU:
+      if (start) TexOutput("mu");
+      break;
+    case ltNU:
+      if (start) TexOutput("nu");
+      break;
+    case ltXI:
+      if (start) TexOutput("xi");
+      break;
+    case ltPI:
+    case ltVARPI:
+      if (start) TexOutput("pi");
+      break;
+    case ltRHO:
+    case ltVARRHO:
+      if (start) TexOutput("rho");
+      break;
+    case ltSIGMA:
+    case ltVARSIGMA:
+      if (start) TexOutput("sigma");
+      break;
+    case ltTAU:
+      if (start) TexOutput("tau");
+      break;
+    case ltUPSILON:
+      if (start) TexOutput("upsilon");
+      break;
+    case ltPHI:
+    case ltVARPHI:
+      if (start) TexOutput("phi");
+      break;
+    case ltCHI:
+      if (start) TexOutput("chi");
+      break;
+    case ltPSI:
+      if (start) TexOutput("psi");
+      break;
+    case ltOMEGA:
+      if (start) TexOutput("omega");
+      break;
+    case ltCAP_GAMMA:
+      if (start) TexOutput("GAMMA");
+      break;
+    case ltCAP_DELTA:
+      if (start) TexOutput("DELTA");
+      break;
+    case ltCAP_THETA:
+      if (start) TexOutput("THETA");
+      break;
+    case ltCAP_LAMBDA:
+      if (start) TexOutput("LAMBDA");
+      break;
+    case ltCAP_XI:
+      if (start) TexOutput("XI");
+      break;
+    case ltCAP_PI:
+      if (start) TexOutput("PI");
+      break;
+    case ltCAP_SIGMA:
+      if (start) TexOutput("SIGMA");
+      break;
+    case ltCAP_UPSILON:
+      if (start) TexOutput("UPSILON");
+      break;
+    case ltCAP_PHI:
+      if (start) TexOutput("PHI");
+      break;
+    case ltCAP_PSI:
+      if (start) TexOutput("PSI");
+      break;
+    case ltCAP_OMEGA:
+      if (start) TexOutput("OMEGA");
+      break;
+
+    // Binary operation symbols
+    case ltLE:
+    case ltLEQ:
+      if (start) TexOutput("<=");
+      break;
+    case ltLL:
+      if (start) TexOutput("<<");
+      break;
+    case ltSUBSET:
+      if (start) TexOutput("SUBSET");
+      break;
+    case ltSUBSETEQ:
+      if (start) TexOutput("SUBSETEQ");
+      break;
+    case ltIN:
+      if (start) TexOutput("IN");
+      break;
+    case ltVDASH:
+      if (start) TexOutput("VDASH");
+      break;
+    case ltMODELS:
+      if (start) TexOutput("MODELS");
+      break;
+    case ltGE:
+    case ltGEQ:
+      if (start) TexOutput(">=");
+      break;
+    case ltGG:
+      if (start) TexOutput(">>");
+      break;
+    case ltSUPSET:
+      if (start) TexOutput("SUPSET");
+      break;
+    case ltSUPSETEQ:
+      if (start) TexOutput("SUPSETEQ");
+      break;
+    case ltNI:
+      if (start) TexOutput("NI");
+      break;
+    case ltDASHV:
+      if (start) TexOutput("DASHV");
+      break;
+    case ltPERP:
+      if (start) TexOutput("PERP");
+      break;
+    case ltNEQ:
+      if (start) TexOutput("NEQ");
+      break;
+    case ltDOTEQ:
+      if (start) TexOutput("DOTEQ");
+      break;
+    case ltAPPROX:
+      if (start) TexOutput("APPROX");
+      break;
+    case ltCONG:
+      if (start) TexOutput("CONG");
+      break;
+    case ltEQUIV:
+      if (start) TexOutput("EQUIV");
+      break;
+    case ltPROPTO:
+      if (start) TexOutput("PROPTO");
+      break;
+    case ltPREC:
+      if (start) TexOutput("PREC");
+      break;
+    case ltPRECEQ:
+      if (start) TexOutput("PRECEQ");
+      break;
+    case ltPARALLEL:
+      if (start) TexOutput("|");
+      break;
+    case ltSIM:
+      if (start) TexOutput("~");
+      break;
+    case ltSIMEQ:
+      if (start) TexOutput("SIMEQ");
+      break;
+    case ltASYMP:
+      if (start) TexOutput("ASYMP");
+      break;
+    case ltSMILE:
+      if (start) TexOutput(":-)");
+      break;
+    case ltFROWN:
+      if (start) TexOutput(":-(");
+      break;
+    case ltSUCC:
+      if (start) TexOutput("SUCC");
+      break;
+    case ltSUCCEQ:
+      if (start) TexOutput("SUCCEQ");
+      break;
+    case ltMID:
+      if (start) TexOutput("|");
+      break;
+
+    // Negated relation symbols
+    case ltNOTEQ:
+      if (start) TexOutput("!=");
+      break;
+    case ltNOTIN:
+      if (start) TexOutput("NOTIN");
+      break;
+    case ltNOTSUBSET:
+      if (start) TexOutput("NOTSUBSET");
+      break;
+
+    // Arrows
+    case ltLEFTARROW:
+      if (start) TexOutput("<--");
+      break;
+    case ltLEFTARROW2:
+      if (start) TexOutput("<==");
+      break;
+    case ltRIGHTARROW:
+      if (start) TexOutput("-->");
+      break;
+    case ltRIGHTARROW2:
+      if (start) TexOutput("==>");
+      break;
+    case ltLEFTRIGHTARROW:
+      if (start) TexOutput("<-->");
+      break;
+    case ltLEFTRIGHTARROW2:
+      if (start) TexOutput("<==>");
+      break;
+    case ltUPARROW:
+      if (start) TexOutput("UPARROW");
+      break;
+    case ltUPARROW2:
+      if (start) TexOutput("UPARROW2");
+      break;
+    case ltDOWNARROW:
+      if (start) TexOutput("DOWNARROW");
+      break;
+    case ltDOWNARROW2:
+      if (start) TexOutput("DOWNARROW2");
+      break;
+    // Miscellaneous symbols
+    case ltALEPH:
+      if (start) TexOutput("ALEPH");
+      break;
+    case ltWP:
+      if (start) TexOutput("WP");
+      break;
+    case ltRE:
+      if (start) TexOutput("RE");
+      break;
+    case ltIM:
+      if (start) TexOutput("IM");
+      break;
+    case ltEMPTYSET:
+      if (start) TexOutput("EMPTYSET");
+      break;
+    case ltNABLA:
+      if (start) TexOutput("NABLA");
+      break;
+    case ltSURD:
+      if (start) TexOutput("SURD");
+      break;
+    case ltPARTIAL:
+      if (start) TexOutput("PARTIAL");
+      break;
+    case ltBOT:
+      if (start) TexOutput("BOT");
+      break;
+    case ltFORALL:
+      if (start) TexOutput("FORALL");
+      break;
+    case ltEXISTS:
+      if (start) TexOutput("EXISTS");
+      break;
+    case ltNEG:
+      if (start) TexOutput("NEG");
+      break;
+    case ltSHARP:
+      if (start) TexOutput("SHARP");
+      break;
+    case ltANGLE:
+      if (start) TexOutput("ANGLE");
+      break;
+    case ltTRIANGLE:
+      if (start) TexOutput("TRIANGLE");
+      break;
+    case ltCLUBSUIT:
+      if (start) TexOutput("CLUBSUIT");
+      break;
+    case ltDIAMONDSUIT:
+      if (start) TexOutput("DIAMONDSUIT");
+      break;
+    case ltHEARTSUIT:
+      if (start) TexOutput("HEARTSUIT");
+      break;
+    case ltSPADESUIT:
+      if (start) TexOutput("SPADESUIT");
+      break;
+    case ltINFTY:
+      if (start) TexOutput("INFTY");
+      break;
+    case ltPM:
+      if (start) TexOutput("PM");
+      break;
+    case ltMP:
+      if (start) TexOutput("MP");
+      break;
+    case ltTIMES:
+      if (start) TexOutput("TIMES");
+      break;
+    case ltDIV:
+      if (start) TexOutput("DIV");
+      break;
+    case ltCDOT:
+      if (start) TexOutput("CDOT");
+      break;
+    case ltAST:
+      if (start) TexOutput("AST");
+      break;
+    case ltSTAR:
+      if (start) TexOutput("STAR");
+      break;
+    case ltCAP:
+      if (start) TexOutput("CAP");
+      break;
+    case ltCUP:
+      if (start) TexOutput("CUP");
+      break;
+    case ltVEE:
+      if (start) TexOutput("VEE");
+      break;
+    case ltWEDGE:
+      if (start) TexOutput("WEDGE");
+      break;
+    case ltCIRC:
+      if (start) TexOutput("CIRC");
+      break;
+    case ltBULLET:
+      if (start) TexOutput("BULLET");
+      break;
+    case ltDIAMOND:
+      if (start) TexOutput("DIAMOND");
+      break;
+    case ltOSLASH:
+      if (start) TexOutput("OSLASH");
+      break;
+    case ltBOX:
+      if (start) TexOutput("BOX");
+      break;
+    case ltDIAMOND2:
+      if (start) TexOutput("DIAMOND2");
+      break;
+    case ltBIGTRIANGLEDOWN:
+      if (start) TexOutput("BIGTRIANGLEDOWN");
+      break;
+    case ltOPLUS:
+      if (start) TexOutput("OPLUS");
+      break;
+    case ltOTIMES:
+      if (start) TexOutput("OTIMES");
+      break;
+    case ltSS:
+      if (start) TexOutput("s");
+      break;
+    case ltBACKSLASHRAW:
+      if (start) TexOutput("\\");
+      break;
+    case ltLBRACERAW:
+      if (start) TexOutput("{");
+      break;
+    case ltRBRACERAW:
+      if (start) TexOutput("}");
+      break;
+    case ltSMALLSPACE1:
+    case ltSMALLSPACE2:
+      if (start) TexOutput(" ");
+      break;
+    default:
+      break;
+  }
+}
+
+// Called on start/end of argument examination
+bool DefaultOnArgument(int macroId, int arg_no, bool start)
+{
+  switch (macroId)
+  {
+    case ltREF:
+    {
+    if (arg_no == 1 && start)
+    {
+      char *refName = GetArgData();
+      if (refName)
+      {
+        TexRef *texRef = FindReference(refName);
+        if (texRef)
+        {
+          // Must strip the 'section' or 'chapter' or 'figure' text
+          // from a normal 'ref' reference
+          char buf[150];
+          strcpy(buf, texRef->sectionNumber);
+          int len = strlen(buf);
+          int i = 0;
+          if (strcmp(buf, "??") != 0)
+          {
+            while (i < len)
+            {
+              if (buf[i] == ' ')
+              {
+                i ++;
+                break;
+              }
+              else i ++;
+            }
+          }
+          TexOutput(texRef->sectionNumber + i, TRUE);
+        }
+        else
+        {
+          char buf[300];
+          TexOutput("??", TRUE);
+          sprintf(buf, "Warning: unresolved reference %s.", refName); 
+          OnInform(buf);
+        }
+      }
+      else TexOutput("??", TRUE);
+      return FALSE;
+    }
+    break;
+    }
+    case ltLABEL:
+    {
+      return FALSE;
+      break;
+    }
+    case ltAUTHOR:
+    {
+      if (start && (arg_no == 1))
+        DocumentAuthor = GetArgChunk();
+      return FALSE;
+      break;
+    }
+    case ltDATE:
+    {
+      if (start && (arg_no == 1))
+        DocumentDate = GetArgChunk();
+      return FALSE;
+      break;
+    }
+    case ltTITLE:
+    {
+      if (start && (arg_no == 1))
+        DocumentTitle = GetArgChunk();
+      return FALSE;
+      break;
+    }
+  case ltDOCUMENTCLASS:
+  case ltDOCUMENTSTYLE:
+  {
+    if (start && !IsArgOptional())
+    {
+      DocumentStyleString = copystring(GetArgData());
+      if (strncmp(DocumentStyleString, "art", 3) == 0)
+        DocumentStyle = LATEX_ARTICLE;
+      else if (strncmp(DocumentStyleString, "rep", 3) == 0)
+        DocumentStyle = LATEX_REPORT;
+      else if (strncmp(DocumentStyleString, "book", 4) == 0 ||
+               strncmp(DocumentStyleString, "thesis", 6) == 0)
+        DocumentStyle = LATEX_BOOK;
+      else if (strncmp(DocumentStyleString, "letter", 6) == 0)
+        DocumentStyle = LATEX_LETTER;
+      else if (strncmp(DocumentStyleString, "slides", 6) == 0)
+        DocumentStyle = LATEX_SLIDES;
+        
+      if (StringMatch("10", DocumentStyleString))
+        SetFontSizes(10);
+      else if (StringMatch("11", DocumentStyleString))
+        SetFontSizes(11);
+      else if (StringMatch("12", DocumentStyleString))
+        SetFontSizes(12);
+
+      OnMacro(ltHELPFONTSIZE, 1, TRUE);
+      sprintf(currentArgData, "%d", normalFont);
+      haveArgData = TRUE;
+      OnArgument(ltHELPFONTSIZE, 1, TRUE);
+      OnArgument(ltHELPFONTSIZE, 1, FALSE);
+      haveArgData = FALSE;
+      OnMacro(ltHELPFONTSIZE, 1, FALSE);
+    }
+    else if (start && IsArgOptional())
+    {
+      MinorDocumentStyleString = copystring(GetArgData());
+
+      if (StringMatch("10", MinorDocumentStyleString))
+        SetFontSizes(10);
+      else if (StringMatch("11", MinorDocumentStyleString))
+        SetFontSizes(11);
+      else if (StringMatch("12", MinorDocumentStyleString))
+        SetFontSizes(12);
+    }
+    return FALSE;
+    break;
+  }
+  case ltBIBLIOGRAPHYSTYLE:
+  {
+    if (start && !IsArgOptional())
+      BibliographyStyleString = copystring(GetArgData());
+    return FALSE;
+    break;
+  }
+  case ltPAGESTYLE:
+  {
+    if (start && !IsArgOptional())
+    {
+      if (PageStyle) delete[] PageStyle;
+      PageStyle = copystring(GetArgData());
+    }
+    return FALSE;
+    break;
+  }
+/*
+  case ltLHEAD:
+  {
+    if (start && !IsArgOptional())
+      LeftHeader = GetArgChunk();
+    return FALSE;
+    break;
+  }
+  case ltLFOOT:
+  {
+    if (start && !IsArgOptional())
+      LeftFooter = GetArgChunk();
+    return FALSE;
+    break;
+  }
+  case ltCHEAD:
+  {
+    if (start && !IsArgOptional())
+      CentreHeader = GetArgChunk();
+    return FALSE;
+    break;
+  }
+  case ltCFOOT:
+  {
+    if (start && !IsArgOptional())
+      CentreFooter = GetArgChunk();
+    return FALSE;
+    break;
+  }
+  case ltRHEAD:
+  {
+    if (start && !IsArgOptional())
+      RightHeader = GetArgChunk();
+    return FALSE;
+    break;
+  }
+  case ltRFOOT:
+  {
+    if (start && !IsArgOptional())
+      RightFooter = GetArgChunk();
+    return FALSE;
+    break;
+  }
+*/
+  case ltCITE:
+  case ltSHORTCITE:
+  {
+    if (start && !IsArgOptional())
+    {
+      char *citeKeys = GetArgData();
+      int pos = 0;
+      char *citeKey = ParseMultifieldString(citeKeys, &pos);
+      while (citeKey)
+      {
+        AddCitation(citeKey);
+        TexRef *ref = FindReference(citeKey);
+        if (ref)
+        {
+          TexOutput(ref->sectionNumber, TRUE);
+          if (strcmp(ref->sectionNumber, "??") == 0)
+          {
+            char buf[300];
+            sprintf(buf, "Warning: unresolved citation %s.", citeKey);
+            OnInform(buf);
+          }
+        }
+        citeKey = ParseMultifieldString(citeKeys, &pos);
+        if (citeKey)
+        {
+          TexOutput(", ", TRUE);
+        }
+      }
+      return FALSE;
+    }
+    break;
+  }
+  case ltNOCITE:
+  {
+    if (start && !IsArgOptional())
+    {
+      char *citeKey = GetArgData();
+      AddCitation(citeKey);
+      return FALSE;
+    }
+    break;
+  }
+  case ltHELPFONTSIZE:
+  {
+    if (start)
+    {
+      char *data = GetArgData();
+      if (strcmp(data, "10") == 0)
+        SetFontSizes(10);
+      else if (strcmp(data, "11") == 0)
+        SetFontSizes(11);
+      else if (strcmp(data, "12") == 0)
+        SetFontSizes(12);
+      return FALSE;
+    }
+    break;
+  }
+  case ltPAGEREF:
+  {
+    if (start)
+    {
+      TexOutput(" ??", TRUE);
+      return FALSE;
+    }
+    break;
+  }
+  case ltPARSKIP:
+  {
+    if (start && arg_no == 1)
+    {
+      char *data = GetArgData();
+      ParSkip = ParseUnitArgument(data);
+      return FALSE;
+    }
+    break;
+  }
+  case ltPARINDENT:
+  {
+    if (start && arg_no == 1)
+    {
+      char *data = GetArgData();
+      ParIndent = ParseUnitArgument(data);
+      return FALSE;
+    }
+    break;
+  }
+  case ltSL:
+  {
+    return OnArgument(ltIT, arg_no, start);
+    break;
+  }
+  case ltSPECIALDOUBLEDOLLAR:
+  {
+    return OnArgument(ltCENTER, arg_no, start);
+    break;
+  }
+  case ltPARAGRAPH:
+  case ltPARAGRAPHSTAR:
+  case ltSUBPARAGRAPH:
+  case ltSUBPARAGRAPHSTAR:
+  {
+    return OnArgument(ltSUBSUBSECTION, arg_no, start);
+    break;
+  }
+  case ltTYPEOUT:
+  {
+    if (start)
+      OnInform(GetArgData());
+    break;
+  }
+  case ltFOOTNOTE:
+  {
+    if (start)
+      TexOutput(" (", TRUE);
+    else
+      TexOutput(")", TRUE);
+    break;
+  }
+  case ltBIBLIOGRAPHY:
+  {
+    if (start)
+    {
+      FILE *fd;
+      int ch;
+      char smallBuf[2];
+      smallBuf[1] = 0;
+      if ((fd = fopen(TexBibName, "r")))
+      {
+        ch = getc(fd);
+        smallBuf[0] = ch;
+        while (ch != EOF)
+        {
+          TexOutput(smallBuf);
+          ch = getc(fd);
+          smallBuf[0] = ch;
+        }
+        fclose(fd);
+      }
+      else
+      {
+        OnInform("Run Tex2RTF again to include bibliography.");
+      }
+
+      // Read in the .bib file, resolve all known references, write out the RTF.
+      char *allFiles = GetArgData();
+      int pos = 0;
+      char *bibFile = ParseMultifieldString(allFiles, &pos);
+      while (bibFile)
+      {
+        char fileBuf[300];
+        strcpy(fileBuf, bibFile);
+        wxString actualFile = TexPathList.FindValidPath(fileBuf);
+        if (actualFile == "")
+        {
+          strcat(fileBuf, ".bib");
+          actualFile = TexPathList.FindValidPath(fileBuf);
+        }
+        if (actualFile != "")
+        {
+          if (!ReadBib((char*) (const char*) actualFile))
+          {
+            char buf[300];
+            sprintf(buf, ".bib file %s not found or malformed", (const char*) actualFile);
+            OnError(buf);
+          }
+        }
+        else
+        {
+          char buf[300];
+          sprintf(buf, ".bib file %s not found", fileBuf);
+          OnError(buf);
+        }
+        bibFile = ParseMultifieldString(allFiles, &pos);
+      }
+
+      ResolveBibReferences();
+
+      // Write it a new bib section in the appropriate format.
+      FILE *save1 = CurrentOutput1;
+      FILE *save2 = CurrentOutput2;
+      FILE *Biblio = fopen(TexTmpBibName, "w");
+      SetCurrentOutput(Biblio);
+      OutputBib();
+      fclose(Biblio);
+      if (wxFileExists(TexTmpBibName))
+      {
+        if (wxFileExists(TexBibName)) wxRemoveFile(TexBibName);
+        wxRenameFile(TexTmpBibName, TexBibName);
+      }
+      SetCurrentOutputs(save1, save2);
+      return FALSE;
+    }
+    break;
+  }
+  case ltMULTICOLUMN:
+  {
+    if (start && (arg_no == 3))
+      return TRUE;
+    else
+      return FALSE;
+    break;
+  }
+  case ltSCSHAPE:
+  case ltTEXTSC:
+  case ltSC:
+  {
+    if (start && (arg_no == 1))
+    {
+      char *s = GetArgData();
+      if (s)
+      {
+        char *s1 = copystring(s);
+        int i;
+        for (i = 0; i < (int)strlen(s); i++)
+          s1[i] = toupper(s[i]);
+        TexOutput(s1);
+        delete[] s1;
+        return FALSE;
+      }
+      else return TRUE;
+
+    }
+    return TRUE;
+    break;
+  }
+  case ltLOWERCASE:
+  {
+    if (start && (arg_no == 1))
+    {
+      char *s = GetArgData();
+      if (s)
+      {
+        char *s1 = copystring(s);
+        int i;
+        for (i = 0; i < (int)strlen(s); i++)
+          s1[i] = tolower(s[i]);
+        TexOutput(s1);
+        delete[] s1;
+        return FALSE;
+      }
+      else return TRUE;
+
+    }
+    return TRUE;
+    break;
+  }
+  case ltUPPERCASE:
+  {
+    if (start && (arg_no == 1))
+    {
+      char *s = GetArgData();
+      if (s)
+      {
+        char *s1 = copystring(s);
+        int i;
+        for (i = 0; i < (int)strlen(s); i++)
+          s1[i] = toupper(s[i]);
+        TexOutput(s1);
+        delete[] s1;
+        return FALSE;
+      }
+      else return TRUE;
+
+    }
+    return TRUE;
+    break;
+  }
+  case ltPOPREF:  // Ignore second argument by default
+  {
+    if (start && (arg_no == 1))
+      return TRUE;
+    else
+      return FALSE;
+    break;
+  }
+  case ltTWOCOLUMN:
+    return TRUE;
+    break;
+  case ltXLPIGNORE:
+    return ((convertMode == TEX_XLP) ? FALSE : TRUE);
+    break;
+  case ltXLPONLY:
+    return ((convertMode != TEX_XLP) ? FALSE : TRUE);
+    break;
+  case ltHTMLIGNORE:
+    return ((convertMode == TEX_HTML) ? FALSE : TRUE);
+    break;
+  case ltHTMLONLY:
+    return ((convertMode != TEX_HTML) ? FALSE : TRUE);
+    break;
+  case ltRTFIGNORE:
+    return (((convertMode == TEX_RTF) && !winHelp) ? FALSE : TRUE);
+    break;
+  case ltRTFONLY:
+    return (!((convertMode == TEX_RTF) && !winHelp) ? FALSE : TRUE);
+    break;
+  case ltWINHELPIGNORE:
+    return (winHelp ? FALSE : TRUE);
+    break;
+  case ltWINHELPONLY:
+    return (!winHelp ? FALSE : TRUE);
+    break;
+  case ltLATEXIGNORE:
+    return TRUE;
+    break;
+  case ltLATEXONLY:
+    return FALSE;
+    break;
+  case ltCLINE:
+  case ltARABIC:
+  case ltALPH1:
+  case ltALPH2:
+  case ltROMAN:
+  case ltROMAN2:
+  case ltSETCOUNTER:
+  case ltADDTOCOUNTER:
+  case ltADDCONTENTSLINE:
+  case ltNEWCOUNTER:
+  case ltTEXTWIDTH:
+  case ltTEXTHEIGHT:
+  case ltBASELINESKIP:
+  case ltVSPACESTAR:
+  case ltHSPACESTAR:
+  case ltVSPACE:
+  case ltHSPACE:
+  case ltVSKIPSTAR:
+  case ltHSKIPSTAR:
+  case ltVSKIP:
+  case ltHSKIP:
+  case ltPAGENUMBERING:
+  case ltTHEPAGE:
+  case ltTHECHAPTER:
+  case ltTHESECTION:
+  case ltITEMSEP:
+  case ltFANCYPLAIN:
+  case ltCHEAD:
+  case ltRHEAD:
+  case ltLHEAD:
+  case ltCFOOT:
+  case ltRFOOT:
+  case ltLFOOT:
+  case ltTHISPAGESTYLE:
+  case ltMARKRIGHT:
+  case ltMARKBOTH:
+  case ltEVENSIDEMARGIN:
+  case ltODDSIDEMARGIN:
+  case ltMARGINPAR:
+  case ltMARGINPARWIDTH:
+  case ltMARGINPARSEP:
+  case ltMARGINPAREVEN:
+  case ltMARGINPARODD:
+  case ltTWOCOLWIDTHA:
+  case ltTWOCOLWIDTHB:
+  case ltTWOCOLSPACING:
+  case ltSETHEADER:
+  case ltSETFOOTER:
+  case ltINDEX:
+  case ltITEM:
+  case ltBCOL:
+  case ltFCOL:
+  case ltSETHOTSPOTCOLOUR:
+  case ltSETHOTSPOTCOLOR:
+  case ltSETHOTSPOTUNDERLINE:
+  case ltSETTRANSPARENCY:
+  case ltUSEPACKAGE:
+  case ltBACKGROUND:
+  case ltBACKGROUNDCOLOUR:
+  case ltBACKGROUNDIMAGE:
+  case ltLINKCOLOUR:
+  case ltFOLLOWEDLINKCOLOUR:
+  case ltTEXTCOLOUR:
+  case ltIMAGE:
+  case ltIMAGEMAP:
+  case ltIMAGEL:
+  case ltIMAGER:
+  case ltPOPREFONLY:
+  case ltINSERTATLEVEL:
+    return FALSE;
+    break;
+  case ltTABULAR:
+  case ltSUPERTABULAR:
+  {
+    if (arg_no == 2)
+      return TRUE;
+    else return FALSE;
+    break;
+  }
+  case ltINDENTED:
+  {
+    if (arg_no == 2) return TRUE;
+    else return FALSE;
+    break;
+  }
+  case ltSIZEDBOX:
+  case ltSIZEDBOXD:
+  {
+    if (arg_no == 2) return TRUE;
+    else return FALSE;
+    break;
+  }
+  case ltDEFINECOLOUR:
+  case ltDEFINECOLOR:
+  {
+    static int redVal = 0;
+    static int greenVal = 0;
+    static int blueVal = 0;
+    static char *colourName = NULL;
+    if (start)
+    {
+      switch (arg_no)
+      {
+        case 1:
+        {
+          if (colourName) delete[] colourName;
+          colourName = copystring(GetArgData());
+          break;
+        }
+        case 2:
+        {
+          redVal = atoi(GetArgData());
+          break;
+        }
+        case 3:
+        {
+          greenVal = atoi(GetArgData());
+          break;
+        }
+        case 4:
+        {
+          blueVal = atoi(GetArgData());
+          AddColour(colourName, redVal, greenVal, blueVal);
+          break;
+        }
+        default:
+          break;
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltFIGURE:
+  case ltFIGURESTAR:
+  case ltNORMALBOX:
+  case ltNORMALBOXD:
+  default:
+  {
+    if (IsArgOptional())
+      return FALSE;
+    else
+      return TRUE;
+    break;
+  }
+  }
+  return TRUE;
+}
+
diff --git a/utils/tex2rtf/src/tex2any.h b/utils/tex2rtf/src/tex2any.h
new file mode 100644 (file)
index 0000000..db5b191
--- /dev/null
@@ -0,0 +1,1067 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        tex2any.h
+// Purpose:     Latex conversion header
+// Author:      Julian Smart
+// Modified by:
+// Created:     7.9.93
+// RCS-ID:      $Id$
+// Copyright:   (c) Julian Smart
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "wx/wx.h"
+#include "wx/utils.h"
+#include "wx/list.h"
+#include "wx/hash.h"
+#include "wxhlpblk.h"
+
+/*
+ * Conversion modes
+ *
+ */
+#define TEX_RTF  1
+#define TEX_XLP  2
+#define TEX_HTML 3
+
+/*
+ * We have a list of macro definitions which we must define
+ * in advance to enable the parsing to recognize macros.
+ */
+
+#define FORBID_OK         0
+#define FORBID_WARN       1
+#define FORBID_ABSOLUTELY 2
+
+class TexMacroDef: public wxObject
+{
+ public:
+  int no_args;
+  char *name;
+  bool ignore;
+  int forbidden;
+  int macroId;
+
+  TexMacroDef(int the_id, char *the_name, int n, bool ig, bool forbidLevel = FORBID_OK);
+  ~TexMacroDef(void);
+};
+
+#define CHUNK_TYPE_MACRO    1
+#define CHUNK_TYPE_ARG      2
+#define CHUNK_TYPE_STRING   3
+
+/*
+ We have nested lists to represent the Tex document.
+ Each element of a list of chunks can be one of:
+  - a plain string
+  - a macro with/without arguments. Arguments are lists of TexChunks.
+
+Example (\toplevel is implicit but made explicit here):
+
+AddMacroDef(ltMYMAT, "mymat", 2);
+
+\toplevel{The cat sat on the \mymat{very coarse and {\it cheap}}{mat}}.
+
+Parsed as:
+
+TexChunk: type = macro, name = toplevel, no_args = 1
+  Children:
+
+    TexChunk: type = argument
+
+      Children:
+        TexChunk: type = string, value = "The cat sat on the "
+        TexChunk: type = macro, name = mymat, no_args = 2
+
+          Children:
+            TexChunk: type = argument
+
+              Children:
+                TexChunk: type = string, value = "very coarse and "
+                TexChunk: type = macro, name = it, no_args = 1
+
+                  Children:
+                    TexChunk: type = argument
+
+                      Children:
+                        TexChunk: type = string, value = "cheap"
+
+            TexChunk: type = argument
+
+              Children:
+                TexChunk: type = string, value = mat
+ */
+
+class TexChunk
+{
+ public:
+  int type;
+//  char *name;
+  TexMacroDef *def;
+  char *value;
+  int macroId;
+  int no_args;
+  int argn;
+  bool optional;      // Is an optional argument
+
+  wxList children;
+  TexChunk(int the_type, TexMacroDef *the_def = NULL);
+  TexChunk(TexChunk& toCopy);
+  virtual ~TexChunk(void);
+};
+
+// Represents a topic, used for generating a table of contents file (.cnt).
+// Also for storing keywords found in a topic, a list of which is then inserted
+// into the topic in the next pass.
+class TexTopic: public wxObject
+{
+ public:
+  // This flag is set to indicate that the topic has children.
+  // If this is the case, we know to insert a 'book' icon at this level,
+  // not just a 'page' icon. We don't want to have to open a book only
+  // to find there's only one page in it. We might force a book to be used if
+  // a top-level topic has no children (?)
+  bool hasChildren;
+  char *filename;
+  wxStringList *keywords;
+  TexTopic(char *f = NULL);
+  ~TexTopic(void);
+};
+extern wxHashTable TopicTable;
+void AddKeyWordForTopic(char *topic, char *entry, char *filename = NULL);
+void ClearKeyWordTable(void);
+
+extern TexChunk     *TopLevel;
+extern wxHashTable  MacroDefs;
+extern wxStringList IgnorableInputFiles; // Ignorable \input files, e.g. psbox.tex
+
+bool read_a_line(char *buf);
+bool TexLoadFile(char *filename);
+int ParseArg(TexChunk *thisArg, wxList& children, char *buffer, int pos,
+           char *environment = NULL, bool parseArgToBrace = TRUE, TexChunk *customMacroArgs = NULL);
+int ParseMacroBody(char *macro_name, TexChunk *parent, int no_args,
+           char *buffer, int pos, char *environment = NULL, bool parseArgToBrace = TRUE, TexChunk *customMacroArgs = NULL);
+void TraverseDocument(void);
+void TraverseFromChunk(TexChunk *chunk, wxNode *thisNode = NULL, bool childrenOnly = FALSE);
+#define TraverseChildrenFromChunk(arg) TraverseFromChunk(arg, NULL, TRUE)
+void SetCurrentOutput(FILE *fd);
+void SetCurrentOutputs(FILE *fd1, FILE *fd2);
+extern FILE *CurrentOutput1;
+extern FILE *CurrentOutput2;
+void AddMacroDef(int the_id, char *name, int n, bool ignore = FALSE, bool forbidden = FALSE);
+void TexInitialize(int bufSize);
+void TexCleanUp(void);
+void TexOutput(char *s, bool ordinaryText = FALSE);
+char *GetArgData(TexChunk *chunk);
+char *GetArgData(void);             // Get the string for the current argument
+int GetNoArgs(void);                // Get the number of arguments for the current macro
+TexChunk *GetArgChunk(void);        // Get the chunk for the current argument
+TexChunk *GetTopLevelChunk(void);   // Get the chunk for the top level
+TexChunk *GetNextChunk(void);       // Look ahead to the next chunk
+bool IsArgOptional(void);           // Is this argument an optional argument?
+void DefineDefaultMacros(void);     // Optional set of default macros
+int GetCurrentColumn(void);         // number of characters on current line
+char *ConvertCase(char *s);         // Convert case, according to upperCaseNames setting.
+extern wxPathList TexPathList;      // Path list, can be used for file searching.
+
+// Define a variable value from the .ini file
+char *RegisterSetting(char *settingName, char *settingValue, bool interactive = TRUE);
+
+// Major document styles
+#define LATEX_REPORT    1
+#define LATEX_ARTICLE   2
+#define LATEX_LETTER    3
+#define LATEX_BOOK      4
+#define LATEX_SLIDES    5
+
+extern TexChunk *DocumentTitle;
+extern TexChunk *DocumentAuthor;
+extern TexChunk *DocumentDate;
+extern int DocumentStyle;
+extern int MinorDocumentStyle;
+extern char *BibliographyStyleString;
+extern char *DocumentStyleString;
+extern char *MinorDocumentStyleString;
+
+extern int normalFont;
+extern int smallFont;
+extern int tinyFont;
+extern int largeFont1;
+extern int LargeFont2;
+extern int LARGEFont3;
+extern int hugeFont1;
+extern int HugeFont2;
+extern int HUGEFont3;
+
+/*
+ * USER-ADJUSTABLE SETTINGS
+ *
+ */
+
+// Section font sizes
+extern int chapterFont;
+extern int sectionFont;
+extern int subsectionFont;
+extern int titleFont;
+extern int authorFont;
+extern bool winHelp;  // Output in Windows Help format if TRUE, linear otherwise
+extern bool isInteractive;
+extern bool runTwice;
+extern int convertMode;
+extern bool stopRunning;
+extern int  mirrorMargins;
+extern bool headerRule;
+extern bool footerRule;
+extern int labelIndentTab;  // From left indent to item label (points)
+extern int itemIndentTab;   // From left indent to item (points)
+extern bool useUpButton;
+extern int htmlBrowseButtons;
+extern bool useHeadingStyles; // Insert \s1, s2 etc.
+extern bool useWord; // Insert Word table of contents, etc. etc.
+extern bool indexSubsections; // put subsections in index
+extern bool compatibilityMode;
+extern bool generateHPJ;      // Generate WinHelp HPJ file
+extern char *winHelpTitle;    // Title for Windows Help file
+extern int defaultTableColumnWidth;
+extern char *bitmapMethod;
+extern bool truncateFilenames; // Truncate for DOS
+extern int  winHelpVersion;    // Version e.g. 4 for Win95
+extern bool winHelpContents;   // Generate .cnt file
+extern bool htmlIndex;         // Generate .htx HTML index file
+extern bool htmlFrameContents; // Use frames for HTML contents page
+extern int  contentsDepth;     // Depth of contents for linear RTF files
+extern bool upperCaseNames;    // Filenames; default is lower case
+extern char *backgroundImageString; // HTML background image
+extern char *backgroundColourString; // HTML background colour
+extern char *textColourString; // HTML text colour
+extern char *linkColourString; // HTML link colour
+extern char *followedLinkColourString; // HTML followed link colour
+extern bool combineSubSections; // Stop splitting files below section
+
+// Names to help with internationalisation
+extern char *ContentsNameString;
+extern char *AbstractNameString;
+extern char *GlossaryNameString;
+extern char *ReferencesNameString;
+extern char *FiguresNameString;
+extern char *TablesNameString;
+extern char *FigureNameString;
+extern char *TableNameString;
+extern char *IndexNameString;
+extern char *ChapterNameString;
+extern char *SectionNameString;
+extern char *SubsectionNameString;
+extern char *SubsubsectionNameString;
+extern char *UpNameString;
+
+/*
+ * HTML button identifiers: what kind of browse buttons
+ * are placed in HTML files, if any.
+ *
+ */
+
+#define HTML_BUTTONS_NONE       0
+#define HTML_BUTTONS_BITMAP     1
+#define HTML_BUTTONS_TEXT       2
+
+/*
+ * Section numbering
+ *
+ */
+
+extern int chapterNo;
+extern int sectionNo;
+extern int subsectionNo;
+extern int subsubsectionNo;
+extern int figureNo;
+extern int tableNo;
+
+extern int ParSkip;
+extern int ParIndent;
+
+extern bool isSync;
+
+// Set by client and by Tex2Any
+extern TexChunk *currentSection;
+
+// Header/footers/pagestyle
+extern TexChunk *      LeftHeaderOdd;
+extern TexChunk *      LeftFooterOdd;
+extern TexChunk *      CentreHeaderOdd;
+extern TexChunk *      CentreFooterOdd;
+extern TexChunk *      RightHeaderOdd;
+extern TexChunk *      RightFooterOdd;
+extern TexChunk *      LeftHeaderEven;
+extern TexChunk *      LeftFooterEven;
+extern TexChunk *      CentreHeaderEven;
+extern TexChunk *      CentreFooterEven;
+extern TexChunk *      RightHeaderEven;
+extern TexChunk *      RightFooterEven;
+extern char *          PageStyle;
+
+// Repeat the currentSection, either real (Chapter) or simulated (References)
+extern void OutputCurrentSection(void);
+extern void OutputCurrentSectionToString(char *buf);
+extern void OutputChunkToString(TexChunk *chunk, char *buf);
+
+extern char *fakeCurrentSection;
+
+// Called by Tex2Any to simulate a section
+extern void FakeCurrentSection(char *fakeSection, bool addToContents = TRUE);
+
+/*
+ * Local to Tex2Any library
+ *
+ */
+extern char *currentArgData;
+extern bool haveArgData; // If TRUE, we're simulating the data.
+void StartSimulateArgument(char *data);
+void EndSimulateArgument(void);
+
+/*
+ * Client-defined
+ *
+ */
+
+// Called on start/end of macro examination
+void OnMacro(int macroId, int no_args, bool start);
+
+// Called on start/end of argument examination.
+// Return TRUE at the start of an argument to traverse
+// (output) the argument.
+bool OnArgument(int macroId, int arg_no, bool start);
+
+// Default: library-defined
+void DefaultOnMacro(int macroId, int no_args, bool start);
+
+// Default: library-defined
+bool DefaultOnArgument(int macroId, int arg_no, bool start);
+
+// Called on error
+void OnError(char *msg);
+
+// Called for information
+void OnInform(char *msg);
+
+// Special yield wrapper
+void Tex2RTFYield(bool force = FALSE);
+
+/*
+ * Useful utilities
+ *
+ */
+
+// Look for \label macro, use this ref name if found or
+// make up a topic name otherwise.
+char *FindTopicName(TexChunk *chunk);
+// Force the current topic to be this (e.g. force 'references' label).
+void ForceTopicName(char *name);
+void ResetTopicCounter(void);
+
+// Parse unit eg. 14, 12pt, 34cm and return value in points.
+int ParseUnitArgument(char *unitArg);
+
+// Set small, large, normal etc. point sizes for reference size
+void SetFontSizes(int pointSize);
+
+/*
+ * Strip off any extension (dot something) from end of file,
+ * IF one exists. Inserts zero into buffer.
+ *
+ */
+void StripExtension(char *buffer);
+
+/*
+ * Reference structure
+ *
+ */
+
+class TexRef: public wxObject
+{
+ public:
+  char *refLabel;      // Reference label
+  char *refFile;       // Reference filename (can be NULL)
+  char *sectionNumber; // Section or figure number (as a string)
+  char *sectionName; // name e.g. 'section'
+  TexRef(char *label, char *file, char *section, char *sectionN = NULL)
+  {
+    refLabel = copystring(label);
+    refFile = file ? copystring(file) : (char*) NULL;
+    sectionNumber = section ? copystring(section) : copystring("??");
+    sectionName = sectionN ? copystring(sectionN) : copystring("??");
+  }
+  ~TexRef(void)
+  {
+    delete[] refLabel; delete[] refFile; delete[] sectionNumber; delete[] sectionName;
+  }
+};
+
+extern wxHashTable TexReferences;
+
+/*
+ * Add a reference
+ *
+ */
+void AddTexRef(char *name, char *file = NULL, char *sectionName = NULL,
+         int chapter = 0, int section = 0, int subsection = 0, int subsubsection = 0);
+
+/*
+ * Read and write reference file (.ref), to resolve refs for second pass.
+ *
+ */
+void WriteTexReferences(char *filename);
+void ReadTexReferences(char *filename);
+
+/*
+ * Bibliography stuff
+ *
+ */
+
+class BibEntry: public wxObject
+{
+ public:
+  char *key;
+
+  /*
+   * book, inbook, article, phdthesis, inproceedings, techreport
+   */
+  char *type;
+
+  /*
+   * Possible fields
+   *
+   */
+  char *editor;
+  char *title;
+  char *booktitle;
+  char *author;
+  char *journal;
+  char *volume;
+  char *number;
+  char *year;
+  char *month;
+  char *pages;
+  char *chapter;
+  char *publisher;
+  char *address;
+  char *institution;
+  char *organization;
+  char *comment;
+
+  inline BibEntry(void)
+  {
+    key = NULL;
+    type = NULL;
+    editor = NULL;
+    title = NULL;
+    booktitle = NULL;
+    author = NULL;
+    journal = NULL;
+    volume = NULL;
+    number = NULL;
+    chapter = NULL;
+    year = NULL;
+    month = NULL;
+    pages = NULL;
+    publisher = NULL;
+    address = NULL;
+    institution = NULL;
+    organization = NULL;
+    comment = NULL;
+  }
+};
+
+extern wxList BibList;
+extern wxStringList CitationList;
+
+bool ReadBib(char *filename);
+void OutputBib(void);
+void ResolveBibReferences(void);
+void AddCitation(char *citeKey);
+TexRef *FindReference(char *key);
+
+/*
+ * Ability to customize, or at least suppress unknown macro errors
+ *
+ */
+
+extern wxList CustomMacroList;
+
+#define CUSTOM_MACRO_IGNORE 0
+#define CUSTOM_MACRO_OUTPUT 1
+#define CUSTOM_MACRO_MARK   2
+
+class CustomMacro: public wxObject
+{
+ public:
+  char *macroName;
+  char *macroBody;
+  int noArgs;
+  inline CustomMacro(char *name, int args, char *body)
+  {
+    noArgs = args;
+    macroName = copystring(name);
+    if (body)
+      macroBody = copystring(body);
+    else
+      macroBody = NULL;
+  }
+};
+
+bool ReadCustomMacros(char *filename);
+void ShowCustomMacros(void);
+CustomMacro *FindCustomMacro(char *name);
+char *ParseMultifieldString(char *s, int *pos);
+
+/*
+ * Colour table stuff
+ *
+ */
+
+class ColourTableEntry: public wxObject
+{
+ public:
+  char *name;
+  unsigned int red;
+  unsigned int green;
+  unsigned int blue;
+
+  ColourTableEntry(char *theName, unsigned int r,  unsigned int g,  unsigned int b);
+  ~ColourTableEntry(void);
+};
+
+extern wxList ColourTable;
+extern void AddColour(char *theName, unsigned int r,  unsigned int g,  unsigned int b);
+extern int FindColourPosition(char *theName);
+// Converts e.g. "red" -> "#FF0000"
+extern bool FindColourHTMLString(char *theName, char *buf);
+extern void InitialiseColourTable(void);
+
+#define ltABSTRACT          1
+#define ltADDCONTENTSLINE   2
+#define ltADDTOCOUNTER      3
+#define ltALPH1             4
+#define ltALPH2             5
+#define ltAPPENDIX          6
+#define ltARABIC            7
+#define ltARRAY             8
+#define ltAUTHOR            9
+
+#define ltBACKSLASH         30
+#define ltBASELINESKIP      31
+#define ltBF                32
+#define ltBIBITEM           33
+#define ltBIBLIOGRAPHYSTYLE 34
+#define ltBIBLIOGRAPHY      35
+#define ltBOXIT             36
+#define ltBACKSLASHRAW      37
+#define ltBACKGROUND        38
+#define ltBACKGROUNDCOLOUR  39
+#define ltBACKGROUNDIMAGE   40
+#define ltBRCLEAR           41
+
+#define ltCAPTIONSTAR       50
+#define ltCAPTION           51
+#define ltCDOTS             52
+#define ltCENTERLINE        53
+#define ltCENTERING         54
+#define ltCENTER            55
+#define ltCEXTRACT          56
+#define ltCHAPTERHEADING    57
+#define ltCHAPTERSTAR       58
+#define ltCHAPTER           59
+#define ltCINSERT           60
+#define ltCITE              61
+#define ltCLASS             62
+#define ltCLEARDOUBLEPAGE   63
+#define ltCLEARPAGE         64
+#define ltCLINE             65
+#define ltCLIPSFUNC         66
+#define ltCOLUMNSEP         67
+#define ltCOMMENT           68
+#define ltCOPYRIGHT         69
+#define ltCPARAM            70
+
+#define ltCHEAD             71
+#define ltCFOOT             72
+
+#define ltCHAPTERHEADINGSTAR 73
+
+#define ltDATE              90
+#define ltDESCRIPTION       91
+#define ltDESTRUCT          92
+#define ltDOCUMENTSTYLE     93
+#define ltDOCUMENT          94
+#define ltDOUBLESPACE       95
+#define ltDEFINECOLOUR      96
+#define ltDEFINECOLOR       97
+
+#define ltEM                120
+#define ltENUMERATE         121
+#define ltEQUATION          122
+#define ltEVENSIDEMARGIN    123
+
+#define ltFBOX              150
+#define ltFIGURE            151
+#define ltFLUSHLEFT         152
+#define ltFLUSHRIGHT        153
+#define ltFOOTHEIGHT        154
+#define ltFOOTNOTE          155
+#define ltFOOTSKIP          156
+#define ltFRAMEBOX          157
+#define ltFUNCTIONSECTION   158
+#define ltFUNC              159
+#define ltFIGURESTAR        160
+#define ltFOOTNOTESIZE      161
+#define ltFOOTNOTEPOPUP     162
+#define ltFANCYPLAIN        163
+#define ltFCOL              164
+#define ltBCOL              165
+#define ltFOLLOWEDLINKCOLOUR 166
+
+#define ltGLOSSARY          180
+#define ltGLOSS             181
+
+#define ltHEADHEIGHT        200
+#define ltHELPGLOSSARY      201
+#define ltHELPIGNORE        202
+#define ltHELPONLY          203
+#define ltHELPINPUT         204
+#define ltHELPFONTFAMILY    205
+#define ltHELPFONTSIZE      206
+#define ltHELPREFN          207
+#define ltHELPREF           208
+#define ltHFILL             209
+#define ltHLINE             210
+#define ltHRULE             211
+#define ltHSPACESTAR        212
+#define ltHSPACE            213
+#define ltHSKIPSTAR         214
+#define ltHSKIP             215
+#define lthuge              216
+#define ltHuge              217
+#define ltHUGE              218
+#define ltHTMLIGNORE        219
+#define ltHTMLONLY          220
+
+#define ltINCLUDEONLY       240
+#define ltINCLUDE           241
+#define ltINDEX             242
+#define ltINPUT             243
+#define ltITEMIZE           244
+#define ltITEM              245
+#define ltIMAGE             246
+#define ltIT                247
+#define ltITEMSEP           248
+#define ltINDENTED          249
+#define ltIMAGEMAP          250
+#define ltIMAGER            251
+#define ltIMAGEL            252
+#define ltINSERTATLEVEL     253
+
+#define ltKILL              260
+
+#define ltLABEL             280
+#define ltlarge             281
+#define ltLarge             282
+#define ltLARGE             283
+#define ltLATEX             284
+#define ltLBOX              285
+#define ltLDOTS             286
+#define ltLINEBREAK         287
+#define ltLISTOFFIGURES     288
+#define ltLISTOFTABLES      289
+#define ltLHEAD             290
+#define ltLFOOT             291
+#define ltLATEXIGNORE       292
+#define ltLATEXONLY         293
+#define ltLOWERCASE         294
+#define ltLBRACERAW         295
+#define ltLINKCOLOUR        296
+
+#define ltMAKEGLOSSARY      300
+#define ltMAKEINDEX         301
+#define ltMAKETITLE         302
+#define ltMARKRIGHT         303
+#define ltMARKBOTH          304
+#define ltMARGINPARWIDTH    305
+#define ltMARGINPAR         306
+#define ltMARGINPARODD      307
+#define ltMARGINPAREVEN     308
+#define ltMBOX              309
+#define ltMEMBERSECTION     310
+#define ltMEMBER            311
+#define ltMULTICOLUMN       312
+#define ltMARGINPARSEP      313
+
+#define ltNEWCOUNTER        330
+#define ltNEWLINE           331
+#define ltNEWPAGE           332
+#define ltNOCITE            333
+#define ltNOINDENT          334
+#define ltNOLINEBREAK       335
+#define ltNOPAGEBREAK       336
+#define ltNORMALSIZE        337
+#define ltNORMALBOX         338
+#define ltNORMALBOXD        339
+#define ltNUMBEREDBIBITEM   340
+
+#define ltONECOLUMN         360
+#define ltODDSIDEMARGIN     361
+
+#define ltPAGEBREAK         380
+#define ltPAGEREF           381
+#define ltPAGESTYLE         382
+#define ltPAGENUMBERING     383
+#define ltPARAGRAPHSTAR     384
+#define ltPARAGRAPH         385
+#define ltPARAM             386
+#define ltPARINDENT         387
+#define ltPARSKIP           388
+#define ltPARTSTAR          389
+#define ltPART              390
+#define ltPAR               391
+#define ltPFUNC             392
+#define ltPICTURE           393
+#define ltPOPREF            394
+#define ltPOUNDS            395
+#define ltPRINTINDEX        396
+#define ltPSBOXTO           397
+#define ltPSBOX             398
+#define ltPOPREFONLY        399
+
+#define ltQUOTE             420
+#define ltQUOTATION         421
+
+#define ltRAGGEDBOTTOM      440
+#define ltRAGGEDLEFT        441
+#define ltRAGGEDRIGHT       442
+#define ltREF               443
+#define ltRM                444
+#define ltROMAN             445
+#define ltROMAN2            446
+#define ltRTFSP             447
+#define ltRULE              448
+#define ltRULEDROW          449
+#define ltDRULED            450
+#define ltRHEAD             451
+#define ltRFOOT             452
+#define ltROW               453
+#define ltRTFIGNORE         454
+#define ltRTFONLY           455
+#define ltRBRACERAW         456
+#define ltREGISTERED        457
+
+#define ltSC                470
+#define ltSECTIONHEADING    471
+#define ltSECTIONSTAR       472
+#define ltSECTION           473
+#define ltSETCOUNTER        474
+#define ltSF                475
+#define ltSHORTCITE         476
+#define ltSINGLESPACE       477
+#define ltSLOPPYPAR         478
+#define ltSLOPPY            479
+#define ltSL                480
+#define ltSMALL             481
+#define ltSUBITEM           482
+#define ltSUBPARAGRAPHSTAR  483
+#define ltSUBPARAGRAPH      484
+#define ltSPECIAL           485
+#define ltSUBSECTIONSTAR    486
+#define ltSUBSECTION        487
+#define ltSUBSUBSECTIONSTAR 488
+#define ltSUBSUBSECTION     489
+#define ltSCRIPTSIZE        490
+#define ltSETHEADER         491
+#define ltSETFOOTER         492
+#define ltSIZEDBOX          493
+#define ltSIZEDBOXD         494
+#define ltSECTIONHEADINGSTAR 495
+#define ltSS                496
+#define ltSETHOTSPOTCOLOUR  497
+#define ltSETHOTSPOTCOLOR   498
+#define ltSETHOTSPOTUNDERLINE 499
+#define ltSETTRANSPARENCY   500
+
+#define ltTABBING           510
+#define ltTABLEOFCONTENTS   511
+#define ltTABLE             512
+#define ltTABULAR           513
+#define ltTAB               514
+#define ltTEX               515
+#define ltTEXTWIDTH         516
+#define ltTEXTHEIGHT        517
+#define ltTHEBIBLIOGRAPHY   518
+#define ltTITLEPAGE         519
+#define ltTITLE             520
+#define ltTINY              521
+#define ltTODAY             522
+#define ltTOPMARGIN         523
+#define ltTOPSKIP           524
+#define ltTT                525
+#define ltTYPEIN            526
+#define ltTYPEOUT           527
+#define ltTWOCOLUMN         528
+#define ltTHEPAGE           529
+#define ltTHECHAPTER        530
+#define ltTHESECTION        531
+#define ltTHISPAGESTYLE     532
+
+#define ltTWOCOLWIDTHA      533
+#define ltTWOCOLWIDTHB      534
+#define ltTWOCOLSPACING     535
+#define ltTWOCOLITEM        536
+#define ltTWOCOLITEMRULED   537
+#define ltTWOCOLLIST        538
+#define ltTEXTCOLOUR        539
+
+#define ltUNDERLINE         550
+#define ltURLREF            551
+#define ltUPPERCASE         552
+#define ltUSEPACKAGE        553
+  
+#define ltVDOTS             570
+#define ltVERBATIMINPUT     571
+#define ltVERBATIM          572
+#define ltVERB              573
+#define ltVERSE             574
+#define ltVFILL             575
+#define ltVLINE             576
+#define ltVOID              577
+#define ltVRULE             578
+#define ltVSPACESTAR        579
+#define ltVSKIPSTAR         580
+#define ltVSPACE            581
+#define ltVSKIP             582
+#define ltVERBSTAR          583
+
+#define ltWXCLIPS           600
+#define ltWINHELPIGNORE     601
+#define ltWINHELPONLY       602
+
+#define ltXLPIGNORE         603
+#define ltXLPONLY           604
+
+#define ltSPACE             620
+#define ltBACKSLASHCHAR     621
+#define ltPIPE              622
+#define ltFORWARDSLASH      623
+#define ltUNDERSCORE        624
+#define ltAMPERSAND         625
+#define ltPERCENT           626
+#define ltDOLLAR            627
+#define ltHASH              628
+#define ltLPARENTH          629
+#define ltRPARENTH          630
+#define ltLBRACE            631
+#define ltRBRACE            632
+#define ltEQUALS            633
+#define ltRANGLEBRA         634
+#define ltLANGLEBRA         635
+#define ltPLUS              636
+#define ltDASH              637
+#define ltSINGLEQUOTE       638
+#define ltBACKQUOTE         639
+#define ltTILDE             640
+#define ltAT_SYMBOL         641
+
+// Characters, not macros but with special Latex significance
+#define ltSPECIALDOLLAR     660
+#define ltSPECIALDOUBLEDOLLAR 661
+#define ltSPECIALTILDE      662
+#define ltSPECIALHASH       663
+#define ltSPECIALAMPERSAND  664
+#define ltSUPERTABULAR      665
+
+// Accents
+#define ltACCENT_GRAVE      700
+#define ltACCENT_ACUTE      701
+#define ltACCENT_CARET      702
+#define ltACCENT_UMLAUT     703
+#define ltACCENT_TILDE      704
+#define ltACCENT_DOT        705
+#define ltACCENT_CADILLA    706
+
+// Symbols
+#define ltALPHA             800
+#define ltBETA              801
+#define ltGAMMA             802
+#define ltDELTA             803
+#define ltEPSILON           804
+#define ltVAREPSILON        805
+#define ltZETA              806
+#define ltETA               807
+#define ltTHETA             808
+#define ltVARTHETA          809
+#define ltIOTA              810
+#define ltKAPPA             811
+#define ltLAMBDA            812
+#define ltMU                813
+#define ltNU                814
+#define ltXI                815
+#define ltPI                816
+#define ltVARPI             817
+#define ltRHO               818
+#define ltVARRHO            819
+#define ltSIGMA             820
+#define ltVARSIGMA          821
+#define ltTAU               822
+#define ltUPSILON           823
+#define ltPHI               824
+#define ltVARPHI            825
+#define ltCHI               826
+#define ltPSI               827
+#define ltOMEGA             828
+
+#define ltCAP_GAMMA         830
+#define ltCAP_DELTA         831
+#define ltCAP_THETA         832
+#define ltCAP_LAMBDA        833
+#define ltCAP_XI            834
+#define ltCAP_PI            835
+#define ltCAP_SIGMA         836
+#define ltCAP_UPSILON       837
+#define ltCAP_PHI           838
+#define ltCAP_PSI           839
+#define ltCAP_OMEGA         840
+
+// Binary operation symbols
+#define ltLE                850
+#define ltLEQ               851
+#define ltLL                852
+#define ltSUBSET            853
+#define ltSUBSETEQ          854
+#define ltSQSUBSET          855
+#define ltSQSUBSETEQ        856
+#define ltIN                857
+#define ltVDASH             858
+#define ltMODELS            859
+#define ltGE                860
+#define ltGEQ               861
+#define ltGG                862
+#define ltSUPSET            863
+#define ltSUPSETEQ          864
+#define ltSQSUPSET          865
+#define ltSQSUPSETEQ        866
+#define ltNI                867
+#define ltDASHV             868
+#define ltPERP              869
+#define ltNEQ               870
+#define ltDOTEQ             871
+#define ltAPPROX            872
+#define ltCONG              873
+#define ltEQUIV             874
+#define ltPROPTO            875
+#define ltPREC              876
+#define ltPRECEQ            877
+#define ltPARALLEL          878
+#define ltSIM               879
+#define ltSIMEQ             880
+#define ltASYMP             881
+#define ltSMILE             882
+#define ltFROWN             883
+#define ltBOWTIE            884
+#define ltSUCC              885
+#define ltSUCCEQ            886
+#define ltMID               887
+
+// Negated relation symbols (selected)
+#define ltNOTEQ             890
+#define ltNOTIN             891
+#define ltNOTSUBSET         892
+
+// Arrows
+#define ltLEFTARROW         900
+#define ltLEFTARROW2        901
+#define ltRIGHTARROW        902
+#define ltRIGHTARROW2       903
+#define ltLEFTRIGHTARROW    904
+#define ltLEFTRIGHTARROW2   905
+#define ltUPARROW           906
+#define ltUPARROW2          907
+#define ltDOWNARROW         908
+#define ltDOWNARROW2        909
+
+// Miscellaneous symbols
+#define ltALEPH             1000
+#define ltWP                1001
+#define ltRE                1002
+#define ltIM                1003
+#define ltEMPTYSET          1004
+#define ltNABLA             1005
+#define ltSURD              1006
+#define ltPARTIAL           1007
+#define ltBOT               1008
+#define ltFORALL            1009
+#define ltEXISTS            1010
+#define ltNEG               1011
+#define ltSHARP             1012
+#define ltANGLE             1013
+#define ltTRIANGLE          1014
+#define ltCLUBSUIT          1015
+#define ltDIAMONDSUIT       1016
+#define ltHEARTSUIT         1017
+#define ltSPADESUIT         1018
+#define ltINFTY             1019
+
+// Binary operation symbols
+#define ltPM                1030
+#define ltMP                1031
+#define ltTIMES             1032
+#define ltDIV               1033
+#define ltCDOT              1034
+#define ltAST               1035
+#define ltSTAR              1036
+#define ltCAP               1037
+#define ltCUP               1038
+#define ltVEE               1039
+#define ltWEDGE             1040
+#define ltCIRC              1041
+#define ltBULLET            1042
+#define ltDIAMOND           1043
+#define ltOSLASH            1044
+#define ltBOX               1045
+#define ltDIAMOND2          1046
+#define ltBIGTRIANGLEDOWN   1047
+#define ltOPLUS             1048
+#define ltOTIMES            1049
+
+// Latex2e commands
+#define ltRMFAMILY          1200
+#define ltSFFAMILY          1201
+#define ltTTFAMILY          1202
+#define ltBFSERIES          1203
+#define ltITSHAPE           1204
+#define ltSLSHAPE           1205
+#define ltSCSHAPE           1206
+
+#define ltMDSERIES          1207
+#define ltUPSHAPE           1208
+
+#define ltTEXTRM            1209
+#define ltTEXTSF            1210
+#define ltTEXTTT            1211
+#define ltTEXTBF            1212
+#define ltTEXTIT            1213
+#define ltTEXTSL            1214
+#define ltTEXTSC            1215
+#define ltEMPH              1216
+
+#define ltDOCUMENTCLASS     1217
+
+// Space macros
+#define ltSMALLSPACE1       1250
+#define ltSMALLSPACE2       1251
+
+// Pseudo-macros
+#define ltTOPLEVEL          15000
+#define ltCUSTOM_MACRO      15001
+#define ltSOLO_BLOCK        15002
+
+
+
diff --git a/utils/tex2rtf/src/tex2rtf.cpp b/utils/tex2rtf/src/tex2rtf.cpp
new file mode 100644 (file)
index 0000000..2ad1a39
--- /dev/null
@@ -0,0 +1,1077 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        tex2rtf.cpp
+// Purpose:     Converts Latex to linear/WinHelp RTF, HTML, wxHelp.
+// Author:      Julian Smart
+// Modified by:
+// Created:     7.9.93
+// RCS-ID:      $Id$
+// Copyright:   (c) Julian Smart
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+#ifndef NO_GUI
+#include <wx/help.h>
+#include <wx/timer.h>
+#endif
+
+#ifdef NO_GUI
+#if wxUSE_IOSTREAMH
+#include <iostream.h>
+#include <fstream.h>
+#else
+#include <iostream>
+#include <fstream>
+#endif
+#endif
+
+#include <ctype.h>
+#include <stdlib.h>
+#include "tex2any.h"
+#include "tex2rtf.h"
+#include "rtfutils.h"
+
+#if (defined(__WXGTK__) || defined(__WXMOTIF__)) && !defined(NO_GUI)
+#include "tex2rtf.xpm"
+#endif
+
+const float versionNo = 2.0;
+
+TexChunk *currentMember = NULL;
+bool startedSections = FALSE;
+char *contentsString = NULL;
+bool suppressNameDecoration = FALSE;
+bool OkToClose = TRUE;
+int passNumber = 1;
+
+#ifndef NO_GUI
+wxHelpController *HelpInstance = NULL;
+
+#ifdef __WXMSW__
+static char *ipc_buffer = NULL;
+static char Tex2RTFLastStatus[100];
+Tex2RTFServer *TheTex2RTFServer = NULL;
+#endif
+#endif
+
+char *bulletFile = NULL;
+
+FILE *Contents = NULL;   // Contents page
+FILE *Chapters = NULL;   // Chapters (WinHelp RTF) or rest of file (linear RTF)
+FILE *Sections = NULL;
+FILE *Subsections = NULL;
+FILE *Subsubsections = NULL;
+FILE *Popups = NULL;
+FILE *WinHelpContentsFile = NULL;
+
+char *InputFile = NULL;
+char *OutputFile = NULL;
+char *MacroFile = copystring("tex2rtf.ini");
+
+char *FileRoot = NULL;
+char *ContentsName = NULL;    // Contents page from last time around
+char *TmpContentsName = NULL; // Current contents page
+char *TmpFrameContentsName = NULL; // Current frame contents page
+char *WinHelpContentsFileName = NULL; // WinHelp .cnt file
+char *RefName = NULL;         // Reference file name
+
+char *RTFCharset = copystring("ansi");
+
+#ifdef __WXMSW__
+int BufSize = 100;             // Size of buffer in K
+#else
+int BufSize = 500;
+#endif
+
+bool Go(void);
+void ShowOptions(void);
+
+#ifdef NO_GUI
+int main(int argc, char **argv)
+#else
+wxMenuBar *menuBar = NULL;
+MyFrame *frame = NULL;
+
+// DECLARE_APP(MyApp)
+IMPLEMENT_APP(MyApp)
+
+// `Main program' equivalent, creating windows and returning main app frame
+bool MyApp::OnInit()
+#endif
+{
+  // Use default list of macros defined in tex2any.cc
+  DefineDefaultMacros();
+  AddMacroDef(ltHARDY, "hardy", 0);
+
+  FileRoot = new char[300];
+  ContentsName = new char[300];
+  TmpContentsName = new char[300];
+  TmpFrameContentsName = new char[300];
+  WinHelpContentsFileName = new char[300];
+  RefName = new char[300];
+
+  int n = 1;
+  
+  // Read input/output files
+  if (argc > 1)
+  {
+    if (argv[1][0] != '-')
+    {
+      InputFile = argv[1];
+      n ++;
+
+      if (argc > 2)
+      {
+        if (argv[2][0] != '-')
+        {
+          OutputFile = argv[2];
+          n ++;
+        }
+      }
+    }
+  }
+
+#ifdef NO_GUI
+  if (!InputFile || !OutputFile)
+  {
+    cout << "Tex2RTF: input or output file is missing.\n";
+    ShowOptions();
+    exit(1);
+  }
+#endif
+  if (InputFile)
+  {
+    TexPathList.EnsureFileAccessible(InputFile);
+  }
+  if (!InputFile || !OutputFile)
+    isInteractive = TRUE;
+
+  for (int i = n; i < argc;)
+  {
+    if (strcmp(argv[i], "-winhelp") == 0)
+    {
+      i ++;
+      convertMode = TEX_RTF;
+      winHelp = TRUE;
+    }
+#ifndef NO_GUI
+    else if (strcmp(argv[i], "-interactive") == 0)
+    {
+      i ++;
+      isInteractive = TRUE;
+    }
+#endif
+    else if (strcmp(argv[i], "-sync") == 0)  // Don't yield
+    {
+      i ++;
+      isSync = TRUE;
+    }
+    else if (strcmp(argv[i], "-rtf") == 0)
+    {
+      i ++;
+      convertMode = TEX_RTF;
+    }
+    else if (strcmp(argv[i], "-html") == 0)
+    {
+      i ++;
+      convertMode = TEX_HTML;
+    }
+    else if (strcmp(argv[i], "-xlp") == 0)
+    {
+      i ++;
+      convertMode = TEX_XLP;
+    }
+    else if (strcmp(argv[i], "-twice") == 0)
+    {
+      i ++;
+      runTwice = TRUE;
+    }
+    else if (strcmp(argv[i], "-macros") == 0)
+    {
+      i ++;
+      if (i < argc)
+      {
+        MacroFile = copystring(argv[i]);
+        i ++;
+      }
+    }
+    else if (strcmp(argv[i], "-bufsize") == 0)
+    {
+      i ++;
+      if (i < argc)
+      {
+        BufSize = atoi(argv[i]);
+        i ++;
+      }
+    }
+    else if (strcmp(argv[i], "-charset") == 0)
+    {
+      i ++;
+      if (i < argc)
+      {
+        char *s = argv[i];
+        i ++;
+        if (strcmp(s, "ansi") == 0 || strcmp(s, "pc") == 0 || strcmp(s, "mac") == 0 ||
+            strcmp(s, "pca") == 0)
+          RTFCharset = copystring(s);
+        else
+        {
+          OnError("Incorrect argument for -charset");
+        }
+      }
+    }
+    else
+    {
+      char buf[100];
+      sprintf(buf, "Invalid switch %s.\n", argv[i]);
+      OnError(buf);
+      i++;
+#ifdef NO_GUI
+      ShowOptions();
+      exit(1);
+#endif
+    }
+  }
+
+#if defined(__WXMSW__) && !defined(NO_GUI)
+  wxDDEInitialize();
+  Tex2RTFLastStatus[0] = 0; // DDE connection return value
+  TheTex2RTFServer = new Tex2RTFServer;
+  TheTex2RTFServer->Create("TEX2RTF");
+#endif
+
+#if defined(__WXMSW__) && defined(__WIN16__)
+  // Limit to max Windows array size
+  if (BufSize > 64) BufSize = 64;
+#endif
+
+  TexInitialize(BufSize);
+  ResetContentsLevels(0);
+
+#ifndef NO_GUI
+
+  if (isInteractive)
+  {
+    char buf[100];
+
+    // Create the main frame window
+    frame = new MyFrame(NULL, -1, "Tex2RTF", wxPoint(-1, -1), wxSize(400, 300));
+    frame->CreateStatusBar(2);
+
+    // Give it an icon
+    // TODO: uncomment this when we have tex2rtf.xpm
+    frame->SetIcon(wxICON(tex2rtf));
+
+    if (InputFile)
+    {
+      sprintf(buf, "Tex2RTF [%s]", FileNameFromPath(InputFile));
+      frame->SetTitle(buf);
+    }
+
+    // Make a menubar
+    wxMenu *file_menu = new wxMenu;
+    file_menu->Append(TEX_GO, "&Go",                        "Run converter");
+    file_menu->Append(TEX_SET_INPUT, "Set &Input File",     "Set the LaTeX input file");
+    file_menu->Append(TEX_SET_OUTPUT, "Set &Output File",   "Set the output file");
+    file_menu->AppendSeparator();
+    file_menu->Append(TEX_VIEW_LATEX, "View &LaTeX File",   "View the LaTeX input file");
+    file_menu->Append(TEX_VIEW_OUTPUT, "View Output &File", "View output file");
+    file_menu->Append(TEX_SAVE_FILE, "&Save log file", "Save displayed text into file");
+    file_menu->AppendSeparator();
+    file_menu->Append(TEX_QUIT, "E&xit",                    "Exit Tex2RTF");
+
+    wxMenu *macro_menu = new wxMenu;
+
+    macro_menu->Append(TEX_LOAD_CUSTOM_MACROS, "&Load Custom Macros", "Load custom LaTeX macro file");
+    macro_menu->Append(TEX_VIEW_CUSTOM_MACROS, "View &Custom Macros", "View custom LaTeX macros");
+
+    wxMenu *mode_menu = new wxMenu;
+
+    mode_menu->Append(TEX_MODE_RTF, "Output linear &RTF",   "Wordprocessor-compatible RTF");
+    mode_menu->Append(TEX_MODE_WINHELP, "Output &WinHelp RTF", "WinHelp-compatible RTF");
+    mode_menu->Append(TEX_MODE_HTML, "Output &HTML",        "HTML World Wide Web hypertext file");
+    mode_menu->Append(TEX_MODE_XLP, "Output &XLP",          "wxHelp hypertext help file");
+
+    wxMenu *help_menu = new wxMenu;
+
+    help_menu->Append(TEX_HELP, "&Help", "Tex2RTF Contents Page");
+    help_menu->Append(TEX_ABOUT, "&About Tex2RTF", "About Tex2RTF");
+
+    menuBar = new wxMenuBar;
+    menuBar->Append(file_menu, "&File");
+    menuBar->Append(macro_menu, "&Macros");
+    menuBar->Append(mode_menu, "&Conversion Mode");
+    menuBar->Append(help_menu, "&Help");
+
+    frame->SetMenuBar(menuBar);
+    frame->textWindow = new wxTextCtrl(frame, -1, "", wxPoint(-1, -1), wxSize(-1, -1), wxTE_READONLY|wxTE_MULTILINE);
+
+    (*frame->textWindow) << "Welcome to Julian Smart's LaTeX to RTF converter.\n";
+//    ShowOptions();    
+
+    HelpInstance = new wxHelpController();
+    HelpInstance->Initialize("tex2rtf");
+
+    /*
+     * Read macro/initialisation file
+     *
+     */
+   
+    wxString path;
+    if ((path = TexPathList.FindValidPath(MacroFile)) != "")
+      ReadCustomMacros((char*) (const char*) path);
+
+    strcpy(buf, "In ");
+
+    if (winHelp && (convertMode == TEX_RTF))
+      strcat(buf, "WinHelp RTF");
+    else if (!winHelp && (convertMode == TEX_RTF))
+      strcat(buf, "linear RTF");
+    else if (convertMode == TEX_HTML) strcat(buf, "HTML");
+    else if (convertMode == TEX_XLP) strcat(buf, "XLP");
+      strcat(buf, " mode.");
+    frame->SetStatusText(buf, 1);
+  
+    frame->Show(TRUE);
+    return TRUE;
+  }
+  else
+#endif // NO_GUI
+  {
+    /*
+     * Read macro/initialisation file
+     *
+     */
+   
+    wxString path;
+    if ((path = TexPathList.FindValidPath(MacroFile)) != "")
+      ReadCustomMacros((char*) (const char*) path);
+
+    Go();
+    if (runTwice) Go();
+#ifdef NO_GUI
+    return 0;
+#else
+    return NULL;
+#endif
+  }
+
+#ifndef NO_GUI
+  // Return the main frame window
+  return TRUE;
+#else
+  return FALSE;
+#endif
+}
+
+int MyApp::OnExit()
+{
+  wxNode *node = CustomMacroList.First();
+  while (node)
+  {
+    CustomMacro *macro = (CustomMacro *)node->Data();
+    delete macro;
+    delete node;
+    node = CustomMacroList.First();
+  }
+  MacroDefs.BeginFind();
+  node = MacroDefs.Next();
+  while (node)
+  {
+    TexMacroDef* def = (TexMacroDef*) node->Data();
+    delete def;
+    node = MacroDefs.Next();
+  }
+  MacroDefs.Clear();
+#ifdef __WXMSW__
+  delete TheTex2RTFServer;
+#endif
+  delete HelpInstance;
+
+  // TODO: this simulates zero-memory leaks!
+  // Otherwise there are just too many...
+  wxDebugContext::SetCheckpoint();
+
+  return 0;
+}
+
+void ShowOptions(void)
+{
+    char buf[100];
+    sprintf(buf, "Tex2RTF version %.2f", versionNo);
+    OnInform(buf);
+    OnInform("Usage: tex2rtf [input] [output] [switches]\n");
+    OnInform("where valid switches are");
+    OnInform("    -interactive");
+    OnInform("    -bufsize <size in K>");
+    OnInform("    -charset <pc | pca | ansi | mac> (default ansi)");
+    OnInform("    -twice");
+    OnInform("    -sync");
+    OnInform("    -macros <filename>");
+    OnInform("    -winhelp");
+    OnInform("    -rtf");
+    OnInform("    -html");
+    OnInform("    -xlp\n");
+}
+
+#ifndef NO_GUI
+
+BEGIN_EVENT_TABLE(MyFrame, wxFrame)
+    EVT_CLOSE(MyFrame::OnCloseWindow)
+    EVT_MENU(TEX_QUIT, MyFrame::OnExit)
+    EVT_MENU(TEX_GO, MyFrame::OnGo)
+    EVT_MENU(TEX_SET_INPUT, MyFrame::OnSetInput)
+    EVT_MENU(TEX_SET_OUTPUT, MyFrame::OnSetOutput)
+    EVT_MENU(TEX_SAVE_FILE, MyFrame::OnSaveFile)
+    EVT_MENU(TEX_VIEW_LATEX, MyFrame::OnViewLatex)
+    EVT_MENU(TEX_VIEW_OUTPUT, MyFrame::OnViewOutput)
+    EVT_MENU(TEX_VIEW_CUSTOM_MACROS, MyFrame::OnShowMacros)
+    EVT_MENU(TEX_LOAD_CUSTOM_MACROS, MyFrame::OnLoadMacros)
+    EVT_MENU(TEX_MODE_RTF, MyFrame::OnModeRTF)
+    EVT_MENU(TEX_MODE_WINHELP, MyFrame::OnModeWinHelp)
+    EVT_MENU(TEX_MODE_HTML, MyFrame::OnModeHTML)
+    EVT_MENU(TEX_MODE_XLP, MyFrame::OnModeXLP)
+    EVT_MENU(TEX_HELP, MyFrame::OnHelp)
+    EVT_MENU(TEX_ABOUT, MyFrame::OnAbout)
+END_EVENT_TABLE()
+
+// My frame constructor
+MyFrame::MyFrame(wxFrame *frame, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size):
+  wxFrame(frame, id, title, pos, size)
+{}
+
+void MyFrame::OnCloseWindow(wxCloseEvent& event)
+{
+  if (!stopRunning && !OkToClose)
+  {
+    stopRunning = TRUE;
+    runTwice = FALSE;
+    return;
+  }
+  else if (OkToClose)
+  {
+#ifdef __WXMSW__
+    delete TheTex2RTFServer;
+    wxDDECleanUp();
+#endif
+    this->Destroy();
+  }
+}
+
+void MyFrame::OnExit(wxCommandEvent& event)
+{
+    this->Destroy();
+}
+
+void MyFrame::OnGo(wxCommandEvent& event)
+{
+      menuBar->EnableTop(0, FALSE);
+      menuBar->EnableTop(1, FALSE);
+      menuBar->EnableTop(2, FALSE);
+      menuBar->EnableTop(3, FALSE);
+      textWindow->Clear();
+      Tex2RTFYield(TRUE);
+      Go();
+
+      if (runTwice)
+      {
+        Tex2RTFYield(TRUE);
+        Go();
+      }
+      menuBar->EnableTop(0, TRUE);
+      menuBar->EnableTop(1, TRUE);
+      menuBar->EnableTop(2, TRUE);
+      menuBar->EnableTop(3, TRUE);
+}
+
+void MyFrame::OnSetInput(wxCommandEvent& event)
+{
+      ChooseInputFile(TRUE);
+}
+
+void MyFrame::OnSetOutput(wxCommandEvent& event)
+{
+      ChooseOutputFile(TRUE);
+}
+
+void MyFrame::OnSaveFile(wxCommandEvent& event)
+{
+      wxString s = wxFileSelector("Save text to file", "", "", "txt", "*.txt");
+      if (s != "")
+      {
+        textWindow->SaveFile(s);
+        char buf[350];
+        sprintf(buf, "Saved text to %s", (const char*) s);
+        frame->SetStatusText(buf, 0);
+      }
+}
+
+void MyFrame::OnViewOutput(wxCommandEvent& event)
+{
+      ChooseOutputFile();
+      if (OutputFile && wxFileExists(OutputFile))
+      {
+        textWindow->LoadFile(OutputFile);
+        char buf[300];
+        wxString str(wxFileNameFromPath(OutputFile));
+        sprintf(buf, "Tex2RTF [%s]", (const char*) str);
+        frame->SetTitle(buf);
+      }
+}
+
+void MyFrame::OnViewLatex(wxCommandEvent& event)
+{
+      ChooseInputFile();
+      if (InputFile && wxFileExists(InputFile))
+      {
+        textWindow->LoadFile(InputFile);
+        char buf[300];
+        wxString str(wxFileNameFromPath(OutputFile));
+        sprintf(buf, "Tex2RTF [%s]", (const char*) str);
+        frame->SetTitle(buf);
+      }
+}
+
+void MyFrame::OnLoadMacros(wxCommandEvent& event)
+{
+      textWindow->Clear();
+      wxString s = wxFileSelector("Choose custom macro file", wxPathOnly(MacroFile), wxFileNameFromPath(MacroFile), "ini", "*.ini");
+      if (s != "" && wxFileExists(s))
+      {
+        MacroFile = copystring(s);
+        ReadCustomMacros((char*) (const char*) s);
+        ShowCustomMacros();
+      }
+}
+
+void MyFrame::OnShowMacros(wxCommandEvent& event)
+{
+      textWindow->Clear();
+      Tex2RTFYield(TRUE);
+      ShowCustomMacros();
+}
+
+void MyFrame::OnModeRTF(wxCommandEvent& event)
+{
+      convertMode = TEX_RTF;
+      winHelp = FALSE;
+      InputFile = NULL;
+      OutputFile = NULL;
+      SetStatusText("In linear RTF mode.", 1);
+}
+
+void MyFrame::OnModeWinHelp(wxCommandEvent& event)
+{
+      convertMode = TEX_RTF;
+      winHelp = TRUE;
+      InputFile = NULL;
+      OutputFile = NULL;
+      SetStatusText("In WinHelp RTF mode.", 1);
+}
+
+void MyFrame::OnModeHTML(wxCommandEvent& event)
+{
+      convertMode = TEX_HTML;
+      winHelp = FALSE;
+      InputFile = NULL;
+      OutputFile = NULL;
+      SetStatusText("In HTML mode.", 1);
+}
+
+void MyFrame::OnModeXLP(wxCommandEvent& event)
+{
+      convertMode = TEX_XLP;
+      InputFile = NULL;
+      OutputFile = NULL;
+      SetStatusText("In XLP mode.", 1);
+}
+
+void MyFrame::OnHelp(wxCommandEvent& event)
+{
+      HelpInstance->LoadFile();
+      HelpInstance->DisplayContents();
+}
+
+void MyFrame::OnAbout(wxCommandEvent& event)
+{
+      char buf[300];
+#ifdef __WIN32__
+      char *platform = " (32-bit)";
+#else
+#ifdef __WXMSW__
+      char *platform = " (16-bit)";
+#else
+      char *platform = "";
+#endif
+#endif
+      sprintf(buf, "Tex2RTF Version %.2f%s\nLaTeX to RTF, WinHelp, HTML and wxHelp Conversion\n\n(c) Julian Smart 1999", versionNo, platform);
+      wxMessageBox(buf, "About Tex2RTF");
+}
+
+void ChooseInputFile(bool force)
+{
+  if (force || !InputFile)
+  {
+    wxString s = wxFileSelector("Choose LaTeX input file", wxPathOnly(InputFile), wxFileNameFromPath(InputFile), "tex", "*.tex");
+    if (s != "")
+    {
+      // Different file, so clear index entries.
+      ClearKeyWordTable();
+      ResetContentsLevels(0);
+      passNumber = 1;
+      char buf[300];
+      InputFile = copystring(s);
+      wxString str = wxFileNameFromPath(InputFile);
+      sprintf(buf, "Tex2RTF [%s]", (const char*) str);
+      frame->SetTitle(buf);
+      OutputFile = NULL;
+    }
+  }
+}
+
+void ChooseOutputFile(bool force)
+{
+  char extensionBuf[10];
+  char wildBuf[10];
+  strcpy(wildBuf, "*.");
+  char *path = NULL;
+  if (OutputFile)
+    path = wxPathOnly(OutputFile);
+  else if (InputFile)
+    path = wxPathOnly(InputFile);
+    
+  switch (convertMode)
+  {
+    case TEX_RTF:
+    {
+      strcpy(extensionBuf, "rtf");
+      strcat(wildBuf, "rtf");
+      break;
+    }
+    case TEX_XLP:
+    {
+      strcpy(extensionBuf, "xlp");
+      strcat(wildBuf, "xlp");
+      break;
+    }
+    case TEX_HTML:
+    {
+#if defined(__WXMSW__) && defined(__WIN16__)
+      strcpy(extensionBuf, "htm");
+      strcat(wildBuf, "htm");
+#else
+      strcpy(extensionBuf, "html");
+      strcat(wildBuf, "html");
+#endif
+      break;
+    }
+  }
+  if (force || !OutputFile)
+  {
+    wxString s = wxFileSelector("Choose output file", path, wxFileNameFromPath(OutputFile),
+                   extensionBuf, wildBuf);
+    if (s != "")
+      OutputFile = copystring(s);
+  }
+}
+#endif
+
+bool Go(void)
+{
+#ifndef NO_GUI
+  ChooseInputFile();
+  ChooseOutputFile();
+#endif
+
+  if (!InputFile || !OutputFile)
+    return FALSE;
+
+#ifndef NO_GUI
+  if (isInteractive)
+  {
+    char buf[300];
+    wxString str = wxFileNameFromPath(InputFile);
+
+    sprintf(buf, "Tex2RTF [%s]", (const char*) str);
+    frame->SetTitle(buf);
+  }
+
+  wxStartTimer();
+#endif
+
+  // Find extension-less filename
+  strcpy(FileRoot, OutputFile);
+  StripExtension(FileRoot);
+
+  if (truncateFilenames && convertMode == TEX_HTML)
+  {
+    // Truncate to five characters. This ensures that
+    // we can generate DOS filenames such as thing999. But 1000 files
+    // may not be enough, of course...
+    char* sName = wxFileNameFromPath( FileRoot);  // this Julian's method is non-destructive reference
+
+    if(sName)
+      if(strlen( sName) > 5)
+        sName[5] = '\0';  // that should do!
+  }
+  
+  sprintf(ContentsName, "%s.con", FileRoot);
+  sprintf(TmpContentsName, "%s.cn1", FileRoot);
+  sprintf(TmpFrameContentsName, "%s.frc", FileRoot);
+  sprintf(WinHelpContentsFileName, "%s.cnt", FileRoot);
+  sprintf(RefName, "%s.ref", FileRoot);
+
+  TexPathList.EnsureFileAccessible(InputFile);
+  if (!bulletFile)
+  {
+    wxString s = TexPathList.FindValidPath("bullet.bmp");
+    if (s != "")
+    {
+      wxString str = wxFileNameFromPath(s);
+      bulletFile = copystring(str);
+    }
+  }
+
+  if (wxFileExists(RefName))
+    ReadTexReferences(RefName);
+    
+  bool success = FALSE;
+
+  if (InputFile && OutputFile)
+  {
+    if (!FileExists(InputFile))
+    {
+      OnError("Cannot open input file!");
+      TexCleanUp();
+      return FALSE;
+    }
+#ifndef NO_GUI
+    if (isInteractive)
+    {
+      char buf[50];
+      sprintf(buf, "Working, pass %d...", passNumber);
+      frame->SetStatusText(buf);
+    }
+#endif
+    OkToClose = FALSE;
+    OnInform("Reading LaTeX file...");
+    TexLoadFile(InputFile);
+
+    switch (convertMode)
+    {
+      case TEX_RTF:
+      {
+        success = RTFGo();
+        break;
+      }
+      case TEX_XLP:
+      {
+        success = XLPGo();
+        break;
+      }
+      case TEX_HTML:
+      {
+        success = HTMLGo();
+        break;
+      }
+    }
+  }
+  if (stopRunning)
+  {
+    OnInform("*** Aborted by user.");
+    success = FALSE;
+    stopRunning = FALSE;
+  }
+
+  if (success)
+  {
+    WriteTexReferences(RefName);
+    TexCleanUp();
+    startedSections = FALSE;
+
+    char buf[100];
+#ifndef NO_GUI
+    long tim = wxGetElapsedTime();
+    sprintf(buf, "Finished in %ld seconds.", (long)(tim/1000.0));
+    OnInform(buf);
+    if (isInteractive)
+    {
+      sprintf(buf, "Done, %d %s.", passNumber, (passNumber > 1) ? "passes" : "pass");
+      frame->SetStatusText(buf);
+    }
+#else
+    sprintf(buf, "Done, %d %s.", passNumber, (passNumber > 1) ? "passes" : "pass");
+    OnInform(buf);
+#endif
+    passNumber ++;
+    OkToClose = TRUE;
+    return TRUE;
+  }
+
+  TexCleanUp();
+  startedSections = FALSE;
+
+  OnInform("Sorry, unsuccessful.");
+  OkToClose = TRUE;
+  return FALSE;
+}
+
+void OnError(char *msg)
+{
+#ifdef NO_GUI
+  cerr << "Error: " << msg << "\n";
+  cerr.flush();
+#else
+  if (isInteractive)
+    (*frame->textWindow) << "Error: " << msg << "\n";
+  else
+#ifdef __UNIX__
+  {
+    cerr << "Error: " << msg << "\n";
+    cerr.flush();
+  }
+#endif
+#ifdef __WXMSW__
+    wxError(msg);
+#endif
+  Tex2RTFYield(TRUE);
+#endif // NO_GUI
+}
+
+void OnInform(char *msg)
+{
+#ifdef NO_GUI
+  cout << msg << "\n";
+  cout.flush();
+#else
+  if (isInteractive)
+    (*frame->textWindow) << msg << "\n";
+  else
+#ifdef __WXMSW__
+  {
+    cout << msg << "\n";
+    cout.flush();
+  }
+#endif
+#ifdef __WXMSW__
+    {}
+#endif
+  if (isInteractive)
+  {
+    Tex2RTFYield(TRUE);
+  }
+#endif // NO_GUI
+}
+
+void OnMacro(int macroId, int no_args, bool start)
+{
+  switch (convertMode)
+  {
+    case TEX_RTF:
+    {
+      RTFOnMacro(macroId, no_args, start);
+      break;
+    }
+    case TEX_XLP:
+    {
+      XLPOnMacro(macroId, no_args, start);
+      break;
+    }
+    case TEX_HTML:
+    {
+      HTMLOnMacro(macroId, no_args, start);
+      break;
+    }
+  }
+}
+
+bool OnArgument(int macroId, int arg_no, bool start)
+{
+  switch (convertMode)
+  {
+    case TEX_RTF:
+    {
+      return RTFOnArgument(macroId, arg_no, start);
+      break;
+    }
+    case TEX_XLP:
+    {
+      return XLPOnArgument(macroId, arg_no, start);
+      break;
+    }
+    case TEX_HTML:
+    {
+      return HTMLOnArgument(macroId, arg_no, start);
+      break;
+    }
+  }
+  return TRUE;
+}
+
+/*
+ * DDE Stuff
+ */
+#if defined(__WXMSW__) && !defined(NO_GUI)
+
+/*
+ * Server
+ */
+
+wxConnectionBase *Tex2RTFServer::OnAcceptConnection(const wxString& topic)
+{
+  if (topic == "TEX2RTF")
+  {
+    if (!ipc_buffer)
+      ipc_buffer = new char[1000];
+      
+    return new Tex2RTFConnection(ipc_buffer, 4000);
+  }
+  else
+    return NULL;
+}
+
+ /*
+  * Connection
+  */
+  
+Tex2RTFConnection::Tex2RTFConnection(char *buf, int size):wxDDEConnection(buf, size)
+{
+}
+
+Tex2RTFConnection::~Tex2RTFConnection(void)
+{
+}
+
+bool SplitCommand(char *data, char *firstArg, char *secondArg)
+{
+  firstArg[0] = 0;
+  secondArg[0] = 0;
+  int i = 0;
+  int len = strlen(data);
+  bool stop = FALSE;
+  // Find first argument (command name)
+  while (!stop)
+  {
+    if (data[i] == ' ' || data[i] == 0)
+      stop = TRUE;
+    else
+    {
+      firstArg[i] = data[i];
+      i ++;
+    }
+  }
+  firstArg[i] = 0;
+  if (data[i] == ' ')
+  {
+    // Find second argument
+    i ++;
+    int j = 0;
+    while (data[i] != 0)
+    {
+      secondArg[j] = data[i];
+      i ++;
+      j ++;
+    }
+    secondArg[j] = 0;
+  }
+  return TRUE;
+}
+
+bool Tex2RTFConnection::OnExecute(const wxString& topic, char *data, int size, int format)
+{
+  strcpy(Tex2RTFLastStatus, "OK");
+
+  char firstArg[50];
+  char secondArg[300];
+  if (SplitCommand(data, firstArg, secondArg))
+  {
+    bool hasArg = (strlen(secondArg) > 0);
+    if (strcmp(firstArg, "INPUT") == 0 && hasArg)
+    {
+      if (InputFile) delete[] InputFile;
+      InputFile = copystring(secondArg);
+      if (frame)
+      {
+        char buf[100];
+        wxString str = wxFileNameFromPath(InputFile);
+        sprintf(buf, "Tex2RTF [%s]", (const char*) str);
+        frame->SetTitle(buf);
+      }
+    }
+    else if (strcmp(firstArg, "OUTPUT") == 0 && hasArg)
+    {
+      if (OutputFile) delete[] OutputFile;
+      OutputFile = copystring(secondArg);
+    }
+    else if (strcmp(firstArg, "GO") == 0)
+    {
+      strcpy(Tex2RTFLastStatus, "WORKING");
+      if (!Go())
+        strcpy(Tex2RTFLastStatus, "CONVERSION ERROR");
+      else
+        strcpy(Tex2RTFLastStatus, "OK");
+    }
+    else if (strcmp(firstArg, "EXIT") == 0)
+    {
+      if (frame && frame->OnClose())
+        delete frame;
+    }
+    else if (strcmp(firstArg, "MINIMIZE") == 0 || strcmp(firstArg, "ICONIZE") == 0)
+    {
+      if (frame)
+        frame->Iconize(TRUE);
+    }
+    else if (strcmp(firstArg, "SHOW") == 0 || strcmp(firstArg, "RESTORE") == 0)
+    {
+      if (frame)
+      {
+        frame->Iconize(FALSE);
+        frame->Show(TRUE);
+      }
+    }
+    else
+    {
+      // Try for a setting
+      strcpy(Tex2RTFLastStatus, RegisterSetting(firstArg, secondArg, FALSE));
+#ifndef NO_GUI
+      if (frame && strcmp(firstArg, "conversionMode") == 0)
+      {
+        char buf[100];
+        strcpy(buf, "In ");
+
+        if (winHelp && (convertMode == TEX_RTF))
+          strcat(buf, "WinHelp RTF");
+        else if (!winHelp && (convertMode == TEX_RTF))
+          strcat(buf, "linear RTF");
+        else if (convertMode == TEX_HTML) strcat(buf, "HTML");
+        else if (convertMode == TEX_XLP) strcat(buf, "XLP");
+          strcat(buf, " mode.");
+        frame->SetStatusText(buf, 1);
+      }
+#endif
+    }
+  }
+  return TRUE;
+}
+
+char *Tex2RTFConnection::OnRequest(const wxString& topic, const wxString& item, int *size, int format)
+{
+  return Tex2RTFLastStatus;
+}
+
+#endif
+
diff --git a/utils/tex2rtf/src/tex2rtf.def b/utils/tex2rtf/src/tex2rtf.def
new file mode 100644 (file)
index 0000000..6a6a2f1
--- /dev/null
@@ -0,0 +1,8 @@
+NAME         TEX2RTF
+DESCRIPTION  'Tex2Rtf'
+EXETYPE      WINDOWS
+STUB         'WINSTUB.EXE'
+CODE         PRELOAD MOVEABLE DISCARDABLE
+DATA         PRELOAD MOVEABLE MULTIPLE
+HEAPSIZE     3000
+STACKSIZE    20000
diff --git a/utils/tex2rtf/src/tex2rtf.h b/utils/tex2rtf/src/tex2rtf.h
new file mode 100644 (file)
index 0000000..70f2156
--- /dev/null
@@ -0,0 +1,157 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        tex2any.h
+// Purpose:     tex2RTF conversion header
+// Author:      Julian Smart
+// Modified by:
+// Created:     7.9.93
+// RCS-ID:      $Id$
+// Copyright:   (c) Julian Smart
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef NO_GUI
+// Define a new application type
+class MyApp: public wxApp
+{ public:
+    bool OnInit();
+    int OnExit();
+};
+
+// Define a new frame type
+class MyFrame: public wxFrame
+{ public:
+    wxTextCtrl *textWindow;
+    MyFrame(wxFrame *frame, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size);
+    void OnMenuCommand(int id);
+
+    void OnCloseWindow(wxCloseEvent& event);
+    void OnExit(wxCommandEvent& event);
+    void OnGo(wxCommandEvent& event);
+    void OnSetInput(wxCommandEvent& event);
+    void OnSetOutput(wxCommandEvent& event);
+    void OnSaveFile(wxCommandEvent& event);
+    void OnViewOutput(wxCommandEvent& event);
+    void OnViewLatex(wxCommandEvent& event);
+    void OnLoadMacros(wxCommandEvent& event);
+    void OnShowMacros(wxCommandEvent& event);
+    void OnModeRTF(wxCommandEvent& event);
+    void OnModeWinHelp(wxCommandEvent& event);
+    void OnModeHTML(wxCommandEvent& event);
+    void OnModeXLP(wxCommandEvent& event);
+    void OnHelp(wxCommandEvent& event);
+    void OnAbout(wxCommandEvent& event);
+
+DECLARE_EVENT_TABLE()
+};
+
+#ifdef __WXMSW__
+#include "wx/dde.h"
+
+class Tex2RTFConnection: public wxDDEConnection
+{
+ public:
+  Tex2RTFConnection(char *buf, int size);
+  ~Tex2RTFConnection(void);
+  bool OnExecute(const wxString& topic, char *data, int size, int format);
+  char *OnRequest(const wxString& topic, const wxString& item, int *size, int format);
+};
+
+class Tex2RTFServer: public wxDDEServer
+{
+ public:
+  wxConnectionBase *OnAcceptConnection(const wxString& topic);
+};
+
+#endif // __WXMSW__
+
+#endif // NO_GUI
+
+/*
+ * Itemize/enumerate structure: put on a stack for
+ * getting the indentation right
+ *
+ */
+
+#define LATEX_ENUMERATE   1
+#define LATEX_ITEMIZE     2
+#define LATEX_DESCRIPTION 3
+#define LATEX_TWOCOL      5
+#define LATEX_INDENT      6
+
+class ItemizeStruc: public wxObject
+{
+  public:
+    int listType;
+    int currentItem;
+    int indentation;
+    int labelIndentation;
+    inline ItemizeStruc(int lType, int indent = 0, int labIndent = 0)
+    { listType = lType; currentItem = 0;
+      indentation = indent; labelIndentation = labIndent; }
+};
+
+// ID for the menu quit command
+#define TEX_QUIT 1
+#define TEX_GO   2
+
+#define TEX_SET_INPUT   3
+#define TEX_SET_OUTPUT  4
+
+#define TEX_VIEW_LATEX  5
+#define TEX_VIEW_OUTPUT 6
+
+#define TEX_VIEW_CUSTOM_MACROS 7
+#define TEX_LOAD_CUSTOM_MACROS 8
+
+#define TEX_MODE_RTF    9
+#define TEX_MODE_WINHELP 10
+#define TEX_MODE_HTML   11
+#define TEX_MODE_XLP    12
+
+#define TEX_HELP        13
+#define TEX_ABOUT       14
+#define TEX_SAVE_FILE   15
+
+extern TexChunk *currentMember;
+extern bool startedSections;
+extern char *contentsString;
+extern bool suppressNameDecoration;
+extern wxList itemizeStack;
+
+extern FILE *Contents;
+extern FILE *Chapters;
+extern FILE *Sections;
+extern FILE *Subsections;
+extern FILE *Subsubsections;
+
+extern char *InputFile;
+extern char *OutputFile;
+extern char *MacroFile;
+
+extern char *FileRoot;
+extern char *ContentsName;    // Contents page from last time around
+extern char *TmpContentsName; // Current contents page
+extern char *TmpFrameContentsName; // Current frame contents page
+extern char *WinHelpContentsFileName; // WinHelp .cnt file
+extern char *RefName;         // Reference file name
+extern char *bulletFile;
+
+#ifndef NO_GUI
+void ChooseOutputFile(bool force = FALSE);
+void ChooseInputFile(bool force = FALSE);
+#endif
+
+void RTFOnMacro(int macroId, int no_args, bool start);
+bool RTFOnArgument(int macroId, int arg_no, bool start);
+
+void HTMLOnMacro(int macroId, int no_args, bool start);
+bool HTMLOnArgument(int macroId, int arg_no, bool start);
+
+void XLPOnMacro(int macroId, int no_args, bool start);
+bool XLPOnArgument(int macroId, int arg_no, bool start);
+
+bool RTFGo(void);
+bool HTMLGo(void);
+bool XLPGo(void);
+
+#define ltHARDY         10000
diff --git a/utils/tex2rtf/src/tex2rtf.ico b/utils/tex2rtf/src/tex2rtf.ico
new file mode 100644 (file)
index 0000000..b681255
Binary files /dev/null and b/utils/tex2rtf/src/tex2rtf.ico differ
diff --git a/utils/tex2rtf/src/tex2rtf.ini b/utils/tex2rtf/src/tex2rtf.ini
new file mode 100644 (file)
index 0000000..48800d3
--- /dev/null
@@ -0,0 +1,17 @@
+runTwice = yes
+titleFontSize = 12
+authorFontSize = 10
+chapterFontSize = 12
+sectionFontSize = 12
+subsectionFontSize = 12
+; RTF only
+headerRule = yes
+footerRule = yes
+useHeadingStyles = yes
+listItemIndent=40
+truncateFilenames = FALSE
+winHelpContents = yes
+winHelpVersion = 4 ; 3 for Windows 3.x, 4 for Windows 95
+generateHPJ = true
+\overview [2] { \image{}{books.bmp}\helpref{#1}{#2}}
+; Some stuff
\ No newline at end of file
diff --git a/utils/tex2rtf/src/tex2rtf.rc b/utils/tex2rtf/src/tex2rtf.rc
new file mode 100644 (file)
index 0000000..b97ff28
--- /dev/null
@@ -0,0 +1,4 @@
+aaa ICON "tex2rtf.ico"
+tex2rtf ICON "tex2rtf.ico"
+#include "wx/msw/wx.rc"
+
diff --git a/utils/tex2rtf/src/tex2rtf.xpm b/utils/tex2rtf/src/tex2rtf.xpm
new file mode 100644 (file)
index 0000000..20e566f
--- /dev/null
@@ -0,0 +1,42 @@
+/* XPM */
+static char *tex2rtf_xpm[] = {
+/* width height num_colors chars_per_pixel */
+"    32    32        3            1",
+/* colors */
+". c #000000",
+"# c #c0c0c0",
+"a c #ffffff",
+/* pixels */
+"aaaaaaaaaaaaaaaaaaaaa.aaaaaaa..a",
+"aaaaaaaaaaaaaaaaaaaaa..aaaaa.aa.",
+"aaaaaaaaaaaaaaaaaaaa#.a.aaaa.aa.",
+"aaaaaaaaaaaaaaaaaaaa#..a.aaaaa.a",
+"aaaaaaaaaaaaaaaaaaaa#...a.aaaa.a",
+"aaaaaaaaaaaaaaaaa........a.aaaaa",
+"aaaaaaaaaaaaa....aaaa.....a.aa.a",
+"aaaaaaaaaaa..aaaa..........a.aaa",
+"aaaaaaaaa..aa...............a.aa",
+"aaaaaaaa.aa..................a.a",
+"aaaaaaa.a.....................#a",
+"aaaaaa.a.....................###",
+"aaaaa.a.....................###a",
+"aaaa.......................###aa",
+"aaaa..............###.....###aaa",
+"aaa...........#######....###aaaa",
+"aaa.........#####aaa#...###aaaaa",
+"aa........###aaaaaaaa..a##aaaaaa",
+"aa.......##aaaaaaaaaa.aa#aaaaaaa",
+"aa......##aaaaaaaaaaaaaaaaaaaaaa",
+"a......##aaaaaaaaaaaaaaaaaaaaaaa",
+"a.....##aaaaaaaaaaaaaaaaaaaaaaaa",
+"a.....#aaaaaaaaaaaaaaaaaaaaaaaaa",
+"a....#aaaaaaaaaaaaaaaaaaaaaaaaaa",
+"a....aaaa.aaaaaaaaaaaaaaaaaaaaaa",
+"a......a.a.a...aaa..a..aaaaaaaaa",
+"a...a.aa...aa.aaaaa.a.aaaaaaaaaa",
+"a...a.a.aaa.a.....aa.aaaaaaaaaaa",
+"aa.aa.aa.aaaa.a.aaa.a.aaaaaaaaaa",
+"aa.a.....aaaa.a..a..a..aaaaaaaaa",
+"aaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaa....aaaaaaaaaaaaaa"
+};
diff --git a/utils/tex2rtf/src/texutils.cpp b/utils/tex2rtf/src/texutils.cpp
new file mode 100644 (file)
index 0000000..5de8abc
--- /dev/null
@@ -0,0 +1,1635 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        texutils.cpp
+// Purpose:     Miscellaneous utilities
+// Author:      Julian Smart
+// Modified by:
+// Created:     7.9.93
+// RCS-ID:      $Id$
+// Copyright:   (c) Julian Smart
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+#include <wx/hash.h>
+
+#if wxUSE_IOSTREAMH
+#include <iostream.h>
+#include <fstream.h>
+#else
+#include <iostream>
+#include <fstream>
+#endif
+
+#include <ctype.h>
+#include "tex2any.h"
+
+wxHashTable TexReferences(wxKEY_STRING);
+wxList BibList(wxKEY_STRING);
+wxStringList CitationList;
+wxList ColourTable(wxKEY_STRING);
+wxHashTable BibStringTable(wxKEY_STRING);
+wxList CustomMacroList(wxKEY_STRING);
+TexChunk *currentSection = NULL;
+char *fakeCurrentSection = NULL;
+
+static long BibLine = 1;
+
+void OutputCurrentSection(void)
+{
+  if (fakeCurrentSection)
+    TexOutput(fakeCurrentSection);
+  else if (currentSection)
+    TraverseChildrenFromChunk(currentSection);
+}
+
+// Nasty but the way things are done now, necessary,
+// in order to output a chunk properly to a string (macros and all).
+void OutputCurrentSectionToString(char *buf)
+{
+    if (fakeCurrentSection)
+        strcpy(buf, fakeCurrentSection);
+    else
+        OutputChunkToString(currentSection, buf);
+}
+
+void OutputChunkToString(TexChunk *chunk, char *buf)
+{
+  FILE *tempfd = fopen("tmp.tmp", "w");
+  if (!tempfd)
+    return;
+    
+  FILE *old1 = CurrentOutput1;
+  FILE *old2 = CurrentOutput2;
+  
+  CurrentOutput1 = tempfd;
+  CurrentOutput2 = NULL;
+  
+  TraverseChildrenFromChunk(chunk);
+    
+  CurrentOutput1 = old1;
+  CurrentOutput2 = old2;
+  
+  fclose(tempfd);
+  
+  // Read from file into string
+  tempfd = fopen("tmp.tmp", "r");
+  if (!tempfd)
+    return;
+
+  buf[0] = 0;
+  int ch = -2;
+  int i = 0;
+  while (ch != EOF)
+  {
+    ch = getc(tempfd);
+    if (ch == EOF)
+      buf[i] = 0;
+    else
+    {
+      buf[i] = ch;
+      i ++;
+    }
+  }
+  fclose(tempfd);
+  wxRemoveFile("tmp.tmp");
+}
+
+// Called by Tex2Any to simulate a section
+void FakeCurrentSection(char *fakeSection, bool addToContents)
+{
+  currentSection = NULL;
+  if (fakeCurrentSection) delete[] fakeCurrentSection;
+  fakeCurrentSection = copystring(fakeSection);
+
+  if (DocumentStyle == LATEX_ARTICLE)
+  {
+    int mac = ltSECTIONHEADING;
+    if (!addToContents)
+      mac = ltSECTIONHEADINGSTAR;
+    OnMacro(mac, 0, TRUE);
+    OnMacro(mac, 0, FALSE);
+  }
+  else
+  {
+    int mac = ltCHAPTERHEADING;
+    if (!addToContents)
+      mac = ltCHAPTERHEADINGSTAR;
+    OnMacro(mac, 0, TRUE);
+    OnMacro(mac, 0, FALSE);
+  }
+  if (fakeCurrentSection) delete[] fakeCurrentSection;
+  fakeCurrentSection = NULL;
+}
+
+// Look for \label macro, use this ref name if found or
+// make up a topic name otherwise.
+static long topicCounter = 0;
+
+void ResetTopicCounter(void)
+{
+  topicCounter = 0;
+}
+
+static char *forceTopicName = NULL;
+
+void ForceTopicName(char *name)
+{
+  if (forceTopicName)
+    delete[] forceTopicName;
+  if (name)
+    forceTopicName = copystring(name);
+  else
+    forceTopicName = NULL;
+}
+
+char *FindTopicName(TexChunk *chunk)
+{
+  if (forceTopicName)
+    return forceTopicName;
+    
+  char *topicName = NULL;
+  static char topicBuf[100];
+
+  if (chunk && (chunk->type == CHUNK_TYPE_MACRO) &&
+      (chunk->macroId == ltLABEL))
+  {
+    wxNode *node = chunk->children.First();
+    if (node)
+    {
+      TexChunk *child = (TexChunk *)node->Data();
+      if (child->type == CHUNK_TYPE_ARG)
+      {
+        wxNode *snode = child->children.First();
+        if (snode)
+        {
+          TexChunk *schunk = (TexChunk *)snode->Data();
+          if (schunk->type == CHUNK_TYPE_STRING)
+            topicName = schunk->value;
+        }
+      }
+    }
+  }
+  if (topicName)
+    return topicName;
+  else
+  {
+    sprintf(topicBuf, "topic%ld", topicCounter);
+    topicCounter ++;
+    return topicBuf;
+  }
+}
+
+/*
+ * Simulate argument data, so we can 'drive' clients which implement
+ * certain basic formatting behaviour.
+ * Snag is that some save a TexChunk, so don't use yet...
+ *
+ */
+void StartSimulateArgument(char *data)
+{
+  strcpy(currentArgData, data);
+  haveArgData = TRUE;
+}
+
+void EndSimulateArgument(void)
+{
+  haveArgData = FALSE;
+}
+
+/*
+ * Parse and convert unit arguments to points
+ *
+ */
+
+int ParseUnitArgument(char *unitArg)
+{
+  float conversionFactor = 1.0;
+  float unitValue = 0.0;
+  int len = strlen(unitArg);
+  // Get rid of any accidentally embedded commands
+  for (int i = 0; i < len; i++)
+    if (unitArg[i] == '\\')
+      unitArg[i] = 0;
+  len = strlen(unitArg);
+      
+  if (unitArg && (len > 0) && (isdigit(unitArg[0]) || unitArg[0] == '-'))
+  {
+    sscanf(unitArg, "%f", &unitValue);
+    if (len > 1)
+    {
+      char units[3]; 
+      units[0] = unitArg[len-2];
+      units[1] = unitArg[len-1];
+      units[2] = 0;
+      if (strcmp(units, "in") == 0)
+        conversionFactor = 72.0;
+      else if (strcmp(units, "cm") == 0)
+        conversionFactor = 72.0/2.51;
+      else if (strcmp(units, "mm") == 0)
+        conversionFactor = 72.0/25.1;
+      else if (strcmp(units, "pt") == 0)
+        conversionFactor = 1;
+    }
+    return (int)(unitValue*conversionFactor);
+  }
+  else return 0;
+}
+
+/*
+ * Strip off any extension (dot something) from end of file,
+ * IF one exists. Inserts zero into buffer.
+ *
+ */
+void StripExtension(char *buffer)
+{
+  int len = strlen(buffer);
+  int i = len-1;
+  while (i > 0)
+  {
+    if (buffer[i] == '.')
+    {
+      buffer[i] = 0;
+      break;
+    }
+    i --;
+  }
+}
+
+/*
+ * Latex font setting
+ *
+ */
+
+void SetFontSizes(int pointSize)
+{
+  switch (pointSize)
+  {
+    case 12:
+    {
+      normalFont = 12;
+      smallFont = 10;
+      tinyFont = 8;
+      largeFont1 = 14;
+      LargeFont2 = 16;
+      LARGEFont3 = 20;
+      hugeFont1 = 24;
+      HugeFont2 = 28;
+      HUGEFont3 = 32;
+      break;
+    }
+    case 11:
+    {
+      normalFont = 11;
+      smallFont = 9;
+      tinyFont = 7;
+      largeFont1 = 13;
+      LargeFont2 = 16;
+      LARGEFont3 = 19;
+      hugeFont1 = 22;
+      HugeFont2 = 26;
+      HUGEFont3 = 30;
+      break;
+    }
+    case 10:
+    {
+      normalFont = 10;
+      smallFont = 8;
+      tinyFont = 6;
+      largeFont1 = 12;
+      LargeFont2 = 14;
+      LARGEFont3 = 18;
+      hugeFont1 = 20;
+      HugeFont2 = 24;
+      HUGEFont3 = 28;
+      break;
+    }
+  }
+}
+
+/*
+ * Latex references
+ *
+ */
+void AddTexRef(char *name, char *file, char *sectionName,
+               int chapter, int section, int subsection, int subsubsection)
+{
+  TexRef *texRef = (TexRef *)TexReferences.Get(name);
+  if (texRef) TexReferences.Delete(name);
+  
+  char buf[100];
+  buf[0] = 0;
+/*
+  if (sectionName)
+  {
+    strcat(buf, sectionName);
+    strcat(buf, " ");
+  }
+*/
+  if (chapter)
+  {
+    char buf2[10];
+    sprintf(buf2, "%d", chapter);
+    strcat(buf, buf2);
+  }
+  if (section)
+  {
+    char buf2[10];
+    if (chapter)
+      strcat(buf, ".");
+
+    sprintf(buf2, "%d", section);
+    strcat(buf, buf2);
+  }
+  if (subsection)
+  {
+    char buf2[10];
+    strcat(buf, ".");
+    sprintf(buf2, "%d", subsection);
+    strcat(buf, buf2);
+  }
+  if (subsubsection)
+  {
+    char buf2[10];
+    strcat(buf, ".");
+    sprintf(buf2, "%d", subsubsection);
+    strcat(buf, buf2);
+  }
+  char *tmp = ((strlen(buf) > 0) ? buf : (char *)NULL);
+  TexReferences.Put(name, new TexRef(name, file, tmp, sectionName));
+}
+
+void WriteTexReferences(char *filename)
+{
+  ofstream ostr(filename);
+  if (ostr.bad()) return;
+  char buf[200];
+  
+  TexReferences.BeginFind();
+  wxNode *node = TexReferences.Next();
+  while (node)
+  {
+    Tex2RTFYield();
+    TexRef *ref = (TexRef *)node->Data();
+    ostr << ref->refLabel << " " << (ref->refFile ? ref->refFile : "??") << " ";
+    ostr << (ref->sectionName ? ref->sectionName : "??") << " ";
+    ostr << (ref->sectionNumber ? ref->sectionNumber : "??") << "\n";
+    if (!ref->sectionNumber || (strcmp(ref->sectionNumber, "??") == 0 && strcmp(ref->sectionName, "??") == 0))
+    {
+      sprintf(buf, "Warning: reference %s not resolved.", ref->refLabel);
+      OnInform(buf);
+    }
+    node = TexReferences.Next();
+  }
+}
+
+void ReadTexReferences(char *filename)
+{
+  ifstream istr(filename, ios::nocreate | ios::in);
+  if (istr.bad()) return;
+
+  char label[100];
+  char file[400];
+  char section[100];
+  char sectionName[100];
+
+  while (!istr.eof())
+  {
+    istr >> label;
+    if (!istr.eof())
+    {
+      istr >> file;
+         istr >> sectionName;
+      char ch;
+      istr.get(ch); // Read past space
+      istr.get(ch);
+      int i = 0;
+      while (ch != '\n' && !istr.eof())
+      {
+        section[i] = ch;
+        i ++;
+        istr.get(ch);
+      }
+      section[i] = 0;
+      TexReferences.Put(label, new TexRef(label, file, section, sectionName));
+    }
+  }
+}
+
+
+/*
+ * Bibliography-handling code
+ *
+ */
+
+void BibEatWhiteSpace(istream& str)
+{
+  char ch = str.peek();
+  
+  while (!str.eof() && (ch == ' ' || ch == '\t' || ch == 13 || ch == 10 || ch == EOF))
+  {
+    if (ch == 10)
+      BibLine ++;
+    str.get(ch);
+    if ((ch == EOF) || str.eof()) return;
+    ch = str.peek();
+  }
+
+  // Ignore end-of-line comments
+  if (ch == '%' || ch == ';' || ch == '#')
+  {
+    str.get(ch);
+    ch = str.peek();
+    while (ch != 10 && ch != 13 && !str.eof())
+    {
+      str.get(ch);
+      ch = str.peek();
+    }
+    BibEatWhiteSpace(str);
+  }
+}
+
+// Read word up to { or , or space
+void BibReadWord(istream& istr, char *buffer)
+{
+  int i = 0;
+  buffer[i] = 0;
+  char ch = istr.peek();
+  while (!istr.eof() && ch != ' ' && ch != '{' && ch != '(' && ch != 13 && ch != 10 && ch != '\t' &&
+         ch != ',' && ch != '=')
+  {
+    istr.get(ch);
+    buffer[i] = ch;
+    i ++;
+    ch = istr.peek();
+  }
+  buffer[i] = 0;
+}
+
+// Read string (double-quoted or not) to end quote or EOL
+void BibReadToEOL(istream& istr, char *buffer)
+{
+  int i = 0;
+  buffer[i] = 0;
+  char ch = istr.peek();
+  bool inQuotes = FALSE;
+  if (ch == '"')
+  {
+    istr.get(ch);
+    ch = istr.peek();
+    inQuotes = TRUE;
+  }
+  // If in quotes, read white space too. If not,
+  // stop at white space or comment.
+  while (!istr.eof() && ch != 13 && ch != 10 && ch != '"' &&
+         (inQuotes || ((ch != ' ') && (ch != 9) &&
+                        (ch != ';') && (ch != '%') && (ch != '#'))))
+  {
+    istr.get(ch);
+    buffer[i] = ch;
+    i ++;
+    ch = istr.peek();
+  }
+  if (ch == '"')
+    istr.get(ch);
+  buffer[i] = 0;
+}
+
+// Read }-terminated value, taking nested braces into account.
+void BibReadValue(istream& istr, char *buffer, bool ignoreBraces = TRUE,
+                  bool quotesMayTerminate = TRUE)
+{
+  int braceCount = 1;
+  int i = 0;
+  buffer[i] = 0;
+  char ch = istr.peek();
+  bool stopping = FALSE;
+  while (!istr.eof() && !stopping)
+  {
+//    i ++;
+    if (i >= 2000)
+    {
+      char buf[100];
+      sprintf(buf, "Sorry, value > 2000 chars in bib file at line %ld, terminating.", BibLine);
+      wxFatalError(buf, "Tex2RTF Fatal Error");
+    }
+    istr.get(ch);
+    
+    if (ch == '{')
+      braceCount ++;
+
+    if (ch == '}')
+    {
+      braceCount --;
+      if (braceCount == 0)
+      {
+        stopping = TRUE;
+        break;
+      }
+    }
+    else if (quotesMayTerminate && ch == '"')
+    {
+      stopping = TRUE;
+      break;
+    }
+    if (!stopping)
+    {
+      if (!ignoreBraces || (ch != '{' && ch != '}'))
+      {
+        buffer[i] = ch;
+        i ++;
+      }
+    }
+    if (ch == 10)
+      BibLine ++;
+  }
+  buffer[i] = 0;
+}
+bool ReadBib(char *filename)
+{
+  char buf[300];
+  ifstream istr(filename, ios::nocreate | ios::in);
+  if (istr.bad()) return FALSE;
+
+  BibLine = 1;
+
+  OnInform("Reading .bib file...");
+
+  char ch;
+  char fieldValue[2000];
+  char recordType[100];
+  char recordKey[100];
+  char recordField[100];
+  while (!istr.eof())
+  {
+    Tex2RTFYield();
+
+    BibEatWhiteSpace(istr);
+    istr.get(ch);
+    if (ch != '@')
+    {
+      sprintf(buf, "Expected @: malformed bib file at line %ld (%s)", BibLine, filename);
+      OnError(buf);
+      return FALSE;
+    }
+    BibReadWord(istr, recordType);
+    BibEatWhiteSpace(istr);
+    istr.get(ch);
+    if (ch != '{' && ch != '(')
+    {
+      sprintf(buf, "Expected { or ( after record type: malformed .bib file at line %ld (%s)", BibLine, filename);
+      OnError(buf);
+      return FALSE;
+    }
+    BibEatWhiteSpace(istr);
+    if (StringMatch(recordType, "string", FALSE, TRUE))
+    {
+      BibReadWord(istr, recordType);
+      BibEatWhiteSpace(istr);
+      istr.get(ch);
+      if (ch != '=')
+      {
+        sprintf(buf, "Expected = after string key: malformed .bib file at line %ld (%s)", BibLine, filename);
+        OnError(buf);
+        return FALSE;
+      }
+      BibEatWhiteSpace(istr);
+      istr.get(ch);
+      if (ch != '"' && ch != '{')
+      {
+        sprintf(buf, "Expected = after string key: malformed .bib file at line %ld (%s)", BibLine, filename);
+        OnError(buf);
+        return FALSE;
+      }
+      BibReadValue(istr, fieldValue);
+
+      // Now put in hash table if necesary
+      if (!BibStringTable.Get(recordType))
+        BibStringTable.Put(recordType, (wxObject *)copystring(fieldValue));
+
+      // Read closing ) or }
+      BibEatWhiteSpace(istr);
+      istr.get(ch);
+      BibEatWhiteSpace(istr);
+    }
+    else
+    {
+      BibReadWord(istr, recordKey);
+
+      BibEntry *bibEntry = new BibEntry;
+      bibEntry->key = copystring(recordKey);
+      bibEntry->type = copystring(recordType);
+
+      bool moreRecords = TRUE;
+      while (moreRecords && !istr.eof())
+      {
+        BibEatWhiteSpace(istr);
+        istr.get(ch);
+        if (ch == '}' || ch == ')')
+        {
+          moreRecords = FALSE;
+        }
+        else if (ch == ',')
+        {
+          BibEatWhiteSpace(istr);
+          BibReadWord(istr, recordField);
+          BibEatWhiteSpace(istr);
+          istr.get(ch);
+          if (ch != '=')
+          {
+            sprintf(buf, "Expected = after field type: malformed .bib file at line %ld (%s)", BibLine, filename);
+            OnError(buf);
+            return FALSE;
+          }
+          BibEatWhiteSpace(istr);
+          istr.get(ch);
+          if (ch != '{' && ch != '"')
+          {
+            fieldValue[0] = ch;
+            BibReadWord(istr, fieldValue+1);
+
+            // If in the table of strings, replace with string from table.
+            char *s = (char *)BibStringTable.Get(fieldValue);
+            if (s)
+            {
+              strcpy(fieldValue, s);
+            }
+          }
+          else
+            BibReadValue(istr, fieldValue, TRUE, (ch == '"' ? TRUE : FALSE));
+
+          // Now we can add a field
+          if (StringMatch(recordField, "author", FALSE, TRUE))
+            bibEntry->author = copystring(fieldValue);
+          else if (StringMatch(recordField, "key", FALSE, TRUE))
+            {}
+          else if (StringMatch(recordField, "annotate", FALSE, TRUE))
+            {}
+          else if (StringMatch(recordField, "abstract", FALSE, TRUE))
+            {}
+          else if (StringMatch(recordField, "edition", FALSE, TRUE))
+            {}
+          else if (StringMatch(recordField, "howpublished", FALSE, TRUE))
+            {}
+          else if (StringMatch(recordField, "note", FALSE, TRUE) || StringMatch(recordField, "notes", FALSE, TRUE))
+            {}
+          else if (StringMatch(recordField, "series", FALSE, TRUE))
+            {}
+          else if (StringMatch(recordField, "type", FALSE, TRUE))
+            {}
+          else if (StringMatch(recordField, "keywords", FALSE, TRUE))
+            {}
+          else if (StringMatch(recordField, "editor", FALSE, TRUE) || StringMatch(recordField, "editors", FALSE, TRUE))
+            bibEntry->editor= copystring(fieldValue);
+          else if (StringMatch(recordField, "title", FALSE, TRUE))
+            bibEntry->title= copystring(fieldValue);
+          else if (StringMatch(recordField, "booktitle", FALSE, TRUE))
+            bibEntry->booktitle= copystring(fieldValue);
+          else if (StringMatch(recordField, "journal", FALSE, TRUE))
+            bibEntry->journal= copystring(fieldValue);
+          else if (StringMatch(recordField, "volume", FALSE, TRUE))
+            bibEntry->volume= copystring(fieldValue);
+          else if (StringMatch(recordField, "number", FALSE, TRUE))
+            bibEntry->number= copystring(fieldValue);
+          else if (StringMatch(recordField, "year", FALSE, TRUE))
+            bibEntry->year= copystring(fieldValue);
+          else if (StringMatch(recordField, "month", FALSE, TRUE))
+            bibEntry->month= copystring(fieldValue);
+          else if (StringMatch(recordField, "pages", FALSE, TRUE))
+            bibEntry->pages= copystring(fieldValue);
+          else if (StringMatch(recordField, "publisher", FALSE, TRUE))
+            bibEntry->publisher= copystring(fieldValue);
+          else if (StringMatch(recordField, "address", FALSE, TRUE))
+            bibEntry->address= copystring(fieldValue);
+          else if (StringMatch(recordField, "institution", FALSE, TRUE) || StringMatch(recordField, "school", FALSE, TRUE))
+            bibEntry->institution= copystring(fieldValue);
+          else if (StringMatch(recordField, "organization", FALSE, TRUE) || StringMatch(recordField, "organisation", FALSE, TRUE))
+            bibEntry->organization= copystring(fieldValue);
+          else if (StringMatch(recordField, "comment", FALSE, TRUE) || StringMatch(recordField, "comments", FALSE, TRUE))
+            bibEntry->comment= copystring(fieldValue);
+          else if (StringMatch(recordField, "annote", FALSE, TRUE))
+            bibEntry->comment= copystring(fieldValue);
+          else if (StringMatch(recordField, "chapter", FALSE, TRUE))
+            bibEntry->chapter= copystring(fieldValue);
+          else
+          {
+            sprintf(buf, "Unrecognised bib field type %s at line %ld (%s)", recordField, BibLine, filename);
+            OnError(buf);
+          }
+        }
+      }
+      BibList.Append(recordKey, bibEntry);
+      BibEatWhiteSpace(istr);
+    }
+  }
+  return TRUE;
+}
+
+void OutputBibItem(TexRef *ref, BibEntry *bib)
+{
+  Tex2RTFYield();
+
+  OnMacro(ltNUMBEREDBIBITEM, 2, TRUE);
+  OnArgument(ltNUMBEREDBIBITEM, 1, TRUE);
+  TexOutput(ref->sectionNumber);
+  OnArgument(ltNUMBEREDBIBITEM, 1, FALSE);
+  OnArgument(ltNUMBEREDBIBITEM, 2, TRUE);
+
+  TexOutput(" ");
+  OnMacro(ltBF, 1, TRUE);
+  OnArgument(ltBF, 1, TRUE);
+  if (bib->author)
+    TexOutput(bib->author);
+  OnArgument(ltBF, 1, FALSE);
+  OnMacro(ltBF, 1, FALSE);
+  if (bib->author && (strlen(bib->author) > 0) && (bib->author[strlen(bib->author) - 1] != '.'))
+    TexOutput(". ");
+  else
+    TexOutput(" ");
+
+  if (bib->year)
+  {
+    TexOutput(bib->year);
+  }
+  if (bib->month)
+  {
+    TexOutput(" (");
+    TexOutput(bib->month);
+    TexOutput(")");
+  }
+  if (bib->year || bib->month)
+    TexOutput(". ");
+
+  if (StringMatch(bib->type, "article", FALSE, TRUE))
+  {
+    if (bib->title)
+    {
+      TexOutput(bib->title);
+      TexOutput(". ");
+    }
+    if (bib->journal)
+    {
+      OnMacro(ltIT, 1, TRUE);
+      OnArgument(ltIT, 1, TRUE);
+      TexOutput(bib->journal);
+      OnArgument(ltIT, 1, FALSE);
+      OnMacro(ltIT, 1, FALSE);
+    }
+    if (bib->volume)
+    {
+      TexOutput(", ");
+      OnMacro(ltBF, 1, TRUE);
+      OnArgument(ltBF, 1, TRUE);
+      TexOutput(bib->volume);
+      OnArgument(ltBF, 1, FALSE);
+      OnMacro(ltBF, 1, FALSE);
+    }
+    if (bib->number)
+    {
+      TexOutput("(");
+      TexOutput(bib->number);
+      TexOutput(")");
+    }
+    if (bib->pages)
+    {
+      TexOutput(", pages ");
+      TexOutput(bib->pages);
+    }
+    TexOutput(".");
+  }
+  else if (StringMatch(bib->type, "book", FALSE, TRUE) ||
+           StringMatch(bib->type, "unpublished", FALSE, TRUE) ||
+           StringMatch(bib->type, "manual", FALSE, TRUE) ||
+           StringMatch(bib->type, "phdthesis", FALSE, TRUE) ||
+           StringMatch(bib->type, "mastersthesis", FALSE, TRUE) ||
+           StringMatch(bib->type, "misc", FALSE, TRUE) ||
+           StringMatch(bib->type, "techreport", FALSE, TRUE) ||
+           StringMatch(bib->type, "booklet", FALSE, TRUE))
+  {
+    if (bib->title || bib->booktitle)
+    {
+      OnMacro(ltIT, 1, TRUE);
+      OnArgument(ltIT, 1, TRUE);
+      TexOutput(bib->title ? bib->title : bib->booktitle);
+      TexOutput(". ");
+      OnArgument(ltIT, 1, FALSE);
+      OnMacro(ltIT, 1, FALSE);
+    }
+    if (StringMatch(bib->type, "phdthesis", FALSE, TRUE))
+      TexOutput("PhD thesis. ");
+    if (StringMatch(bib->type, "techreport", FALSE, TRUE))
+      TexOutput("Technical report. ");
+    if (bib->editor)
+    {
+      TexOutput("Ed. ");
+      TexOutput(bib->editor);
+      TexOutput(". ");
+    }
+    if (bib->institution)
+    {
+      TexOutput(bib->institution);
+      TexOutput(". ");
+    }
+    if (bib->organization)
+    {
+      TexOutput(bib->organization);
+      TexOutput(". ");
+    }
+    if (bib->publisher)
+    {
+      TexOutput(bib->publisher);
+      TexOutput(". ");
+    }
+    if (bib->address)
+    {
+      TexOutput(bib->address);
+      TexOutput(". ");
+    }
+  }
+  else if (StringMatch(bib->type, "inbook", FALSE, TRUE) ||
+           StringMatch(bib->type, "inproceedings", FALSE, TRUE) ||
+           StringMatch(bib->type, "incollection", FALSE, TRUE) ||
+           StringMatch(bib->type, "conference", FALSE, TRUE))
+  {
+    if (bib->title)
+    {
+      TexOutput(bib->title);
+    }
+    if (bib->booktitle)
+    {
+      TexOutput(", from ");
+      OnMacro(ltIT, 1, TRUE);
+      OnArgument(ltIT, 1, TRUE);
+      TexOutput(bib->booktitle);
+      TexOutput(".");
+      OnArgument(ltIT, 1, FALSE);
+      OnMacro(ltIT, 1, FALSE);
+    }
+    if (bib->editor)
+    {
+      TexOutput(", ed. ");
+      TexOutput(bib->editor);
+    }
+    if (bib->publisher)
+    {
+      TexOutput(" ");
+      TexOutput(bib->publisher);
+    }
+    if (bib->address)
+    {
+      if (bib->publisher) TexOutput(", ");
+      else TexOutput(" ");
+      TexOutput(bib->address);
+    }
+    if (bib->publisher || bib->address)
+      TexOutput(".");
+
+    if (bib->volume)
+    {
+      TexOutput(" ");
+      OnMacro(ltBF, 1, TRUE);
+      OnArgument(ltBF, 1, TRUE);
+      TexOutput(bib->volume);
+      OnArgument(ltBF, 1, FALSE);
+      OnMacro(ltBF, 1, FALSE);
+    }
+    if (bib->number)
+    {
+      if (bib->volume)
+      {
+        TexOutput("(");
+        TexOutput(bib->number);
+        TexOutput(").");
+      }
+      else
+      {
+        TexOutput(" Number ");
+        TexOutput(bib->number);
+        TexOutput(".");
+      }
+    }
+    if (bib->chapter)
+    {
+      TexOutput(" Chap. "); TexOutput(bib->chapter);
+    }
+    if (bib->pages)
+    {
+      if (bib->chapter) TexOutput(", pages ");
+      else TexOutput(" Pages ");
+      TexOutput(bib->pages);
+      TexOutput(".");
+    }
+  }
+  OnArgument(ltNUMBEREDBIBITEM, 2, FALSE);
+  OnMacro(ltNUMBEREDBIBITEM, 2, FALSE);
+}
+
+void OutputBib(void)
+{
+  // Write the heading
+  ForceTopicName("bibliography");
+  FakeCurrentSection(ReferencesNameString);
+  ForceTopicName(NULL);
+
+  OnMacro(ltPAR, 0, TRUE);
+  OnMacro(ltPAR, 0, FALSE);
+
+  if ((convertMode == TEX_RTF) && !winHelp)
+  {
+    OnMacro(ltPAR, 0, TRUE);
+    OnMacro(ltPAR, 0, FALSE);
+  }
+
+  wxNode *node = CitationList.First();
+  while (node)
+  {
+    char *citeKey = (char *)node->Data();
+//    wxNode *texNode = TexReferences.Find(citeKey);
+    TexRef *ref = (TexRef *)TexReferences.Get(citeKey);
+    wxNode *bibNode = BibList.Find(citeKey);
+    if (bibNode && ref)
+    {
+      BibEntry *entry = (BibEntry *)bibNode->Data();
+      OutputBibItem(ref, entry);
+    }
+    node = node->Next();
+  }
+}
+
+static int citeCount = 1;
+
+void ResolveBibReferences(void)
+{
+  if (CitationList.Number() > 0)
+    OnInform("Resolving bibliographic references...");
+
+  citeCount = 1;
+  char buf[200];
+  wxNode *node = CitationList.First();
+  while (node)
+  {
+    Tex2RTFYield();
+    char *citeKey = (char *)node->Data();
+//    wxNode *texNode = TexReferences.Find(citeKey);
+    TexRef *ref = (TexRef *)TexReferences.Get(citeKey);
+    wxNode *bibNode = BibList.Find(citeKey);
+    if (bibNode && ref)
+    {
+      // Unused Variable
+      //BibEntry *entry = (BibEntry *)bibNode->Data();
+      if (ref->sectionNumber) delete[] ref->sectionNumber;
+      sprintf(buf, "[%d]", citeCount);
+      ref->sectionNumber = copystring(buf);
+      citeCount ++;
+    }
+    else
+    {
+      sprintf(buf, "Warning: bib ref %s not resolved.", citeKey);
+      OnInform(buf);
+    }
+    node = node->Next();
+  }
+}
+
+// Remember we need to resolve this citation
+void AddCitation(char *citeKey)
+{
+  if (!CitationList.Member(citeKey))
+    CitationList.Add(citeKey);
+
+  if (!TexReferences.Get(citeKey))
+  {
+    TexReferences.Put(citeKey, new TexRef(citeKey, "??", NULL));
+  }
+}
+
+TexRef *FindReference(char *key)
+{
+  return (TexRef *)TexReferences.Get(key);
+}
+
+/*
+ * Custom macro stuff
+ *
+ */
+
+bool StringTobool(char *val)
+{
+  if (strncmp(val, "yes", 3) == 0 || strncmp(val, "YES", 3) == 0 ||
+      strncmp(val, "on", 2) == 0 || strncmp(val, "ON", 2) == 0 ||
+      strncmp(val, "true", 4) == 0 || strncmp(val, "TRUE", 4) == 0 ||
+      strncmp(val, "ok", 2) == 0 || strncmp(val, "OK", 2) == 0 ||
+      strncmp(val, "1", 1) == 0)
+    return TRUE;
+  else
+    return FALSE;
+}
+
+// Define a variable value from the .ini file
+char *RegisterSetting(char *settingName, char *settingValue, bool interactive)
+{
+  static char errorCode[100];
+  strcpy(errorCode, "OK");
+  if (StringMatch(settingName, "chapterName", FALSE, TRUE))
+  {
+    delete[] ChapterNameString;
+    ChapterNameString = copystring(settingValue);
+  }
+  else if (StringMatch(settingName, "sectionName", FALSE, TRUE))
+  {
+    delete[] SectionNameString;
+    SectionNameString = copystring(settingValue);
+  }
+  else if (StringMatch(settingName, "subsectionName", FALSE, TRUE))
+  {
+    delete[] SubsectionNameString;
+    SubsectionNameString = copystring(settingValue);
+  }
+  else if (StringMatch(settingName, "subsubsectionName", FALSE, TRUE))
+  {
+    delete[] SubsubsectionNameString;
+    SubsubsectionNameString = copystring(settingValue);
+  }
+  else if (StringMatch(settingName, "indexName", FALSE, TRUE))
+  {
+    delete[] IndexNameString;
+    IndexNameString = copystring(settingValue);
+  }
+  else if (StringMatch(settingName, "contentsName", FALSE, TRUE))
+  {
+    delete[] ContentsNameString;
+    ContentsNameString = copystring(settingValue);
+  }
+  else if (StringMatch(settingName, "glossaryName", FALSE, TRUE))
+  {
+    delete[] GlossaryNameString;
+    GlossaryNameString = copystring(settingValue);
+  }
+  else if (StringMatch(settingName, "referencesName", FALSE, TRUE))
+  {
+    delete[] ReferencesNameString;
+    ReferencesNameString = copystring(settingValue);
+  }
+  else if (StringMatch(settingName, "tablesName", FALSE, TRUE))
+  {
+    delete[] TablesNameString;
+    TablesNameString = copystring(settingValue);
+  }
+  else if (StringMatch(settingName, "figuresName", FALSE, TRUE))
+  {
+    delete[] FiguresNameString;
+    FiguresNameString = copystring(settingValue);
+  }
+  else if (StringMatch(settingName, "tableName", FALSE, TRUE))
+  {
+    delete[] TableNameString;
+    TableNameString = copystring(settingValue);
+  }
+  else if (StringMatch(settingName, "figureName", FALSE, TRUE))
+  {
+    delete[] FigureNameString;
+    FigureNameString = copystring(settingValue);
+  }
+  else if (StringMatch(settingName, "abstractName", FALSE, TRUE))
+  {
+    delete[] AbstractNameString;
+    AbstractNameString = copystring(settingValue);
+  }
+  else if (StringMatch(settingName, "chapterFontSize", FALSE, TRUE))
+    StringToInt(settingValue, &chapterFont);
+  else if (StringMatch(settingName, "sectionFontSize", FALSE, TRUE))
+    StringToInt(settingValue, &sectionFont);
+  else if (StringMatch(settingName, "subsectionFontSize", FALSE, TRUE))
+    StringToInt(settingValue, &subsectionFont);
+  else if (StringMatch(settingName, "titleFontSize", FALSE, TRUE))
+    StringToInt(settingValue, &titleFont);
+  else if (StringMatch(settingName, "authorFontSize", FALSE, TRUE))
+    StringToInt(settingValue, &authorFont);
+  else if (StringMatch(settingName, "ignoreInput", FALSE, TRUE))
+    IgnorableInputFiles.Add(FileNameFromPath(settingValue));
+  else if (StringMatch(settingName, "mirrorMargins", FALSE, TRUE))
+    mirrorMargins = StringTobool(settingValue);
+  else if (StringMatch(settingName, "runTwice", FALSE, TRUE))
+    runTwice = StringTobool(settingValue);
+  else if (StringMatch(settingName, "isInteractive", FALSE, TRUE))
+    isInteractive = StringTobool(settingValue);
+  else if (StringMatch(settingName, "headerRule", FALSE, TRUE))
+    headerRule = StringTobool(settingValue);
+  else if (StringMatch(settingName, "footerRule", FALSE, TRUE))
+    footerRule = StringTobool(settingValue);
+  else if (StringMatch(settingName, "combineSubSections", FALSE, TRUE))
+    combineSubSections = StringTobool(settingValue);
+  else if (StringMatch(settingName, "listLabelIndent", FALSE, TRUE))
+    StringToInt(settingValue, &labelIndentTab);
+  else if (StringMatch(settingName, "listItemIndent", FALSE, TRUE))
+    StringToInt(settingValue, &itemIndentTab);
+  else if (StringMatch(settingName, "useUpButton", FALSE, TRUE))
+    useUpButton = StringTobool(settingValue);
+  else if (StringMatch(settingName, "useHeadingStyles", FALSE, TRUE))
+    useHeadingStyles = StringTobool(settingValue);
+  else if (StringMatch(settingName, "useWord", FALSE, TRUE))
+    useWord = StringTobool(settingValue);
+  else if (StringMatch(settingName, "contentsDepth", FALSE, TRUE))
+    StringToInt(settingValue, &contentsDepth);
+  else if (StringMatch(settingName, "generateHPJ", FALSE, TRUE))
+    generateHPJ = StringTobool(settingValue);
+  else if (StringMatch(settingName, "truncateFilenames", FALSE, TRUE))
+    truncateFilenames = StringTobool(settingValue);
+  else if (StringMatch(settingName, "winHelpVersion", FALSE, TRUE))
+    StringToInt(settingValue, &winHelpVersion);
+  else if (StringMatch(settingName, "winHelpContents", FALSE, TRUE))
+    winHelpContents = StringTobool(settingValue);
+  else if (StringMatch(settingName, "htmlIndex", FALSE, TRUE))
+    htmlIndex = StringTobool(settingValue);
+  else if (StringMatch(settingName, "htmlFrameContents", FALSE, TRUE))
+    htmlFrameContents = StringTobool(settingValue);
+  else if (StringMatch(settingName, "upperCaseNames", FALSE, TRUE))
+    upperCaseNames = StringTobool(settingValue);
+  else if (StringMatch(settingName, "winHelpTitle", FALSE, TRUE))
+  {
+    if (winHelpTitle)
+      delete[] winHelpTitle;
+    winHelpTitle = copystring(settingValue);
+  }
+  else if (StringMatch(settingName, "indexSubsections", FALSE, TRUE))
+    indexSubsections = StringTobool(settingValue);
+  else if (StringMatch(settingName, "compatibility", FALSE, TRUE))
+    compatibilityMode = StringTobool(settingValue);
+  else if (StringMatch(settingName, "defaultColumnWidth", FALSE, TRUE))
+  {
+    StringToInt(settingValue, &defaultTableColumnWidth);
+    defaultTableColumnWidth = 20*defaultTableColumnWidth;
+  }
+  else if (StringMatch(settingName, "bitmapMethod", FALSE, TRUE))
+  {
+    if ((strcmp(settingValue, "includepicture") != 0) && (strcmp(settingValue, "hex") != 0) &&
+        (strcmp(settingValue, "import") != 0))
+    {
+      if (interactive)
+        OnError("Unknown bitmapMethod");
+      strcpy(errorCode, "Unknown bitmapMethod");
+    }
+    else
+    {
+      delete[] bitmapMethod;
+      bitmapMethod = copystring(settingValue);
+    }
+  }
+  else if (StringMatch(settingName, "htmlBrowseButtons", FALSE, TRUE))
+  {
+    if (strcmp(settingValue, "none") == 0)
+      htmlBrowseButtons = HTML_BUTTONS_NONE;
+    else if (strcmp(settingValue, "bitmap") == 0)
+      htmlBrowseButtons = HTML_BUTTONS_BITMAP;
+    else if (strcmp(settingValue, "text") == 0)
+      htmlBrowseButtons = HTML_BUTTONS_TEXT;
+    else
+    {
+      if (interactive)
+        OnInform("Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text.");
+      strcpy(errorCode, "Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text.");
+    }
+  }
+  else if (StringMatch(settingName, "backgroundImage", FALSE, TRUE))
+  {
+    backgroundImageString = copystring(settingValue);
+  }
+  else if (StringMatch(settingName, "backgroundColour", FALSE, TRUE))
+  {
+    delete[] backgroundColourString;
+    backgroundColourString = copystring(settingValue);
+  }
+  else if (StringMatch(settingName, "textColour", FALSE, TRUE))
+  {
+    textColourString = copystring(settingValue);
+  }
+  else if (StringMatch(settingName, "linkColour", FALSE, TRUE))
+  {
+    linkColourString = copystring(settingValue);
+  }
+  else if (StringMatch(settingName, "followedLinkColour", FALSE, TRUE))
+  {
+    followedLinkColourString = copystring(settingValue);
+  }
+  else if (StringMatch(settingName, "conversionMode", FALSE, TRUE))
+  {
+    if (StringMatch(settingValue, "RTF", FALSE, TRUE))
+    {
+      winHelp = FALSE; convertMode = TEX_RTF;
+    }
+    else if (StringMatch(settingValue, "WinHelp", FALSE, TRUE))
+    {
+      winHelp = TRUE; convertMode = TEX_RTF;
+    }
+    else if (StringMatch(settingValue, "XLP", FALSE, TRUE) ||
+             StringMatch(settingValue, "wxHelp", FALSE, TRUE))
+    {
+      convertMode = TEX_XLP;
+    }
+    else if (StringMatch(settingValue, "HTML", FALSE, TRUE))
+    {
+      convertMode = TEX_HTML;
+    }
+    else
+    {
+      if (interactive)
+        OnInform("Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML.");
+      strcpy(errorCode, "Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML.");
+    }
+  }
+  else if (StringMatch(settingName, "documentFontSize", FALSE, TRUE))
+  {
+    int n;
+    StringToInt(settingValue, &n);
+    if (n == 10 || n == 11 || n == 12)
+      SetFontSizes(n);
+    else
+    {
+      char buf[200];
+      sprintf(buf, "Initialisation file error: nonstandard document font size %d.", n);
+      if (interactive)
+        OnInform(buf);
+      strcpy(errorCode, buf);
+    }
+  }
+  else
+  {
+    char buf[200];
+    sprintf(buf, "Initialisation file error: unrecognised setting %s.", settingName);
+    if (interactive)
+      OnInform(buf);
+    strcpy(errorCode, buf);
+  }
+  return errorCode;
+}
+
+bool ReadCustomMacros(char *filename)
+{
+  ifstream istr(filename, ios::nocreate | ios::in);
+  if (istr.bad()) return FALSE;
+
+  CustomMacroList.Clear();
+  char ch;
+  char macroName[100];
+  char macroBody[1000];
+  int noArgs;
+
+  while (!istr.eof())
+  {
+    BibEatWhiteSpace(istr);
+    istr.get(ch);
+    if (istr.eof())
+      break;
+      
+    if (ch != '\\') // Not a macro definition, so must be NAME=VALUE
+    {
+      char settingName[100];
+      settingName[0] = ch;
+      BibReadWord(istr, (settingName+1));
+      BibEatWhiteSpace(istr);
+      istr.get(ch);
+      if (ch != '=')
+      {
+        OnError("Expected = following name: malformed tex2rtf.ini file.");
+        return FALSE;
+      }
+      else
+      {
+        char settingValue[200];
+        BibEatWhiteSpace(istr);
+        BibReadToEOL(istr, settingValue);
+        RegisterSetting(settingName, settingValue);
+      }
+    }
+    else
+    {
+      BibReadWord(istr, macroName);
+      BibEatWhiteSpace(istr);
+      istr.get(ch);
+      if (ch != '[')
+      {
+        OnError("Expected [ followed by number of arguments: malformed tex2rtf.ini file.");
+        return FALSE;
+      }
+      istr >> noArgs;
+      istr.get(ch);
+      if (ch != ']')
+      {
+        OnError("Expected ] following number of arguments: malformed tex2rtf.ini file.");
+        return FALSE;
+      }
+      BibEatWhiteSpace(istr);
+      istr.get(ch);
+      if (ch != '{')
+      {
+        OnError("Expected { followed by macro body: malformed tex2rtf.ini file.");
+        return FALSE;
+      }
+      CustomMacro *macro = new CustomMacro(macroName, noArgs, NULL);
+      BibReadValue(istr, macroBody, FALSE, FALSE); // Don't ignore extra braces
+      if (strlen(macroBody) > 0)
+        macro->macroBody = copystring(macroBody);
+    
+      BibEatWhiteSpace(istr);
+      CustomMacroList.Append(macroName, macro);
+      AddMacroDef(ltCUSTOM_MACRO, macroName, noArgs);
+    }
+  }
+  char mbuf[200];
+  sprintf(mbuf, "Read initialization file %s.", filename);
+  OnInform(mbuf);
+  return TRUE;
+}
+CustomMacro *FindCustomMacro(char *name)
+{
+  wxNode *node = CustomMacroList.Find(name);
+  if (node)
+  {
+    CustomMacro *macro = (CustomMacro *)node->Data();
+    return macro;
+  }
+  return NULL;
+}
+
+// Display custom macros
+void ShowCustomMacros(void)
+{
+  wxNode *node = CustomMacroList.First();
+  if (!node)
+  {
+    OnInform("No custom macros loaded.\n");
+    return;
+  }
+  
+  char buf[400];
+  while (node)
+  {
+    CustomMacro *macro = (CustomMacro *)node->Data();
+    sprintf(buf, "\\%s[%d]\n    {%s}", macro->macroName, macro->noArgs,
+     macro->macroBody ? macro->macroBody : "");
+    OnInform(buf);
+    node = node->Next();
+  }
+}
+
+// Parse a string into several comma-separated fields
+char *ParseMultifieldString(char *allFields, int *pos)
+{
+  static char buffer[300];
+  int i = 0;
+  int fieldIndex = *pos;
+  int len = strlen(allFields);
+  int oldPos = *pos;
+  bool keepGoing = TRUE;
+  while ((fieldIndex <= len) && keepGoing)
+  {
+    if (allFields[fieldIndex] == ' ')
+    {
+      // Skip
+      fieldIndex ++;
+    }
+    else if (allFields[fieldIndex] == ',')
+    {
+      *pos = fieldIndex + 1;
+      keepGoing = FALSE;
+    }
+    else if (allFields[fieldIndex] == 0)
+    {
+      *pos = fieldIndex + 1;
+      keepGoing = FALSE;
+    }
+    else
+    {
+      buffer[i] = allFields[fieldIndex];
+      fieldIndex ++;
+      i++;
+    }
+  }
+  buffer[i] = 0;
+  if (oldPos == (*pos))
+    *pos = len + 1;
+    
+  if (i == 0)
+    return NULL;
+  else
+    return buffer;
+}
+
+/*
+ * Colour tables
+ *
+ */
+ColourTableEntry::ColourTableEntry(char *theName, unsigned int r,  unsigned int g,  unsigned int b)
+{
+  name = copystring(theName);
+  red = r;
+  green = g;
+  blue = b;
+}
+
+ColourTableEntry::~ColourTableEntry(void)
+{
+  delete[] name;
+}
+
+void AddColour(char *theName, unsigned int r,  unsigned int g,  unsigned int b)
+{
+  wxNode *node = ColourTable.Find(theName);
+  if (node)
+  {
+    ColourTableEntry *entry = (ColourTableEntry *)node->Data();
+    if (entry->red == r || entry->green == g || entry->blue == b)
+      return;
+    else
+    {
+      delete entry;
+      delete node;
+    }
+  }
+  ColourTableEntry *entry = new ColourTableEntry(theName, r, g, b);
+  ColourTable.Append(theName, entry);
+}
+
+int FindColourPosition(char *theName)
+{
+  int i = 0;
+  wxNode *node = ColourTable.First();
+  while (node)
+  {
+    ColourTableEntry *entry = (ColourTableEntry *)node->Data();
+    if (strcmp(theName, entry->name) == 0)
+      return i;
+    i ++;
+    node = node->Next();
+  }
+  return -1;
+}
+
+// Converts e.g. "red" -> "#FF0000"
+extern void DecToHex(int, char *);
+bool FindColourHTMLString(char *theName, char *buf)
+{
+  int i = 0;
+  wxNode *node = ColourTable.First();
+  while (node)
+  {
+    ColourTableEntry *entry = (ColourTableEntry *)node->Data();
+    if (strcmp(theName, entry->name) == 0)
+    {
+        strcpy(buf, "#");
+        
+        char buf2[3];
+        DecToHex(entry->red, buf2);
+        strcat(buf, buf2);
+        DecToHex(entry->green, buf2);
+        strcat(buf, buf2);
+        DecToHex(entry->blue, buf2);
+        strcat(buf, buf2);
+
+        return TRUE;
+    }
+    i ++;
+    node = node->Next();
+  }
+  return FALSE;
+}
+
+  
+void InitialiseColourTable(void)
+{
+  // \\red0\\green0\\blue0;
+  AddColour("black", 0,0,0);
+
+  // \\red0\\green0\\blue255;\\red0\\green255\\blue255;\n");
+  AddColour("cyan", 0,255,255);
+
+  // \\red0\\green255\\blue0;
+  AddColour("green", 0,255,0);
+  
+  // \\red255\\green0\\blue255;
+  AddColour("magenta", 255,0,255);
+
+  // \\red255\\green0\\blue0;
+  AddColour("red", 255,0,0);
+  
+  // \\red255\\green255\\blue0;
+  AddColour("yellow", 255,255,0);
+  
+  // \\red255\\green255\\blue255;}");
+  AddColour("white", 255,255,255);
+}
+
+/*
+ * The purpose of this is to reduce the number of times wxYield is
+ * called, since under Windows this can slow things down.
+ */
+static int yieldCount = 0;
+
+void Tex2RTFYield(bool force)
+{
+#ifdef __WXMSW__
+  if (isSync)
+    return;
+    
+  if (force)
+    yieldCount = 0;
+  if (yieldCount == 0)
+  {
+    wxYield();
+    yieldCount = 10;
+  }
+  yieldCount --;
+#endif
+}
+
+// In both RTF generation and HTML generation for wxHelp version 2,
+// we need to associate \indexed keywords with the current filename/topics.
+
+// Hash table for lists of keywords for topics (WinHelp).
+wxHashTable TopicTable(wxKEY_STRING);
+void AddKeyWordForTopic(char *topic, char *entry, char *filename)
+{
+  TexTopic *texTopic = (TexTopic *)TopicTable.Get(topic);
+  if (!texTopic)
+  {
+    texTopic = new TexTopic(filename);
+    texTopic->keywords = new wxStringList;
+    TopicTable.Put(topic, texTopic);
+  }
+  
+  if (!texTopic->keywords->Member(entry))
+    texTopic->keywords->Add(entry);
+}
+
+void ClearKeyWordTable(void)
+{
+  TopicTable.BeginFind();
+  wxNode *node = TopicTable.Next();
+  while (node)
+  {
+    TexTopic *texTopic = (TexTopic *)node->Data();
+    delete texTopic;
+    node = TopicTable.Next();
+  }
+  TopicTable.Clear();
+}
+
+
+/*
+ * TexTopic structure
+ */
+TexTopic::TexTopic(char *f)
+{
+  if (f)
+    filename = copystring(f);
+  else
+    filename = NULL;
+  hasChildren = FALSE;
+  keywords = NULL;
+}
+
+TexTopic::~TexTopic(void)
+{
+  if (keywords)
+    delete keywords;
+  if (filename)
+    delete[] filename;
+}
+
+// Convert case, according to upperCaseNames setting.
+char *ConvertCase(char *s)
+{
+  static char buf[256];
+  int len = strlen(s);
+  int i;
+  if (upperCaseNames)
+    for (i = 0; i < len; i ++)
+      buf[i] = wxToUpper(s[i]);
+  else
+    for (i = 0; i < len; i ++)
+      buf[i] = wxToLower(s[i]);
+  buf[i] = 0;
+  return buf;  
+}
diff --git a/utils/tex2rtf/src/wxhlpblk.h b/utils/tex2rtf/src/wxhlpblk.h
new file mode 100644 (file)
index 0000000..6cfeb75
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * File:       wxhlpblk.h
+ * Purpose:    Text blocks used in wxHelp
+ * Author:     Julian Smart
+ * Created:    1993
+ * Updated:    
+ * Copyright:  (c) 1993, AIAI, University of Edinburgh
+ */
+
+/* sccsid[] = "%W% %G%" */
+
+#ifndef wxhlpblkh
+#define wxhlpblkh
+
+#define hyBLOCK_NORMAL                      1
+#define hyBLOCK_RED                         2
+#define hyBLOCK_BLUE                        3
+#define hyBLOCK_GREEN                       4
+#define hyBLOCK_LARGE_HEADING               5
+#define hyBLOCK_SMALL_HEADING               6
+#define hyBLOCK_ITALIC                      7
+#define hyBLOCK_BOLD                        8
+#define hyBLOCK_INVISIBLE_SECTION           9
+#define hyBLOCK_LARGE_VISIBLE_SECTION       10
+#define hyBLOCK_SMALL_VISIBLE_SECTION       11
+#define hyBLOCK_SMALL_TEXT                  12
+#define hyBLOCK_RED_ITALIC                  13
+#define hyBLOCK_TELETYPE                    14
+
+#endif // wxhlpblkh
diff --git a/utils/tex2rtf/src/xlputils.cpp b/utils/tex2rtf/src/xlputils.cpp
new file mode 100644 (file)
index 0000000..bcbc4a0
--- /dev/null
@@ -0,0 +1,1219 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        xlputils.cpp
+// Purpose:     Converts Latex to obsolete XLP format
+// Author:      Julian Smart
+// Modified by:
+// Created:     7.9.93
+// RCS-ID:      $Id$
+// Copyright:   (c) Julian Smart
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+#include "tex2any.h"
+#include "tex2rtf.h"
+#include <ctype.h>
+
+long currentBlockId = -1;
+static TexChunk *descriptionItemArg = NULL;
+static int indentLevel = 0;
+static int noColumns = 0;
+static int currentTab = 0;
+static bool tableVerticalLineLeft = FALSE;
+static bool tableVerticalLineRight = FALSE;
+static bool inTable = FALSE;
+static int citeCount = 1;
+wxList hyperLinks(wxKEY_INTEGER);
+wxList hyperLabels(wxKEY_STRING);
+FILE *Index = NULL;
+
+void PadToTab(int tabPos)
+{
+  int currentCol = GetCurrentColumn();
+  for (int i = currentCol; i < tabPos; i++)
+    TexOutput(" ", TRUE);
+}
+
+static long xlpBlockId = 0;
+long NewBlockId(void)
+{
+  return xlpBlockId ++;
+}
+
+// Called on start/end of macro examination
+void XLPOnMacro(int macroId, int no_args, bool start)
+{
+  char buf[100];
+  switch (macroId)
+  {
+  case ltCHAPTER:
+  case ltCHAPTERSTAR:
+  case ltCHAPTERHEADING:
+  {
+    if (!start)
+    {
+      sectionNo = 0;
+      figureNo = 0;
+      subsectionNo = 0;
+      subsubsectionNo = 0;
+      if (macroId != ltCHAPTERSTAR)
+        chapterNo ++;
+
+      SetCurrentOutputs(Contents, Chapters);
+      long id1 = NewBlockId();
+      currentBlockId = NewBlockId();
+
+      startedSections = TRUE;
+      fprintf(Contents, "\\hy-%d{%ld}{", hyBLOCK_SMALL_HEADING, id1);
+      fprintf(Chapters, "\n\\hy-%d{%ld}{", hyBLOCK_LARGE_VISIBLE_SECTION, currentBlockId);
+      fprintf(Index, "%ld %ld\n", id1, currentBlockId);
+
+      OutputCurrentSection(); // Repeat section header
+
+      fprintf(Contents, "}\n\n");
+      fprintf(Chapters, "}\n\n");
+      SetCurrentOutput(Chapters);
+      char *topicName = FindTopicName(GetNextChunk());
+      hyperLabels.Append(topicName, (wxObject *)currentBlockId);
+    }
+    break;
+  }
+  case ltSECTION:
+  case ltSECTIONSTAR:
+  case ltSECTIONHEADING:
+  case ltGLOSS:
+  {
+    if (!start)
+    {
+      subsectionNo = 0;
+      subsubsectionNo = 0;
+
+      if (macroId != ltSECTIONSTAR)
+        sectionNo ++;
+        
+      SetCurrentOutputs(Chapters, Sections);
+      long id1 = NewBlockId();
+      currentBlockId = NewBlockId();
+
+      startedSections = TRUE;
+
+      if (DocumentStyle == LATEX_ARTICLE)
+        fprintf(Contents, "\\hy-%d{%ld}{", hyBLOCK_LARGE_HEADING, id1);
+      else
+        fprintf(Chapters, "\\hy-%d{%ld}{", hyBLOCK_BOLD, id1);
+      fprintf(Sections, "\n\\hy-%d{%ld}{", hyBLOCK_LARGE_VISIBLE_SECTION, currentBlockId);
+      fprintf(Index, "%ld %ld\n", id1, currentBlockId);
+
+      OutputCurrentSection(); // Repeat section header
+
+      if (DocumentStyle == LATEX_ARTICLE)
+        fprintf(Contents, "}\n\n");
+      else
+        fprintf(Chapters, "}\n\n");
+      fprintf(Sections, "}\n\n");
+      SetCurrentOutput(Sections);
+      char *topicName = FindTopicName(GetNextChunk());
+      hyperLabels.Append(topicName, (wxObject *)currentBlockId);
+    }
+    break;
+  }
+  case ltSUBSECTION:
+  case ltSUBSECTIONSTAR:
+  case ltMEMBERSECTION:
+  case ltFUNCTIONSECTION:
+  {
+    if (!start)
+    {
+      subsubsectionNo = 0;
+
+      if (macroId != ltSUBSECTIONSTAR)
+        subsectionNo ++;
+
+      SetCurrentOutputs(Sections, Subsections);
+      long id1 = NewBlockId();
+      currentBlockId = NewBlockId();
+      fprintf(Sections, "\\hy-%d{%ld}{", hyBLOCK_BOLD, id1);
+      fprintf(Subsections, "\n\\hy-%d{%ld}{", hyBLOCK_LARGE_VISIBLE_SECTION, currentBlockId);
+      fprintf(Index, "%ld %ld\n", id1, currentBlockId);
+
+      OutputCurrentSection(); // Repeat section header
+
+      fprintf(Sections, "}\n\n");
+      fprintf(Subsections, "}\n\n");
+      SetCurrentOutput(Subsections);
+      char *topicName = FindTopicName(GetNextChunk());
+      hyperLabels.Append(topicName, (wxObject *)currentBlockId);
+    }
+    break;
+  }
+  case ltSUBSUBSECTION:
+  case ltSUBSUBSECTIONSTAR:
+  {
+    if (!start)
+    {
+      if (macroId != ltSUBSUBSECTIONSTAR)
+        subsubsectionNo ++;
+
+      SetCurrentOutputs(Subsections, Subsubsections);
+      long id1 = NewBlockId();
+      currentBlockId = NewBlockId();
+      fprintf(Subsections, "\\hy-%d{%ld}{", hyBLOCK_BOLD, id1);
+      fprintf(Subsubsections, "\n\\hy-%d{%ld}{", hyBLOCK_LARGE_VISIBLE_SECTION, currentBlockId);
+      fprintf(Index, "%ld %ld\n", id1, currentBlockId);
+
+      OutputCurrentSection(); // Repeat section header
+
+      fprintf(Subsections, "}\n\n");
+      fprintf(Subsubsections, "}\n\n");
+      SetCurrentOutput(Subsubsections);
+      char *topicName = FindTopicName(GetNextChunk());
+      hyperLabels.Append(topicName, (wxObject *)currentBlockId);
+    }
+    break;
+  }
+  case ltFUNC:
+  case ltPFUNC:
+  case ltMEMBER:
+  {
+    SetCurrentOutput(Subsections);
+    if (start)
+    {
+      long id = NewBlockId();
+      fprintf(Subsections, "\\hy-%d{%ld}{", hyBLOCK_BOLD, id);
+    }
+    else
+      fprintf(Subsections, "}");
+    break;
+  }
+  case ltVOID:
+//    if (start)
+//      TexOutput("void", TRUE);
+    break;
+  case ltBACKSLASHCHAR:
+    if (start)
+      TexOutput("\n", TRUE);
+    break;
+  case ltPAR:
+  {
+    if (start)
+    {
+      if (ParSkip > 0)
+        TexOutput("\n", TRUE);
+      TexOutput("\n", TRUE);
+    }
+    break;
+  }
+  case ltRMFAMILY:
+  case ltTEXTRM:
+  case ltRM:
+  {
+    break;
+  }
+  case ltTEXTBF:
+  case ltBFSERIES:
+  case ltBF:
+  {
+    if (start)
+    {
+      char buf[100];
+      long id = NewBlockId();
+      sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_BOLD, id);
+      TexOutput(buf);
+    }
+    else TexOutput("}");
+    break;
+  }
+  case ltTEXTIT:
+  case ltITSHAPE:
+  case ltIT:
+  {
+    if (start)
+    {
+      char buf[100];
+      long id = NewBlockId();
+      sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_ITALIC, id);
+      TexOutput(buf);
+    }
+    else TexOutput("}");
+    break;
+  }
+  case ltTTFAMILY:
+  case ltTEXTTT:
+  case ltTT:
+  {
+    if (start)
+    {
+      long id = NewBlockId();
+      sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_TELETYPE, id);
+      TexOutput(buf);
+    }
+    else TexOutput("}");
+    break;
+  }
+  case ltSMALL:
+  {
+    if (start)
+    {
+      sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_SMALL_TEXT, NewBlockId());
+      TexOutput(buf);
+    }
+    else TexOutput("}");
+    break;
+  }
+  case ltTINY:
+  {
+    if (start)
+    {
+      sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_SMALL_TEXT, NewBlockId());
+      TexOutput(buf);
+    }
+    else TexOutput("}");
+    break;
+  }
+  case ltNORMALSIZE:
+  {
+    if (start)
+    {
+      sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_NORMAL, NewBlockId());
+      TexOutput(buf);
+    }
+    else TexOutput("}");
+    break;
+  }
+  case ltlarge:
+  {
+    if (start)
+    {
+      sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_SMALL_HEADING, NewBlockId());
+      TexOutput(buf);
+    }
+    else TexOutput("}\n");
+    break;
+  }
+  case ltLARGE:
+  {
+    if (start)
+    {
+      sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_LARGE_HEADING, NewBlockId());
+      TexOutput(buf);
+    }
+    else TexOutput("}\n");
+    break;
+  }
+  case ltITEMIZE:
+  case ltENUMERATE:
+  case ltDESCRIPTION:
+  case ltTWOCOLLIST:
+  {
+    if (start)
+    {
+//      tabCount ++;
+
+//      if (indentLevel > 0)
+//        TexOutput("\\par\\par\n");
+      indentLevel ++;
+      int listType;
+      if (macroId == ltENUMERATE)
+        listType = LATEX_ENUMERATE;
+      else if (macroId == ltITEMIZE)
+        listType = LATEX_ITEMIZE;
+      else
+        listType = LATEX_DESCRIPTION;
+      itemizeStack.Insert(new ItemizeStruc(listType));
+
+    }
+    else
+    {
+      indentLevel --;
+
+      if (itemizeStack.First())
+      {
+        ItemizeStruc *struc = (ItemizeStruc *)itemizeStack.First()->Data();
+        delete struc;
+        delete itemizeStack.First();
+      }
+    }
+    break;
+  }
+  case ltITEM:
+  {
+    wxNode *node = itemizeStack.First();
+    if (node)
+    {
+      ItemizeStruc *struc = (ItemizeStruc *)node->Data();
+      if (!start)
+      {
+        struc->currentItem += 1;
+        char indentBuf[30];
+
+        switch (struc->listType)
+        {
+          case LATEX_ENUMERATE:
+          {
+            sprintf(indentBuf, "\\hy-%d{%ld}{%d.} ",
+              hyBLOCK_BOLD, NewBlockId(), struc->currentItem);
+            TexOutput(indentBuf);
+            break;
+          }
+          case LATEX_ITEMIZE:
+          {
+            sprintf(indentBuf, "\\hy-%d{%ld}{o} ",
+              hyBLOCK_BOLD, NewBlockId());
+            TexOutput(indentBuf);
+            break;
+          }
+          default:
+          case LATEX_DESCRIPTION:
+          {
+            if (descriptionItemArg)
+            {
+              sprintf(indentBuf, "\\hy-%d{%ld}{",
+                 hyBLOCK_BOLD, NewBlockId());
+              TexOutput(indentBuf);
+              TraverseChildrenFromChunk(descriptionItemArg);
+              TexOutput("} ");
+              descriptionItemArg = NULL;
+            }
+            break;
+          }
+       }
+      }
+    }
+    break;
+  }
+  case ltMAKETITLE:
+  {
+    if (start && DocumentTitle && DocumentAuthor)
+    {
+      sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_LARGE_HEADING, NewBlockId());
+      TexOutput(buf);
+      TraverseChildrenFromChunk(DocumentTitle);
+      TexOutput("}\n\n");
+      sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_SMALL_HEADING, NewBlockId());
+      TexOutput(buf);
+      TraverseChildrenFromChunk(DocumentAuthor);
+      TexOutput("}\n\n");
+      if (DocumentDate)
+      {
+        TraverseChildrenFromChunk(DocumentDate);
+        TexOutput("\n");
+      }
+    }
+    break;
+  }
+  case ltTABLEOFCONTENTS:
+  {
+    if (start)
+    {
+      FILE *fd = fopen(ContentsName, "r");
+      if (fd)
+      {
+        int ch = getc(fd);
+        while (ch != EOF)
+        {
+          putc(ch, Chapters);
+          ch = getc(fd);
+        }
+        fclose(fd);
+      }
+      else
+      {
+        TexOutput("RUN TEX2RTF AGAIN FOR CONTENTS PAGE\n");
+        OnInform("Run Tex2RTF again to include contents page.");
+      }
+    }
+    break;
+  }
+  case ltHARDY:
+  {
+    if (start)
+      TexOutput("HARDY", TRUE);
+    break;
+  }
+  case ltWXCLIPS:
+  {
+    if (start)
+      TexOutput("wxCLIPS", TRUE);
+    break;
+  }
+  case ltVERBATIM:
+  {
+    if (start)
+    {
+      char buf[100];
+      long id = NewBlockId();
+      sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_TELETYPE, id);
+      TexOutput(buf);
+    }
+    else TexOutput("}");
+    break;
+  }
+  case ltHRULE:
+  {
+    if (start)
+    {
+      TexOutput("\n------------------------------------------------------------------", TRUE);
+    }
+    break;
+  }
+  case ltHLINE:
+  {
+    if (start)
+    {
+      TexOutput("--------------------------------------------------------------------------------", TRUE);
+    }
+    break;
+  }
+  case ltSPECIALAMPERSAND:
+  {
+    if (start)
+    {
+      currentTab ++;
+      int tabPos = (80/noColumns)*currentTab;
+      PadToTab(tabPos);
+    }
+    break;
+  }
+  case ltTABULAR:
+  case ltSUPERTABULAR:
+  {
+    if (start)
+    {
+      sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_TELETYPE, NewBlockId());
+      TexOutput(buf);
+    }
+    else
+      TexOutput("}");
+    break;
+  }
+  case ltNUMBEREDBIBITEM:
+  {
+    if (!start)
+      TexOutput("\n\n", TRUE);
+    break;
+  }
+  case ltCAPTION:
+  case ltCAPTIONSTAR:
+  {
+    if (start)
+    {
+      figureNo ++;
+
+      char figBuf[40];
+      if (DocumentStyle != LATEX_ARTICLE)
+        sprintf(figBuf, "Figure %d.%d: ", chapterNo, figureNo);
+      else
+        sprintf(figBuf, "Figure %d: ", figureNo);
+
+      TexOutput(figBuf);
+    }
+    else
+    {
+      char *topicName = FindTopicName(GetNextChunk());
+
+      AddTexRef(topicName, NULL, NULL,
+           ((DocumentStyle != LATEX_ARTICLE) ? chapterNo : figureNo),
+            ((DocumentStyle != LATEX_ARTICLE) ? figureNo : 0));
+    }
+    break;
+  }
+  default:
+  {
+    DefaultOnMacro(macroId, no_args, start);
+    break;
+  }
+  }
+}
+
+bool XLPOnArgument(int macroId, int arg_no, bool start)
+{
+  char buf[300];
+  switch (macroId)
+  {
+  case ltCHAPTER:
+  case ltCHAPTERSTAR:
+  case ltCHAPTERHEADING:
+  case ltSECTION:
+  case ltSECTIONSTAR:
+  case ltSECTIONHEADING:
+  case ltSUBSECTION:
+  case ltSUBSECTIONSTAR:
+  case ltSUBSUBSECTION:
+  case ltSUBSUBSECTIONSTAR:
+  case ltGLOSS:
+  case ltMEMBERSECTION:
+  case ltFUNCTIONSECTION:
+  {
+    if (!start && (arg_no == 1))
+      currentSection = GetArgChunk();
+    return FALSE;
+    break;
+  }
+  case ltFUNC:
+  {
+    if (!start && (arg_no == 1))
+      TexOutput(" ", TRUE);
+    if (start && (arg_no == 3))
+      TexOutput("(", TRUE);
+    if (!start && (arg_no == 3))
+     TexOutput(")", TRUE);
+    break;
+  }
+  case ltPFUNC:
+  {
+    if (!start && (arg_no == 1))
+      TexOutput(" ", TRUE);
+
+    if (start && (arg_no == 2))
+      TexOutput("(*", TRUE);
+    if (!start && (arg_no == 2))
+      TexOutput(")", TRUE);
+
+    if (start && (arg_no == 3))
+      TexOutput("(", TRUE);
+    if (!start && (arg_no == 3))
+      TexOutput(")", TRUE);
+    break;
+  }
+  case ltCLIPSFUNC:
+  {
+    if (!start && (arg_no == 1))
+      TexOutput(" ", TRUE);
+    if (start && (arg_no == 2))
+    {
+      TexOutput("(", TRUE);
+      long id = NewBlockId();
+      sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_BOLD, id);
+      TexOutput(buf);
+    }
+    if (!start && (arg_no == 2))
+    {
+      TexOutput("}");
+    }
+    if (!start && (arg_no == 3))
+     TexOutput(")", TRUE);
+    break;
+  }
+  case ltPARAM:
+  {
+    if (start && (arg_no == 2))
+    {
+      long id = NewBlockId();
+      sprintf(buf, " \\hy-%d{%ld}{", hyBLOCK_BOLD, id);
+      TexOutput(buf);
+    }
+    if (!start && (arg_no == 2))
+    {
+      TexOutput("}");
+    }
+    break;
+  }
+  case ltCPARAM:
+  {
+    if (start && (arg_no == 2))
+    {
+      long id = NewBlockId();
+      sprintf(buf, " \\hy-%d{%ld}{", hyBLOCK_BOLD, id);
+      TexOutput(buf);
+    }
+    if (!start && (arg_no == 2))
+    {
+      TexOutput("}");
+    }
+    break;
+  }
+  case ltMEMBER:
+  {
+    if (!start && (arg_no == 1))
+      TexOutput(" ", TRUE);
+    break;
+  }
+  case ltLABEL:
+  {
+    return FALSE;
+    break;
+  }
+  case ltREF:
+  {
+    if (start)
+    {
+      char *sec = NULL;
+      
+      char *refName = GetArgData();
+      if (refName)
+      {
+        TexRef *texRef = FindReference(refName);
+        if (texRef)
+        {
+          sec = texRef->sectionNumber;
+        }
+      }
+      if (sec)
+      {
+        TexOutput(sec);
+      }
+      return FALSE;
+    }
+    break;
+  }
+  case ltHELPREF:
+  case ltHELPREFN:
+  case ltPOPREF:
+  {
+    if (arg_no == 1)
+    {
+      if (start)
+      {
+        currentBlockId = NewBlockId();
+        sprintf(buf, "\\hy-%d{%ld}{", hyBLOCK_RED_ITALIC, currentBlockId);
+        TexOutput(buf);
+      }
+      else TexOutput("}");
+    }
+    if (arg_no == 2)
+    {
+      if (start)
+      {
+        char *label = GetArgData();
+        hyperLinks.Append(currentBlockId, (wxObject *)copystring(label));
+      }
+      
+      return FALSE;
+    }
+    break;
+  }
+  case ltURLREF:
+  {
+    if (arg_no == 1)
+    {
+      return TRUE;
+    }
+    else if (arg_no == 2)
+    {
+      if (start)
+        TexOutput(" (");
+      else
+        TexOutput(")");
+      return TRUE;
+    }
+    break;
+  }
+  case ltITEM:
+  {
+    if (start && IsArgOptional())
+    {
+      descriptionItemArg = GetArgChunk();
+      return FALSE;
+    }
+    break;
+  }
+  case ltTABULAR:
+  case ltSUPERTABULAR:
+  {
+    if (arg_no == 1)
+    {
+      if (start)
+      {
+        inTable = TRUE;
+        tableVerticalLineLeft = FALSE;
+        tableVerticalLineRight = FALSE;
+
+        char *alignString = copystring(GetArgData());
+
+        // Count the number of columns
+        noColumns = 0;
+        int len = strlen(alignString);
+        if (len > 0)
+        {
+          if (alignString[0] == '|')
+            tableVerticalLineLeft = TRUE;
+          if (alignString[len-1] == '|')
+            tableVerticalLineRight = TRUE;
+        }
+
+        for (int i = 0; i < len; i++)
+          if (isalpha(alignString[i]))
+            noColumns ++;
+
+/*
+      // Experimental
+      TexOutput("\\brdrt\\brdrs");
+      if (tableVerticalLineLeft)
+        TexOutput("\\brdrl\\brdrs");
+      if (tableVerticalLineRight)
+        TexOutput("\\brdrr\\brdrs");
+*/
+
+        // Calculate a rough size for each column
+//        int tabPos = 80/noColumns;
+        currentTab = 0;
+
+        return FALSE;
+      }
+    }
+    else if (arg_no == 2 && !start)
+    {
+      inTable = FALSE;
+    }
+    else if (arg_no == 2 && start)
+      return TRUE;
+    break;
+  }
+  case ltMARGINPAR:
+  case ltMARGINPAREVEN:
+  case ltMARGINPARODD:
+  case ltNORMALBOX:
+  case ltNORMALBOXD:
+  {
+    if (start)
+    {
+      TexOutput("----------------------------------------------------------------------\n", TRUE);
+      return TRUE;
+    }
+    else
+      TexOutput("\n----------------------------------------------------------------------\n", TRUE);
+    break;
+  }
+  case ltBIBITEM:
+  {
+    char buf[100];
+    if (arg_no == 1 && start)
+    {
+      char *citeKey = GetArgData();
+      TexRef *ref = (TexRef *)TexReferences.Get(citeKey);
+      if (ref)
+      {
+        if (ref->sectionNumber) delete[] ref->sectionNumber;
+        sprintf(buf, "[%d]", citeCount);
+        ref->sectionNumber = copystring(buf);
+      }
+
+      sprintf(buf, "\\hy-%d{%ld}{[%d]} ", hyBLOCK_BOLD, NewBlockId(), citeCount);
+      TexOutput(buf);
+      citeCount ++;
+      return FALSE;
+    }
+    return TRUE;
+    break;
+  }
+  case ltTHEBIBLIOGRAPHY:
+  {
+    if (start && (arg_no == 1))
+    {
+      citeCount = 1;
+
+      SetCurrentOutput(Chapters);
+
+      SetCurrentOutputs(Contents, Chapters);
+      long id1 = NewBlockId();
+      long id2 = NewBlockId();
+      fprintf(Contents, "\\hy-%d{%ld}{%s}\n", hyBLOCK_SMALL_HEADING, id1, ReferencesNameString);
+      fprintf(Chapters, "\\hy-%d{%ld}{%s}\n\n\n", hyBLOCK_LARGE_VISIBLE_SECTION, id2, ReferencesNameString);
+      fprintf(Index, "%ld %ld\n", id1, id2);
+
+      SetCurrentOutput(Chapters);
+      return FALSE;
+    }
+    if (!start && (arg_no == 2))
+    {
+    }
+    return TRUE;
+    break;
+  }
+  case ltTWOCOLITEM:
+  case ltTWOCOLITEMRULED:
+  {
+    if (start && (arg_no == 2))
+      TexOutput("\n    ");
+
+    if (!start && (arg_no == 2))
+      TexOutput("\n");
+    return TRUE;
+  }
+  /*
+   * Accents
+   *
+   */
+  case ltACCENT_GRAVE:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        switch (val[0])
+        {
+          case 'a':
+           TexOutput("a");
+           break;
+          case 'e':
+           TexOutput("e");
+           break;
+          case 'i':
+           TexOutput("i");
+           break;
+          case 'o':
+           TexOutput("o");
+           break;
+          case 'u':
+           TexOutput("u");
+           break;
+          case 'A':
+           TexOutput("a");
+           break;
+          case 'E':
+           TexOutput("E");
+           break;
+          case 'I':
+           TexOutput("I");
+           break;
+          case 'O':
+           TexOutput("O");
+           break;
+          case 'U':
+           TexOutput("U");
+           break;
+          default:
+           break;
+        }
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltACCENT_ACUTE:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        switch (val[0])
+        {
+          case 'a':
+           TexOutput("a");
+           break;
+          case 'e':
+           TexOutput("e");
+           break;
+          case 'i':
+           TexOutput("i");
+           break;
+          case 'o':
+           TexOutput("o");
+           break;
+          case 'u':
+           TexOutput("u");
+           break;
+          case 'y':
+           TexOutput("y");
+           break;
+          case 'A':
+           TexOutput("A");
+           break;
+          case 'E':
+           TexOutput("E");
+           break;
+          case 'I':
+           TexOutput("I");
+           break;
+          case 'O':
+           TexOutput("O");
+           break;
+          case 'U':
+           TexOutput("U");
+           break;
+          case 'Y':
+           TexOutput("Y");
+           break;
+          default:
+           break;
+        }
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltACCENT_CARET:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        switch (val[0])
+        {
+          case 'a':
+           TexOutput("a");
+           break;
+          case 'e':
+           TexOutput("e");
+           break;
+          case 'i':
+           TexOutput("i");
+           break;
+          case 'o':
+           TexOutput("o");
+           break;
+          case 'u':
+           TexOutput("u");
+           break;
+          case 'A':
+           TexOutput("A");
+           break;
+          case 'E':
+           TexOutput("E");
+           break;
+          case 'I':
+           TexOutput("I");
+           break;
+          case 'O':
+           TexOutput("O");
+           break;
+          case 'U':
+           TexOutput("U");
+           break;
+          default:
+           break;
+        }
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltACCENT_TILDE:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        switch (val[0])
+        {
+          case 'a':
+           TexOutput("a");
+           break;
+          case ' ':
+           TexOutput("~");
+           break;
+          case 'n':
+           TexOutput("n");
+           break;
+          case 'o':
+           TexOutput("o");
+           break;
+          case 'A':
+           TexOutput("A");
+           break;
+          case 'N':
+           TexOutput("N");
+           break;
+          case 'O':
+           TexOutput("O");
+           break;
+          default:
+           break;
+        }
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltACCENT_UMLAUT:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        switch (val[0])
+        {
+          case 'a':
+           TexOutput("a");
+           break;
+          case 'e':
+           TexOutput("e");
+           break;
+          case 'i':
+           TexOutput("i");
+           break;
+          case 'o':
+           TexOutput("o");
+           break;
+          case 'u':
+           TexOutput("u");
+           break;
+          case 'y':
+           TexOutput("y");
+           break;
+          case 'A':
+           TexOutput("A");
+           break;
+          case 'E':
+           TexOutput("E");
+           break;
+          case 'I':
+           TexOutput("I");
+           break;
+          case 'O':
+           TexOutput("O");
+           break;
+          case 'U':
+           TexOutput("U");
+           break;
+          case 'Y':
+           TexOutput("Y");
+           break;
+          default:
+           break;
+        }
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltACCENT_DOT:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        switch (val[0])
+        {
+          case 'a':
+           TexOutput("a");
+           break;
+          case 'A':
+           TexOutput("A");
+           break;
+          default:
+           break;
+        }
+      }
+    }
+    return FALSE;
+    break;
+  }
+  case ltACCENT_CADILLA:
+  {
+    if (start)
+    {
+      char *val = GetArgData();
+      if (val)
+      {
+        switch (val[0])
+        {
+          case 'c':
+           TexOutput("c");
+           break;
+          case 'C':
+           TexOutput("C");
+           break;
+          default:
+           break;
+        }
+      }
+    }
+    return FALSE;
+    break;
+  }
+  default:
+  {
+    return DefaultOnArgument(macroId, arg_no, start);
+    break;
+  }
+  }
+  return TRUE;
+}
+
+bool XLPGo(void)
+{
+  xlpBlockId = 0;
+
+  if (InputFile && OutputFile)
+  {
+    Contents = fopen(TmpContentsName, "w");
+    Chapters = fopen("chapters.xlp", "w");
+    Sections = fopen("sections.xlp", "w");
+    Subsections = fopen("subsections.xlp", "w");
+    Subsubsections = fopen("subsubsections.xlp", "w");
+    Index = fopen("index.xlp", "w");
+
+    // Insert invisible section marker at beginning
+    fprintf(Chapters, "\\hy-%d{%ld}{%s}\n",
+                hyBLOCK_INVISIBLE_SECTION, NewBlockId(), "\n");
+
+    fprintf(Contents, "\\hy-%d{%ld}{%s}\n\n",
+//                hyBLOCK_LARGE_HEADING, NewBlockId(), "\n\n%s\n\n", ContentsNameString);
+                hyBLOCK_LARGE_HEADING, NewBlockId(), ContentsNameString);
+
+    SetCurrentOutput(Chapters);
+
+    fprintf(Index, "\n\\hyindex{\n\"%s\"\n",
+             contentsString ? contentsString : "WXHELPCONTENTS");
+    TraverseDocument();
+
+    wxNode *node = hyperLinks.First();
+    while (node)
+    {
+      long from = node->GetKeyInteger();
+      char *label = (char *)node->Data();
+      wxNode *otherNode = hyperLabels.Find(label);
+      if (otherNode)
+      {
+        long to = (long)otherNode->Data();
+        fprintf(Index, "%ld %ld\n", from, to);
+      }
+      node = node->Next();
+    }
+
+    fprintf(Index, "}\n");
+
+    fclose(Contents); Contents = NULL;
+    fclose(Chapters); Chapters = NULL;
+    fclose(Sections); Sections = NULL;
+    fclose(Subsections); Subsections = NULL;
+    fclose(Subsubsections); Subsubsections = NULL;
+    fclose(Index); Index = NULL;
+
+    if (FileExists(ContentsName)) wxRemoveFile(ContentsName);
+
+    if (!wxRenameFile(TmpContentsName, ContentsName))
+    {
+      wxCopyFile(TmpContentsName, ContentsName);
+      wxRemoveFile(TmpContentsName);
+    }
+
+    wxConcatFiles("chapters.xlp", "sections.xlp", "tmp2.xlp");
+    wxConcatFiles("tmp2.xlp", "subsections.xlp", "tmp1.xlp");
+    wxConcatFiles("tmp1.xlp", "subsubsections.xlp", "tmp2.xlp");
+    wxConcatFiles("tmp2.xlp", "index.xlp", OutputFile);
+
+    wxRemoveFile("tmp1.xlp");
+    wxRemoveFile("tmp2.xlp");
+
+    wxRemoveFile("chapters.xlp");
+    wxRemoveFile("sections.xlp");
+    wxRemoveFile("subsections.xlp");
+    wxRemoveFile("subsubsections.xlp");
+    wxRemoveFile("index.xlp");
+    return TRUE;
+  }
+  return FALSE;
+}
+