1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     Miscellaneous utilities 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  13 #pragma implementation 
  16 // For compilers that support precompilation, includes "wx.h". 
  17 #include "wx/wxprec.h" 
  40 wxHashTable 
TexReferences(wxKEY_STRING
); 
  41 wxList 
BibList(wxKEY_STRING
); 
  42 wxStringList CitationList
; 
  43 wxList 
ColourTable(wxKEY_STRING
); 
  44 wxHashTable 
BibStringTable(wxKEY_STRING
); 
  45 wxList 
CustomMacroList(wxKEY_STRING
); 
  46 TexChunk 
*currentSection 
= NULL
; 
  47 char *fakeCurrentSection 
= NULL
; 
  49 static long BibLine 
= 1; 
  51 void OutputCurrentSection(void) 
  53   if (fakeCurrentSection
) 
  54     TexOutput(fakeCurrentSection
); 
  55   else if (currentSection
) 
  56     TraverseChildrenFromChunk(currentSection
); 
  59 // Nasty but the way things are done now, necessary, 
  60 // in order to output a chunk properly to a string (macros and all). 
  61 void OutputCurrentSectionToString(char *buf
) 
  63     if (fakeCurrentSection
) 
  64         strcpy(buf
, fakeCurrentSection
); 
  66         OutputChunkToString(currentSection
, buf
); 
  69 void OutputChunkToString(TexChunk 
*chunk
, char *buf
) 
  71   FILE *tempfd 
= fopen("tmp.tmp", "w"); 
  75   FILE *old1 
= CurrentOutput1
; 
  76   FILE *old2 
= CurrentOutput2
; 
  78   CurrentOutput1 
= tempfd
; 
  79   CurrentOutput2 
= NULL
; 
  81   TraverseChildrenFromChunk(chunk
); 
  83   CurrentOutput1 
= old1
; 
  84   CurrentOutput2 
= old2
; 
  88   // Read from file into string 
  89   tempfd 
= fopen("tmp.tmp", "r"); 
 108   wxRemoveFile("tmp.tmp"); 
 111 // Called by Tex2Any to simulate a section 
 112 void FakeCurrentSection(char *fakeSection
, bool addToContents
) 
 114   currentSection 
= NULL
; 
 115   if (fakeCurrentSection
) delete[] fakeCurrentSection
; 
 116   fakeCurrentSection 
= copystring(fakeSection
); 
 118   if (DocumentStyle 
== LATEX_ARTICLE
) 
 120     int mac 
= ltSECTIONHEADING
; 
 122       mac 
= ltSECTIONHEADINGSTAR
; 
 123     OnMacro(mac
, 0, TRUE
); 
 124     OnMacro(mac
, 0, FALSE
); 
 128     int mac 
= ltCHAPTERHEADING
; 
 130       mac 
= ltCHAPTERHEADINGSTAR
; 
 131     OnMacro(mac
, 0, TRUE
); 
 132     OnMacro(mac
, 0, FALSE
); 
 134   if (fakeCurrentSection
) delete[] fakeCurrentSection
; 
 135   fakeCurrentSection 
= NULL
; 
 138 // Look for \label macro, use this ref name if found or 
 139 // make up a topic name otherwise. 
 140 static long topicCounter 
= 0; 
 142 void ResetTopicCounter(void) 
 147 static char *forceTopicName 
= NULL
; 
 149 void ForceTopicName(char *name
) 
 152     delete[] forceTopicName
; 
 154     forceTopicName 
= copystring(name
); 
 156     forceTopicName 
= NULL
; 
 159 char *FindTopicName(TexChunk 
*chunk
) 
 162     return forceTopicName
; 
 164   char *topicName 
= NULL
; 
 165   static char topicBuf
[100]; 
 167   if (chunk 
&& (chunk
->type 
== CHUNK_TYPE_MACRO
) && 
 168       (chunk
->macroId 
== ltLABEL
)) 
 170     wxNode 
*node 
= chunk
->children
.First(); 
 173       TexChunk 
*child 
= (TexChunk 
*)node
->Data(); 
 174       if (child
->type 
== CHUNK_TYPE_ARG
) 
 176         wxNode 
*snode 
= child
->children
.First(); 
 179           TexChunk 
*schunk 
= (TexChunk 
*)snode
->Data(); 
 180           if (schunk
->type 
== CHUNK_TYPE_STRING
) 
 181             topicName 
= schunk
->value
; 
 190     sprintf(topicBuf
, "topic%ld", topicCounter
); 
 197  * Simulate argument data, so we can 'drive' clients which implement 
 198  * certain basic formatting behaviour. 
 199  * Snag is that some save a TexChunk, so don't use yet... 
 203 void StartSimulateArgument(char *data
) 
 205   strcpy(currentArgData
, data
); 
 209 void EndSimulateArgument(void) 
 215  * Parse and convert unit arguments to points 
 219 int ParseUnitArgument(char *unitArg
) 
 221   float conversionFactor 
= 1.0; 
 222   float unitValue 
= 0.0; 
 223   int len 
= strlen(unitArg
); 
 224   // Get rid of any accidentally embedded commands 
 225   for (int i 
= 0; i 
< len
; i
++) 
 226     if (unitArg
[i
] == '\\') 
 228   len 
= strlen(unitArg
); 
 230   if (unitArg 
&& (len 
> 0) && (isdigit(unitArg
[0]) || unitArg
[0] == '-')) 
 232     sscanf(unitArg
, "%f", &unitValue
); 
 236       units
[0] = unitArg
[len
-2]; 
 237       units
[1] = unitArg
[len
-1]; 
 239       if (strcmp(units
, "in") == 0) 
 240         conversionFactor 
= 72.0; 
 241       else if (strcmp(units
, "cm") == 0) 
 242         conversionFactor 
= 72.0/2.51; 
 243       else if (strcmp(units
, "mm") == 0) 
 244         conversionFactor 
