Category : EmTeX is a TeX/LaTeX document editor
Archive   : TEX2RTF.ZIP
Filename : RTFUTILS.CC

 
Output of file : RTFUTILS.CC contained in archive : TEX2RTF.ZIP

/*
* rtfutils.cc
*
* Utility functions for helping convert Latex files
* into RTF files suitable for compiling into WinHelp
* files.
*
* Julian Smart September 1993
*
*/

#include "wx.h"
#include "tex2any.h"
#include "tex2rtf.h"
#include
#include "bmputils.h"

wxList itemizeStack;
static int tabCount = 0; // Output a tab if we've set a tab stop in an environment
static int indentLevel = 0;
static int forbidParindent = 0; // if > 0, no parindent (e.g. in center environment)
static char *contentsLineSection = NULL;
static char *contentsLineValue = NULL;
static TexChunk *descriptionItemArg = NULL;
static wxStringList environmentStack; // Stack of paragraph styles we need to remember
Bool inTable = FALSE;
Bool startRows = FALSE;
Bool tableVerticalLineLeft = FALSE;
Bool tableVerticalLineRight = FALSE;
int noColumns = 0; // Current number of columns in table
extern Bool winHelp;
extern Bool startedSections;
extern FILE *Contents;
extern FILE *Chapters;
// 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;


/*
* Write a suitable RTF header.
*
*/

void WriteRTFHeader(FILE *fd)
{
fprintf(fd, "{\\rtf1\\ansi \\deff0\n");
fprintf(fd, "{\\fonttbl{\\f0\\froman Times New Roman;}{\\f1\\fdecor Symbol;}{\\f2\\fswiss Arial;}\n");
fprintf(fd, "{\\f3\\fmodern Courier;}\n}\n{\\colortbl;\n");
fprintf(fd, "\\red0\\green0\\blue0;\\red0\\green0\\blue255;\\red0\\green255\\blue255;\n");
fprintf(fd, "\\red0\\green255\\blue0;\n");
fprintf(fd, "\\red255\\green0\\blue255;\\red255\\green0\\blue0;\\red255\\green255\\blue0;\n");
fprintf(fd, "\\red255\\green255\\blue255;}\n");
}


