]> git.saurik.com Git - wxWidgets.git/blobdiff - utils/tex2rtf/src/tex2any.cpp
Fix for Bug #229543
[wxWidgets.git] / utils / tex2rtf / src / tex2any.cpp
index 6bdc76b38f685ba4783a79a9e232db9182dbb3e9..71ab0cf7b970a95f97c72e45e501330e2feba7b0 100644 (file)
@@ -121,6 +121,11 @@ char            *textColourString = NULL;
 char            *linkColourString = NULL;
 char            *followedLinkColourString = NULL;
 bool            combineSubSections = FALSE;
+bool            htmlWorkshopFiles = FALSE;
+
+extern int passNumber;
+
+extern wxHashTable TexReferences;
 
 /*
  * International support
@@ -190,6 +195,32 @@ TexMacroDef *VerbatimMacroDef = NULL;
 
 #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);
@@ -362,6 +393,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 leftCurly = 0;
+unsigned long rightCurly = 0;
+static wxString currentFileName = "";
+
 bool read_a_line(char *buf)
 {
   if (CurrentInputIndex < 0)
@@ -371,15 +410,45 @@ bool read_a_line(char *buf)
   }
   
   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 CHECK_BRACES
+    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--;
+       }
+    }
+#endif
+
     if (ch != EOF)
     {
       // Check for 2 consecutive newlines and replace with \par
@@ -389,19 +458,38 @@ 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
@@ -416,41 +504,75 @@ bool read_a_line(char *buf)
                case 0xd6: // Ö
                case 0xc4: // Ä
                case 0xdc: // Ü         
-                               buf[i++]='\\';
-                               buf[i++]='"';
-                               buf[i++]='{';
+                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[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; // Ü                                      
+                                       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[i++]='}';
+                               buf[bufIndex++]='}';
                                break;
                case 0xdf: // ß 
-                       buf[i++]='\\';
-                       buf[i++]='s';
-                       buf[i++]='s';
-            buf[i++]='\\';
-            buf[i++]='/';
+            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:
-                       buf[i++] = ch;
+            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;
                        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 CHECK_BRACES
+      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;
+#endif
       if (readingVerbatim)
       {
         readingVerbatim = FALSE;
@@ -462,7 +584,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 +599,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 +609,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 +662,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 +674,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 +708,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,10 +721,10 @@ 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);
@@ -599,8 +737,17 @@ bool read_a_line(char *buf)
            strncmp(buf, "\\end{toocomplex}", 16) == 0)
     readInVerbatim = FALSE;
 
+#if CHECK_BRACES
+  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());
+  }
+#endif
+
   return (ch == EOF);
-}
+}  // read_a_line
 
 /*
  * Parse newcommand
@@ -677,7 +824,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 +838,9 @@ 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());
 }
 
 /*
@@ -792,11 +939,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;
 
@@ -1387,6 +1534,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 +1543,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,7 +1558,8 @@ 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)
@@ -1753,17 +1901,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 +2181,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 +2234,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);
 
@@ -3185,16 +3343,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);
       }