X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0e6ca3948f52d439fe2940daee9dfe7cac578f1c..6d26dc89c5e7a421f4f8807728928eee91aa5f7e:/utils/tex2rtf/src/tex2any.cpp diff --git a/utils/tex2rtf/src/tex2any.cpp b/utils/tex2rtf/src/tex2any.cpp index 71ab0cf7b9..51fdab5dbd 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 @@ -122,6 +144,8 @@ char *linkColourString = NULL; char *followedLinkColourString = NULL; bool combineSubSections = FALSE; bool htmlWorkshopFiles = FALSE; +bool ignoreBadRefs = FALSE; +char *htmlFaceName = copystring("Times New Roman"); extern int passNumber; @@ -196,7 +220,8 @@ TexMacroDef *VerbatimMacroDef = NULL; #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; @@ -221,7 +246,7 @@ CustomMacro::~CustomMacro() delete [] macroBody; } -void TexOutput(char *s, bool ordinaryText) +void TexOutput(const char *s, bool ordinaryText) { int len = strlen(s); @@ -252,19 +277,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: @@ -395,10 +420,10 @@ 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 +// #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) @@ -408,7 +433,7 @@ bool read_a_line(char *buf) buf[0] = 0; return FALSE; } - + int ch = -2; int bufIndex = 0; buf[0] = 0; @@ -430,24 +455,25 @@ bool read_a_line(char *buf) 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) { @@ -496,14 +522,14 @@ bool read_a_line(char *buf) { // 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; @@ -512,21 +538,21 @@ bool read_a_line(char *buf) 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; @@ -535,13 +561,13 @@ bool read_a_line(char *buf) 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; @@ -550,8 +576,46 @@ bool read_a_line(char *buf) 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 } @@ -563,16 +627,19 @@ bool read_a_line(char *buf) 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; @@ -730,6 +797,41 @@ bool read_a_line(char *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; @@ -737,14 +839,15 @@ bool read_a_line(char *buf) 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 @@ -841,6 +944,14 @@ void MacroError(char *buffer) 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; + } } /* @@ -921,6 +1032,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) { @@ -1007,7 +1121,6 @@ int ParseArg(TexChunk *thisArg, wxList& children, char *buffer, int pos, char *e } pos ++; - // Try matching \end{environment} if (environment && FindEndEnvironment(buffer, &pos, environment)) { @@ -1032,7 +1145,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) @@ -1043,37 +1156,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) @@ -1094,7 +1207,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); } @@ -1139,8 +1252,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); @@ -1149,6 +1262,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; @@ -1237,7 +1351,7 @@ int ParseArg(TexChunk *thisArg, wxList& children, char *buffer, int pos, char *e } // delete chunk; // Might delete children - } + } } else { @@ -1245,7 +1359,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 @@ -1278,7 +1392,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 '$': @@ -1440,7 +1554,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) @@ -1505,6 +1619,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; @@ -1562,7 +1689,7 @@ bool TexLoadFile(char *filename) 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; @@ -1754,14 +1881,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); @@ -1789,7 +1918,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; @@ -1807,7 +1937,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; @@ -1832,7 +1964,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)); } @@ -3037,10 +3169,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); @@ -3199,9 +3330,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);