X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9a29912f608e082001ee53b9873323c4bcd71f21..8ac5de361e03c042736ac03fbcd8c959036ed799:/utils/tex2rtf/src/tex2any.cpp diff --git a/utils/tex2rtf/src/tex2any.cpp b/utils/tex2rtf/src/tex2any.cpp index 40e159eeae..2fcb1d64ef 100644 --- a/utils/tex2rtf/src/tex2any.cpp +++ b/utils/tex2rtf/src/tex2any.cpp @@ -72,6 +72,26 @@ int hugeFont1 = 20; 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 * @@ -88,6 +108,8 @@ bool winHelp = FALSE; // Output in Windows Help format if TRUE, line 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 @@ -107,6 +129,7 @@ int winHelpVersion = 3; // WinHelp Version (3 for Windows 3.1, 4 for 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 @@ -121,6 +144,13 @@ char *textColourString = NULL; char *linkColourString = NULL; char *followedLinkColourString = NULL; bool combineSubSections = FALSE; +bool htmlWorkshopFiles = FALSE; +bool ignoreBadRefs = FALSE; +char *htmlFaceName = copystring("Times New Roman"); + +extern int passNumber; + +extern wxHashTable TexReferences; /* * International support @@ -162,7 +192,7 @@ int tableNo = 0; FILE *CurrentOutput1 = NULL; FILE *CurrentOutput2 = NULL; FILE *Inputs[15]; -int LineNumbers[15]; +unsigned long LineNumbers[15]; char *FileNames[15]; int CurrentInputIndex = 0; @@ -178,7 +208,7 @@ bool haveArgData = FALSE; // If TRUE, we're simulating the data. TexChunk *currentArgument = NULL; TexChunk *nextChunk = NULL; bool isArgOptional = FALSE; -bool noArgs = 0; +int noArgs = 0; TexChunk *TopLevel = NULL; // wxList MacroDefs(wxKEY_STRING); @@ -190,7 +220,34 @@ TexMacroDef *VerbatimMacroDef = NULL; #define IncrementLineNumber() LineNumbers[CurrentInputIndex] ++ -void TexOutput(char *s, bool ordinaryText) + +TexRef::TexRef(const char *label, const char *file, + const char *section, const 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(const char *s, bool ordinaryText) { int len = strlen(s); @@ -221,19 +278,19 @@ void TexOutput(char *s, bool ordinaryText) 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: @@ -362,6 +419,14 @@ bool FindEndEnvironment(char *buffer, int *pos, char *env) 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 leftCurley = 0; +unsigned long rightCurley = 0; +static wxString currentFileName = ""; + bool read_a_line(char *buf) { if (CurrentInputIndex < 0) @@ -369,17 +434,48 @@ bool read_a_line(char *buf) buf[0] = 0; return FALSE; } - + int ch = -2; - int i = 0; + unsigned long 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) + 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--; + } + } + } + if (ch != EOF) { // Check for 2 consecutive newlines and replace with \par @@ -389,68 +485,162 @@ bool read_a_line(char *buf) 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 (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 } 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 (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; + } + if (readingVerbatim) { readingVerbatim = FALSE; @@ -462,7 +652,7 @@ bool read_a_line(char *buf) if (ch == 10) IncrementLineNumber(); } - buf[i] = 0; + buf[bufIndex] = 0; // Strip out comment environment if (strncmp(buf, "\\begin{comment}", 15) == 0) @@ -477,7 +667,7 @@ bool read_a_line(char *buf) int wordLen = 14; char *fileName = buf + wordLen + 1; - int j = i - 1; + int j = bufIndex - 1; buf[j] = 0; // thing}\par -- eliminate the \par! @@ -487,19 +677,24 @@ bool read_a_line(char *buf) 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]) @@ -535,7 +730,7 @@ bool read_a_line(char *buf) char *fileName = buf + wordLen + 1; - int j = i - 1; + int j = bufIndex - 1; buf[j] = 0; // \input{thing}\par -- eliminate the \par! @@ -547,26 +742,33 @@ bool read_a_line(char *buf) 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 { @@ -574,7 +776,11 @@ bool read_a_line(char *buf) // 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]) @@ -583,15 +789,50 @@ bool read_a_line(char *buf) 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].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; @@ -599,8 +840,18 @@ bool read_a_line(char *buf) strncmp(buf, "\\end{toocomplex}", 16) == 0) readInVerbatim = FALSE; + if (checkCurleyBraces) + { + 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()); + } + } + return (ch == EOF); -} +} // read_a_line /* * Parse newcommand @@ -677,7 +928,7 @@ bool ParseNewCommand(char *buffer, int *pos) void MacroError(char *buffer) { - char errBuf[300]; + wxString errBuf; char macroBuf[200]; macroBuf[0] = '\\'; int i = 1; @@ -691,9 +942,17 @@ void MacroError(char *buffer) 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()); + + if (wxStrcmp(macroBuf,"\\end{document}") == 0) + { + wxString buf; + buf = "Halted build due to unrecoverable error."; + OnInform((char *)buf.c_str()); + stopRunning = TRUE; + } } /* @@ -774,6 +1033,9 @@ int ParseArg(TexChunk *thisArg, wxList& children, char *buffer, int pos, char *e 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) { @@ -792,11 +1054,11 @@ int ParseArg(TexChunk *thisArg, wxList& children, char *buffer, int pos, char *e 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; @@ -860,7 +1122,6 @@ int ParseArg(TexChunk *thisArg, wxList& children, char *buffer, int pos, char *e } pos ++; - // Try matching \end{environment} if (environment && FindEndEnvironment(buffer, &pos, environment)) { @@ -885,7 +1146,7 @@ int ParseArg(TexChunk *thisArg, wxList& children, char *buffer, int pos, char *e pos ++; int noBraces = 1; - wxBuffer[0] = 0; + wxTex2RTFBuffer[0] = 0; int i = 0; bool end = FALSE; while (!end) @@ -896,37 +1157,37 @@ int ParseArg(TexChunk *thisArg, wxList& children, char *buffer, int pos, char *e 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) @@ -947,7 +1208,7 @@ int ParseArg(TexChunk *thisArg, wxList& children, char *buffer, int pos, char *e 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); } @@ -992,8 +1253,8 @@ int ParseArg(TexChunk *thisArg, wxList& children, char *buffer, int pos, char *e children.Append((wxObject *)chunk); } - else - { + else + { char *env = NULL; bool tmpParseToBrace = TRUE; TexMacroDef *def = MatchMacro(buffer, &pos, &env, &tmpParseToBrace); @@ -1002,6 +1263,7 @@ int ParseArg(TexChunk *thisArg, wxList& children, char *buffer, int pos, char *e 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; @@ -1090,7 +1352,7 @@ int ParseArg(TexChunk *thisArg, wxList& children, char *buffer, int pos, char *e } // delete chunk; // Might delete children - } + } } else { @@ -1098,7 +1360,7 @@ int ParseArg(TexChunk *thisArg, wxList& children, char *buffer, int pos, char *e } } else - { + { /* * If all else fails, we assume that we have * a pair of braces on their own, so return a `dummy' macro @@ -1131,7 +1393,7 @@ int ParseArg(TexChunk *thisArg, wxList& children, char *buffer, int pos, char *e arg->macroId = chunk->macroId; pos = ParseArg(arg, arg->children, buffer, pos, NULL, TRUE, customMacroArgs); - } + } break; } case '$': @@ -1293,7 +1555,7 @@ int ParseArg(TexChunk *thisArg, wxList& children, char *buffer, int pos, char *e * */ -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) @@ -1358,6 +1620,19 @@ int ParseMacroBody(char *macro_name, TexChunk *parent, 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; @@ -1387,6 +1662,7 @@ int ParseMacroBody(char *macro_name, TexChunk *parent, bool TexLoadFile(char *filename) { + static char *line_buffer; stopRunning = FALSE; strcpy(TexFileRoot, filename); StripExtension(TexFileRoot); @@ -1395,11 +1671,10 @@ bool TexLoadFile(char *filename) 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; @@ -1411,10 +1686,11 @@ bool TexLoadFile(char *filename) 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) +TexMacroDef::TexMacroDef(int the_id, const char *the_name, int n, bool ig, bool forbidLevel) { name = copystring(the_name); no_args = n; @@ -1606,14 +1882,16 @@ void TraverseFromChunk(TexChunk *chunk, wxNode *thisNode, bool childrenOnly) 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); @@ -1641,7 +1919,8 @@ void TraverseFromChunk(TexChunk *chunk, wxNode *thisNode, bool childrenOnly) 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; @@ -1659,7 +1938,9 @@ void TraverseFromChunk(TexChunk *chunk, wxNode *thisNode, bool childrenOnly) // 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; @@ -1684,7 +1965,7 @@ void SetCurrentOutputs(FILE *fd1, FILE *fd2) 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)); } @@ -1753,17 +2034,27 @@ void TexCleanUp(void) 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) @@ -2023,7 +2314,7 @@ void DefineDefaultMacros(void) 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); @@ -2076,8 +2367,8 @@ void DefineDefaultMacros(void) 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); @@ -2879,10 +3170,9 @@ bool DefaultOnArgument(int macroId, int arg_no, bool start) } 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); @@ -3041,9 +3331,9 @@ bool DefaultOnArgument(int macroId, int arg_no, bool start) 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); @@ -3185,16 +3475,16 @@ bool DefaultOnArgument(int macroId, int arg_no, bool start) { 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); }