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"
46 #if !WXWIN_COMPATIBILITY_2_4
47 static inline wxChar
* copystring(const wxChar
* s
)
48 { return wxStrcpy(new wxChar
[wxStrlen(s
) + 1], s
); }
49 static inline void StringToInt (const wxChar
*s
, int *number
)
51 if (s
&& *s
&& number
)
52 *number
= (int) wxStrtol (s
, (wxChar
**) NULL
, 10);
56 wxHashTable
TexReferences(wxKEY_STRING
);
57 wxList
BibList(wxKEY_STRING
);
58 wxStringList CitationList
;
59 wxList
ColourTable(wxKEY_STRING
);
60 wxHashTable
BibStringTable(wxKEY_STRING
);
61 wxList
CustomMacroList(wxKEY_STRING
);
62 TexChunk
*currentSection
= NULL
;
63 wxChar
*fakeCurrentSection
= NULL
;
65 static long BibLine
= 1;
67 void OutputCurrentSection(void)
69 if (fakeCurrentSection
)
70 TexOutput(fakeCurrentSection
);
71 else if (currentSection
)
72 TraverseChildrenFromChunk(currentSection
);
75 // Nasty but the way things are done now, necessary,
76 // in order to output a chunk properly to a string (macros and all).
77 void OutputCurrentSectionToString(wxChar
*buf
)
79 if (fakeCurrentSection
)
80 wxStrcpy(buf
, fakeCurrentSection
);
82 OutputChunkToString(currentSection
, buf
);
85 void OutputChunkToString(TexChunk
*chunk
, wxChar
*buf
)
87 FILE *tempfd
= wxFopen(_T("tmp.tmp"), _T("w"));
91 FILE *old1
= CurrentOutput1
;
92 FILE *old2
= CurrentOutput2
;
94 CurrentOutput1
= tempfd
;
95 CurrentOutput2
= NULL
;
97 TraverseChildrenFromChunk(chunk
);
99 CurrentOutput1
= old1
;
100 CurrentOutput2
= old2
;
104 // Read from file into string
105 tempfd
= wxFopen(_T("tmp.tmp"), _T("r"));
124 wxRemoveFile(_T("tmp.tmp"));
127 // Called by Tex2Any to simulate a section
128 void FakeCurrentSection(wxChar
*fakeSection
, bool addToContents
)
130 currentSection
= NULL
;
131 if (fakeCurrentSection
) delete[] fakeCurrentSection
;
132 fakeCurrentSection
= copystring(fakeSection
);
134 if (DocumentStyle
== LATEX_ARTICLE
)
136 int mac
= ltSECTIONHEADING
;
138 mac
= ltSECTIONHEADINGSTAR
;
139 OnMacro(mac
, 0, TRUE
);
140 OnMacro(mac
, 0, FALSE
);
144 int mac
= ltCHAPTERHEADING
;
146 mac
= ltCHAPTERHEADINGSTAR
;
147 OnMacro(mac
, 0, TRUE
);
148 OnMacro(mac
, 0, FALSE
);
150 if (fakeCurrentSection
) delete[] fakeCurrentSection
;
151 fakeCurrentSection
= NULL
;
154 // Look for \label macro, use this ref name if found or
155 // make up a topic name otherwise.
156 static long topicCounter
= 0;
158 void ResetTopicCounter(void)
163 static wxChar
*forceTopicName
= NULL
;
165 void ForceTopicName(const wxChar
*name
)
168 delete[] forceTopicName
;
170 forceTopicName
= copystring(name
);
172 forceTopicName
= NULL
;
175 wxChar
*FindTopicName(TexChunk
*chunk
)
178 return forceTopicName
;
180 wxChar
*topicName
= NULL
;
181 static wxChar topicBuf
[100];
183 if (chunk
&& (chunk
->type
== CHUNK_TYPE_MACRO
) &&
184 (chunk
->macroId
== ltLABEL
))
186 wxNode
*node
= chunk
->children
.GetFirst();
189 TexChunk
*child
= (TexChunk
*)node
->GetData();
190 if (child
->type
== CHUNK_TYPE_ARG
)
192 wxNode
*snode
= child
->children
.GetFirst();
195 TexChunk
*schunk
= (TexChunk
*)snode
->GetData();
196 if (schunk
->type
== CHUNK_TYPE_STRING
)
197 topicName
= schunk
->value
;
206 wxSprintf(topicBuf
, _T("topic%ld"), topicCounter
);
213 * Simulate argument data, so we can 'drive' clients which implement
214 * certain basic formatting behaviour.
215 * Snag is that some save a TexChunk, so don't use yet...
219 void StartSimulateArgument(wxChar
*data
)
221 wxStrcpy(currentArgData
, data
);
225 void EndSimulateArgument(void)
231 * Parse and convert unit arguments to points
235 int ParseUnitArgument(wxChar
*unitArg
)
237 float conversionFactor
= 1.0;
238 float unitValue
= 0.0;
239 int len
= wxStrlen(unitArg
);
240 // Get rid of any accidentally embedded commands
241 for (int i
= 0; i
< len
; i
++)
242 if (unitArg
[i
] == '\\')
244 len
= wxStrlen(unitArg
);
246 if (unitArg
&& (len
> 0) && (isdigit(unitArg
[0]) || unitArg
[0] == '-'))
248 wxSscanf(unitArg
, _T("%f"), &unitValue
);
252 units
[0] = unitArg
[len
-2];
253 units
[1] = unitArg
[len
-1];
255 if (wxStrcmp(units
, _T("in")) == 0)
256 conversionFactor
= 72.0;
257 else if (wxStrcmp(units
, _T("cm")) == 0)
258 conversionFactor
= (float)72.0/(float)2.51;
259 else if (wxStrcmp(units
, _T("mm")) == 0)
260 conversionFactor
= (float)72.0/(float)25.1;
261 else if (wxStrcmp(units
, _T("pt")) == 0)
262 conversionFactor
= 1;
264 return (int)(unitValue
*conversionFactor
);
270 * Strip off any extension (dot something) from end of file,
271 * IF one exists. Inserts zero into buffer.
275 void StripExtension(wxChar
*buffer
)
277 int len
= wxStrlen(buffer
);
281 if (buffer
[i
] == '.')
295 void SetFontSizes(int pointSize
)
347 void AddTexRef(wxChar
*name
, wxChar
*file
, wxChar
*sectionName
,
348 int chapter
, int section
, int subsection
, int subsubsection
)
350 TexRef
*texRef
= (TexRef
*)TexReferences
.Get(name
);
351 if (texRef
) TexReferences
.Delete(name
);
358 wxStrcat(buf, sectionName);
365 wxSprintf(buf2
, _T("%d"), chapter
);
372 wxStrcat(buf
, _T("."));
374 wxSprintf(buf2
, _T("%d"), section
);
380 wxStrcat(buf
, _T("."));
381 wxSprintf(buf2
, _T("%d"), subsection
);
387 wxStrcat(buf
, _T("."));
388 wxSprintf(buf2
, _T("%d"), subsubsection
);
391 wxChar
*tmp
= ((wxStrlen(buf
) > 0) ? buf
: (wxChar
*)NULL
);
392 TexReferences
.Put(name
, new TexRef(name
, file
, tmp
, sectionName
));
395 void WriteTexReferences(wxChar
*filename
)
397 wxSTD ofstream
ostr(filename
);
398 if (ostr
.bad()) return;
401 TexReferences
.BeginFind();
402 wxNode
*node
= TexReferences
.Next();
406 TexRef
*ref
= (TexRef
*)node
->GetData();
407 ostr
<< ref
->refLabel
<< _T(" ") << (ref
->refFile
? ref
->refFile
: _T("??")) << _T(" ");
408 ostr
<< (ref
->sectionName
? ref
->sectionName
: _T("??")) << _T(" ");
409 ostr
<< (ref
->sectionNumber
? ref
->sectionNumber
: _T("??")) << _T("\n");
410 if (!ref
->sectionNumber
|| (wxStrcmp(ref
->sectionNumber
, _T("??")) == 0 && wxStrcmp(ref
->sectionName
, _T("??")) == 0))
412 wxSprintf(buf
, _T("Warning: reference %s not resolved."), ref
->refLabel
);
415 node
= TexReferences
.Next();
419 void ReadTexReferences(wxChar
*filename
)
421 if (!wxFileExists(filename
))
424 wxSTD ifstream
istr(filename
, wxSTD
ios::in
);
426 if (istr
.bad()) return;
431 wxChar sectionName
[100];
441 istr
.get(ch
); // Read past space
444 while (ch
!= '\n' && !istr
.eof())
452 // gt - needed to trick the hash table "TexReferences" into deleting the key
453 // strings it creates in the Put() function, but not the item that is
454 // created here, as that is destroyed elsewhere. Without doing this, there
455 // were massive memory leaks
456 TexReferences
.DeleteContents(TRUE
);
457 TexReferences
.Put(label
, new TexRef(label
, file
, section
, sectionName
));
458 TexReferences
.DeleteContents(FALSE
);
465 * Bibliography-handling code
469 void BibEatWhiteSpace(wxSTD istream
& str
)
471 char ch
= str
.peek();
473 while (!str
.eof() && (ch
== ' ' || ch
== '\t' || ch
== 13 || ch
== 10 || ch
== EOF
))
478 if ((ch
== EOF
) || str
.eof()) return;
482 // Ignore end-of-line comments
483 if (ch
== '%' || ch
== ';' || ch
== '#')
487 while (ch
!= 10 && ch
!= 13 && !str
.eof())
492 BibEatWhiteSpace(str
);
496 // Read word up to { or , or space
497 void BibReadWord(wxSTD istream
& istr
, wxChar
*buffer
)
501 char ch
= istr
.peek();
502 while (!istr
.eof() && ch
!= ' ' && ch
!= '{' && ch
!= '(' && ch
!= 13 && ch
!= 10 && ch
!= '\t' &&
503 ch
!= ',' && ch
!= '=')
513 // Read string (double-quoted or not) to end quote or EOL
514 void BibReadToEOL(wxSTD istream
& istr
, wxChar
*buffer
)
518 wxChar ch
= istr
.peek();
519 bool inQuotes
= FALSE
;
526 // If in quotes, read white space too. If not,
527 // stop at white space or comment.
528 while (!istr
.eof() && ch
!= 13 && ch
!= 10 && ch
!= _T('"') &&
529 (inQuotes
|| ((ch
!= _T(' ')) && (ch
!= 9) &&
530 (ch
!= _T(';')) && (ch
!= _T('%')) && (ch
!= _T('#')))))
542 // Read }-terminated value, taking nested braces into account.
543 void BibReadValue(wxSTD istream
& istr
, wxChar
*buffer
, bool ignoreBraces
= TRUE
,
544 bool quotesMayTerminate
= TRUE
)
549 char ch
= istr
.peek();
550 bool stopping
= FALSE
;
551 while (!istr
.eof() && !stopping
)
557 wxSprintf(buf
, _T("Sorry, value > 4000 chars in bib file at line %ld."), BibLine
);
558 wxLogError(buf
, "Tex2RTF Fatal Error");
575 else if (quotesMayTerminate
&& ch
== '"')
582 if (!ignoreBraces
|| (ch
!= '{' && ch
!= '}'))
592 wxUnusedVar(stopping
);
595 bool ReadBib(wxChar
*filename
)
597 if (!wxFileExists(filename
))
601 wxSTD ifstream
istr(filename
, wxSTD
ios::in
);
602 if (istr
.bad()) return FALSE
;
606 OnInform(_T("Reading .bib file..."));
609 wxChar fieldValue
[4000];
610 wxChar recordType
[100];
611 wxChar recordKey
[100];
612 wxChar recordField
[100];
617 BibEatWhiteSpace(istr
);
621 wxSprintf(buf
, _T("Expected @: malformed bib file at line %ld (%s)"), BibLine
, filename
);
625 BibReadWord(istr
, recordType
);
626 BibEatWhiteSpace(istr
);
628 if (ch
!= '{' && ch
!= '(')
630 wxSprintf(buf
, _T("Expected { or ( after record type: malformed .bib file at line %ld (%s)"), BibLine
, filename
);
634 BibEatWhiteSpace(istr
);
635 if (StringMatch(recordType
, _T("string"), FALSE
, TRUE
))
637 BibReadWord(istr
, recordType
);
638 BibEatWhiteSpace(istr
);
642 wxSprintf(buf
, _T("Expected = after string key: malformed .bib file at line %ld (%s)"), BibLine
, filename
);
646 BibEatWhiteSpace(istr
);
648 if (ch
!= '"' && ch
!= '{')
650 wxSprintf(buf
, _T("Expected = after string key: malformed .bib file at line %ld (%s)"), BibLine
, filename
);
654 BibReadValue(istr
, fieldValue
);
656 // Now put in hash table if necesary
657 if (!BibStringTable
.Get(recordType
))
658 BibStringTable
.Put(recordType
, (wxObject
*)copystring(fieldValue
));
660 // Read closing ) or }
661 BibEatWhiteSpace(istr
);
663 BibEatWhiteSpace(istr
);
667 BibReadWord(istr
, recordKey
);
669 BibEntry
*bibEntry
= new BibEntry
;
670 bibEntry
->key
= copystring(recordKey
);
671 bibEntry
->type
= copystring(recordType
);
673 bool moreRecords
= TRUE
;
674 while (moreRecords
&& !istr
.eof())
676 BibEatWhiteSpace(istr
);
678 if (ch
== '}' || ch
== ')')
684 BibEatWhiteSpace(istr
);
685 BibReadWord(istr
, recordField
);
686 BibEatWhiteSpace(istr
);
690 wxSprintf(buf
, _T("Expected = after field type: malformed .bib file at line %ld (%s)"), BibLine
, filename
);
694 BibEatWhiteSpace(istr
);
696 if (ch
!= '{' && ch
!= '"')
699 BibReadWord(istr
, fieldValue
+1);
701 // If in the table of strings, replace with string from table.
702 wxChar
*s
= (wxChar
*)BibStringTable
.Get(fieldValue
);
705 wxStrcpy(fieldValue
, s
);
709 BibReadValue(istr
, fieldValue
, TRUE
, (ch
== _T('"') ? TRUE
: FALSE
));
711 // Now we can add a field
712 if (StringMatch(recordField
, _T("author"), FALSE
, TRUE
))
713 bibEntry
->author
= copystring(fieldValue
);
714 else if (StringMatch(recordField
, _T("key"), FALSE
, TRUE
))
716 else if (StringMatch(recordField
, _T("annotate"), FALSE
, TRUE
))
718 else if (StringMatch(recordField
, _T("abstract"), FALSE
, TRUE
))
720 else if (StringMatch(recordField
, _T("edition"), FALSE
, TRUE
))
722 else if (StringMatch(recordField
, _T("howpublished"), FALSE
, TRUE
))
724 else if (StringMatch(recordField
, _T("note"), FALSE
, TRUE
) || StringMatch(recordField
, _T("notes"), FALSE
, TRUE
))
726 else if (StringMatch(recordField
, _T("series"), FALSE
, TRUE
))
728 else if (StringMatch(recordField
, _T("type"), FALSE
, TRUE
))
730 else if (StringMatch(recordField
, _T("keywords"), FALSE
, TRUE
))
732 else if (StringMatch(recordField
, _T("editor"), FALSE
, TRUE
) || StringMatch(recordField
, _T("editors"), FALSE
, TRUE
))
733 bibEntry
->editor
= copystring(fieldValue
);
734 else if (StringMatch(recordField
, _T("title"), FALSE
, TRUE
))
735 bibEntry
->title
= copystring(fieldValue
);
736 else if (StringMatch(recordField
, _T("booktitle"), FALSE
, TRUE
))
737 bibEntry
->booktitle
= copystring(fieldValue
);
738 else if (StringMatch(recordField
, _T("journal"), FALSE
, TRUE
))
739 bibEntry
->journal
= copystring(fieldValue
);
740 else if (StringMatch(recordField
, _T("volume"), FALSE
, TRUE
))
741 bibEntry
->volume
= copystring(fieldValue
);
742 else if (StringMatch(recordField
, _T("number"), FALSE
, TRUE
))
743 bibEntry
->number
= copystring(fieldValue
);
744 else if (StringMatch(recordField
, _T("year"), FALSE
, TRUE
))
745 bibEntry
->year
= copystring(fieldValue
);
746 else if (StringMatch(recordField
, _T("month"), FALSE
, TRUE
))
747 bibEntry
->month
= copystring(fieldValue
);
748 else if (StringMatch(recordField
, _T("pages"), FALSE
, TRUE
))
749 bibEntry
->pages
= copystring(fieldValue
);
750 else if (StringMatch(recordField
, _T("publisher"), FALSE
, TRUE
))
751 bibEntry
->publisher
= copystring(fieldValue
);
752 else if (StringMatch(recordField
, _T("address"), FALSE
, TRUE
))
753 bibEntry
->address
= copystring(fieldValue
);
754 else if (StringMatch(recordField
, _T("institution"), FALSE
, TRUE
) || StringMatch(recordField
, _T("school"), FALSE
, TRUE
))
755 bibEntry
->institution
= copystring(fieldValue
);
756 else if (StringMatch(recordField
, _T("organization"), FALSE
, TRUE
) || StringMatch(recordField
, _T("organisation"), FALSE
, TRUE
))
757 bibEntry
->organization
= copystring(fieldValue
);
758 else if (StringMatch(recordField
, _T("comment"), FALSE
, TRUE
) || StringMatch(recordField
, _T("comments"), FALSE
, TRUE
))
759 bibEntry
->comment
= copystring(fieldValue
);
760 else if (StringMatch(recordField
, _T("annote"), FALSE
, TRUE
))
761 bibEntry
->comment
= copystring(fieldValue
);
762 else if (StringMatch(recordField
, _T("chapter"), FALSE
, TRUE
))
763 bibEntry
->chapter
= copystring(fieldValue
);
766 wxSprintf(buf
, _T("Unrecognised bib field type %s at line %ld (%s)"), recordField
, BibLine
, filename
);
771 BibList
.Append(recordKey
, bibEntry
);
772 BibEatWhiteSpace(istr
);
778 void OutputBibItem(TexRef
*ref
, BibEntry
*bib
)
782 OnMacro(ltNUMBEREDBIBITEM
, 2, TRUE
);
783 OnArgument(ltNUMBEREDBIBITEM
, 1, TRUE
);
784 TexOutput(ref
->sectionNumber
);
785 OnArgument(ltNUMBEREDBIBITEM
, 1, FALSE
);
786 OnArgument(ltNUMBEREDBIBITEM
, 2, TRUE
);
789 OnMacro(ltBF
, 1, TRUE
);
790 OnArgument(ltBF
, 1, TRUE
);
792 TexOutput(bib
->author
);
793 OnArgument(ltBF
, 1, FALSE
);
794 OnMacro(ltBF
, 1, FALSE
);
795 if (bib
->author
&& (wxStrlen(bib
->author
) > 0) && (bib
->author
[wxStrlen(bib
->author
) - 1] != '.'))
802 TexOutput(bib
->year
);
807 TexOutput(bib
->month
);
810 if (bib
->year
|| bib
->month
)
813 if (StringMatch(bib
->type
, _T("article"), FALSE
, TRUE
))
817 TexOutput(bib
->title
);
822 OnMacro(ltIT
, 1, TRUE
);
823 OnArgument(ltIT
, 1, TRUE
);
824 TexOutput(bib
->journal
);
825 OnArgument(ltIT
, 1, FALSE
);
826 OnMacro(ltIT
, 1, FALSE
);
831 OnMacro(ltBF
, 1, TRUE
);
832 OnArgument(ltBF
, 1, TRUE
);
833 TexOutput(bib
->volume
);
834 OnArgument(ltBF
, 1, FALSE
);
835 OnMacro(ltBF
, 1, FALSE
);
840 TexOutput(bib
->number
);
845 TexOutput(_T(", pages "));
846 TexOutput(bib
->pages
);
850 else if (StringMatch(bib
->type
, _T("book"), FALSE
, TRUE
) ||
851 StringMatch(bib
->type
, _T("unpublished"), FALSE
, TRUE
) ||
852 StringMatch(bib
->type
, _T("manual"), FALSE
, TRUE
) ||
853 StringMatch(bib
->type
, _T("phdthesis"), FALSE
, TRUE
) ||
854 StringMatch(bib
->type
, _T("mastersthesis"), FALSE
, TRUE
) ||
855 StringMatch(bib
->type
, _T("misc"), FALSE
, TRUE
) ||
856 StringMatch(bib
->type
, _T("techreport"), FALSE
, TRUE
) ||
857 StringMatch(bib
->type
, _T("booklet"), FALSE
, TRUE
))
859 if (bib
->title
|| bib
->booktitle
)
861 OnMacro(ltIT
, 1, TRUE
);
862 OnArgument(ltIT
, 1, TRUE
);
863 TexOutput(bib
->title
? bib
->title
: bib
->booktitle
);
865 OnArgument(ltIT
, 1, FALSE
);
866 OnMacro(ltIT
, 1, FALSE
);
868 if (StringMatch(bib
->type
, _T("phdthesis"), FALSE
, TRUE
))
869 TexOutput(_T("PhD thesis. "));
870 if (StringMatch(bib
->type
, _T("techreport"), FALSE
, TRUE
))
871 TexOutput(_T("Technical report. "));
874 TexOutput(_T("Ed. "));
875 TexOutput(bib
->editor
);
878 if (bib
->institution
)
880 TexOutput(bib
->institution
);
883 if (bib
->organization
)
885 TexOutput(bib
->organization
);
890 TexOutput(bib
->publisher
);
895 TexOutput(bib
->address
);
899 else if (StringMatch(bib
->type
, _T("inbook"), FALSE
, TRUE
) ||
900 StringMatch(bib
->type
, _T("inproceedings"), FALSE
, TRUE
) ||
901 StringMatch(bib
->type
, _T("incollection"), FALSE
, TRUE
) ||
902 StringMatch(bib
->type
, _T("conference"), FALSE
, TRUE
))
906 TexOutput(bib
->title
);
910 TexOutput(_T(", from "));
911 OnMacro(ltIT
, 1, TRUE
);
912 OnArgument(ltIT
, 1, TRUE
);
913 TexOutput(bib
->booktitle
);
915 OnArgument(ltIT
, 1, FALSE
);
916 OnMacro(ltIT
, 1, FALSE
);
920 TexOutput(_T(", ed. "));
921 TexOutput(bib
->editor
);
926 TexOutput(bib
->publisher
);
930 if (bib
->publisher
) TexOutput(_T(", "));
931 else TexOutput(_T(" "));
932 TexOutput(bib
->address
);
934 if (bib
->publisher
|| bib
->address
)
940 OnMacro(ltBF
, 1, TRUE
);
941 OnArgument(ltBF
, 1, TRUE
);
942 TexOutput(bib
->volume
);
943 OnArgument(ltBF
, 1, FALSE
);
944 OnMacro(ltBF
, 1, FALSE
);
951 TexOutput(bib
->number
);
956 TexOutput(_T(" Number "));
957 TexOutput(bib
->number
);
963 TexOutput(_T(" Chap. "));
964 TexOutput(bib
->chapter
);
968 if (bib
->chapter
) TexOutput(_T(", pages "));
969 else TexOutput(_T(" Pages "));
970 TexOutput(bib
->pages
);
974 OnArgument(ltNUMBEREDBIBITEM
, 2, FALSE
);
975 OnMacro(ltNUMBEREDBIBITEM
, 2, FALSE
);
981 ForceTopicName(_T("bibliography"));
982 FakeCurrentSection(ReferencesNameString
);
983 ForceTopicName(NULL
);
985 OnMacro(ltPAR
, 0, TRUE
);
986 OnMacro(ltPAR
, 0, FALSE
);
988 if ((convertMode
== TEX_RTF
) && !winHelp
)
990 OnMacro(ltPAR
, 0, TRUE
);
991 OnMacro(ltPAR
, 0, FALSE
);
994 wxStringListNode
*node
= CitationList
.GetFirst();
997 wxChar
*citeKey
= (wxChar
*)node
->GetData();
998 // wxNode *texNode = TexReferences.Find(citeKey);
999 TexRef
*ref
= (TexRef
*)TexReferences
.Get(citeKey
);
1000 wxNode
*bibNode
= BibList
.Find(citeKey
);
1003 BibEntry
*entry
= (BibEntry
*)bibNode
->GetData();
1004 OutputBibItem(ref
, entry
);
1006 node
= node
->GetNext();
1010 static int citeCount
= 1;
1012 void ResolveBibReferences(void)
1014 if (CitationList
.GetCount() > 0)
1015 OnInform(_T("Resolving bibliographic references..."));
1019 wxStringListNode
*node
= CitationList
.GetFirst();
1023 wxChar
*citeKey
= (wxChar
*)node
->GetData();
1024 // wxNode *texNode = TexReferences.Find(citeKey);
1025 TexRef
*ref
= (TexRef
*)TexReferences
.Get(citeKey
);
1026 wxNode
*bibNode
= BibList
.Find(citeKey
);
1030 //BibEntry *entry = (BibEntry *)bibNode->GetData();
1031 if (ref
->sectionNumber
) delete[] ref
->sectionNumber
;
1032 wxSprintf(buf
, _T("[%d]"), citeCount
);
1033 ref
->sectionNumber
= copystring(buf
);
1038 wxSprintf(buf
, _T("Warning: bib ref %s not resolved."), citeKey
);
1041 node
= node
->GetNext();
1045 // Remember we need to resolve this citation
1046 void AddCitation(wxChar
*citeKey
)
1048 if (!CitationList
.Member(citeKey
))
1049 CitationList
.Add(citeKey
);
1051 if (!TexReferences
.Get(citeKey
))
1053 TexReferences
.Put(citeKey
, new TexRef(citeKey
, _T("??"), NULL
));
1057 TexRef
*FindReference(wxChar
*key
)
1059 return (TexRef
*)TexReferences
.Get(key
);
1063 * Custom macro stuff
1067 bool StringTobool(wxChar
*val
)
1069 if (wxStrncmp(val
, _T("yes"), 3) == 0 || wxStrncmp(val
, _T("YES"), 3) == 0 ||
1070 wxStrncmp(val
, _T("on"), 2) == 0 || wxStrncmp(val
, _T("ON"), 2) == 0 ||
1071 wxStrncmp(val
, _T("true"), 4) == 0 || wxStrncmp(val
, _T("TRUE"), 4) == 0 ||
1072 wxStrncmp(val
, _T("ok"), 2) == 0 || wxStrncmp(val
, _T("OK"), 2) == 0 ||
1073 wxStrncmp(val
, _T("1"), 1) == 0)
1079 // Define a variable value from the .ini file
1080 wxChar
*RegisterSetting(wxChar
*settingName
, wxChar
*settingValue
, bool interactive
)
1082 static wxChar errorCode
[100];
1083 wxStrcpy(errorCode
, _T("OK"));
1084 if (StringMatch(settingName
, _T("chapterName"), FALSE
, TRUE
))
1086 delete[] ChapterNameString
;
1087 ChapterNameString
= copystring(settingValue
);
1089 else if (StringMatch(settingName
, _T("sectionName"), FALSE
, TRUE
))
1091 delete[] SectionNameString
;
1092 SectionNameString
= copystring(settingValue
);
1094 else if (StringMatch(settingName
, _T("subsectionName"), FALSE
, TRUE
))
1096 delete[] SubsectionNameString
;
1097 SubsectionNameString
= copystring(settingValue
);
1099 else if (StringMatch(settingName
, _T("subsubsectionName"), FALSE
, TRUE
))
1101 delete[] SubsubsectionNameString
;
1102 SubsubsectionNameString
= copystring(settingValue
);
1104 else if (StringMatch(settingName
, _T("indexName"), FALSE
, TRUE
))
1106 delete[] IndexNameString
;
1107 IndexNameString
= copystring(settingValue
);
1109 else if (StringMatch(settingName
, _T("contentsName"), FALSE
, TRUE
))
1111 delete[] ContentsNameString
;
1112 ContentsNameString
= copystring(settingValue
);
1114 else if (StringMatch(settingName
, _T("glossaryName"), FALSE
, TRUE
))
1116 delete[] GlossaryNameString
;
1117 GlossaryNameString
= copystring(settingValue
);
1119 else if (StringMatch(settingName
, _T("referencesName"), FALSE
, TRUE
))
1121 delete[] ReferencesNameString
;
1122 ReferencesNameString
= copystring(settingValue
);
1124 else if (StringMatch(settingName
, _T("tablesName"), FALSE
, TRUE
))
1126 delete[] TablesNameString
;
1127 TablesNameString
= copystring(settingValue
);
1129 else if (StringMatch(settingName
, _T("figuresName"), FALSE
, TRUE
))
1131 delete[] FiguresNameString
;
1132 FiguresNameString
= copystring(settingValue
);
1134 else if (StringMatch(settingName
, _T("tableName"), FALSE
, TRUE
))
1136 delete[] TableNameString
;
1137 TableNameString
= copystring(settingValue
);
1139 else if (StringMatch(settingName
, _T("figureName"), FALSE
, TRUE
))
1141 delete[] FigureNameString
;
1142 FigureNameString
= copystring(settingValue
);
1144 else if (StringMatch(settingName
, _T("abstractName"), FALSE
, TRUE
))
1146 delete[] AbstractNameString
;
1147 AbstractNameString
= copystring(settingValue
);
1149 else if (StringMatch(settingName
, _T("chapterFontSize"), FALSE
, TRUE
))
1150 StringToInt(settingValue
, &chapterFont
);
1151 else if (StringMatch(settingName
, _T("sectionFontSize"), FALSE
, TRUE
))
1152 StringToInt(settingValue
, §ionFont
);
1153 else if (StringMatch(settingName
, _T("subsectionFontSize"), FALSE
, TRUE
))
1154 StringToInt(settingValue
, &subsectionFont
);
1155 else if (StringMatch(settingName
, _T("titleFontSize"), FALSE
, TRUE
))
1156 StringToInt(settingValue
, &titleFont
);
1157 else if (StringMatch(settingName
, _T("authorFontSize"), FALSE
, TRUE
))
1158 StringToInt(settingValue
, &authorFont
);
1159 else if (StringMatch(settingName
, _T("ignoreInput"), FALSE
, TRUE
))
1160 IgnorableInputFiles
.Add(wxFileNameFromPath(settingValue
));
1161 else if (StringMatch(settingName
, _T("mirrorMargins"), FALSE
, TRUE
))
1162 mirrorMargins
= StringTobool(settingValue
);
1163 else if (StringMatch(settingName
, _T("runTwice"), FALSE
, TRUE
))
1164 runTwice
= StringTobool(settingValue
);
1165 else if (StringMatch(settingName
, _T("isInteractive"), FALSE
, TRUE
))
1166 isInteractive
= StringTobool(settingValue
);
1167 else if (StringMatch(settingName
, _T("headerRule"), FALSE
, TRUE
))
1168 headerRule
= StringTobool(settingValue
);
1169 else if (StringMatch(settingName
, _T("footerRule"), FALSE
, TRUE
))
1170 footerRule
= StringTobool(settingValue
);
1171 else if (StringMatch(settingName
, _T("combineSubSections"), FALSE
, TRUE
))
1172 combineSubSections
= StringTobool(settingValue
);
1173 else if (StringMatch(settingName
, _T("listLabelIndent"), FALSE
, TRUE
))
1174 StringToInt(settingValue
, &labelIndentTab
);
1175 else if (StringMatch(settingName
, _T("listItemIndent"), FALSE
, TRUE
))
1176 StringToInt(settingValue
, &itemIndentTab
);
1177 else if (StringMatch(settingName
, _T("useUpButton"), FALSE
, TRUE
))
1178 useUpButton
= StringTobool(settingValue
);
1179 else if (StringMatch(settingName
, _T("useHeadingStyles"), FALSE
, TRUE
))
1180 useHeadingStyles
= StringTobool(settingValue
);
1181 else if (StringMatch(settingName
, _T("useWord"), FALSE
, TRUE
))
1182 useWord
= StringTobool(settingValue
);
1183 else if (StringMatch(settingName
, _T("contentsDepth"), FALSE
, TRUE
))
1184 StringToInt(settingValue
, &contentsDepth
);
1185 else if (StringMatch(settingName
, _T("generateHPJ"), FALSE
, TRUE
))
1186 generateHPJ
= StringTobool(settingValue
);
1187 else if (StringMatch(settingName
, _T("truncateFilenames"), FALSE
, TRUE
))
1188 truncateFilenames
= StringTobool(settingValue
);
1189 else if (StringMatch(settingName
, _T("winHelpVersion"), FALSE
, TRUE
))
1190 StringToInt(settingValue
, &winHelpVersion
);
1191 else if (StringMatch(settingName
, _T("winHelpContents"), FALSE
, TRUE
))
1192 winHelpContents
= StringTobool(settingValue
);
1193 else if (StringMatch(settingName
, _T("htmlIndex"), FALSE
, TRUE
))
1194 htmlIndex
= StringTobool(settingValue
);
1195 else if (StringMatch(settingName
, _T("htmlWorkshopFiles"), FALSE
, TRUE
))
1196 htmlWorkshopFiles
= StringTobool(settingValue
);
1197 else if (StringMatch(settingName
, _T("htmlFrameContents"), FALSE
, TRUE
))
1198 htmlFrameContents
= StringTobool(settingValue
);
1199 else if (StringMatch(settingName
, _T("htmlStylesheet"), FALSE
, TRUE
))
1201 if (htmlStylesheet
) delete[] htmlStylesheet
;
1202 htmlStylesheet
= copystring(settingValue
);
1204 else if (StringMatch(settingName
, _T("upperCaseNames"), FALSE
, TRUE
))
1205 upperCaseNames
= StringTobool(settingValue
);
1206 else if (StringMatch(settingName
, _T("ignoreBadRefs"), FALSE
, TRUE
))
1207 ignoreBadRefs
= StringTobool(settingValue
);
1208 else if (StringMatch(settingName
, _T("htmlFaceName"), FALSE
, TRUE
))
1210 delete[] htmlFaceName
;
1211 htmlFaceName
= copystring(settingValue
);
1213 else if (StringMatch(settingName
, _T("winHelpTitle"), FALSE
, TRUE
))
1216 delete[] winHelpTitle
;
1217 winHelpTitle
= copystring(settingValue
);
1219 else if (StringMatch(settingName
, _T("indexSubsections"), FALSE
, TRUE
))
1220 indexSubsections
= StringTobool(settingValue
);
1221 else if (StringMatch(settingName
, _T("compatibility"), FALSE
, TRUE
))
1222 compatibilityMode
= StringTobool(settingValue
);
1223 else if (StringMatch(settingName
, _T("defaultColumnWidth"), FALSE
, TRUE
))
1225 StringToInt(settingValue
, &defaultTableColumnWidth
);
1226 defaultTableColumnWidth
= 20*defaultTableColumnWidth
;
1228 else if (StringMatch(settingName
, _T("bitmapMethod"), FALSE
, TRUE
))
1230 if ((wxStrcmp(settingValue
, _T("includepicture")) != 0) && (wxStrcmp(settingValue
, _T("hex")) != 0) &&
1231 (wxStrcmp(settingValue
, _T("import")) != 0))
1234 OnError(_T("Unknown bitmapMethod"));
1235 wxStrcpy(errorCode
, _T("Unknown bitmapMethod"));
1239 delete[] bitmapMethod
;
1240 bitmapMethod
= copystring(settingValue
);
1243 else if (StringMatch(settingName
, _T("htmlBrowseButtons"), FALSE
, TRUE
))
1245 if (wxStrcmp(settingValue
, _T("none")) == 0)
1246 htmlBrowseButtons
= HTML_BUTTONS_NONE
;
1247 else if (wxStrcmp(settingValue
, _T("bitmap")) == 0)
1248 htmlBrowseButtons
= HTML_BUTTONS_BITMAP
;
1249 else if (wxStrcmp(settingValue
, _T("text")) == 0)
1250 htmlBrowseButtons
= HTML_BUTTONS_TEXT
;
1254 OnInform(_T("Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text."));
1255 wxStrcpy(errorCode
, _T("Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text."));
1258 else if (StringMatch(settingName
, _T("backgroundImage"), FALSE
, TRUE
))
1260 backgroundImageString
= copystring(settingValue
);
1262 else if (StringMatch(settingName
, _T("backgroundColour"), FALSE
, TRUE
))
1264 delete[] backgroundColourString
;
1265 backgroundColourString
= copystring(settingValue
);
1267 else if (StringMatch(settingName
, _T("textColour"), FALSE
, TRUE
))
1269 textColourString
= copystring(settingValue
);
1271 else if (StringMatch(settingName
, _T("linkColour"), FALSE
, TRUE
))
1273 linkColourString
= copystring(settingValue
);
1275 else if (StringMatch(settingName
, _T("followedLinkColour"), FALSE
, TRUE
))
1277 followedLinkColourString
= copystring(settingValue
);
1279 else if (StringMatch(settingName
, _T("conversionMode"), FALSE
, TRUE
))
1281 if (StringMatch(settingValue
, _T("RTF"), FALSE
, TRUE
))
1283 winHelp
= FALSE
; convertMode
= TEX_RTF
;
1285 else if (StringMatch(settingValue
, _T("WinHelp"), FALSE
, TRUE
))
1287 winHelp
= TRUE
; convertMode
= TEX_RTF
;
1289 else if (StringMatch(settingValue
, _T("XLP"), FALSE
, TRUE
) ||
1290 StringMatch(settingValue
, _T("wxHelp"), FALSE
, TRUE
))
1292 convertMode
= TEX_XLP
;
1294 else if (StringMatch(settingValue
, _T("HTML"), FALSE
, TRUE
))
1296 convertMode
= TEX_HTML
;
1301 OnInform(_T("Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML."));
1302 wxStrcpy(errorCode
, _T("Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML."));
1305 else if (StringMatch(settingName
, _T("documentFontSize"), FALSE
, TRUE
))
1308 StringToInt(settingValue
, &n
);
1309 if (n
== 10 || n
== 11 || n
== 12)
1314 wxSprintf(buf
, _T("Initialisation file error: nonstandard document font size %d."), n
);
1317 wxStrcpy(errorCode
, buf
);
1323 wxSprintf(buf
, _T("Initialisation file error: unrecognised setting %s."), settingName
);
1326 wxStrcpy(errorCode
, buf
);
1331 bool ReadCustomMacros(wxChar
*filename
)
1333 if (!wxFileExists(filename
))
1336 wxSTD ifstream
istr(filename
, wxSTD
ios::in
);
1338 if (istr
.bad()) return FALSE
;
1340 CustomMacroList
.Clear();
1342 wxChar macroName
[100];
1343 wxChar macroBody
[1000];
1348 BibEatWhiteSpace(istr
);
1353 if (ch
!= '\\') // Not a macro definition, so must be NAME=VALUE
1355 wxChar settingName
[100];
1356 settingName
[0] = ch
;
1357 BibReadWord(istr
, (settingName
+1));
1358 BibEatWhiteSpace(istr
);
1362 OnError(_T("Expected = following name: malformed tex2rtf.ini file."));
1367 wxChar settingValue
[200];
1368 BibEatWhiteSpace(istr
);
1369 BibReadToEOL(istr
, settingValue
);
1370 RegisterSetting(settingName
, settingValue
);
1375 BibReadWord(istr
, macroName
);
1376 BibEatWhiteSpace(istr
);
1380 OnError(_T("Expected [ followed by number of arguments: malformed tex2rtf.ini file."));
1387 OnError(_T("Expected ] following number of arguments: malformed tex2rtf.ini file."));
1390 BibEatWhiteSpace(istr
);
1394 OnError(_T("Expected { followed by macro body: malformed tex2rtf.ini file."));
1397 CustomMacro
*macro
= new CustomMacro(macroName
, noArgs
, NULL
);
1398 BibReadValue(istr
, macroBody
, FALSE
, FALSE
); // Don't ignore extra braces
1399 if (wxStrlen(macroBody
) > 0)
1400 macro
->macroBody
= copystring(macroBody
);
1402 BibEatWhiteSpace(istr
);
1403 CustomMacroList
.Append(macroName
, macro
);
1404 AddMacroDef(ltCUSTOM_MACRO
, macroName
, noArgs
);
1408 wxSprintf(mbuf
, _T("Read initialization file %s."), filename
);
1413 CustomMacro
*FindCustomMacro(wxChar
*name
)
1415 wxNode
*node
= CustomMacroList
.Find(name
);
1418 CustomMacro
*macro
= (CustomMacro
*)node
->GetData();
1424 // Display custom macros
1425 void ShowCustomMacros(void)
1427 wxNode
*node
= CustomMacroList
.GetFirst();
1430 OnInform(_T("No custom macros loaded.\n"));
1437 CustomMacro
*macro
= (CustomMacro
*)node
->GetData();
1438 wxSprintf(buf
, _T("\\%s[%d]\n {%s}"), macro
->macroName
, macro
->noArgs
,
1439 macro
->macroBody
? macro
->macroBody
: _T(""));
1441 node
= node
->GetNext();
1445 // Parse a string into several comma-separated fields
1446 wxChar
*ParseMultifieldString(wxChar
*allFields
, int *pos
)
1448 static wxChar buffer
[300];
1450 int fieldIndex
= *pos
;
1451 int len
= wxStrlen(allFields
);
1453 bool keepGoing
= TRUE
;
1454 while ((fieldIndex
<= len
) && keepGoing
)
1456 if (allFields
[fieldIndex
] == _T(' '))
1461 else if (allFields
[fieldIndex
] == _T(','))
1463 *pos
= fieldIndex
+ 1;
1466 else if (allFields
[fieldIndex
] == 0)
1468 *pos
= fieldIndex
+ 1;
1473 buffer
[i
] = allFields
[fieldIndex
];
1479 if (oldPos
== (*pos
))
1493 ColourTableEntry::ColourTableEntry(const wxChar
*theName
, unsigned int r
, unsigned int g
, unsigned int b
)
1495 name
= copystring(theName
);
1501 ColourTableEntry::~ColourTableEntry(void)
1506 void AddColour(const wxChar
*theName
, unsigned int r
, unsigned int g
, unsigned int b
)
1508 wxNode
*node
= ColourTable
.Find(theName
);
1511 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->GetData();
1512 if (entry
->red
== r
|| entry
->green
== g
|| entry
->blue
== b
)
1520 ColourTableEntry
*entry
= new ColourTableEntry(theName
, r
, g
, b
);
1521 ColourTable
.Append(theName
, entry
);
1524 int FindColourPosition(wxChar
*theName
)
1527 wxNode
*node
= ColourTable
.GetFirst();
1530 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->GetData();
1531 if (wxStrcmp(theName
, entry
->name
) == 0)
1534 node
= node
->GetNext();
1539 // Converts e.g. "red" -> "#FF0000"
1540 extern void DecToHex(int, wxChar
*);
1541 bool FindColourHTMLString(wxChar
*theName
, wxChar
*buf
)
1543 wxNode
*node
= ColourTable
.GetFirst();
1546 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->GetData();
1547 if (wxStrcmp(theName
, entry
->name
) == 0)
1549 wxStrcpy(buf
, _T("#"));
1552 DecToHex(entry
->red
, buf2
);
1553 wxStrcat(buf
, buf2
);
1554 DecToHex(entry
->green
, buf2
);
1555 wxStrcat(buf
, buf2
);
1556 DecToHex(entry
->blue
, buf2
);
1557 wxStrcat(buf
, buf2
);
1561 node
= node
->GetNext();
1567 void InitialiseColourTable(void)
1569 // \\red0\\green0\\blue0;
1570 AddColour(_T("black"), 0,0,0);
1572 // \\red0\\green0\\blue255;\\red0\\green255\\blue255;\n");
1573 AddColour(_T("cyan"), 0,255,255);
1575 // \\red0\\green255\\blue0;
1576 AddColour(_T("green"), 0,255,0);
1578 // \\red255\\green0\\blue255;
1579 AddColour(_T("magenta"), 255,0,255);
1581 // \\red255\\green0\\blue0;
1582 AddColour(_T("red"), 255,0,0);
1584 // \\red255\\green255\\blue0;
1585 AddColour(_T("yellow"), 255,255,0);
1587 // \\red255\\green255\\blue255;}");
1588 AddColour(_T("white"), 255,255,255);
1592 * The purpose of this is to reduce the number of times wxYield is
1593 * called, since under Windows this can slow things down.
1596 void Tex2RTFYield(bool force
)
1599 static int yieldCount
= 0;
1606 if (yieldCount
== 0)
1616 // In both RTF generation and HTML generation for wxHelp version 2,
1617 // we need to associate \indexed keywords with the current filename/topics.
1619 // Hash table for lists of keywords for topics (WinHelp).
1620 wxHashTable
TopicTable(wxKEY_STRING
);
1621 void AddKeyWordForTopic(wxChar
*topic
, wxChar
*entry
, wxChar
*filename
)
1623 TexTopic
*texTopic
= (TexTopic
*)TopicTable
.Get(topic
);
1626 texTopic
= new TexTopic(filename
);
1627 texTopic
->keywords
= new wxStringList
;
1628 TopicTable
.Put(topic
, texTopic
);
1631 if (!texTopic
->keywords
->Member(entry
))
1632 texTopic
->keywords
->Add(entry
);
1635 void ClearKeyWordTable(void)
1637 TopicTable
.BeginFind();
1638 wxNode
*node
= TopicTable
.Next();
1641 TexTopic
*texTopic
= (TexTopic
*)node
->GetData();
1643 node
= TopicTable
.Next();
1650 * TexTopic structure
1653 TexTopic::TexTopic(wxChar
*f
)
1656 filename
= copystring(f
);
1659 hasChildren
= FALSE
;
1663 TexTopic::~TexTopic(void)
1671 // Convert case, according to upperCaseNames setting.
1672 wxChar
*ConvertCase(wxChar
*s
)
1674 static wxChar buf
[256];
1675 int len
= wxStrlen(s
);
1678 for (i
= 0; i
< len
; i
++)
1679 buf
[i
] = wxToupper(s
[i
]);
1681 for (i
= 0; i
< len
; i
++)
1682 buf
[i
] = wxTolower(s
[i
]);
1687 #if !WXWIN_COMPATIBILITY_2
1688 // if substring is TRUE, search for str1 in str2
1689 bool StringMatch(const wxChar
*str1
, const wxChar
*str2
, bool subString
,
1694 wxString
Sstr1(str1
);
1695 wxString
Sstr2(str2
);
1701 return Sstr2
.Index(Sstr1
) != (size_t)wxNOT_FOUND
;
1704 return exact
? wxString(str2
).Cmp(str1
) == 0 :
1705 wxString(str2
).CmpNoCase(str1
) == 0;