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)
+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
char *linkColourString = NULL;
char *followedLinkColourString = NULL;
bool combineSubSections = FALSE;
+bool htmlWorkshopFiles = FALSE;
+
+extern int passNumber;
+
+extern wxHashTable TexReferences;
/*
* International support
TexChunk *currentArgument = NULL;
TexChunk *nextChunk = NULL;
bool isArgOptional = FALSE;
-bool noArgs = 0;
+int noArgs = 0;
TexChunk *TopLevel = NULL;
// wxList MacroDefs(wxKEY_STRING);
#define IncrementLineNumber() LineNumbers[CurrentInputIndex] ++
+
+TexRef::TexRef(char *label, char *file, char *section, char *sectionN)
+{
+ refLabel = copystring(label);
+ refFile = file ? copystring(file) : (char*) NULL;
+ sectionNumber = section ? copystring(section) : copystring("??");
+ sectionName = sectionN ? copystring(sectionN) : copystring("??");
+}
+
+TexRef::~TexRef(void)
+{
+ delete [] refLabel; refLabel = NULL;
+ delete [] refFile; refFile = NULL;
+ delete [] sectionNumber; sectionNumber = NULL;
+ delete [] sectionName; sectionName = NULL;
+}
+
+
+CustomMacro::~CustomMacro()
+{
+ if (macroName)
+ delete [] macroName;
+ if (macroBody)
+ delete [] macroBody;
+}
+
void TexOutput(char *s, bool ordinaryText)
{
int len = strlen(s);
bool readingVerbatim = FALSE;
bool readInVerbatim = FALSE; // Within a verbatim, but not nec. verbatiminput
+// Switched this off because e.g. \verb${$ causes it to fail. There is no
+// detection of \verb yet.
+// #define CHECK_BRACES 1
+
+unsigned long leftCurly = 0;
+unsigned long rightCurly = 0;
+static wxString currentFileName = "";
+
bool read_a_line(char *buf)
{
if (CurrentInputIndex < 0)
buf[0] = 0;
return FALSE;
}
-
+
int ch = -2;
- int i = 0;
+ int bufIndex = 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)))
+ if (bufIndex >= MAX_LINE_BUFFER_SIZE)
+ {
+ 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);
+ OnError((char *)errBuf.c_str());
+ return FALSE;
+ }
+
+ if (((bufIndex == 14) && (strncmp(buf, "\\end{verbatim}", 14) == 0)) ||
+ ((bufIndex == 16) && (strncmp(buf, "\\end{toocomplex}", 16) == 0)))
readInVerbatim = FALSE;
ch = getc(Inputs[CurrentInputIndex]);
+
+ if (checkCurleyBraces)
+ {
+ if (ch == '{' && !readInVerbatim)
+ leftCurly++;
+ if (ch == '}' && !readInVerbatim)
+ {
+ 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 != EOF)
{
// Check for 2 consecutive newlines and replace with \par
if ((ch1 == 10) || (ch1 == 13))
{
// Eliminate newline (10) following DOS linefeed
- if (ch1 == 13) ch1 = getc(Inputs[CurrentInputIndex]);
- buf[i] = 0;
+ if (ch1 == 13)
+ ch1 = getc(Inputs[CurrentInputIndex]);
+ buf[bufIndex] = 0;
IncrementLineNumber();
// strcat(buf, "\\par\n");
// i += 6;
+ if (bufIndex+5 >= MAX_LINE_BUFFER_SIZE)
+ {
+ 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);
+ OnError((char *)errBuf.c_str());
+ return FALSE;
+ }
strcat(buf, "\\par");
- i += 5;
+ bufIndex += 5;
+
}
else
{
ungetc(ch1, Inputs[CurrentInputIndex]);
- buf[i] = ch;
- i ++;
+ if (bufIndex >= MAX_LINE_BUFFER_SIZE)
+ {
+ 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);
+ OnError((char *)errBuf.c_str());
+ return FALSE;
+ }
+
+ buf[bufIndex] = ch;
+ bufIndex ++;
}
}
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;
- }
-
- }
+ switch(ch)
+ {
+ case 0xf6: // ö
+ case 0xe4: // ü
+ case 0xfc: // ü
+ case 0xd6: // Ö
+ case 0xc4: // Ä
+ case 0xdc: // Ü
+ if (bufIndex+5 >= MAX_LINE_BUFFER_SIZE)
+ {
+ 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);
+ 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: // ß
+ if (bufIndex+5 >= MAX_LINE_BUFFER_SIZE)
+ {
+ 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);
+ OnError((char *)errBuf.c_str());
+ return FALSE;
+ }
+ buf[bufIndex++]='\\';
+ buf[bufIndex++]='s';
+ buf[bufIndex++]='s';
+ buf[bufIndex++]='\\';
+ buf[bufIndex++]='/';
+ break;
+ default:
+ if (bufIndex >= MAX_LINE_BUFFER_SIZE)
+ {
+ 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);
+ OnError((char *)errBuf.c_str());
+ return FALSE;
+ }
+ // 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 (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
+ {
+ 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
}
else
{
- buf[i] = 0;
+ buf[bufIndex] = 0;
fclose(Inputs[CurrentInputIndex]);
Inputs[CurrentInputIndex] = NULL;
- if (CurrentInputIndex > 0) ch = ' '; // No real end of file
+ if (CurrentInputIndex > 0)
+ ch = ' '; // No real end of file
CurrentInputIndex --;
+
+ if (checkCurleyBraces)
+ {
+ if (leftCurly != rightCurly)
+ {
+ 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());
+ }
+ leftCurly = 0;
+ rightCurly = 0;
+ }
+
if (readingVerbatim)
{
readingVerbatim = FALSE;
if (ch == 10)
IncrementLineNumber();
}
- buf[i] = 0;
+ buf[bufIndex] = 0;
// Strip out comment environment
if (strncmp(buf, "\\begin{comment}", 15) == 0)
int wordLen = 14;
char *fileName = buf + wordLen + 1;
- int j = i - 1;
+ int j = bufIndex - 1;
buf[j] = 0;
// thing}\par -- eliminate the \par!
buf[j] = 0;
}
- if (buf[j-1] == '}') buf[j-1] = 0; // Ignore final brace
+ if (buf[j-1] == '}')
+ buf[j-1] = 0; // Ignore final brace
wxString actualFile = TexPathList.FindValidPath(fileName);
+ currentFileName = actualFile;
if (actualFile == "")
{
- char errBuf[300];
- strcpy(errBuf, "Could not find file: ");
- strncat(errBuf, fileName, 100);
- OnError(errBuf);
+ wxString errBuf;
+ errBuf.Printf("Could not find file: %s",fileName);
+ OnError((char *)errBuf.c_str());
}
else
{
+ wxString informStr;
+ informStr.Printf("Processing: %s",actualFile.c_str());
+ OnInform((char *)informStr.c_str());
CurrentInputIndex ++;
+
Inputs[CurrentInputIndex] = fopen(actualFile, "r");
LineNumbers[CurrentInputIndex] = 1;
if (FileNames[CurrentInputIndex])
char *fileName = buf + wordLen + 1;
- int j = i - 1;
+ int j = bufIndex - 1;
buf[j] = 0;
// \input{thing}\par -- eliminate the \par!
buf[j] = 0;
}
- if (buf[j-1] == '}') buf[j-1] = 0; // Ignore final brace
+ if (buf[j-1] == '}')
+ buf[j-1] = 0; // Ignore final brace
+
+ // Remove backslashes from name
+ wxString fileNameStr(fileName);
+ fileNameStr.Replace("\\", "");
// Ignore some types of input files (e.g. macro definition files)
- char *fileOnly = FileNameFromPath(fileName);
+ char *fileOnly = FileNameFromPath((char*) (const char*) fileNameStr);
+ currentFileName = fileOnly;
if (IgnorableInputFiles.Member(fileOnly))
return read_a_line(buf);
- wxString actualFile = TexPathList.FindValidPath(fileName);
+ wxString actualFile = TexPathList.FindValidPath(fileNameStr);
if (actualFile == "")
{
char buf2[400];
- sprintf(buf2, "%s.tex", fileName);
+ sprintf(buf2, "%s.tex", (const char*) fileNameStr);
actualFile = TexPathList.FindValidPath(buf2);
}
+ currentFileName = actualFile;
+
if (actualFile == "")
{
- char errBuf[300];
- strcpy(errBuf, "Could not find file: ");
- strncat(errBuf, fileName, 100);
- OnError(errBuf);
+ wxString errBuf;
+ errBuf.Printf("Could not find file: %s",fileName);
+ OnError((char *)errBuf.c_str());
}
else
{
// then we look in the same directory as this one.
TexPathList.EnsureFileAccessible(actualFile);
+ wxString informStr;
+ informStr.Printf("Processing: %s",actualFile.c_str());
+ OnInform((char *)informStr.c_str());
CurrentInputIndex ++;
+
Inputs[CurrentInputIndex] = fopen(actualFile, "r");
LineNumbers[CurrentInputIndex] = 1;
if (FileNames[CurrentInputIndex])
if (!Inputs[CurrentInputIndex])
{
- char errBuf[300];
- sprintf(errBuf, "Could not open include file %s", (const char*) actualFile);
+ wxString errBuf;
+ errBuf.Printf("Could not open include file %s", (const char*) actualFile);
CurrentInputIndex --;
- OnError(errBuf);
+ OnError((char *)errBuf.c_str());
}
}
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], LineNumbers[CurrentInputIndex], (const char*) 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], LineNumbers[CurrentInputIndex], (const char*) 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 (checkCurleyBraces)
+ {
+ if (ch == EOF && leftCurly != rightCurly)
+ {
+ 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());
+ }
+ }
+
return (ch == EOF);
-}
+} // read_a_line
/*
* Parse newcommand
void MacroError(char *buffer)
{
- char errBuf[300];
+ wxString errBuf;
char macroBuf[200];
macroBuf[0] = '\\';
int i = 1;
if (i > 20)
macroBuf[20] = 0;
- sprintf(errBuf, "Could not find macro: %s at line %d, file %s",
+ errBuf.Printf("Could not find macro: %s at line %d, file %s",
macroBuf, (int)(LineNumbers[CurrentInputIndex]-1), FileNames[CurrentInputIndex]);
- OnError(errBuf);
+ OnError((char *)errBuf.c_str());
}
/*
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)
{
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;
}
pos ++;
-
// Try matching \end{environment}
if (environment && FindEndEnvironment(buffer, &pos, environment))
{
children.Append((wxObject *)chunk);
}
- else
- {
+ else
+ {
char *env = NULL;
bool tmpParseToBrace = TRUE;
TexMacroDef *def = MatchMacro(buffer, &pos, &env, &tmpParseToBrace);
}
// 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 '$':
bool TexLoadFile(char *filename)
{
+ static char *line_buffer;
stopRunning = FALSE;
strcpy(TexFileRoot, filename);
StripExtension(TexFileRoot);
TexPathList.EnsureFileAccessible(filename);
-#ifdef __WXMSW__
- static char *line_buffer = new char[600];
-#else
- static char *line_buffer = new char[11000];
-#endif
+ if (line_buffer)
+ delete line_buffer;
+
+ line_buffer = new char[MAX_LINE_BUFFER_SIZE];
Inputs[0] = fopen(filename, "r");
LineNumbers[0] = 1;
if (Inputs[0]) fclose(Inputs[0]);
return TRUE;
}
- else return FALSE;
+
+ return FALSE;
}
TexMacroDef::TexMacroDef(int the_id, char *the_name, int n, bool ig, bool forbidLevel)
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)
+
+ // gt - Changed this so if this is the final pass
+ // then we DO want to remove these macros, so that
+ // memory is not MASSIVELY leaked if the user
+ // does not exit the program, but instead runs
+ // the program again
+ if ((passNumber == 1 && !runTwice) ||
+ (passNumber == 2 && runTwice))
{
- CustomMacro *macro = (CustomMacro *)node->Data();
- delete macro;
- delete node;
- node = CustomMacroList.First();
+/* 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)
AddMacroDef(ltNABLA, "nabla", 0);
AddMacroDef(ltNEG, "neg", 0);
AddMacroDef(ltNEQ, "neq", 0);
- AddMacroDef(ltNEWCOUNTER, "newcounter", 1, FALSE, FORBID_ABSOLUTELY);
+ AddMacroDef(ltNEWCOUNTER, "newcounter", 1, FALSE, (bool)FORBID_ABSOLUTELY);
AddMacroDef(ltNEWLINE, "newline", 0);
AddMacroDef(ltNEWPAGE, "newpage", 0);
AddMacroDef(ltNI, "ni", 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(ltPSBOXTO, "psboxto", 1, FALSE, (bool)FORBID_ABSOLUTELY);
+ AddMacroDef(ltPSBOX, "psbox", 1, FALSE, (bool)FORBID_ABSOLUTELY);
AddMacroDef(ltPSI, "psi", 0);
AddMacroDef(ltCAP_PSI, "Psi", 0);
{
if (!ReadBib((char*) (const char*) actualFile))
{
- char buf[300];
- sprintf(buf, ".bib file %s not found or malformed", (const char*) actualFile);
- OnError(buf);
+ wxString errBuf;
+ errBuf.Printf(".bib file %s not found or malformed", (const char*) actualFile);
+ OnError((char *)errBuf.c_str());
}
}
else
{
- char buf[300];
- sprintf(buf, ".bib file %s not found", fileBuf);
- OnError(buf);
+ wxString errBuf;
+ errBuf.Printf(".bib file %s not found", fileBuf);
+ OnError((char *)errBuf.c_str());
}
bibFile = ParseMultifieldString(allFiles, &pos);
}