= 72.0/25.1; 
 245       else if (strcmp(units
, "pt") == 0) 
 246         conversionFactor 
= 1; 
 248     return (int)(unitValue
*conversionFactor
); 
 254  * Strip off any extension (dot something) from end of file, 
 255  * IF one exists. Inserts zero into buffer. 
 259 void StripExtension(char *buffer
) 
 261   int len 
= strlen(buffer
); 
 265     if (buffer
[i
] == '.') 
 279 void SetFontSizes(int pointSize
) 
 331 void AddTexRef(char *name
, char *file
, char *sectionName
, 
 332                int chapter
, int section
, int subsection
, int subsubsection
) 
 334   TexRef 
*texRef 
= (TexRef 
*)TexReferences
.Get(name
); 
 335   if (texRef
) TexReferences
.Delete(name
); 
 342     strcat(buf, sectionName); 
 349     sprintf(buf2
, "%d", chapter
); 
 358     sprintf(buf2
, "%d", section
); 
 365     sprintf(buf2
, "%d", subsection
); 
 372     sprintf(buf2
, "%d", subsubsection
); 
 375   char *tmp 
= ((strlen(buf
) > 0) ? buf 
: (char *)NULL
); 
 376   TexReferences
.Put(name
, new TexRef(name
, file
, tmp
, sectionName
)); 
 379 void WriteTexReferences(char *filename
) 
 381   ofstream 
ostr(filename
); 
 382   if (ostr
.bad()) return; 
 385   TexReferences
.BeginFind(); 
 386   wxNode 
*node 
= TexReferences
.Next(); 
 390     TexRef 
*ref 
= (TexRef 
*)node
->Data(); 
 391     ostr 
<< ref
->refLabel 
<< " " << (ref
->refFile 
? ref
->refFile 
: "??") << " "; 
 392     ostr 
<< (ref
->sectionName 
? ref
->sectionName 
: "??") << " "; 
 393     ostr 
<< (ref
->sectionNumber 
? ref
->sectionNumber 
: "??") << "\n"; 
 394     if (!ref
->sectionNumber 
|| (strcmp(ref
->sectionNumber
, "??") == 0 && strcmp(ref
->sectionName
, "??") == 0)) 
 396       sprintf(buf
, "Warning: reference %s not resolved.", ref
->refLabel
); 
 399     node 
= TexReferences
.Next(); 
 403 void ReadTexReferences(char *filename
) 
 405 #if !wxUSE_IOSTREAMH && __WXMSW__ 
 406   ifstream 
istr(filename
, ios::in
); 
 408   ifstream 
istr(filename
, ios::nocreate 
| ios::in
); 
 410   if (istr
.bad()) return; 
 415   char sectionName
[100]; 
 425       istr
.get(ch
); // Read past space 
 428       while (ch 
!= '\n' && !istr
.eof()) 
 435       TexReferences
.Put(label
, new TexRef(label
, file
, section
, sectionName
)); 
 442  * Bibliography-handling code 
 446 void BibEatWhiteSpace(istream
& str
) 
 448   char ch 
= str
.peek(); 
 450   while (!str
.eof() && (ch 
== ' ' || ch 
== '\t' || ch 
== 13 || ch 
== 10 || ch 
== EOF
)) 
 455     if ((ch 
== EOF
) || str
.eof()) return; 
 459   // Ignore end-of-line comments 
 460   if (ch 
== '%' || ch 
== ';' || ch 
== '#') 
 464     while (ch 
!= 10 && ch 
!= 13 && !str
.eof()) 
 469     BibEatWhiteSpace(str
); 
 473 // Read word up to { or , or space 
 474 void BibReadWord(istream
& istr
, char *buffer
) 
 478   char ch 
= istr
.peek(); 
 479   while (!istr
.eof() && ch 
!= ' ' && ch 
!= '{' && ch 
!= '(' && ch 
!= 13 && ch 
!= 10 && ch 
!= '\t' && 
 480          ch 
!= ',' && ch 
!= '=') 
 490 // Read string (double-quoted or not) to end quote or EOL 
 491 void BibReadToEOL(istream
& istr
, char *buffer
) 
 495   char ch 
= istr
.peek(); 
 496   bool inQuotes 
= FALSE
; 
 503   // If in quotes, read white space too. If not, 
 504   // stop at white space or comment. 
 505   while (!istr
.eof() && ch 
!= 13 && ch 
!= 10 && ch 
!= '"' && 
 506          (inQuotes 
|| ((ch 
!= ' ') && (ch 
!= 9) && 
 507                         (ch 
!= ';') && (ch 
!= '%') && (ch 
!= '#')))) 
 519 // Read }-terminated value, taking nested braces into account. 
 520 void BibReadValue(istream
& istr
, char *buffer
, bool ignoreBraces 
= TRUE
, 
 521                   bool quotesMayTerminate 
= TRUE
) 
 526   char ch 
= istr
.peek(); 
 527   bool stopping 
= FALSE
; 
 528   while (!istr
.eof() && !stopping
) 
 534       sprintf(buf
, "Sorry, value > 2000 chars in bib file at line %ld, terminating.", BibLine
); 
 535       wxFatalError(buf
, "Tex2RTF Fatal Error"); 
 551     else if (quotesMayTerminate 
&& ch 
== '"') 
 558       if (!ignoreBraces 
|| (ch 
!= '{' && ch 
!= '}')) 
 570 bool ReadBib(char *filename
) 
 573 #if !wxUSE_IOSTREAMH && __WXMSW__ 
 574   ifstream 
istr(filename
, ios::in
); 
 576   ifstream 
istr(filename
, ios::nocreate 
| ios::in
); 
 578   if (istr
.bad()) return FALSE
; 
 582   OnInform("Reading .bib file..."); 
 585   char fieldValue
[2000]; 
 586   char recordType
[100]; 
 588   char recordField