/*
* 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, "\\line\n"); ptr += 6;
i ++;
changed = TRUE;
}
else
{
/*
// 2 newlines means 2 \pars
if ((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, "\\sa240\\par\\pard\n"); ptr += 16;
strcat(BigBuffer, "\\par\\par\n"); ptr += 9;
i += 2;
changed = TRUE;
}
*/
// If the first character of the next line is ASCII,
// put a space in. Implicit in Latex, not in RTF.
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]))))
{
// 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)
{
switch (chunk->type)
{
case CHUNK_TYPE_MACRO:
{
TexMacroDef *def = NULL;
wxNode *node = MacroDefs.Find(chunk->name);

if (node)
{
def = (TexMacroDef *)node->Data();
if (def->ignore)
return;
}

if (def && strcmp(def->name, "verbatim") == 0)
inVerbatim = TRUE;

node = chunk->children.First();
while (node)
{
TexChunk *child_chunk = (TexChunk *)node->Data();
Text2RTF(child_chunk);
node = node->Next();
}

if (def && strcmp(def->name, "verbatim") == 0)
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[100];
char *GetBrowseString(void)
{
sprintf(browseBuf, "%ld", NewId());
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 (!inTable && (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");
}


// Called on start/end of macro examination
void RTFOnMacro(char *name, int no_args, Bool start)
{
char buf[300];
if (strcmp(name, "chapter") == 0 || strcmp(name, "chapter*") == 0 || strcmp(name, "myheading") == 0)
{
if (start)
{
sectionNo = 0;
figureNo = 0;
subsectionNo = 0;
subsubsectionNo = 0;
if (CurrentLabel)
{
delete[] CurrentLabel;
CurrentLabel = NULL;
}

if (winHelp)
SetCurrentOutputs(Contents, Chapters);
else
SetCurrentOutput(Contents);

fprintf(Chapters, "\\page\n");
if (!startedSections)
fprintf(Contents, "{\n\\par\n\\pard\\b\\fs%d Contents}\\par\\par\\pard\n\n",
chapterFont*2);

if (winHelp)
fprintf(Contents, "\n{\\uldb ");
else if (strcmp(name, "chapter*") != 0 && strcmp(name, "myheading") != 0)
{
chapterNo ++;
fprintf(Contents, "\\par\n\\pard{\\b %d\\tab ", chapterNo);
}
else SetCurrentOutput(NULL);

startedSections = TRUE;

if (winHelp)
fprintf(Chapters, "\n${\\footnote ");
}
else
{
char *topicName = FindTopicName(GetNextChunk());

if (!winHelp)
AddTexRef(topicName, NULL, "chapter", chapterNo);

if (winHelp)
fprintf(Contents, "}{\\v %s}\\par\\pard\n", topicName);
else if (strcmp(name, "chapter*") != 0 && strcmp(name, "myheading") != 0)
fprintf(Contents, "}\\par\\par\\pard\n");

SetCurrentOutput(Chapters);

if (winHelp)
{
fprintf(Chapters, "}\n#{\\footnote %s}\n", topicName);
fprintf(Chapters, "+{\\footnote b}\n");
fprintf(Chapters, "K{\\footnote ");
TraverseChildrenFromChunk(currentSection);
fprintf(Chapters, "}\n");
}

fprintf(Chapters, "\\pard{%s\\b\\fs%d ", (winHelp ? "\\keepn" : ""), chapterFont*2);
if (!winHelp)
{
if (strcmp(name, "chapter*") != 0)

fprintf(Chapters, "Chapter %d\\par\\par\n", chapterNo);
}
TraverseChildrenFromChunk(currentSection);
TexOutput("}\n");
// if (winHelp) TexOutput("\\pard");
}
}
else if (strcmp(name, "section") == 0 || strcmp(name, "section*") == 0 ||
strcmp(name, "gloss") == 0 || strcmp(name, "problem") == 0)
{
FILE *jumpFrom;
if (DocumentStyle == LATEX_ARTICLE)
jumpFrom = Contents;
else
jumpFrom = Chapters;

if (start)
{
subsectionNo = 0;
subsubsectionNo = 0;

if (CurrentLabel)
{
delete[] CurrentLabel;
CurrentLabel = NULL;
}
if (winHelp)
{
SetCurrentOutputs(jumpFrom, Sections);
// Newline for a new section if this is an article
if ((DocumentStyle == LATEX_ARTICLE) && (strcmp(name, "section") == 0 || strcmp(name, "section*") == 0))
fprintf(Sections, "\\page\n");
}
else
SetCurrentOutput(Contents);


if (!startedSections) // Might be an article, with no Chapters
fprintf(Contents, "{\n\\par\n\\pard\\b\\fs%d Contents}\\par\\par\\pard\n\n",
sectionFont*2);

if (winHelp)
fprintf(jumpFrom, "\n{\\uldb ");
else if (strcmp(name, "section*") != 0)
{
sectionNo ++;

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 SetCurrentOutput(NULL);

if (startedSections)
{
if (winHelp)
fprintf(Sections, "\\page\n");
}

startedSections = TRUE;

if (winHelp)
fprintf(Sections, "\n${\\footnote ");
}
else
{
char *topicName = FindTopicName(GetNextChunk());
if (!winHelp)
AddTexRef(topicName, NULL, "section", chapterNo, sectionNo);

if (winHelp)
fprintf(jumpFrom, "}{\\v %s}\\par\\pard\n", topicName);
else if (strcmp(name, "section*") != 0)
{
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 b}\n");
fprintf(Sections, "K{\\footnote ");
TraverseChildrenFromChunk(currentSection);
fprintf(Sections, "}\n");
}

fprintf(winHelp ? Sections : Chapters, "\\pard{%s\\b\\fs%d ", (winHelp ? "\\keepn" : ""),
sectionFont*2);
if (!winHelp)
{
if (strcmp(name, "section*") != 0)
{
if (DocumentStyle == LATEX_REPORT)
fprintf(Chapters, "%d.%d. ", chapterNo, sectionNo);
else
fprintf(Chapters, "%d. ", sectionNo);
}
}
TraverseChildrenFromChunk(currentSection);
TexOutput("}\n");
// if (winHelp) TexOutput("\\pard");
}
}
// Write references title as if it were a chapter or section
else if (strcmp(name, "references") == 0)
{
FILE *jumpTo;
if (DocumentStyle == LATEX_ARTICLE)
jumpTo = Sections;
else
jumpTo = Chapters;

if (start)
{
if (winHelp)
{
SetCurrentOutputs(Contents, jumpTo);

// Newline for a new section if this is an article
if ((DocumentStyle == LATEX_ARTICLE) && (strcmp(name, "section") == 0 || strcmp(name, "section*") == 0))
fprintf(Sections, "\\page\n");
}
else
SetCurrentOutput(Contents);

if (!startedSections) // Might be an article, with no Chapters
fprintf(Contents, "{\n\\par\n\\pard\\b\\fs%d Contents}\\par\\par\\pard\n\n",
sectionFont*2);

if (winHelp)
fprintf(Contents, "\n{\\uldb References}");
else
{
fprintf(Contents, "\n\\par\\pard{\\b References}\\par\\par\\pard");
}

if (startedSections && winHelp)
fprintf(jumpTo, "\\page\n");

startedSections = TRUE;

if (winHelp)
fprintf(jumpTo, "\n${\\footnote References}");

char *topicName = "references";
if (!winHelp)
AddTexRef(topicName, NULL, "chapter", chapterNo);

if (winHelp)
fprintf(Contents, "{\\v %s}\\par\\pard\n", topicName);

SetCurrentOutput(jumpTo);

if (winHelp)
{
fprintf(jumpTo, "\n#{\\footnote %s}\n", topicName);
fprintf(jumpTo, "+{\\footnote b}\n");
fprintf(jumpTo, "K{\\footnote references}\n");
}

fprintf(jumpTo, "\\pard{%s\\b\\fs%d References}", (winHelp ? "\\keepn" : ""),
sectionFont*2);
TexOutput("\\par\\pard\\par\\par");
WriteEnvironmentStyles();
}
}
else if (strcmp(name, "subsection") == 0 || strcmp(name, "subsection*") == 0 ||
strcmp(name, "membersection") == 0 || strcmp(name, "functionsection") == 0)
{
if (start)
{
subsubsectionNo = 0;

if (CurrentLabel)
{
delete[] CurrentLabel;
CurrentLabel = NULL;
}

if (winHelp)
SetCurrentOutputs(Sections, Subsections);
else
SetCurrentOutput(Contents);

if (winHelp)
{
SetCurrentOutputs(Sections, Subsections);
fprintf(Sections, "\n{\\uldb ");
}
else if (strcmp(name, "subsection*") != 0 && strcmp(name, "membersection") != 0 &&
strcmp(name, "functionsection") != 0)
{
subsectionNo ++;

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)
fprintf(Subsections, "\\page\n");
else
fprintf(Chapters, "\\par\n");
}
startedSections = TRUE;

if (winHelp)
fprintf(Subsections, "\n${\\footnote ");
}
else
{
char *topicName = FindTopicName(GetNextChunk());

if (!winHelp)
AddTexRef(topicName, NULL, "section", chapterNo, sectionNo, subsectionNo);

if (winHelp)
fprintf(Sections, "}{\\v %s}\\par\\pard\n", topicName);
else if (strcmp(name, "subsection*") != 0 && strcmp(name, "membersection") != 0 &&
strcmp(name, "functionsection") != 0)
fprintf(Contents, "\\par\\pard\n");

SetCurrentOutput(winHelp ? Subsections : Chapters);
if (winHelp)
{
fprintf(Subsections, "}\n#{\\footnote %s}\n", topicName);
fprintf(Subsections, "+{\\footnote c}\n");
}

fprintf(winHelp ? Subsections : Chapters, "\\pard{\\b\\fs%d ", subsectionFont*2);
if (!winHelp &&
(strcmp(name, "subsection*") != 0 && strcmp(name, "membersection") != 0 &&
strcmp(name, "functionsection") != 0))
{
if (DocumentStyle == LATEX_REPORT)
fprintf(Chapters, "%d.%d.%d. ", chapterNo, sectionNo, subsectionNo);
else
fprintf(Chapters, "%d.%d. ", sectionNo, subsectionNo);
}
TraverseChildrenFromChunk(currentSection); // Repeat section header
TexOutput("}\n");
// if (winHelp) TexOutput("\\pard");
}
}
else if (strcmp(name, "subsubsection") == 0)
{
if (start)
{
if (CurrentLabel)
{
delete[] CurrentLabel;
CurrentLabel = NULL;
}

if (winHelp)
{
SetCurrentOutputs(Subsections, Subsubsections);
fprintf(Subsections, "\n{\\uldb ");
}
else if (strcmp(name, "subsubsection*") != 0)
{
subsubsectionNo ++;
if (DocumentStyle == LATEX_ARTICLE)
{
SetCurrentOutput(Contents);
fprintf(Contents, "\n\\tab\\tab %d.%d.%d\\tab ",
sectionNo, subsectionNo, subsubsectionNo);
}
}
else
SetCurrentOutput(NULL);

if (startedSections)
{
if (winHelp)
fprintf(Subsubsections, "\\page\n");
else
fprintf(Chapters, "\\par\n");
}

startedSections = TRUE;

if (winHelp)
fprintf(Subsubsections, "\n${\\footnote ");
}
else
{
char *topicName = FindTopicName(GetNextChunk());

if (!winHelp)
AddTexRef(topicName, NULL, "section", chapterNo, sectionNo, subsectionNo, subsubsectionNo);

if (winHelp)
fprintf(Subsections, "}{\\v %s}\\par\\pard\n", topicName);
else if ((DocumentStyle == LATEX_ARTICLE) && strcmp(name, "subsubsection*") != 0)
fprintf(Contents, "\\par\\pard\n");

SetCurrentOutput(winHelp ? Subsubsections : Chapters);
if (winHelp)
{
fprintf(Subsubsections, "}\n#{\\footnote %s}\n", topicName);
fprintf(Subsubsections, "+{\\footnote c}\n");
}

fprintf(winHelp ? Subsubsections : Chapters, "\\pard{\\b\\fs%d ", subsectionFont*2);
if (!winHelp && (DocumentStyle == LATEX_ARTICLE))
fprintf(Chapters, "%d.%d.%d. ", sectionNo, subsectionNo, subsubsectionNo);

TraverseChildrenFromChunk(currentSection); // Repeat section header
TexOutput("}\n");
// if (winHelp) TexOutput("\\pard");
}
}
else if (strcmp(name, "caption") == 0 || strcmp(name, "caption*") == 0)
{
if (start)
{
figureNo ++;

if (CurrentLabel)
{
delete[] CurrentLabel;
CurrentLabel = NULL;
}

char figBuf[40];
if (DocumentStyle != LATEX_ARTICLE)
sprintf(figBuf, "Figure %d.%d: ", chapterNo, figureNo);
else
sprintf(figBuf, "Figure %d: ", figureNo);

TexOutput("\\pard\\qc{\\b ");
TexOutput(figBuf);
}
else
{
TexOutput("}\\par\\pard\n");
WriteEnvironmentStyles();

char *topicName = FindTopicName(GetNextChunk());

if (!winHelp)
AddTexRef(topicName, NULL, "figure",
((DocumentStyle != LATEX_ARTICLE) ? chapterNo : figureNo),
((DocumentStyle != LATEX_ARTICLE) ? figureNo : 0));
}
}
else if ((strcmp(name, "func") == 0) || (strcmp(name, "pfunc") == 0))
{
SetCurrentOutput(winHelp ? Subsections : Chapters);
if (start)
{
TexOutput("{");
}
else
{
TexOutput("}\n");
if (winHelp)
{
fprintf(Subsections, "K{\\footnote ");
suppressNameDecoration = TRUE;
TraverseChildrenFromChunk(currentMember);
suppressNameDecoration = FALSE;
fprintf(Subsections, "}\n");
}
}
}
else if (strcmp(name, "clipsfunc") == 0)
{
SetCurrentOutput(winHelp ? Subsections : Chapters);
if (start)
{
TexOutput("{");
}
else
{
TexOutput("}\n");
if (winHelp)
{
fprintf(Subsections, "K{\\footnote ");
suppressNameDecoration = TRUE; // Necessary so don't print "(\\bf" etc.
TraverseChildrenFromChunk(currentMember);
suppressNameDecoration = FALSE;
fprintf(Subsections, "}\n");
}
}
}
else if (strcmp(name, "member") == 0)
{
SetCurrentOutput(winHelp ? Subsections : Chapters);
if (start)
{
TexOutput("{\\b ");
}
else
{
TexOutput("}\n");
if (winHelp)
{
fprintf(Subsections, "K{\\footnote ");
TraverseChildrenFromChunk(currentMember);
fprintf(Subsections, "}\n");
}
}
}
else if (strcmp(name, "document") == 0)
{
if (start)
SetCurrentOutput(Chapters);
}
else if (strcmp(name, "tableofcontents") == 0)
{
if (start)
{
// fprintf(Contents, "{\n\\par\\par\\par\n\\b\\fs%d Contents}\\par\\par\\pard\n\n",
// (isReport ? chapterFont : sectionFont) * 2);

FILE *fd = fopen(ContentsName, "r");
if (fd)
{
char 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.");
}
}
}
else if ((strcmp(name, "void") == 0) && start)
TexOutput("{\\b void}");
else if ((strcmp(name, "hardy") == 0) && start)
TexOutput("{\\scaps HARDY}");
else if ((strcmp(name, "wxclips") == 0) && start)
TexOutput("wxCLIPS");
else if ((strcmp(name, "_&") == 0) && start)
{
if (inTable)
TexOutput("\\tab\n");
else
TexOutput("&");
}
else if ((strcmp(name, "\\") == 0) && start)
{
if (inTable)
// TexOutput("\\cell\n\\row\\pard\n\\intbl\n");
{
if (tableVerticalLineLeft)
TexOutput("\\brdrl\\brdrs");
if (tableVerticalLineRight)
TexOutput("\\brdrr\\brdrs");

TexOutput("\\par\\pard\n");

// Calculate a rough size for each column
int colSize = 6000/(noColumns-1);
int colPos = colSize;
for (int j = 0; j < noColumns; j++)
{
sprintf(buf, "\\tx%d", colPos);
TexOutput(buf);
colPos += colSize;
}
TexOutput("\n");
}
else
TexOutput("\\line\n");
}
else if ((strcmp(name, ">") == 0) && start)
{
TexOutput("\tab ");
}
else if ((strcmp(name, "rtfsp") == 0) && start) // Explicit space, RTF only
TexOutput(" ");
else if ((strcmp(name, "itemize") == 0) ||
(strcmp(name, "enumerate") == 0) ||
(strcmp(name, "description") == 0))
{
if (start)
{
// tabCount ++;

if (indentLevel > 0)
TexOutput("\\par\\par\n");
indentLevel ++;
TexOutput("\\fi0\n");
int listType;
if (strcmp(name, "enumerate") == 0)

listType = LATEX_ENUMERATE;
else if (strcmp(name, "itemize") == 0)
listType = LATEX_ITEMIZE;
else
listType = LATEX_DESCRIPTION;
itemizeStack.Insert(new ItemizeStruc(listType));

int indentSize = (int)(indentLevel*360);
sprintf(buf, "\\tx%d\\li%d", indentSize, indentSize);
PushEnvironmentStyle(buf);
}
else
{
indentLevel --;
// tabCount --;
PopEnvironmentStyle();

if (indentLevel == 0)
{
TexOutput("\\par\\pard\n");
WriteEnvironmentStyles();
}
if (itemizeStack.First())
{
ItemizeStruc *struc = (ItemizeStruc *)itemizeStack.First()->Data();
delete struc;
delete itemizeStack.First();
}
}
}
else if (strcmp(name, "item") == 0)
{
wxNode *node = itemizeStack.First();
if (node)
{
ItemizeStruc *struc = (ItemizeStruc *)node->Data();
if (!start)
{
struc->currentItem += 1;
char indentBuf[30];

int indentSize = (int)(indentLevel*360);

TexOutput("\n");
if (struc->currentItem > 1)
{
TexOutput("\\par\\par");
// WriteEnvironmentStyles();
}

sprintf(buf, "\\tx%d\\li%d\\fi-360\n", indentSize, indentSize);
TexOutput(buf);

switch (struc->listType)
{
case LATEX_ENUMERATE:
{
sprintf(indentBuf, "{\\b %d.}\\tab", struc->currentItem);
TexOutput(indentBuf);
break;
}
case LATEX_ITEMIZE:
{
sprintf(indentBuf, "{\\b o}\\tab");
TexOutput(indentBuf);
break;
}
default:
case LATEX_DESCRIPTION:
{
if (descriptionItemArg)
{
TexOutput("{\\b ");
TraverseChildrenFromChunk(descriptionItemArg);
TexOutput("} ");
descriptionItemArg = NULL;

}
break;
}
}
}
}
}
else if (strcmp(name, "verbatim") == 0)
{
if (start)
{
sprintf(buf, "\\pard{\\f3\\fs16 ");
TexOutput(buf);
}
else
{
TexOutput("}\\par\\pard\n");
WriteEnvironmentStyles();
}
}
else if (strcmp(name, "centerline") == 0 || strcmp(name, "center") == 0)
{
if (start)
{
TexOutput("\\fi0\\qc ");
forbidParindent ++;
PushEnvironmentStyle("\\qc");
}
else
{
TexOutput("\\par\\pard\n");
forbidParindent --;
PopEnvironmentStyle();
WriteEnvironmentStyles();
}
}
else if (strcmp(name, "flushleft") == 0)
{
if (start)
{
TexOutput("\\fi0\\ql ");
forbidParindent ++;
PushEnvironmentStyle("\\ql");
}
else
{
TexOutput("\\par\\pard\n");
forbidParindent --;
PopEnvironmentStyle();
WriteEnvironmentStyles();
}
}
else if (strcmp(name, "flushright") == 0)
{
if (start)
{
TexOutput("\\fi0\\qr ");
forbidParindent ++;
PushEnvironmentStyle("\\qr");
}
else
{
TexOutput("\\par\\pard\n");
forbidParindent --;
PopEnvironmentStyle();
WriteEnvironmentStyles();
}
}
else if (strcmp(name, "small") == 0)
{
if (start)
{
sprintf(buf, "{\\fs%d\n", smallFont*2);
TexOutput(buf);
}
else TexOutput("}\n");
}
else if (strcmp(name, "tiny") == 0)
{
if (start)
{
sprintf(buf, "{\\fs%d\n", tinyFont*2);
TexOutput(buf);
}
else TexOutput("}\n");
}
else if (strcmp(name, "normalsize") == 0)
{
if (start)
{
sprintf(buf, "{\\fs%d\n", normalFont*2);
TexOutput(buf);
}
else TexOutput("}\n");
}
else if (strcmp(name, "large") == 0)
{
if (start)
{
sprintf(buf, "{\\fs%d\n", largeFont1*2);
TexOutput(buf);
}
else TexOutput("}\n");
}
else if (strcmp(name, "Large") == 0)
{
if (start)
{
sprintf(buf, "{\\fs%d\n", LargeFont2*2);
TexOutput(buf);
}
else TexOutput("}\n");
}
else if (strcmp(name, "LARGE") == 0)
{
if (start)
{
sprintf(buf, "{\\fs%d\n", LARGEFont3*2);
TexOutput(buf);
}
else TexOutput("}\n");
}
else if (strcmp(name, "huge") == 0)
{
if (start)
{
sprintf(buf, "{\\fs%d\n", hugeFont1*2);
TexOutput(buf);
}
else TexOutput("}\n");
}
else if (strcmp(name, "Huge") == 0)
{
if (start)
{
sprintf(buf, "{\\fs%d\n", HugeFont2*2);
TexOutput(buf);
}
else TexOutput("}\n");
}
else if (strcmp(name, "HUGE") == 0)
{
if (start)
{
sprintf(buf, "{\\fs%d\n", HUGEFont3*2);
TexOutput(buf);
}
else TexOutput("}\n");
}
else if (strcmp(name, "bf") == 0)
{
if (start)
{
TexOutput("{\\b ");
}
else TexOutput("}");
}
else if (strcmp(name, "underline") == 0)
{
if (start)
{
TexOutput("{\\ul ");
}
else TexOutput("}");
}
else if (strcmp(name, "it") == 0 || strcmp(name, "em") == 0)
{
if (start)
{
TexOutput("{\\i ");
}
else TexOutput("}");
}
else if (strcmp(name, "rm") == 0)
{
/*
if (start)
{
TexOutput("{\\plain ");
}
else TexOutput("}");
*/
}
else if (strcmp(name, "sc") == 0)
{
if (start)
{
TexOutput("{\\scaps ");
}
else TexOutput("}");
}
else if (strcmp(name, "tt") == 0)
{
if (start)
{
TexOutput("{\\f3 ");
}
else TexOutput("}");
}
else if ((strcmp(name, "{") == 0) && start)
TexOutput("\\{");
else if ((strcmp(name, "}") == 0) && start)
TexOutput("\\}");
else if ((strcmp(name, "backslash") == 0) && start)
TexOutput("\\\\");
else if (strcmp(name, "par") == 0)
{
if (start)
{
TexOutput("\\par");

TexOutput("\\pard\n");

// Extra par if parskip is more than zero (usually looks best.)
if (!inTable && (ParSkip > 0))
TexOutput("\\par");

if (!inTable && (ParIndent > 0) && (forbidParindent == 0))
{
sprintf(buf, "\\fi%d ", ParIndent*20);
TexOutput(buf);
}

// Ought to tab if we're in a list or tab count is > 0
if (tabCount > 0)
TexOutput("\\tab");
WriteEnvironmentStyles();
TexOutput("\n");
}
}
else if (strcmp(name, "newpage") == 0)
{
// In Windows Help, no newpages until we've started some chapters or sections!
if (!(winHelp && !startedSections))
if (start)
TexOutput("\\page\n");
}
else if (strcmp(name, "maketitle") == 0)
{
if (start && DocumentTitle && DocumentAuthor)
{
TexOutput("\\pard\\par\\par\\qc{\\fs36\\b ");
TraverseChildrenFromChunk(DocumentTitle);
TexOutput("}\\par\\par\\par\\pard\n\\qc{\\fs32 ");
TraverseChildrenFromChunk(DocumentAuthor);
TexOutput("}\\par\\par\\pard\n");
if (DocumentDate)
{
TexOutput("\\qc{\\fs32 ");
TraverseChildrenFromChunk(DocumentDate);
TexOutput("}\\par\\pard\n");
}
}
}
else if ((strcmp(name, "addcontentsline") == 0) && !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);
}
}
}
else if (strcmp(name, "hrule") == 0)
{
if (start)
{
TexOutput("\\brdrb\\brdrs\\par\\pard\n");
WriteEnvironmentStyles();
}
}
else if (strcmp(name, "hline") == 0)
{
if (start)
{
TexOutput("\\brdrt\\brdrs\n");
WriteEnvironmentStyles();
}
}
else if (strcmp(name, "bibitem") == 0)
{
if (start)
TexOutput("\\li260\\fi-260 "); // Indent from 2nd line
else
TexOutput("\\par\\pard\\par\n\n");
}
else DefaultOnMacro(name, no_args, start);
}

// Called on start/end of argument examination
Bool RTFOnArgument(char *macro_name, int arg_no, Bool start)
{
char buf[300];
if ((strcmp(macro_name, "chapter") == 0) ||
(strcmp(macro_name, "chapter*") == 0) ||
(strcmp(macro_name, "myheading") == 0) ||
(strcmp(macro_name, "section") == 0) ||
(strcmp(macro_name, "section*") == 0) ||
(strcmp(macro_name, "subsection") == 0) ||
(strcmp(macro_name, "subsection*") == 0) ||
(strcmp(macro_name, "subsubsection") == 0) ||
(strcmp(macro_name, "subsubsection*") == 0) ||
(strcmp(macro_name, "gloss") == 0) ||
(strcmp(macro_name, "membersection") == 0) ||
(strcmp(macro_name, "functionsection") == 0))
{
if (!start && (arg_no == 1))
currentSection = GetArgChunk();
}
else if (strcmp(macro_name, "func") == 0)
{
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("(");
if (!start && (arg_no == 3))
{
TexOutput(")\\li0\\fi0");
WriteEnvironmentStyles();
}
}
else if (strcmp(macro_name, "clipsfunc") == 0)
{
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();
}
}
else if (strcmp(macro_name, "pfunc") == 0)
{
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();
}
}
else if (strcmp(macro_name, "param") == 0)
{
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("}");
}
}
else if (strcmp(macro_name, "cparam") == 0)
{
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("}");
}
}
else if (strcmp(macro_name, "member") == 0)
{
if (!start && (arg_no == 1))
TexOutput(" ");

if (start && (arg_no == 2))
currentMember = GetArgChunk();
}
else if (strcmp(macro_name, "helpref") == 0 || strcmp(macro_name, "helprefn") == 0)
{
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 ");
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 bold plus
// the section/figure number.
if (start)
TexOutput("{\\b ");
else
TexOutput("}");
return TRUE;
}
else if ((GetNoArgs() - arg_no) == 0) // Arg = 2, or 3 if first is optional
{
if (strcmp(macro_name, "helprefn") != 0)
{
if (start)
{
TexOutput(" (");
char *refName = GetArgData();
if (refName)
{
wxNode *node = TexReferences.Find(refName);
if (node)
{
TexRef *texRef = (TexRef *)node->Data();
TexOutput(texRef->sectionNumber);
}
else
{
TexOutput("??");
sprintf(buf, "Warning: unresolved reference %s.", refName);
OnInform(buf);
}
}
else TexOutput("??");
}
else TexOutput(")");
}
return FALSE;
}
}
}
else if (strcmp(macro_name, "addcontentsline") == 0)
{
if (start && !winHelp)
{
if (arg_no == 2)
contentsLineSection = copystring(GetArgData());
else if (arg_no == 3)
contentsLineValue = copystring(GetArgData());
return FALSE;
}
else return FALSE;
}
else if (strcmp(macro_name, "image") == 0 || strcmp(macro_name, "psboxto") == 0)
{
if (start && (arg_no == 2 || !IsArgOptional()))
{
char *filename = copystring(GetArgData());
strcpy(buf, filename);
StripExtension(buf);
strcat(buf, ".bmp");
char *f = TexPathList.FindValidPath(buf);
if (f)
{
FILE *fd = fopen(f, "r");
if (OutputBitmapHeader(fd, winHelp))
OutputBitmapData(fd);
}
else
{
TexOutput("(Insert image file ");
TexOutput(filename);
TexOutput(")\n");
sprintf(buf, "Warning: could not find a BMP equivalent for %s.", filename);
OnInform(buf);
}
return FALSE;
}
else
return FALSE;
}
else if (strcmp(macro_name, "tabular") == 0 || strcmp(macro_name, "supertabular") == 0)
{
if (arg_no == 1)
{
if (start)
{
inTable = TRUE;
startRows = 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 colSize = 6000/(noColumns-1);
int colPos = colSize;
for (int j = 0; j < noColumns; j++)
{
sprintf(buf, "\\tx%d ", colPos);
TexOutput(buf);
colPos += colSize;
}

/*
// Calculate a rough size for each column
int colSize = 6000/(noColumns-1);
int colPos = colSize;
for (int j = 0; j < noColumns; j++)
{
sprintf(buf, "%d", colPos);
TexOutput("\\colx"); TexOutput(buf);
colPos += colSize;
}
TexOutput("\\brdrb\\brdrs\n\\intbl\n");
*/
return FALSE;
}
}
else if (arg_no == 2 && !start)
{
TexOutput("\\par\\pard\n");
WriteEnvironmentStyles();
inTable = FALSE;
}
}
else if (strcmp(macro_name, "quote") == 0 || strcmp(macro_name, "verse") == 0)
{
if (start)
{
TexOutput("\\li360\n");
forbidParindent ++;
PushEnvironmentStyle("\\li360");
}
else
{
TexOutput("\\par\\pard\n");
forbidParindent --;
PopEnvironmentStyle();
WriteEnvironmentStyles();
}
}
else if (strcmp(macro_name, "quotation") == 0)
{
if (start)
{
TexOutput("\\li360\n");
PushEnvironmentStyle("\\li360");
}
else
{
TexOutput("\\par\\pard\n");
PopEnvironmentStyle();
WriteEnvironmentStyles();
}
}
else if (strcmp(macro_name, "boxit") == 0 || strcmp(macro_name, "framebox") == 0 ||
strcmp(macro_name, "fbox") == 0 || strcmp(macro_name, "mbox") == 0)
{
if (start)
{
TexOutput("\\box\n");
PushEnvironmentStyle("\\box");
}
else
{
TexOutput("\\par\\pard\n");
PopEnvironmentStyle();
WriteEnvironmentStyles();
}
}
else if (strcmp(macro_name, "helpfontsize") == 0)
{
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;
}
}
else if (strcmp(macro_name, "helpfontfamily") == 0)
{
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;
}
}
else if (strcmp(macro_name, "parindent") == 0)
{
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;
}
}
else if (strcmp(macro_name, "item") == 0)
{
if (start && IsArgOptional())
{
descriptionItemArg = GetArgChunk();
return FALSE;
}
}
else return DefaultOnArgument(macro_name, arg_no, start);
return TRUE;
}

