#endif
#ifndef WX_PRECOMP
-#include "wx/wx.h"
#endif
#include <ctype.h>
#include <stdlib.h>
#include <time.h>
+#if !WXWIN_COMPATIBILITY_2_4
+static inline wxChar* copystring(const wxChar* s)
+ { return wxStrcpy(new wxChar[wxStrlen(s) + 1], s); }
+#endif
+
/*
* Variables accessible from clients
*
int HugeFont2 = 24;
int HUGEFont3 = 28;
+// All of these tokens MUST be found on a line by themselves (no other
+// text) and must start at the first character of the line, or tex2rtf
+// will fail to process them correctly (a limitation of tex2rtf, not TeX)
+static const wxString syntaxTokens[] =
+{ "\\begin{verbatim}",
+ "\\begin{toocomplex}",
+ "\\end{verbatim}",
+ "\\end{toocomplex}",
+ "\\verb",
+ "\\begin{comment}",
+ "\\end{comment}",
+ "\\verbatiminput",
+// "\\par",
+ "\\input",
+ "\\helpinput",
+ "\\include",
+ wxEmptyString
+};
+
+
/*
* USER-ADJUSTABLE SETTINGS
*
bool isInteractive = FALSE;
bool runTwice = FALSE;
int convertMode = TEX_RTF;
+bool checkCurleyBraces = FALSE;
+bool checkSyntax = FALSE;
bool headerRule = FALSE;
bool footerRule = FALSE;
bool compatibilityMode = FALSE; // If TRUE, maximum Latex compatibility
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
+char *htmlStylesheet = NULL; // Use this CSS stylesheet for HTML pages
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
char *followedLinkColourString = NULL;
bool combineSubSections = FALSE;
bool htmlWorkshopFiles = FALSE;
+bool ignoreBadRefs = FALSE;
+char *htmlFaceName = NULL;
extern int passNumber;
FILE *CurrentOutput1 = NULL;
FILE *CurrentOutput2 = NULL;
FILE *Inputs[15];
-int LineNumbers[15];
+unsigned long LineNumbers[15];
char *FileNames[15];
int CurrentInputIndex = 0;
#define IncrementLineNumber() LineNumbers[CurrentInputIndex] ++
-TexRef::TexRef(char *label, char *file, char *section, char *sectionN)
+TexRef::TexRef(const char *label, const char *file,
+ const char *section, const char *sectionN)
{
refLabel = copystring(label);
refFile = file ? copystring(file) : (char*) NULL;
delete [] macroBody;
}
-void TexOutput(char *s, bool ordinaryText)
+void TexOutput(const char *s, bool ordinaryText)
{
int len = strlen(s);
void ForbidWarning(TexMacroDef *def)
{
- char buf[100];
+ wxString informBuf;
switch (def->forbidden)
{
case FORBID_WARN:
{
- sprintf(buf, "Warning: it is recommended that command %s is not used.", def->name);
- OnInform(buf);
+ informBuf.Printf("Warning: it is recommended that command %s is not used.", def->name);
+ OnInform((char *)informBuf.c_str());
break;
}
case FORBID_ABSOLUTELY:
{
- sprintf(buf, "Error: command %s cannot be used and will lead to errors.", def->name);
- OnInform(buf);
+ informBuf.Printf("Error: command %s cannot be used and will lead to errors.", def->name);
+ OnInform((char *)informBuf.c_str());
break;
}
default:
// Switched this off because e.g. \verb${$ causes it to fail. There is no
// detection of \verb yet.
-#define CHECK_BRACES 1
+// #define CHECK_BRACES 1
-unsigned long leftCurly = 0;
-unsigned long rightCurly = 0;
+unsigned long leftCurley = 0;
+unsigned long rightCurley = 0;
static wxString currentFileName = "";
bool read_a_line(char *buf)
buf[0] = 0;
return FALSE;
}
-
+
int ch = -2;
- int bufIndex = 0;
+ unsigned long bufIndex = 0;
buf[0] = 0;
while (ch != EOF && ch != 10)
{
wxString errBuf;
errBuf.Printf("Line %lu of file %s is too long. Lines can be no longer than %lu characters. Truncated.",
- LineNumbers[CurrentInputIndex], (const char*) currentFileName.c_str(),MAX_LINE_BUFFER_SIZE);
+ LineNumbers[CurrentInputIndex], (const char*) currentFileName.c_str(), MAX_LINE_BUFFER_SIZE);
OnError((char *)errBuf.c_str());
return FALSE;
}
ch = getc(Inputs[CurrentInputIndex]);
-#if CHECK_BRACES
- if (ch == '{' && !readInVerbatim)
- leftCurly++;
- if (ch == '}' && !readInVerbatim)
+ if (checkCurleyBraces)
{
- rightCurly++;
- if (rightCurly > leftCurly)
- {
- wxString errBuf;
- errBuf.Printf("An extra right curly brace ('}') was detected at line %lu inside file %s",LineNumbers[CurrentInputIndex], (const char*) currentFileName.c_str());
- OnError((char *)errBuf.c_str());
-
- // Reduce the count of right curly braces, so the mismatched count
- // isn't reported on every line that has a '}' after the first mismatch
- rightCurly--;
- }
+ if (ch == '{' && !readInVerbatim)
+ leftCurley++;
+ if (ch == '}' && !readInVerbatim)
+ {
+ rightCurley++;
+ if (rightCurley > leftCurley)
+ {
+ wxString errBuf;
+ errBuf.Printf("An extra right Curley brace ('}') was detected at line %lu inside file %s", LineNumbers[CurrentInputIndex], (const char*) currentFileName.c_str());
+ OnError((char *)errBuf.c_str());
+
+ // Reduce the count of right Curley braces, so the mismatched count
+ // isn't reported on every line that has a '}' after the first mismatch
+ rightCurley--;
+ }
+ }
}
-#endif
if (ch != EOF)
{
{
// Convert embedded characters to RTF equivalents
- switch(ch)
- {
- case 0xf6: // ö
- case 0xe4: // ü
- case 0xfc: // ü
- case 0xd6: // Ö
- case 0xc4: // Ä
- case 0xdc: // Ü
+ switch(ch)
+ {
+ case 0xf6: // ö
+ case 0xe4: // ü
+ case 0xfc: // ü
+ case 0xd6: // Ö
+ case 0xc4: // Ä
+ case 0xdc: // Ü
if (bufIndex+5 >= MAX_LINE_BUFFER_SIZE)
{
wxString errBuf;
OnError((char *)errBuf.c_str());
return FALSE;
}
- buf[bufIndex++]='\\';
- buf[bufIndex++]='"';
- buf[bufIndex++]='{';
- switch(ch)
- {
- case 0xf6:buf[bufIndex++]='o';break; // ö
- case 0xe4:buf[bufIndex++]='a';break; // ä
- case 0xfc:buf[bufIndex++]='u';break; // ü
- case 0xd6:buf[bufIndex++]='O';break; // Ö
- case 0xc4:buf[bufIndex++]='A';break; // Ä
- case 0xdc:buf[bufIndex++]='U';break; // Ü
- }
- buf[bufIndex++]='}';
- break;
- case 0xdf: // ß
+ buf[bufIndex++]='\\';
+ buf[bufIndex++]='"';
+ buf[bufIndex++]='{';
+ switch(ch)
+ {
+ case 0xf6:buf[bufIndex++]='o';break; // ö
+ case 0xe4:buf[bufIndex++]='a';break; // ä
+ case 0xfc:buf[bufIndex++]='u';break; // ü
+ case 0xd6:buf[bufIndex++]='O';break; // Ö
+ case 0xc4:buf[bufIndex++]='A';break; // Ä
+ case 0xdc:buf[bufIndex++]='U';break; // Ü
+ }
+ buf[bufIndex++]='}';
+ break;
+ case 0xdf: // ß
if (bufIndex+5 >= MAX_LINE_BUFFER_SIZE)
{
wxString errBuf;
OnError((char *)errBuf.c_str());
return FALSE;
}
- buf[bufIndex++]='\\';
- buf[bufIndex++]='s';
- buf[bufIndex++]='s';
+ buf[bufIndex++]='\\';
+ buf[bufIndex++]='s';
+ buf[bufIndex++]='s';
buf[bufIndex++]='\\';
buf[bufIndex++]='/';
- break;
- default:
+ break;
+ default:
if (bufIndex >= MAX_LINE_BUFFER_SIZE)
{
wxString errBuf;
OnError((char *)errBuf.c_str());
return FALSE;
}
- buf[bufIndex++] = ch;
- break;
+ // If the current character read in is a '_', we need to check
+ // whether there should be a '\' before it or not
+ if (ch != '_')
+ {
+ buf[bufIndex++] = ch;
+ break;
+ }
+
+ if (checkSyntax)
+ {
+ if (readInVerbatim)
+ {
+ // There should NOT be a '\' before the '_'
+ if ((bufIndex > 0 && (buf[bufIndex-1] == '\\')) && (buf[0] != '%'))
+ {
+ wxString errBuf;
+ errBuf.Printf("An underscore ('_') was detected at line %lu inside file %s that should NOT have a '\\' before it.",LineNumbers[CurrentInputIndex], (const char*) currentFileName.c_str());
+ OnError((char *)errBuf.c_str());
+ }
+ }
+ else
+ {
+ // There should be a '\' before the '_'
+ if (bufIndex == 0)
+ {
+ wxString errBuf;
+ errBuf.Printf("An underscore ('_') was detected at line %lu inside file %s that may need a '\\' before it.",LineNumbers[CurrentInputIndex], (const char*) currentFileName.c_str());
+ OnError((char *)errBuf.c_str());
+ }
+ else if ((buf[bufIndex-1] != '\\') && (buf[0] != '%') && // If it is a comment line, then no warnings
+ (strncmp(buf, "\\input", 6))) // do not report filenames that have underscores in them
+ {
+ wxString errBuf;
+ errBuf.Printf("An underscore ('_') was detected at line %lu inside file %s that may need a '\\' before it.",LineNumbers[CurrentInputIndex], (const char*) currentFileName.c_str());
+ OnError((char *)errBuf.c_str());
+ }
+ }
+ }
+ buf[bufIndex++] = ch;
+ break;
} // switch
} // else
}
if (CurrentInputIndex > 0)
ch = ' '; // No real end of file
CurrentInputIndex --;
-#if CHECK_BRACES
- if (leftCurly != rightCurly)
+
+ if (checkCurleyBraces)
{
- wxString errBuf;
- errBuf.Printf("Curly braces do not match inside file %s\n%lu opens, %lu closes", (const char*) currentFileName.c_str(),leftCurly,rightCurly);
- OnError((char *)errBuf.c_str());
+ if (leftCurley != rightCurley)
+ {
+ wxString errBuf;
+ errBuf.Printf("Curley braces do not match inside file %s\n%lu opens, %lu closes", (const char*) currentFileName.c_str(),leftCurley,rightCurley);
+ OnError((char *)errBuf.c_str());
+ }
+ leftCurley = 0;
+ rightCurley = 0;
}
- leftCurly = 0;
- rightCurly = 0;
-#endif
+
if (readingVerbatim)
{
readingVerbatim = FALSE;
fileNameStr.Replace("\\", "");
// Ignore some types of input files (e.g. macro definition files)
- char *fileOnly = FileNameFromPath((char*) (const char*) fileNameStr);
+ char *fileOnly = wxFileNameFromPath((char*) (const char*) fileNameStr);
currentFileName = fileOnly;
if (IgnorableInputFiles.Member(fileOnly))
return read_a_line(buf);
bool succ = read_a_line(buf);
return succ;
}
+
+ if (checkSyntax)
+ {
+ wxString bufStr = buf;
+ int index = 0;
+ size_t pos = 0;
+ for (index=0; syntaxTokens[index] != wxEmptyString; index++)
+ {
+ pos = bufStr.find(syntaxTokens[index]);
+ if (pos != wxString::npos && pos != 0)
+ {
+ size_t commentStart = bufStr.find("%");
+ if (commentStart == wxString::npos || commentStart > pos)
+ {
+ wxString errBuf;
+ if (syntaxTokens[index] == "\\verb")
+ {
+ errBuf.Printf("'%s$....$' was detected at line %lu inside file %s. Please replace this form with \\tt{....}",
+ syntaxTokens[index].c_str(),
+ LineNumbers[CurrentInputIndex],
+ currentFileName.c_str());
+ }
+ else
+ {
+ errBuf.Printf("'%s' was detected at line %lu inside file %s that is not the only text on the line, starting at column one.",
+ syntaxTokens[index].c_str(),
+ LineNumbers[CurrentInputIndex],
+ currentFileName.c_str());
+ }
+ OnError((char *)errBuf.c_str());
+ }
+ }
+ }
+ } // checkSyntax
+
if (strncmp(buf, "\\begin{verbatim}", 16) == 0 ||
strncmp(buf, "\\begin{toocomplex}", 18) == 0)
readInVerbatim = TRUE;
strncmp(buf, "\\end{toocomplex}", 16) == 0)
readInVerbatim = FALSE;
-#if CHECK_BRACES
- if (ch == EOF && leftCurly != rightCurly)
+ if (checkCurleyBraces)
{
- wxString errBuf;
- errBuf.Printf("Curly braces do not match inside file %s\n%lu opens, %lu closes", (const char*) currentFileName.c_str(),leftCurly,rightCurly);
- OnError((char *)errBuf.c_str());
+ if (ch == EOF && leftCurley != rightCurley)
+ {
+ wxString errBuf;
+ errBuf.Printf("Curley braces do not match inside file %s\n%lu opens, %lu closes", (const char*) currentFileName.c_str(),leftCurley,rightCurley);
+ OnError((char *)errBuf.c_str());
+ }
}
-#endif
return (ch == EOF);
} // read_a_line
errBuf.Printf("Could not find macro: %s at line %d, file %s",
macroBuf, (int)(LineNumbers[CurrentInputIndex]-1), FileNames[CurrentInputIndex]);
OnError((char *)errBuf.c_str());
+
+ if (wxStrcmp(macroBuf,"\\end{document}") == 0)
+ {
+ wxString buf;
+ buf = "Halted build due to unrecoverable error.";
+ OnInform((char *)buf.c_str());
+ stopRunning = TRUE;
+ }
}
/*
pos = 0;
len = strlen(buffer);
// Check for verbatim (or toocomplex, which comes to the same thing)
+ wxString bufStr = buffer;
+// if (bufStr.find("\\begin{verbatim}") != wxString::npos ||
+// bufStr.find("\\begin{toocomplex}") != wxString::npos)
if (strncmp(buffer, "\\begin{verbatim}", 16) == 0 ||
strncmp(buffer, "\\begin{toocomplex}", 18) == 0)
{
}
pos ++;
-
// Try matching \end{environment}
if (environment && FindEndEnvironment(buffer, &pos, environment))
{
pos ++;
int noBraces = 1;
- wxBuffer[0] = 0;
+ wxTex2RTFBuffer[0] = 0;
int i = 0;
bool end = FALSE;
while (!end)
noBraces --;
if (noBraces == 0)
{
- wxBuffer[i] = 0;
+ wxTex2RTFBuffer[i] = 0;
end = TRUE;
}
else
{
- wxBuffer[i] = '}';
+ wxTex2RTFBuffer[i] = '}';
i ++;
}
pos ++;
}
else if (ch == '{')
{
- wxBuffer[i] = '{';
+ wxTex2RTFBuffer[i] = '{';
i ++;
pos ++;
}
else if (ch == '\\' && buffer[pos+1] == '}')
{
- wxBuffer[i] = '}';
+ wxTex2RTFBuffer[i] = '}';
pos += 2;
i++;
}
else if (ch == '\\' && buffer[pos+1] == '{')
{
- wxBuffer[i] = '{';
+ wxTex2RTFBuffer[i] = '{';
pos += 2;
i++;
}
else
{
- wxBuffer[i] = ch;
+ wxTex2RTFBuffer[i] = ch;
pos ++;
i ++;
if (ch == 0)
TexChunk *argValue = new TexChunk(CHUNK_TYPE_STRING);
arg->children.Append((wxObject *)argValue);
argValue->argn = 1;
- argValue->value = copystring(wxBuffer);
+ argValue->value = copystring(wxTex2RTFBuffer);
children.Append((wxObject *)chunk);
}
children.Append((wxObject *)chunk);
}
- else
- {
+ else
+ {
char *env = NULL;
bool tmpParseToBrace = TRUE;
TexMacroDef *def = MatchMacro(buffer, &pos, &env, &tmpParseToBrace);
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;
}
// delete chunk; // Might delete children
- }
+ }
}
else
{
}
}
else
- {
+ {
/*
* If all else fails, we assume that we have
* a pair of braces on their own, so return a `dummy' macro
arg->macroId = chunk->macroId;
pos = ParseArg(arg, arg->children, buffer, pos, NULL, TRUE, customMacroArgs);
- }
+ }
break;
}
case '$':
*
*/
-int ParseMacroBody(char *macro_name, TexChunk *parent,
+int ParseMacroBody(const char *macro_name, TexChunk *parent,
int no_args, char *buffer, int pos,
char *environment, bool parseToBrace,
TexChunk *customMacroArgs)
isOptional = TRUE;
pos += 2;
}
+ else if (i > 0)
+ {
+ wxString errBuf;
+ wxString tmpBuffer(buffer);
+ if (tmpBuffer.length() > 4)
+ {
+ if (tmpBuffer.Right(4) == "\\par")
+ tmpBuffer = tmpBuffer.Mid(0,tmpBuffer.length()-4);
+ }
+ errBuf.Printf("Missing macro argument in the line:\n\t%s\n",tmpBuffer.c_str());
+ OnError((char *)errBuf.c_str());
+ }
+
}
arg->optional = isOptional;
return FALSE;
}
-TexMacroDef::TexMacroDef(int the_id, char *the_name, int n, bool ig, bool forbidLevel)
+TexMacroDef::TexMacroDef(int the_id, const char *the_name, int n, bool ig, bool forbidLevel)
{
name = copystring(the_name);
no_args = n;
OnMacro(chunk->macroId, chunk->no_args, TRUE);
wxNode *node = chunk->children.First();
+ TexChunk *child_chunk = NULL;
while (node)
{
- TexChunk *child_chunk = (TexChunk *)node->Data();
+ child_chunk = (TexChunk *)node->Data();
TraverseFromChunk(child_chunk, node);
node = node->Next();
}
- if (thisNode && thisNode->Next()) nextChunk = (TexChunk *)thisNode->Next()->Data();
+ if (thisNode && thisNode->Next())
+ nextChunk = (TexChunk *)thisNode->Next()->Data();
if (!childrenOnly)
OnMacro(chunk->macroId, chunk->no_args, FALSE);
currentArgument = chunk;
- if (thisNode && thisNode->Next()) nextChunk = (TexChunk *)thisNode->Next()->Data();
+ if (thisNode && thisNode->Next())
+ nextChunk = (TexChunk *)thisNode->Next()->Data();
isArgOptional = chunk->optional;
noArgs = chunk->no_args;
// 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;
CurrentOutput2 = fd2;
}
-void AddMacroDef(int the_id, char *name, int n, bool ignore, bool forbid)
+void AddMacroDef(int the_id, const char *name, int n, bool ignore, bool forbid)
{
MacroDefs.Put(name, new TexMacroDef(the_id, name, n, ignore, forbid));
}
}
else
{
- char buf[300];
- TexOutput("??", TRUE);
- sprintf(buf, "Warning: unresolved reference %s.", refName);
- OnInform(buf);
+ wxString informBuf;
+ informBuf.Printf("Warning: unresolved reference '%s'", refName);
+ OnInform((char *)informBuf.c_str());
}
}
else TexOutput("??", TRUE);
TexOutput(ref->sectionNumber, TRUE);
if (strcmp(ref->sectionNumber, "??") == 0)
{
- char buf[300];
- sprintf(buf, "Warning: unresolved citation %s.", citeKey);
- OnInform(buf);
+ wxString informBuf;
+ informBuf.Printf("Warning: unresolved citation %s.", citeKey);
+ OnInform((char *)informBuf.c_str());
}
}
citeKey = ParseMultifieldString(citeKeys, &pos);