[100]; 
 593     BibEatWhiteSpace(istr
); 
 597       sprintf(buf
, "Expected @: malformed bib file at line %ld (%s)", BibLine
, filename
); 
 601     BibReadWord(istr
, recordType
); 
 602     BibEatWhiteSpace(istr
); 
 604     if (ch 
!= '{' && ch 
!= '(') 
 606       sprintf(buf
, "Expected { or ( after record type: malformed .bib file at line %ld (%s)", BibLine
, filename
); 
 610     BibEatWhiteSpace(istr
); 
 611     if (StringMatch(recordType
, "string", FALSE
, TRUE
)) 
 613       BibReadWord(istr
, recordType
); 
 614       BibEatWhiteSpace(istr
); 
 618         sprintf(buf
, "Expected = after string key: malformed .bib file at line %ld (%s)", BibLine
, filename
); 
 622       BibEatWhiteSpace(istr
); 
 624       if (ch 
!= '"' && ch 
!= '{') 
 626         sprintf(buf
, "Expected = after string key: malformed .bib file at line %ld (%s)", BibLine
, filename
); 
 630       BibReadValue(istr
, fieldValue
); 
 632       // Now put in hash table if necesary 
 633       if (!BibStringTable
.Get(recordType
)) 
 634         BibStringTable
.Put(recordType
, (wxObject 
*)copystring(fieldValue
)); 
 636       // Read closing ) or } 
 637       BibEatWhiteSpace(istr
); 
 639       BibEatWhiteSpace(istr
); 
 643       BibReadWord(istr
, recordKey
); 
 645       BibEntry 
*bibEntry 
= new BibEntry
; 
 646       bibEntry
->key 
= copystring(recordKey
); 
 647       bibEntry
->type 
= copystring(recordType
); 
 649       bool moreRecords 
= TRUE
; 
 650       while (moreRecords 
&& !istr
.eof()) 
 652         BibEatWhiteSpace(istr
); 
 654         if (ch 
== '}' || ch 
== ')') 
 660           BibEatWhiteSpace(istr
); 
 661           BibReadWord(istr
, recordField
); 
 662           BibEatWhiteSpace(istr
); 
 666             sprintf(buf
, "Expected = after field type: malformed .bib file at line %ld (%s)", BibLine
, filename
); 
 670           BibEatWhiteSpace(istr
); 
 672           if (ch 
!= '{' && ch 
!= '"') 
 675             BibReadWord(istr
, fieldValue
+1); 
 677             // If in the table of strings, replace with string from table. 
 678             char *s 
= (char *)BibStringTable
.Get(fieldValue
); 
 681               strcpy(fieldValue
, s
); 
 685             BibReadValue(istr
, fieldValue
, TRUE
, (ch 
== '"' ? TRUE 
: FALSE
)); 
 687           // Now we can add a field 
 688           if (StringMatch(recordField
, "author", FALSE
, TRUE
)) 
 689             bibEntry
->author 
= copystring(fieldValue
); 
 690           else if (StringMatch(recordField
, "key", FALSE
, TRUE
)) 
 692           else if (StringMatch(recordField
, "annotate", FALSE
, TRUE
)) 
 694           else if (StringMatch(recordField
, "abstract", FALSE
, TRUE
)) 
 696           else if (StringMatch(recordField
, "edition", FALSE
, TRUE
)) 
 698           else if (StringMatch(recordField
, "howpublished", FALSE
, TRUE
)) 
 700           else if (StringMatch(recordField
, "note", FALSE
, TRUE
) || StringMatch(recordField
, "notes", FALSE
, TRUE
)) 
 702           else if (StringMatch(recordField
, "series", FALSE
, TRUE
)) 
 704           else if (StringMatch(recordField
, "type", FALSE
, TRUE
)) 
 706           else if (StringMatch(recordField
, "keywords", FALSE
, TRUE
)) 
 708           else if (StringMatch(recordField
, "editor", FALSE
, TRUE
) || StringMatch(recordField
, "editors", FALSE
, TRUE
)) 
 709             bibEntry
->editor
= copystring(fieldValue
); 
 710           else if (StringMatch(recordField
, "title", FALSE
, TRUE
)) 
 711             bibEntry
->title
= copystring(fieldValue
); 
 712           else if (StringMatch(recordField
, "booktitle", FALSE
, TRUE
)) 
 713             bibEntry
->booktitle
= copystring(fieldValue
); 
 714           else if (StringMatch(recordField
, "journal", FALSE
, TRUE
)) 
 715             bibEntry
->journal
= copystring(fieldValue
); 
 716           else if (StringMatch(recordField
, "volume", FALSE
, TRUE
)) 
 717             bibEntry
->volume
= copystring(fieldValue
); 
 718           else if (StringMatch(recordField
, "number", FALSE
, TRUE
)) 
 719             bibEntry
->number
= copystring(fieldValue
); 
 720           else if (StringMatch(recordField
, "year", FALSE
, TRUE
)) 
 721             bibEntry
->year
= copystring(fieldValue
); 
 722           else if (StringMatch(recordField
, "month", FALSE
, TRUE
)) 
 723             bibEntry
->month
= copystring(fieldValue
); 
 724           else if (StringMatch(recordField
, "pages", FALSE
, TRUE
)) 
 725             bibEntry
->pages
= copystring(fieldValue
); 
 726           else if (StringMatch(recordField
, "publisher", FALSE
, TRUE
)) 
 727             bibEntry
->publisher
= copystring(fieldValue
); 
 728           else if (StringMatch(recordField
, "address", FALSE
, TRUE
)) 
 729             bibEntry
->address
= copystring(fieldValue
); 
 730           else if (StringMatch(recordField
, "institution", FALSE
, TRUE
) || StringMatch(recordField
, "school", FALSE
, TRUE
)) 
 731             bibEntry