Bool RTFGo(void)
{
// Reset variables
tabCount = 0;
indentLevel = 0;
forbidParindent = 0;
contentsLineSection = NULL;
contentsLineValue = NULL;
descriptionItemArg = NULL;
inTable = FALSE;
startRows = FALSE;
tableVerticalLineLeft = FALSE;
tableVerticalLineRight = FALSE;
noColumns = 0;
startedSections = FALSE;
inVerbatim = FALSE;

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");
}

WriteRTFHeader(Chapters);

// By default, Swiss, 10 point.
fprintf(Chapters, "\\f2\\fs20\n");

/*
fprintf(Contents, "#{\\footnote contents}\n${\\footnote %s}\n",
contentsString ? contentsString : "WXHELPCONTENTS");
fprintf(Contents, "K{\\footnote Contents}\n+{\\footnote a}\n");
fprintf(Contents, "{\\b\\fs%d %s\\sa240\\par\\pard}\n", LARGEFont3*2,
contentsString ? contentsString : "WXHELPCONTENTS");
*/
SetCurrentOutput(Chapters);

OnInform("Converting...");
TraverseDocument();

if (winHelp)
{
// fprintf(Contents, "\\page\n");
fprintf(Chapters, "\\page\n");
fprintf(Sections, "\\page\n");
fprintf(Subsections, "\\page\n");
fprintf(Subsubsections, "\\page\n}\n");
}

/*
TexOutput("\n\\info{\\doccomm Document created by Julian Smart's Tex2RTF.}\n");
if (DocumentTitle)
{
TexOutput("{\\title ");
TraverseChildrenFromChunk(DocumentTitle);
TexOutput("}\n");
}
if (DocumentAuthor)
{
TexOutput("{\\author ");
TraverseChildrenFromChunk(DocumentAuthor);
TexOutput("}\n");
}
*/
if (!winHelp)
TexOutput("}\n");

fclose(Contents);
fclose(Chapters);
if (winHelp)
{
fclose(Sections);
fclose(Subsections);
fclose(Subsubsections);
}

if (winHelp)
{
wxConcatFiles("chapters.rtf", "sections.rtf", "tmp1.rtf");
wxConcatFiles("tmp1.rtf", "subsections.rtf", "tmp2.rtf");
wxConcatFiles("tmp2.rtf", "subsubsections.rtf", OutputFile);

wxRemoveFile("tmp1.rtf");
wxRemoveFile("tmp2.rtf");
}
else
{
if (FileExists(OutputFile)) wxRemoveFile(OutputFile);
wxCopyFile("chapters.rtf", OutputFile);
}

if (FileExists(ContentsName)) wxRemoveFile(ContentsName);
wxRenameFile(TmpContentsName, ContentsName);

wxRemoveFile("chapters.rtf");

if (winHelp)
{
wxRemoveFile("sections.rtf");
wxRemoveFile("subsections.rtf");
wxRemoveFile("subsubsections.rtf");
}
return TRUE;
}
return FALSE;
}