->institution
= copystring(fieldValue
); 
 732           else if (StringMatch(recordField
, "organization", FALSE
, TRUE
) || StringMatch(recordField
, "organisation", FALSE
, TRUE
)) 
 733             bibEntry
->organization
= copystring(fieldValue
); 
 734           else if (StringMatch(recordField
, "comment", FALSE
, TRUE
) || StringMatch(recordField
, "comments", FALSE
, TRUE
)) 
 735             bibEntry
->comment
= copystring(fieldValue
); 
 736           else if (StringMatch(recordField
, "annote", FALSE
, TRUE
)) 
 737             bibEntry
->comment
= copystring(fieldValue
); 
 738           else if (StringMatch(recordField
, "chapter", FALSE
, TRUE
)) 
 739             bibEntry
->chapter
= copystring(fieldValue
); 
 742             sprintf(buf
, "Unrecognised bib field type %s at line %ld (%s)", recordField
, BibLine
, filename
); 
 747       BibList
.Append(recordKey
, bibEntry
); 
 748       BibEatWhiteSpace(istr
); 
 754 void OutputBibItem(TexRef 
*ref
, BibEntry 
*bib
) 
 758   OnMacro(ltNUMBEREDBIBITEM
, 2, TRUE
); 
 759   OnArgument(ltNUMBEREDBIBITEM
, 1, TRUE
); 
 760   TexOutput(ref
->sectionNumber
); 
 761   OnArgument(ltNUMBEREDBIBITEM
, 1, FALSE
); 
 762   OnArgument(ltNUMBEREDBIBITEM
, 2, TRUE
); 
 765   OnMacro(ltBF
, 1, TRUE
); 
 766   OnArgument(ltBF
, 1, TRUE
); 
 768     TexOutput(bib
->author
); 
 769   OnArgument(ltBF
, 1, FALSE
); 
 770   OnMacro(ltBF
, 1, FALSE
); 
 771   if (bib
->author 
&& (strlen(bib
->author
) > 0) && (bib
->author
[strlen(bib
->author
) - 1] != '.')) 
 778     TexOutput(bib
->year
); 
 783     TexOutput(bib
->month
); 
 786   if (bib
->year 
|| bib
->month
) 
 789   if (StringMatch(bib
->type
, "article", FALSE
, TRUE
)) 
 793       TexOutput(bib
->title
); 
 798       OnMacro(ltIT
, 1, TRUE
); 
 799       OnArgument(ltIT
, 1, TRUE
); 
 800       TexOutput(bib
->journal
); 
 801       OnArgument(ltIT
, 1, FALSE
); 
 802       OnMacro(ltIT
, 1, FALSE
); 
 807       OnMacro(ltBF
, 1, TRUE
); 
 808       OnArgument(ltBF
, 1, TRUE
); 
 809       TexOutput(bib
->volume
); 
 810       OnArgument(ltBF
, 1, FALSE
); 
 811       OnMacro(ltBF
, 1, FALSE
); 
 816       TexOutput(bib
->number
); 
 821       TexOutput(", pages "); 
 822       TexOutput(bib
->pages
); 
 826   else if (StringMatch(bib
->type
, "book", FALSE
, TRUE
) || 
 827            StringMatch(bib
->type
, "unpublished", FALSE
, TRUE
) || 
 828            StringMatch(bib
->type
, "manual", FALSE
, TRUE
) || 
 829            StringMatch(bib
->type
, "phdthesis", FALSE
, TRUE
) || 
 830            StringMatch(bib
->type
, "mastersthesis", FALSE
, TRUE
) || 
 831            StringMatch(bib
->type
, "misc", FALSE
, TRUE
) || 
 832            StringMatch(bib
->type
, "techreport", FALSE
, TRUE
) || 
 833            StringMatch(bib
->type
, "booklet", FALSE
, TRUE
)) 
 835     if (bib
->title 
|| bib
->booktitle
) 
 837       OnMacro(ltIT
, 1, TRUE
); 
 838       OnArgument(ltIT
, 1, TRUE
); 
 839       TexOutput(bib
->title 
? bib
->title 
: bib
->booktitle
); 
 841       OnArgument(ltIT
, 1, FALSE
); 
 842       OnMacro(ltIT
, 1, FALSE
); 
 844     if (StringMatch(bib
->type
, "phdthesis", FALSE
, TRUE
)) 
 845       TexOutput("PhD thesis. "); 
 846     if (StringMatch(bib
->type
, "techreport", FALSE
, TRUE
)) 
 847       TexOutput("Technical report. "); 
 851       TexOutput(bib
->editor
); 
 854     if (bib
->institution
) 
 856       TexOutput(bib
->institution
); 
 859     if (bib
->organization
) 
 861       TexOutput(bib
->organization
); 
 866       TexOutput(bib
->publisher
); 
 871       TexOutput(bib
->address
); 
 875   else if (StringMatch(bib
->type
, "inbook", FALSE
, TRUE
) || 
 876            StringMatch(bib
->type
, "inproceedings", FALSE
, TRUE
) || 
 877            StringMatch(bib
->type
, "incollection", FALSE
, TRUE
) || 
 878            StringMatch(bib
->type
, "conference", FALSE
, TRUE
)) 
 882       TexOutput(bib
->title
); 
 886       TexOutput(", from "); 
 887       OnMacro(ltIT
, 1, TRUE
); 
 888       OnArgument(ltIT
, 1, TRUE
); 
 889       TexOutput(bib
->booktitle
); 
 891       OnArgument(ltIT
, 1, FALSE
); 
 892       OnMacro(ltIT
, 1, FALSE
); 
 897       TexOutput(bib
->editor
); 
 902       TexOutput(bib
->publisher
); 
 906       if (bib
->publisher
) TexOutput(", "); 
 908       TexOutput(bib
->address
); 
 910     if (bib
->publisher 
|| bib
->address
) 
 916       OnMacro(ltBF
, 1, TRUE
); 
 917       OnArgument(ltBF
, 1, TRUE
); 
 918       TexOutput(bib
->volume
); 
 919       OnArgument(ltBF
, 1, FALSE
); 
 920       OnMacro(ltBF
, 1, FALSE
); 
 927         TexOutput(bib
->number
); 
 932         TexOutput(" Number "); 
 933         TexOutput(bib
->number
); 
 939       TexOutput(" Chap. "); TexOutput(bib
->chapter
); 
 943       if (bib
->chapter
) TexOutput(", pages "); 
 944       else TexOutput(" Pages "); 
 945       TexOutput(bib
->pages
); 
 949   OnArgument(ltNUMBEREDBIBITEM
, 2, FALSE
); 
 950   OnMacro(ltNUMBEREDBIBITEM
, 2, FALSE
); 
 956   ForceTopicName("bibliography"); 
 957   FakeCurrentSection(ReferencesNameString
); 
 958   ForceTopicName(NULL
); 
 960   OnMacro(ltPAR
, 0, TRUE
); 
 961   OnMacro(ltPAR
, 0, FALSE
); 
 963   if ((convertMode 
== TEX_RTF
) && !winHelp
) 
 965     OnMacro(ltPAR
, 0, TRUE
); 
 966     OnMacro(ltPAR
, 0, FALSE
); 
 969   wxNode 
*node 
= CitationList
.First(); 
 972     char *citeKey 
= (char *)node
->Data(); 
 973 //    wxNode *texNode = TexReferences.Find(citeKey); 
 974     TexRef 
*ref 
= (TexRef 
*)TexReferences
.Get(citeKey
); 
 975     wxNode 
*bibNode 
= BibList
.Find(citeKey
); 
 978       BibEntry 
*entry 
= (BibEntry 
*)bibNode
->Data(); 
 979       OutputBibItem(ref
, entry
); 
 985 static int citeCount 
= 1; 
 987 void ResolveBibReferences(void) 
 989   if (CitationList
.Number() > 0) 
 990     OnInform("Resolving bibliographic references..."); 
 994   wxNode 
*node 
= CitationList
.First(); 
 998     char *citeKey 
= (char *)node
->Data(); 
 999 //    wxNode *texNode = TexReferences.Find(citeKey); 
1000     TexRef 
*ref 
= (TexRef 
*)TexReferences
.Get(citeKey
); 
1001     wxNode 
*bibNode 
= BibList
.Find(citeKey
); 
1005       //BibEntry *entry = (BibEntry *)bibNode->Data(); 
1006       if (ref
->sectionNumber
) delete[] ref
->sectionNumber
; 
1007       sprintf(buf
, "[%d]", citeCount
); 
1008       ref
->sectionNumber 
= copystring(buf
); 
1013       sprintf(buf
, "Warning: bib ref %s not resolved.", citeKey
); 
1016     node 
= node
->Next(); 
1020 // Remember we need to resolve this citation 
1021 void AddCitation(char *citeKey
) 
1023   if (!CitationList
.Member(citeKey
)) 
1024     CitationList
.Add(citeKey
); 
1026   if (!TexReferences
.Get(citeKey
)) 
1028     TexReferences
.Put(citeKey
, new TexRef(citeKey
, "??", NULL
)); 
1032 TexRef 
*FindReference(char *key
) 
1034   return (TexRef 
*)TexReferences
.Get(key
); 
1038  * Custom macro stuff 
1042 bool StringTobool(char *val
) 
1044   if (strncmp(val
, "yes", 3) == 0 || strncmp(val
, "YES", 3) == 0 || 
1045       strncmp(val
, "on", 2) == 0 || strncmp(val
, "ON", 2) == 0 || 
1046       strncmp(val
, "true", 4) == 0 || strncmp(val
, "TRUE", 4) == 0 || 
1047       strncmp(val
, "ok", 2) == 0 || strncmp(val
, "OK", 2) == 0 || 
1048       strncmp(val
, "1", 1) == 0) 
1054 // Define a variable value from the .ini file 
1055 char *RegisterSetting(char *settingName
, char *settingValue
, bool interactive
) 
1057   static char errorCode
[100]; 
1058   strcpy(errorCode
, "OK"); 
1059   if (StringMatch(settingName
, "chapterName", FALSE
, TRUE
)) 
1061     delete[] ChapterNameString
; 
1062     ChapterNameString 
= copystring(settingValue
); 
1064   else if (StringMatch(settingName
, "sectionName", FALSE
, TRUE
)) 
1066     delete[] SectionNameString
; 
1067     SectionNameString 
= copystring(settingValue
); 
1069   else if (StringMatch(settingName
, "subsectionName", FALSE
, TRUE
)) 
1071     delete[] SubsectionNameString
; 
1072     SubsectionNameString 
= copystring(settingValue
); 
1074   else if (StringMatch(settingName
, "subsubsectionName", FALSE
, TRUE
)) 
1076     delete[] SubsubsectionNameString
; 
1077     SubsubsectionNameString 
= copystring(settingValue
); 
1079   else if (StringMatch(settingName
, "indexName", FALSE
, TRUE
)) 
1081     delete[] IndexNameString
; 
1082     IndexNameString 
= copystring(settingValue
); 
1084   else if (StringMatch(settingName
, "contentsName", FALSE
, TRUE
)) 
1086     delete[] ContentsNameString
; 
1087     ContentsNameString 
= copystring(settingValue
); 
1089   else if (StringMatch(settingName
, "glossaryName", FALSE
, TRUE
)) 
1091     delete[] GlossaryNameString
; 
1092     GlossaryNameString 
= copystring(settingValue
); 
1094   else if (StringMatch(settingName
, "referencesName", FALSE
, TRUE
)) 
1096     delete[] ReferencesNameString
; 
1097     ReferencesNameString 
= copystring(settingValue
); 
1099   else if (StringMatch(settingName
, "tablesName", FALSE
, TRUE
)) 
1101     delete[] TablesNameString
; 
1102     TablesNameString 
= copystring(settingValue
); 
1104   else if (StringMatch(settingName
, "figuresName", FALSE
, TRUE
)) 
1106     delete[] FiguresNameString
; 
1107     FiguresNameString 
= copystring(settingValue
); 
1109   else if (StringMatch(settingName
, "tableName", FALSE
, TRUE
)) 
1111     delete[] TableNameString
; 
1112     TableNameString 
= copystring(settingValue
); 
1114   else if (StringMatch(settingName
, "figureName", FALSE
, TRUE
)) 
1116     delete[] FigureNameString
; 
1117     FigureNameString 
= copystring(settingValue
); 
1119   else if (StringMatch(settingName
, "abstractName", FALSE
, TRUE
)) 
1121     delete[] AbstractNameString
; 
1122     AbstractNameString 
= copystring(settingValue
); 
1124   else if (StringMatch(settingName
, "chapterFontSize", FALSE
, TRUE
)) 
1125     StringToInt(settingValue
, &chapterFont
); 
1126   else if (StringMatch(settingName
, "sectionFontSize", FALSE
, TRUE
)) 
1127     StringToInt(settingValue
, §ionFont
); 
1128   else if (StringMatch(settingName
, "subsectionFontSize", FALSE
, TRUE
)) 
1129     StringToInt(settingValue
, &subsectionFont
); 
1130   else if (StringMatch(settingName
, "titleFontSize", FALSE
, TRUE
)) 
1131     StringToInt(settingValue
, &titleFont
); 
1132   else if (StringMatch(settingName
, "authorFontSize", FALSE
, TRUE
)) 
1133     StringToInt(settingValue
, &authorFont
); 
1134   else if (StringMatch(settingName
, "ignoreInput", FALSE
, TRUE
)) 
1135     IgnorableInputFiles
.Add(FileNameFromPath(settingValue
)); 
1136   else if (StringMatch(settingName
, "mirrorMargins", FALSE
, TRUE
)) 
1137     mirrorMargins 
= StringTobool(settingValue
); 
1138   else if (StringMatch(settingName
, "runTwice", FALSE
, TRUE
)) 
1139     runTwice 
= StringTobool(settingValue
); 
1140   else if (StringMatch(settingName
, "isInteractive", FALSE
, TRUE
)) 
1141     isInteractive 
= StringTobool(settingValue
); 
1142   else if (StringMatch(settingName
, "headerRule", FALSE
, TRUE
)) 
1143     headerRule 
= StringTobool(settingValue
); 
1144   else if (StringMatch(settingName
, "footerRule", FALSE
, TRUE
)) 
1145     footerRule 
= StringTobool(settingValue
); 
1146   else if (StringMatch(settingName
, "combineSubSections", FALSE
, TRUE
)) 
1147     combineSubSections 
= StringTobool(settingValue
); 
1148   else if (StringMatch(settingName
, "listLabelIndent", FALSE
, TRUE
)) 
1149     StringToInt(settingValue
, &labelIndentTab
); 
1150   else if (StringMatch(settingName
, "listItemIndent", FALSE
, TRUE
)) 
1151     StringToInt(settingValue
, &itemIndentTab
); 
1152   else if (StringMatch(settingName
, "useUpButton", FALSE
, TRUE
)) 
1153     useUpButton 
= StringTobool(settingValue
); 
1154   else if (StringMatch(settingName
, "useHeadingStyles", FALSE
, TRUE
)) 
1155     useHeadingStyles 
= StringTobool(settingValue
); 
1156   else if (StringMatch(settingName
, "useWord", FALSE
, TRUE
)) 
1157     useWord 
= StringTobool(settingValue
); 
1158   else if (StringMatch(settingName
, "contentsDepth", FALSE
, TRUE
)) 
1159     StringToInt(settingValue
, &contentsDepth
); 
1160   else if (StringMatch(settingName
, "generateHPJ", FALSE
, TRUE
)) 
1161     generateHPJ 
= StringTobool(settingValue
); 
1162   else if (StringMatch(settingName
, "truncateFilenames", FALSE
, TRUE
)) 
1163     truncateFilenames 
= StringTobool(settingValue
); 
1164   else if (StringMatch(settingName
, "winHelpVersion", FALSE
, TRUE
)) 
1165     StringToInt(settingValue
, &winHelpVersion
); 
1166   else if (StringMatch(settingName
, "winHelpContents", FALSE
, TRUE
)) 
1167     winHelpContents 
= StringTobool(settingValue
); 
1168   else if (StringMatch(settingName
, "htmlIndex", FALSE
, TRUE
)) 
1169     htmlIndex 
= StringTobool(settingValue
); 
1170   else if (StringMatch(settingName
, "htmlFrameContents", FALSE
, TRUE
)) 
1171     htmlFrameContents 
= StringTobool(settingValue
); 
1172   else if (StringMatch(settingName
, "upperCaseNames", FALSE
, TRUE
)) 
1173     upperCaseNames 
= StringTobool(settingValue
); 
1174   else if (StringMatch(settingName
, "winHelpTitle", FALSE
, TRUE
)) 
1177       delete[] winHelpTitle
; 
1178     winHelpTitle 
= copystring(settingValue
); 
1180   else if (StringMatch(settingName
, "indexSubsections", FALSE
, TRUE
)) 
1181     indexSubsections 
= StringTobool(settingValue
); 
1182   else if (StringMatch(settingName
, "compatibility", FALSE
, TRUE
)) 
1183     compatibilityMode 
= StringTobool(settingValue
); 
1184   else if (StringMatch(settingName
, "defaultColumnWidth", FALSE
, TRUE
)) 
1186     StringToInt(settingValue
, &defaultTableColumnWidth
); 
1187     defaultTableColumnWidth 
= 20*defaultTableColumnWidth
; 
1189   else if (StringMatch(settingName
, "bitmapMethod", FALSE
, TRUE
)) 
1191     if ((strcmp(settingValue
, "includepicture") != 0) && (strcmp(settingValue
, "hex") != 0) && 
1192         (strcmp(settingValue
, "import") != 0)) 
1195         OnError("Unknown bitmapMethod"); 
1196       strcpy(errorCode
, "Unknown bitmapMethod"); 
1200       delete[] bitmapMethod
; 
1201       bitmapMethod 
= copystring(settingValue
); 
1204   else if (StringMatch(settingName
, "htmlBrowseButtons", FALSE
, TRUE
)) 
1206     if (strcmp(settingValue
, "none") == 0) 
1207       htmlBrowseButtons 
= HTML_BUTTONS_NONE
; 
1208     else if (strcmp(settingValue
, "bitmap") == 0) 
1209       htmlBrowseButtons 
= HTML_BUTTONS_BITMAP
; 
1210     else if (strcmp(settingValue
, "text") == 0) 
1211       htmlBrowseButtons 
= HTML_BUTTONS_TEXT
; 
1215         OnInform("Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text."); 
1216       strcpy(errorCode
, "Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text."); 
1219   else if (StringMatch(settingName
, "backgroundImage", FALSE
, TRUE
)) 
1221     backgroundImageString 
= copystring(settingValue
); 
1223   else if (StringMatch(settingName
, "backgroundColour", FALSE
, TRUE
)) 
1225     delete[] backgroundColourString
; 
1226     backgroundColourString 
= copystring(settingValue
); 
1228   else if (StringMatch(settingName
, "textColour", FALSE
, TRUE
)) 
1230     textColourString 
= copystring(settingValue
); 
1232   else if (StringMatch(settingName
, "linkColour", FALSE
, TRUE
)) 
1234     linkColourString 
= copystring(settingValue
); 
1236   else if (StringMatch(settingName
, "followedLinkColour", FALSE
, TRUE
)) 
1238     followedLinkColourString 
= copystring(settingValue
); 
1240   else if (StringMatch(settingName
, "conversionMode", FALSE
, TRUE
)) 
1242     if (StringMatch(settingValue
, "RTF", FALSE
, TRUE
)) 
1244       winHelp 
= FALSE
; convertMode 
= TEX_RTF
; 
1246     else if (StringMatch(settingValue
, "WinHelp", FALSE
, TRUE
)) 
1248       winHelp 
= TRUE
; convertMode 
= TEX_RTF
; 
1250     else if (StringMatch(settingValue
, "XLP", FALSE
, TRUE
) || 
1251              StringMatch(settingValue
, "wxHelp", FALSE
, TRUE
)) 
1253       convertMode 
= TEX_XLP
; 
1255     else if (StringMatch(settingValue
, "HTML", FALSE
, TRUE
)) 
1257       convertMode 
= TEX_HTML
; 
1262         OnInform("Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML."); 
1263       strcpy(errorCode
, "Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML."); 
1266   else if (StringMatch(settingName
, "documentFontSize", FALSE
, TRUE
)) 
1269     StringToInt(settingValue
, &n
); 
1270     if (n 
== 10 || n 
== 11 || n 
== 12) 
1275       sprintf(buf
, "Initialisation file error: nonstandard document font size %d.", n
); 
1278       strcpy(errorCode
, buf
); 
1284     sprintf(buf
, "Initialisation file error: unrecognised setting %s.", settingName
); 
1287     strcpy(errorCode
, buf
); 
1292 bool ReadCustomMacros(char *filename
) 
1294 #if !wxUSE_IOSTREAMH && __WXMSW__ 
1295   ifstream 
istr(filename
, ios::in
); 
1297   ifstream 
istr(filename
, ios::nocreate 
| ios::in
); 
1299   if (istr
.bad()) return FALSE
; 
1301   CustomMacroList
.Clear(); 
1303   char macroName
[100]; 
1304   char macroBody
[1000]; 
1309     BibEatWhiteSpace(istr
); 
1314     if (ch 
!= '\\') // Not a macro definition, so must be NAME=VALUE 
1316       char settingName
[100]; 
1317       settingName
[0] = ch
; 
1318       BibReadWord(istr
, (settingName
+1)); 
1319       BibEatWhiteSpace(istr
); 
1323         OnError("Expected = following name: malformed tex2rtf.ini file."); 
1328         char settingValue
[200]; 
1329         BibEatWhiteSpace(istr
); 
1330         BibReadToEOL(istr
, settingValue
); 
1331         RegisterSetting(settingName
, settingValue
); 
1336       BibReadWord(istr
, macroName
); 
1337       BibEatWhiteSpace(istr
); 
1341         OnError("Expected [ followed by number of arguments: malformed tex2rtf.ini file."); 
1348         OnError("Expected ] following number of arguments: malformed tex2rtf.ini file."); 
1351       BibEatWhiteSpace(istr
); 
1355         OnError("Expected { followed by macro body: malformed tex2rtf.ini file."); 
1358       CustomMacro 
*macro 
= new CustomMacro(macroName
, noArgs
, NULL
); 
1359       BibReadValue(istr
, macroBody
, FALSE
, FALSE
); // Don't ignore extra braces 
1360       if (strlen(macroBody
) > 0) 
1361         macro
->macroBody 
= copystring(macroBody
); 
1363       BibEatWhiteSpace(istr
); 
1364       CustomMacroList
.Append(macroName
, macro
); 
1365       AddMacroDef(ltCUSTOM_MACRO
, macroName
, noArgs
); 
1369   sprintf(mbuf
, "Read initialization file %s.", filename
); 
1374 CustomMacro 
*FindCustomMacro(char *name
) 
1376   wxNode 
*node 
= CustomMacroList
.Find(name
); 
1379     CustomMacro 
*macro 
= (CustomMacro 
*)node
->Data(); 
1385 // Display custom macros 
1386 void ShowCustomMacros(void) 
1388   wxNode 
*node 
= CustomMacroList
.First(); 
1391     OnInform("No custom macros loaded.\n"); 
1398     CustomMacro 
*macro 
= (CustomMacro 
*)node
->Data(); 
1399     sprintf(buf
, "\\%s[%d]\n    {%s}", macro
->macroName
, macro
->noArgs
, 
1400      macro
->macroBody 
? macro
->macroBody 
: ""); 
1402     node 
= node
->Next(); 
1406 // Parse a string into several comma-separated fields 
1407 char *ParseMultifieldString(char *allFields
, int *pos
) 
1409   static char buffer
[300]; 
1411   int fieldIndex 
= *pos
; 
1412   int len 
= strlen(allFields
); 
1414   bool keepGoing 
= TRUE
; 
1415   while ((fieldIndex 
<= len
) && keepGoing
) 
1417     if (allFields
[fieldIndex
] == ' ') 
1422     else if (allFields
[fieldIndex
] == ',') 
1424       *pos 
= fieldIndex 
+ 1; 
1427     else if (allFields
[fieldIndex
] == 0) 
1429       *pos 
= fieldIndex 
+ 1; 
1434       buffer
[i
] = allFields
[fieldIndex
]; 
1440   if (oldPos 
== (*pos
)) 
1454 ColourTableEntry::ColourTableEntry(char *theName
, unsigned int r
,  unsigned int g
,  unsigned int b
) 
1456   name 
= copystring(theName
); 
1462 ColourTableEntry::~ColourTableEntry(void) 
1467 void AddColour(char *theName
, unsigned int r
,  unsigned int g
,  unsigned int b
) 
1469   wxNode 
*node 
= ColourTable
.Find(theName
); 
1472     ColourTableEntry 
*entry 
= (ColourTableEntry 
*)node
->Data(); 
1473     if (entry
->red 
== r 
|| entry
->green 
== g 
|| entry
->blue 
== b
) 
1481   ColourTableEntry 
*entry 
= new ColourTableEntry(theName
, r
, g
, b
); 
1482   ColourTable
.Append(theName
, entry
); 
1485 int FindColourPosition(char *theName
) 
1488   wxNode 
*node 
= ColourTable
.First(); 
1491     ColourTableEntry 
*entry 
= (ColourTableEntry 
*)node
->Data(); 
1492     if (strcmp(theName
, entry
->name
) == 0) 
1495     node 
= node
->Next(); 
1500 // Converts e.g. "red" -> "#FF0000" 
1501 extern void DecToHex(int, char *); 
1502 bool FindColourHTMLString(char *theName
, char *buf
) 
1505   wxNode 
*node 
= ColourTable
.First(); 
1508     ColourTableEntry 
*entry 
= (ColourTableEntry 
*)node
->Data(); 
1509     if (strcmp(theName
, entry
->name
) == 0) 
1514         DecToHex(entry
->red
, buf2
); 
1516         DecToHex(entry
->green
, buf2
); 
1518         DecToHex(entry
->blue
, buf2
); 
1524     node 
= node
->Next(); 
1530 void InitialiseColourTable(void) 
1532   // \\red0\\green0\\blue0; 
1533   AddColour("black", 0,0,0); 
1535   // \\red0\\green0\\blue255;\\red0\\green255\\blue255;\n"); 
1536   AddColour("cyan", 0,255,255); 
1538   // \\red0\\green255\\blue0; 
1539   AddColour("green", 0,255,0); 
1541   // \\red255\\green0\\blue255; 
1542   AddColour("magenta", 255,0,255); 
1544   // \\red255\\green0\\blue0; 
1545   AddColour("red", 255,0,0); 
1547   // \\red255\\green255\\blue0; 
1548   AddColour("yellow", 255,255,0); 
1550   // \\red255\\green255\\blue255;}"); 
1551   AddColour("white", 255,255,255); 
1555  * The purpose of this is to reduce the number of times wxYield is 
1556  * called, since under Windows this can slow things down. 
1559 static int yieldCount 
= 0; 
1561 void Tex2RTFYield(bool force
) 
1569   if (yieldCount 
== 0) 
1578 // In both RTF generation and HTML generation for wxHelp version 2, 
1579 // we need to associate \indexed keywords with the current filename/topics. 
1581 // Hash table for lists of keywords for topics (WinHelp). 
1582 wxHashTable 
TopicTable(wxKEY_STRING
); 
1583 void AddKeyWordForTopic(char *topic
, char *entry
, char *filename
) 
1585   TexTopic 
*texTopic 
= (TexTopic 
*)TopicTable
.Get(topic
); 
1588     texTopic 
= new TexTopic(filename
); 
1589     texTopic
->keywords 
= new wxStringList
; 
1590     TopicTable
.Put(topic
, texTopic
); 
1593   if (!texTopic
->keywords
->Member(entry
)) 
1594     texTopic
->keywords
->Add(entry
); 
1597 void ClearKeyWordTable(void) 
1599   TopicTable
.BeginFind(); 
1600   wxNode 
*node 
= TopicTable
.Next(); 
1603     TexTopic 
*texTopic 
= (TexTopic 
*)node
->Data(); 
1605     node 
= TopicTable
.Next(); 
1612  * TexTopic structure 
1615 TexTopic::TexTopic(char *f
) 
1618     filename 
= copystring(f
); 
1621   hasChildren 
= FALSE
; 
1625 TexTopic::~TexTopic(void) 
1633 // Convert case, according to upperCaseNames setting. 
1634 char *ConvertCase(char *s
) 
1636   static char buf
[256]; 
1637   int len 
= strlen(s
); 
1640     for (i 
= 0; i 
< len
; i 
++) 
1641       buf
[i
] = wxToUpper(s
[i
]); 
1643     for (i 
= 0; i 
< len
; i 
++) 
1644       buf
[i
] = wxToLower(s
[i
]);