1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Miscellaneous utilities
4 // Author: Julian Smart
5 // Modified by: Wlodzimiez ABX Skiba 2003/2004 Unicode support
9 // Copyright: (c) Julian Smart
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
14 #pragma implementation
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
47 #if !WXWIN_COMPATIBILITY_2_4
48 static inline wxChar
* copystring(const wxChar
* s
)
49 { return wxStrcpy(new wxChar
[wxStrlen(s
) + 1], s
); }
52 wxHashTable
TexReferences(wxKEY_STRING
);
53 wxList
BibList(wxKEY_STRING
);
54 wxStringList CitationList
;
55 wxList
ColourTable(wxKEY_STRING
);
56 wxHashTable
BibStringTable(wxKEY_STRING
);
57 wxList
CustomMacroList(wxKEY_STRING
);
58 TexChunk
*currentSection
= NULL
;
59 wxChar
*fakeCurrentSection
= NULL
;
61 static long BibLine
= 1;
63 void OutputCurrentSection(void)
65 if (fakeCurrentSection
)
66 TexOutput(fakeCurrentSection
);
67 else if (currentSection
)
68 TraverseChildrenFromChunk(currentSection
);
71 // Nasty but the way things are done now, necessary,
72 // in order to output a chunk properly to a string (macros and all).
73 void OutputCurrentSectionToString(wxChar
*buf
)
75 if (fakeCurrentSection
)
76 wxStrcpy(buf
, fakeCurrentSection
);
78 OutputChunkToString(currentSection
, buf
);
81 void OutputChunkToString(TexChunk
*chunk
, wxChar
*buf
)
83 FILE *tempfd
= wxFopen(_T("tmp.tmp"), _T("w"));
87 FILE *old1
= CurrentOutput1
;
88 FILE *old2
= CurrentOutput2
;
90 CurrentOutput1
= tempfd
;
91 CurrentOutput2
= NULL
;
93 TraverseChildrenFromChunk(chunk
);
95 CurrentOutput1
= old1
;
96 CurrentOutput2
= old2
;
100 // Read from file into string
101 tempfd
= wxFopen(_T("tmp.tmp"), _T("r"));
120 wxRemoveFile(_T("tmp.tmp"));
123 // Called by Tex2Any to simulate a section
124 void FakeCurrentSection(wxChar
*fakeSection
, bool addToContents
)
126 currentSection
= NULL
;
127 if (fakeCurrentSection
) delete[] fakeCurrentSection
;
128 fakeCurrentSection
= copystring(fakeSection
);
130 if (DocumentStyle
== LATEX_ARTICLE
)
132 int mac
= ltSECTIONHEADING
;
134 mac
= ltSECTIONHEADINGSTAR
;
135 OnMacro(mac
, 0, true);
136 OnMacro(mac
, 0, false);
140 int mac
= ltCHAPTERHEADING
;
142 mac
= ltCHAPTERHEADINGSTAR
;
143 OnMacro(mac
, 0, true);
144 OnMacro(mac
, 0, false);
146 if (fakeCurrentSection
) delete[] fakeCurrentSection
;
147 fakeCurrentSection
= NULL
;
150 // Look for \label macro, use this ref name if found or
151 // make up a topic name otherwise.
152 static long topicCounter
= 0;
154 void ResetTopicCounter(void)
159 static wxChar
*forceTopicName
= NULL
;
161 void ForceTopicName(const wxChar
*name
)
164 delete[] forceTopicName
;
166 forceTopicName
= copystring(name
);
168 forceTopicName
= NULL
;
171 wxChar
*FindTopicName(TexChunk
*chunk
)
174 return forceTopicName
;
176 wxChar
*topicName
= NULL
;
177 static wxChar topicBuf
[100];
179 if (chunk
&& (chunk
->type
== CHUNK_TYPE_MACRO
) &&
180 (chunk
->macroId
== ltLABEL
))
182 wxNode
*node
= chunk
->children
.GetFirst();
185 TexChunk
*child
= (TexChunk
*)node
->GetData();
186 if (child
->type
== CHUNK_TYPE_ARG
)
188 wxNode
*snode
= child
->children
.GetFirst();
191 TexChunk
*schunk
= (TexChunk
*)snode
->GetData();
192 if (schunk
->type
== CHUNK_TYPE_STRING
)
193 topicName
= schunk
->value
;
202 wxSnprintf(topicBuf
, sizeof(topicBuf
), _T("topic%ld"), topicCounter
);
209 * Simulate argument data, so we can 'drive' clients which implement
210 * certain basic formatting behaviour.
211 * Snag is that some save a TexChunk, so don't use yet...
215 void StartSimulateArgument(wxChar
*data
)
217 wxStrcpy(currentArgData
, data
);
221 void EndSimulateArgument(void)
227 * Parse and convert unit arguments to points
231 int ParseUnitArgument(wxChar
*unitArg
)
233 float conversionFactor
= 1.0;
234 float unitValue
= 0.0;
235 int len
= wxStrlen(unitArg
);
236 // Get rid of any accidentally embedded commands
237 for (int i
= 0; i
< len
; i
++)
238 if (unitArg
[i
] == '\\')
240 len
= wxStrlen(unitArg
);
242 if (unitArg
&& (len
> 0) && (isdigit(unitArg
[0]) || unitArg
[0] == '-'))
244 wxSscanf(unitArg
, _T("%f"), &unitValue
);
248 units
[0] = unitArg
[len
-2];
249 units
[1] = unitArg
[len
-1];
251 if (wxStrcmp(units
, _T("in")) == 0)
252 conversionFactor
= 72.0;
253 else if (wxStrcmp(units
, _T("cm")) == 0)
254 conversionFactor
= (float)72.0/(float)2.51;
255 else if (wxStrcmp(units
, _T("mm")) == 0)
256 conversionFactor
= (float)72.0/(float)25.1;
257 else if (wxStrcmp(units
, _T("pt")) == 0)
258 conversionFactor
= 1;
260 return (int)(unitValue
*conversionFactor
);
266 * Strip off any extension (dot something) from end of file,
267 * IF one exists. Inserts zero into buffer.
271 void StripExtension(wxChar
*buffer
)
273 int len
= wxStrlen(buffer
);
277 if (buffer
[i
] == '.')
291 void SetFontSizes(int pointSize
)
343 void AddTexRef(wxChar
*name
, wxChar
*file
, wxChar
*sectionName
,
344 int chapter
, int section
, int subsection
, int subsubsection
)
346 TexRef
*texRef
= (TexRef
*)TexReferences
.Get(name
);
347 if (texRef
) TexReferences
.Delete(name
);
354 wxStrcat(buf, sectionName);
361 wxSnprintf(buf2
, sizeof(buf2
), _T("%d"), chapter
);
368 wxStrcat(buf
, _T("."));
370 wxSnprintf(buf2
, sizeof(buf2
), _T("%d"), section
);
376 wxStrcat(buf
, _T("."));
377 wxSnprintf(buf2
, sizeof(buf2
), _T("%d"), subsection
);
383 wxStrcat(buf
, _T("."));
384 wxSnprintf(buf2
, sizeof(buf2
), _T("%d"), subsubsection
);
387 wxChar
*tmp
= ((wxStrlen(buf
) > 0) ? buf
: (wxChar
*)NULL
);
388 TexReferences
.Put(name
, new TexRef(name
, file
, tmp
, sectionName
));
391 void WriteTexReferences(wxChar
*filename
)
394 wxString name
= filename
;
395 wxSTD ofstream
ostr((char const *)name
.fn_str());
396 if (ostr
.bad()) return;
398 TexReferences
.BeginFind();
399 wxHashTable::Node
*node
= TexReferences
.Next();
403 TexRef
*ref
= (TexRef
*)node
->GetData();
404 converter
= ref
->refLabel
;
405 ostr
<< converter
.mb_str();
407 converter
= (ref
->refFile
? ref
->refFile
: _T("??"));
408 ostr
<< converter
.mb_str();
410 converter
= (ref
->sectionName
? ref
->sectionName
: _T("??")) ;
411 ostr
<< converter
.mb_str();
413 converter
= (ref
->sectionNumber
? ref
->sectionNumber
: _T("??")) ;
414 ostr
<< converter
.mb_str();
416 if (!ref
->sectionNumber
|| (wxStrcmp(ref
->sectionNumber
, _T("??")) == 0 && wxStrcmp(ref
->sectionName
, _T("??")) == 0))
419 wxSnprintf(buf
, sizeof(buf
), _T("Warning: reference %s not resolved."), ref
->refLabel
);
422 node
= TexReferences
.Next();
426 void ReadTexReferences(wxChar
*filename
)
428 if (!wxFileExists(filename
))
431 wxString name
= filename
;
432 wxSTD ifstream
istr((char const *)name
.fn_str(), wxSTD
ios::in
);
434 if (istr
.bad()) return;
439 char sectionName
[100];
449 istr
.get(ch
); // Read past space
452 while (ch
!= '\n' && !istr
.eof())
460 wxString label_string
= wxString::FromAscii(label
);
461 wxString file_string
= wxString::FromAscii(file
);
462 wxString sectionName_string
= wxString::FromAscii(sectionName
);
463 wxString section_string
= wxString::FromAscii(section
);
465 // gt - needed to trick the hash table "TexReferences" into deleting the key
466 // strings it creates in the Put() function, but not the item that is
467 // created here, as that is destroyed elsewhere. Without doing this, there
468 // were massive memory leaks
469 TexReferences
.DeleteContents(true);
471 label_string
.c_str(),
473 label_string
.c_str(),
475 section_string
.c_str(),
476 sectionName_string
.c_str()
479 TexReferences
.DeleteContents(false);
486 * Bibliography-handling code
490 void BibEatWhiteSpace(wxSTD istream
& str
)
492 char ch
= (char)str
.peek();
494 while (!str
.eof() && (ch
== ' ' || ch
== '\t' || ch
== 13 || ch
== 10 || ch
== (char)EOF
))
499 if ((ch
== (char)EOF
) || str
.eof()) return;
500 ch
= (char)str
.peek();
503 // Ignore end-of-line comments
504 if (ch
== '%' || ch
== ';' || ch
== '#')
507 ch
= (char)str
.peek();
508 while (ch
!= 10 && ch
!= 13 && !str
.eof())
511 ch
= (char)str
.peek();
513 BibEatWhiteSpace(str
);
517 // Read word up to { or , or space
518 void BibReadWord(wxSTD istream
& istr
, wxChar
*buffer
)
522 char ch
= (char)istr
.peek();
523 while (!istr
.eof() && ch
!= ' ' && ch
!= '{' && ch
!= '(' && ch
!= 13 && ch
!= 10 && ch
!= '\t' &&
524 ch
!= ',' && ch
!= '=')
529 ch
= (char)istr
.peek();
534 // Read string (double-quoted or not) to end quote or EOL
535 void BibReadToEOL(wxSTD istream
& istr
, wxChar
*buffer
)
539 char ch
= (char)istr
.peek();
540 bool inQuotes
= false;
544 ch
= (char)istr
.peek();
547 // If in quotes, read white space too. If not,
548 // stop at white space or comment.
549 while (!istr
.eof() && ch
!= 13 && ch
!= 10 && ch
!= _T('"') &&
550 (inQuotes
|| ((ch
!= _T(' ')) && (ch
!= 9) &&
551 (ch
!= _T(';')) && (ch
!= _T('%')) && (ch
!= _T('#')))))
556 ch
= (char)istr
.peek();
563 // Read }-terminated value, taking nested braces into account.
564 void BibReadValue(wxSTD istream
& istr
, wxChar
*buffer
, bool ignoreBraces
= true,
565 bool quotesMayTerminate
= true)
570 char ch
= (char)istr
.peek();
571 bool stopping
= false;
572 while (!istr
.eof() && !stopping
)
578 wxSnprintf(buf
, sizeof(buf
), _T("Sorry, value > 4000 chars in bib file at line %ld."), BibLine
);
579 wxLogError(buf
, "Tex2RTF Fatal Error");
596 else if (quotesMayTerminate
&& ch
== '"')
603 if (!ignoreBraces
|| (ch
!= '{' && ch
!= '}'))
613 wxUnusedVar(stopping
);
616 bool ReadBib(wxChar
*filename
)
618 if (!wxFileExists(filename
))
621 wxString name
= filename
;
623 wxSTD ifstream
istr((char const *)name
.fn_str(), wxSTD
ios::in
);
624 if (istr
.bad()) return false;
628 OnInform(_T("Reading .bib file..."));
631 wxChar fieldValue
[4000];
632 wxChar recordType
[100];
633 wxChar recordKey
[100];
634 wxChar recordField
[100];
639 BibEatWhiteSpace(istr
);
643 wxSnprintf(buf
, sizeof(buf
), _T("Expected @: malformed bib file at line %ld (%s)"), BibLine
, filename
);
647 BibReadWord(istr
, recordType
);
648 BibEatWhiteSpace(istr
);
650 if (ch
!= '{' && ch
!= '(')
652 wxSnprintf(buf
, sizeof(buf
), _T("Expected { or ( after record type: malformed .bib file at line %ld (%s)"), BibLine
, filename
);
656 BibEatWhiteSpace(istr
);
657 if (StringMatch(recordType
, _T("string"), false, true))
659 BibReadWord(istr
, recordType
);
660 BibEatWhiteSpace(istr
);
664 wxSnprintf(buf
, sizeof(buf
), _T("Expected = after string key: malformed .bib file at line %ld (%s)"), BibLine
, filename
);
668 BibEatWhiteSpace(istr
);
670 if (ch
!= '"' && ch
!= '{')
672 wxSnprintf(buf
, sizeof(buf
), _T("Expected = after string key: malformed .bib file at line %ld (%s)"), BibLine
, filename
);
676 BibReadValue(istr
, fieldValue
);
678 // Now put in hash table if necesary
679 if (!BibStringTable
.Get(recordType
))
680 BibStringTable
.Put(recordType
, (wxObject
*)copystring(fieldValue
));
682 // Read closing ) or }
683 BibEatWhiteSpace(istr
);
685 BibEatWhiteSpace(istr
);
689 BibReadWord(istr
, recordKey
);
691 BibEntry
*bibEntry
= new BibEntry
;
692 bibEntry
->key
= copystring(recordKey
);
693 bibEntry
->type
= copystring(recordType
);
695 bool moreRecords
= true;
696 while (moreRecords
&& !istr
.eof())
698 BibEatWhiteSpace(istr
);
700 if (ch
== '}' || ch
== ')')
706 BibEatWhiteSpace(istr
);
707 BibReadWord(istr
, recordField
);
708 BibEatWhiteSpace(istr
);
712 wxSnprintf(buf
, sizeof(buf
), _T("Expected = after field type: malformed .bib file at line %ld (%s)"), BibLine
, filename
);
716 BibEatWhiteSpace(istr
);
718 if (ch
!= '{' && ch
!= '"')
721 BibReadWord(istr
, fieldValue
+1);
723 // If in the table of strings, replace with string from table.
724 wxChar
*s
= (wxChar
*)BibStringTable
.Get(fieldValue
);
727 wxStrcpy(fieldValue
, s
);
731 BibReadValue(istr
, fieldValue
, true, (ch
== _T('"') ? true : false));
733 // Now we can add a field
734 if (StringMatch(recordField
, _T("author"), false, true))
735 bibEntry
->author
= copystring(fieldValue
);
736 else if (StringMatch(recordField
, _T("key"), false, true))
738 else if (StringMatch(recordField
, _T("annotate"), false, true))
740 else if (StringMatch(recordField
, _T("abstract"), false, true))
742 else if (StringMatch(recordField
, _T("edition"), false, true))
744 else if (StringMatch(recordField
, _T("howpublished"), false, true))
746 else if (StringMatch(recordField
, _T("note"), false, true) || StringMatch(recordField
, _T("notes"), false, true))
748 else if (StringMatch(recordField
, _T("series"), false, true))
750 else if (StringMatch(recordField
, _T("type"), false, true))
752 else if (StringMatch(recordField
, _T("keywords"), false, true))
754 else if (StringMatch(recordField
, _T("editor"), false, true) || StringMatch(recordField
, _T("editors"), false, true))
755 bibEntry
->editor
= copystring(fieldValue
);
756 else if (StringMatch(recordField
, _T("title"), false, true))
757 bibEntry
->title
= copystring(fieldValue
);
758 else if (StringMatch(recordField
, _T("booktitle"), false, true))
759 bibEntry
->booktitle
= copystring(fieldValue
);
760 else if (StringMatch(recordField
, _T("journal"), false, true))
761 bibEntry
->journal
= copystring(fieldValue
);
762 else if (StringMatch(recordField
, _T("volume"), false, true))
763 bibEntry
->volume
= copystring(fieldValue
);
764 else if (StringMatch(recordField
, _T("number"), false, true))
765 bibEntry
->number
= copystring(fieldValue
);
766 else if (StringMatch(recordField
, _T("year"), false, true))
767 bibEntry
->year
= copystring(fieldValue
);
768 else if (StringMatch(recordField
, _T("month"), false, true))
769 bibEntry
->month
= copystring(fieldValue
);
770 else if (StringMatch(recordField
, _T("pages"), false, true))
771 bibEntry
->pages
= copystring(fieldValue
);
772 else if (StringMatch(recordField
, _T("publisher"), false, true))
773 bibEntry
->publisher
= copystring(fieldValue
);
774 else if (StringMatch(recordField
, _T("address"), false, true))
775 bibEntry
->address
= copystring(fieldValue
);
776 else if (StringMatch(recordField
, _T("institution"), false, true) || StringMatch(recordField
, _T("school"), false, true))
777 bibEntry
->institution
= copystring(fieldValue
);
778 else if (StringMatch(recordField
, _T("organization"), false, true) || StringMatch(recordField
, _T("organisation"), false, true))
779 bibEntry
->organization
= copystring(fieldValue
);
780 else if (StringMatch(recordField
, _T("comment"), false, true) || StringMatch(recordField
, _T("comments"), false, true))
781 bibEntry
->comment
= copystring(fieldValue
);
782 else if (StringMatch(recordField
, _T("annote"), false, true))
783 bibEntry
->comment
= copystring(fieldValue
);
784 else if (StringMatch(recordField
, _T("chapter"), false, true))
785 bibEntry
->chapter
= copystring(fieldValue
);
788 wxSnprintf(buf
, sizeof(buf
), _T("Unrecognised bib field type %s at line %ld (%s)"), recordField
, BibLine
, filename
);
793 BibList
.Append(recordKey
, bibEntry
);
794 BibEatWhiteSpace(istr
);
800 void OutputBibItem(TexRef
*ref
, BibEntry
*bib
)
804 OnMacro(ltNUMBEREDBIBITEM
, 2, true);
805 OnArgument(ltNUMBEREDBIBITEM
, 1, true);
806 TexOutput(ref
->sectionNumber
);
807 OnArgument(ltNUMBEREDBIBITEM
, 1, false);
808 OnArgument(ltNUMBEREDBIBITEM
, 2, true);
811 OnMacro(ltBF
, 1, true);
812 OnArgument(ltBF
, 1, true);
814 TexOutput(bib
->author
);
815 OnArgument(ltBF
, 1, false);
816 OnMacro(ltBF
, 1, false);
817 if (bib
->author
&& (wxStrlen(bib
->author
) > 0) && (bib
->author
[wxStrlen(bib
->author
) - 1] != '.'))
824 TexOutput(bib
->year
);
829 TexOutput(bib
->month
);
832 if (bib
->year
|| bib
->month
)
835 if (StringMatch(bib
->type
, _T("article"), false, true))
839 TexOutput(bib
->title
);
844 OnMacro(ltIT
, 1, true);
845 OnArgument(ltIT
, 1, true);
846 TexOutput(bib
->journal
);
847 OnArgument(ltIT
, 1, false);
848 OnMacro(ltIT
, 1, false);
853 OnMacro(ltBF
, 1, true);
854 OnArgument(ltBF
, 1, true);
855 TexOutput(bib
->volume
);
856 OnArgument(ltBF
, 1, false);
857 OnMacro(ltBF
, 1, false);
862 TexOutput(bib
->number
);
867 TexOutput(_T(", pages "));
868 TexOutput(bib
->pages
);
872 else if (StringMatch(bib
->type
, _T("book"), false, true) ||
873 StringMatch(bib
->type
, _T("unpublished"), false, true) ||
874 StringMatch(bib
->type
, _T("manual"), false, true) ||
875 StringMatch(bib
->type
, _T("phdthesis"), false, true) ||
876 StringMatch(bib
->type
, _T("mastersthesis"), false, true) ||
877 StringMatch(bib
->type
, _T("misc"), false, true) ||
878 StringMatch(bib
->type
, _T("techreport"), false, true) ||
879 StringMatch(bib
->type
, _T("booklet"), false, true))
881 if (bib
->title
|| bib
->booktitle
)
883 OnMacro(ltIT
, 1, true);
884 OnArgument(ltIT
, 1, true);
885 TexOutput(bib
->title
? bib
->title
: bib
->booktitle
);
887 OnArgument(ltIT
, 1, false);
888 OnMacro(ltIT
, 1, false);
890 if (StringMatch(bib
->type
, _T("phdthesis"), false, true))
891 TexOutput(_T("PhD thesis. "));
892 if (StringMatch(bib
->type
, _T("techreport"), false, true))
893 TexOutput(_T("Technical report. "));
896 TexOutput(_T("Ed. "));
897 TexOutput(bib
->editor
);
900 if (bib
->institution
)
902 TexOutput(bib
->institution
);
905 if (bib
->organization
)
907 TexOutput(bib
->organization
);
912 TexOutput(bib
->publisher
);
917 TexOutput(bib
->address
);
921 else if (StringMatch(bib
->type
, _T("inbook"), false, true) ||
922 StringMatch(bib
->type
, _T("inproceedings"), false, true) ||
923 StringMatch(bib
->type
, _T("incollection"), false, true) ||
924 StringMatch(bib
->type
, _T("conference"), false, true))
928 TexOutput(bib
->title
);
932 TexOutput(_T(", from "));
933 OnMacro(ltIT
, 1, true);
934 OnArgument(ltIT
, 1, true);
935 TexOutput(bib
->booktitle
);
937 OnArgument(ltIT
, 1, false);
938 OnMacro(ltIT
, 1, false);
942 TexOutput(_T(", ed. "));
943 TexOutput(bib
->editor
);
948 TexOutput(bib
->publisher
);
952 if (bib
->publisher
) TexOutput(_T(", "));
953 else TexOutput(_T(" "));
954 TexOutput(bib
->address
);
956 if (bib
->publisher
|| bib
->address
)
962 OnMacro(ltBF
, 1, true);
963 OnArgument(ltBF
, 1, true);
964 TexOutput(bib
->volume
);
965 OnArgument(ltBF
, 1, false);
966 OnMacro(ltBF
, 1, false);
973 TexOutput(bib
->number
);
978 TexOutput(_T(" Number "));
979 TexOutput(bib
->number
);
985 TexOutput(_T(" Chap. "));
986 TexOutput(bib
->chapter
);
990 if (bib
->chapter
) TexOutput(_T(", pages "));
991 else TexOutput(_T(" Pages "));
992 TexOutput(bib
->pages
);
996 OnArgument(ltNUMBEREDBIBITEM
, 2, false);
997 OnMacro(ltNUMBEREDBIBITEM
, 2, false);
1000 void OutputBib(void)
1002 // Write the heading
1003 ForceTopicName(_T("bibliography"));
1004 FakeCurrentSection(ReferencesNameString
);
1005 ForceTopicName(NULL
);
1007 OnMacro(ltPAR
, 0, true);
1008 OnMacro(ltPAR
, 0, false);
1010 if ((convertMode
== TEX_RTF
) && !winHelp
)
1012 OnMacro(ltPAR
, 0, true);
1013 OnMacro(ltPAR
, 0, false);
1016 wxStringListNode
*node
= CitationList
.GetFirst();
1019 wxChar
*citeKey
= (wxChar
*)node
->GetData();
1020 // wxNode *texNode = TexReferences.Find(citeKey);
1021 TexRef
*ref
= (TexRef
*)TexReferences
.Get(citeKey
);
1022 wxNode
*bibNode
= BibList
.Find(citeKey
);
1025 BibEntry
*entry
= (BibEntry
*)bibNode
->GetData();
1026 OutputBibItem(ref
, entry
);
1028 node
= node
->GetNext();
1032 static int citeCount
= 1;
1034 void ResolveBibReferences(void)
1036 if (CitationList
.GetCount() > 0)
1037 OnInform(_T("Resolving bibliographic references..."));
1041 wxStringListNode
*node
= CitationList
.GetFirst();
1045 wxChar
*citeKey
= (wxChar
*)node
->GetData();
1046 // wxNode *texNode = TexReferences.Find(citeKey);
1047 TexRef
*ref
= (TexRef
*)TexReferences
.Get(citeKey
);
1048 wxNode
*bibNode
= BibList
.Find(citeKey
);
1052 //BibEntry *entry = (BibEntry *)bibNode->GetData();
1053 if (ref
->sectionNumber
) delete[] ref
->sectionNumber
;
1054 wxSnprintf(buf
, sizeof(buf
), _T("[%d]"), citeCount
);
1055 ref
->sectionNumber
= copystring(buf
);
1060 wxSnprintf(buf
, sizeof(buf
), _T("Warning: bib ref %s not resolved."), citeKey
);
1063 node
= node
->GetNext();
1067 // Remember we need to resolve this citation
1068 void AddCitation(wxChar
*citeKey
)
1070 if (!CitationList
.Member(citeKey
))
1071 CitationList
.Add(citeKey
);
1073 if (!TexReferences
.Get(citeKey
))
1075 TexReferences
.Put(citeKey
, new TexRef(citeKey
, _T("??"), NULL
));
1079 TexRef
*FindReference(wxChar
*key
)
1081 return (TexRef
*)TexReferences
.Get(key
);
1085 * Custom macro stuff
1089 bool StringTobool(wxChar
*val
)
1091 if (wxStrncmp(val
, _T("yes"), 3) == 0 || wxStrncmp(val
, _T("YES"), 3) == 0 ||
1092 wxStrncmp(val
, _T("on"), 2) == 0 || wxStrncmp(val
, _T("ON"), 2) == 0 ||
1093 wxStrncmp(val
, _T("true"), 4) == 0 || wxStrncmp(val
, _T("true"), 4) == 0 ||
1094 wxStrncmp(val
, _T("ok"), 2) == 0 || wxStrncmp(val
, _T("OK"), 2) == 0 ||
1095 wxStrncmp(val
, _T("1"), 1) == 0)
1101 void RegisterIntSetting (const wxString
& s
, int *number
)
1111 // Define a variable value from the .ini file
1112 wxChar
*RegisterSetting(wxChar
*settingName
, wxChar
*settingValue
, bool interactive
)
1114 wxString
settingValueStr( settingValue
);
1116 static wxChar errorCode
[100];
1117 wxStrcpy(errorCode
, _T("OK"));
1118 if (StringMatch(settingName
, _T("chapterName"), false, true))
1120 delete[] ChapterNameString
;
1121 ChapterNameString
= copystring(settingValue
);
1123 else if (StringMatch(settingName
, _T("sectionName"), false, true))
1125 delete[] SectionNameString
;
1126 SectionNameString
= copystring(settingValue
);
1128 else if (StringMatch(settingName
, _T("subsectionName"), false, true))
1130 delete[] SubsectionNameString
;
1131 SubsectionNameString
= copystring(settingValue
);
1133 else if (StringMatch(settingName
, _T("subsubsectionName"), false, true))
1135 delete[] SubsubsectionNameString
;
1136 SubsubsectionNameString
= copystring(settingValue
);
1138 else if (StringMatch(settingName
, _T("indexName"), false, true))
1140 delete[] IndexNameString
;
1141 IndexNameString
= copystring(settingValue
);
1143 else if (StringMatch(settingName
, _T("contentsName"), false, true))
1145 delete[] ContentsNameString
;
1146 ContentsNameString
= copystring(settingValue
);
1148 else if (StringMatch(settingName
, _T("glossaryName"), false, true))
1150 delete[] GlossaryNameString
;
1151 GlossaryNameString
= copystring(settingValue
);
1153 else if (StringMatch(settingName
, _T("referencesName"), false, true))
1155 delete[] ReferencesNameString
;
1156 ReferencesNameString
= copystring(settingValue
);
1158 else if (StringMatch(settingName
, _T("tablesName"), false, true))
1160 delete[] TablesNameString
;
1161 TablesNameString
= copystring(settingValue
);
1163 else if (StringMatch(settingName
, _T("figuresName"), false, true))
1165 delete[] FiguresNameString
;
1166 FiguresNameString
= copystring(settingValue
);
1168 else if (StringMatch(settingName
, _T("tableName"), false, true))
1170 delete[] TableNameString
;
1171 TableNameString
= copystring(settingValue
);
1173 else if (StringMatch(settingName
, _T("figureName"), false, true))
1175 delete[] FigureNameString
;
1176 FigureNameString
= copystring(settingValue
);
1178 else if (StringMatch(settingName
, _T("abstractName"), false, true))
1180 delete[] AbstractNameString
;
1181 AbstractNameString
= copystring(settingValue
);
1183 else if (StringMatch(settingName
, _T("chapterFontSize"), false, true))
1184 RegisterIntSetting(settingValueStr
, &chapterFont
);
1185 else if (StringMatch(settingName
, _T("sectionFontSize"), false, true))
1186 RegisterIntSetting(settingValueStr
, §ionFont
);
1187 else if (StringMatch(settingName
, _T("subsectionFontSize"), false, true))
1188 RegisterIntSetting(settingValueStr
, &subsectionFont
);
1189 else if (StringMatch(settingName
, _T("titleFontSize"), false, true))
1190 RegisterIntSetting(settingValueStr
, &titleFont
);
1191 else if (StringMatch(settingName
, _T("authorFontSize"), false, true))
1192 RegisterIntSetting(settingValueStr
, &authorFont
);
1193 else if (StringMatch(settingName
, _T("ignoreInput"), false, true))
1194 IgnorableInputFiles
.Add(wxFileNameFromPath(settingValue
));
1195 else if (StringMatch(settingName
, _T("mirrorMargins"), false, true))
1196 mirrorMargins
= StringTobool(settingValue
);
1197 else if (StringMatch(settingName
, _T("runTwice"), false, true))
1198 runTwice
= StringTobool(settingValue
);
1199 else if (StringMatch(settingName
, _T("isInteractive"), false, true))
1200 isInteractive
= StringTobool(settingValue
);
1201 else if (StringMatch(settingName
, _T("headerRule"), false, true))
1202 headerRule
= StringTobool(settingValue
);
1203 else if (StringMatch(settingName
, _T("footerRule"), false, true))
1204 footerRule
= StringTobool(settingValue
);
1205 else if (StringMatch(settingName
, _T("combineSubSections"), false, true))
1206 combineSubSections
= StringTobool(settingValue
);
1207 else if (StringMatch(settingName
, _T("listLabelIndent"), false, true))
1208 RegisterIntSetting(settingValueStr
, &labelIndentTab
);
1209 else if (StringMatch(settingName
, _T("listItemIndent"), false, true))
1210 RegisterIntSetting(settingValueStr
, &itemIndentTab
);
1211 else if (StringMatch(settingName
, _T("useUpButton"), false, true))
1212 useUpButton
= StringTobool(settingValue
);
1213 else if (StringMatch(settingName
, _T("useHeadingStyles"), false, true))
1214 useHeadingStyles
= StringTobool(settingValue
);
1215 else if (StringMatch(settingName
, _T("useWord"), false, true))
1216 useWord
= StringTobool(settingValue
);
1217 else if (StringMatch(settingName
, _T("contentsDepth"), false, true))
1218 RegisterIntSetting(settingValueStr
, &contentsDepth
);
1219 else if (StringMatch(settingName
, _T("generateHPJ"), false, true))
1220 generateHPJ
= StringTobool(settingValue
);
1221 else if (StringMatch(settingName
, _T("truncateFilenames"), false, true))
1222 truncateFilenames
= StringTobool(settingValue
);
1223 else if (StringMatch(settingName
, _T("winHelpVersion"), false, true))
1224 RegisterIntSetting(settingValueStr
, &winHelpVersion
);
1225 else if (StringMatch(settingName
, _T("winHelpContents"), false, true))
1226 winHelpContents
= StringTobool(settingValue
);
1227 else if (StringMatch(settingName
, _T("htmlIndex"), false, true))
1228 htmlIndex
= StringTobool(settingValue
);
1229 else if (StringMatch(settingName
, _T("htmlWorkshopFiles"), false, true))
1230 htmlWorkshopFiles
= StringTobool(settingValue
);
1231 else if (StringMatch(settingName
, _T("htmlFrameContents"), false, true))
1232 htmlFrameContents
= StringTobool(settingValue
);
1233 else if (StringMatch(settingName
, _T("htmlStylesheet"), false, true))
1236 delete[] htmlStylesheet
;
1237 htmlStylesheet
= copystring(settingValue
);
1239 else if (StringMatch(settingName
, _T("upperCaseNames"), false, true))
1240 upperCaseNames
= StringTobool(settingValue
);
1241 else if (StringMatch(settingName
, _T("ignoreBadRefs"), false, true))
1242 ignoreBadRefs
= StringTobool(settingValue
);
1243 else if (StringMatch(settingName
, _T("htmlFaceName"), false, true))
1245 delete[] htmlFaceName
;
1246 htmlFaceName
= copystring(settingValue
);
1248 else if (StringMatch(settingName
, _T("winHelpTitle"), false, true))
1251 delete[] winHelpTitle
;
1252 winHelpTitle
= copystring(settingValue
);
1254 else if (StringMatch(settingName
, _T("indexSubsections"), false, true))
1255 indexSubsections
= StringTobool(settingValue
);
1256 else if (StringMatch(settingName
, _T("compatibility"), false, true))
1257 compatibilityMode
= StringTobool(settingValue
);
1258 else if (StringMatch(settingName
, _T("defaultColumnWidth"), false, true))
1260 RegisterIntSetting(settingValueStr
, &defaultTableColumnWidth
);
1261 defaultTableColumnWidth
= 20*defaultTableColumnWidth
;
1263 else if (StringMatch(settingName
, _T("bitmapMethod"), false, true))
1265 if ((wxStrcmp(settingValue
, _T("includepicture")) != 0) && (wxStrcmp(settingValue
, _T("hex")) != 0) &&
1266 (wxStrcmp(settingValue
, _T("import")) != 0))
1269 OnError(_T("Unknown bitmapMethod"));
1270 wxStrcpy(errorCode
, _T("Unknown bitmapMethod"));
1274 delete[] bitmapMethod
;
1275 bitmapMethod
= copystring(settingValue
);
1278 else if (StringMatch(settingName
, _T("htmlBrowseButtons"), false, true))
1280 if (wxStrcmp(settingValue
, _T("none")) == 0)
1281 htmlBrowseButtons
= HTML_BUTTONS_NONE
;
1282 else if (wxStrcmp(settingValue
, _T("bitmap")) == 0)
1283 htmlBrowseButtons
= HTML_BUTTONS_BITMAP
;
1284 else if (wxStrcmp(settingValue
, _T("text")) == 0)
1285 htmlBrowseButtons
= HTML_BUTTONS_TEXT
;
1289 OnInform(_T("Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text."));
1290 wxStrcpy(errorCode
, _T("Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text."));
1293 else if (StringMatch(settingName
, _T("backgroundImage"), false, true))
1295 backgroundImageString
= copystring(settingValue
);
1297 else if (StringMatch(settingName
, _T("backgroundColour"), false, true))
1299 delete[] backgroundColourString
;
1300 backgroundColourString
= copystring(settingValue
);
1302 else if (StringMatch(settingName
, _T("textColour"), false, true))
1304 textColourString
= copystring(settingValue
);
1306 else if (StringMatch(settingName
, _T("linkColour"), false, true))
1308 linkColourString
= copystring(settingValue
);
1310 else if (StringMatch(settingName
, _T("followedLinkColour"), false, true))
1312 followedLinkColourString
= copystring(settingValue
);
1314 else if (StringMatch(settingName
, _T("conversionMode"), false, true))
1316 if (StringMatch(settingValue
, _T("RTF"), false, true))
1318 winHelp
= false; convertMode
= TEX_RTF
;
1320 else if (StringMatch(settingValue
, _T("WinHelp"), false, true))
1322 winHelp
= true; convertMode
= TEX_RTF
;
1324 else if (StringMatch(settingValue
, _T("XLP"), false, true) ||
1325 StringMatch(settingValue
, _T("wxHelp"), false, true))
1327 convertMode
= TEX_XLP
;
1329 else if (StringMatch(settingValue
, _T("HTML"), false, true))
1331 convertMode
= TEX_HTML
;
1336 OnInform(_T("Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML."));
1337 wxStrcpy(errorCode
, _T("Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML."));
1340 else if (StringMatch(settingName
, _T("documentFontSize"), false, true))
1343 RegisterIntSetting(settingValueStr
, &n
);
1344 if (n
== 10 || n
== 11 || n
== 12)
1349 wxSnprintf(buf
, sizeof(buf
), _T("Initialisation file error: nonstandard document font size %d."), n
);
1352 wxStrcpy(errorCode
, buf
);
1358 wxSnprintf(buf
, sizeof(buf
), _T("Initialisation file error: unrecognised setting %s."), settingName
);
1361 wxStrcpy(errorCode
, buf
);
1366 bool ReadCustomMacros(wxChar
*filename
)
1368 if (!wxFileExists(filename
))
1371 wxString name
= filename
;
1372 wxSTD ifstream
istr((char const *)name
.fn_str(), wxSTD
ios::in
);
1374 if (istr
.bad()) return false;
1376 CustomMacroList
.Clear();
1378 wxChar macroName
[100];
1379 wxChar macroBody
[1000];
1384 BibEatWhiteSpace(istr
);
1389 if (ch
!= '\\') // Not a macro definition, so must be NAME=VALUE
1391 wxChar settingName
[100];
1392 settingName
[0] = ch
;
1393 BibReadWord(istr
, (settingName
+1));
1394 BibEatWhiteSpace(istr
);
1398 OnError(_T("Expected = following name: malformed tex2rtf.ini file."));
1403 wxChar settingValue
[200];
1404 BibEatWhiteSpace(istr
);
1405 BibReadToEOL(istr
, settingValue
);
1406 RegisterSetting(settingName
, settingValue
);
1411 BibReadWord(istr
, macroName
);
1412 BibEatWhiteSpace(istr
);
1416 OnError(_T("Expected [ followed by number of arguments: malformed tex2rtf.ini file."));
1423 OnError(_T("Expected ] following number of arguments: malformed tex2rtf.ini file."));
1426 BibEatWhiteSpace(istr
);
1430 OnError(_T("Expected { followed by macro body: malformed tex2rtf.ini file."));
1433 CustomMacro
*macro
= new CustomMacro(macroName
, noArgs
, NULL
);
1434 BibReadValue(istr
, macroBody
, false, false); // Don't ignore extra braces
1435 if (wxStrlen(macroBody
) > 0)
1436 macro
->macroBody
= copystring(macroBody
);
1438 BibEatWhiteSpace(istr
);
1439 CustomMacroList
.Append(macroName
, macro
);
1440 AddMacroDef(ltCUSTOM_MACRO
, macroName
, noArgs
);
1444 wxSnprintf(mbuf
, sizeof(mbuf
), _T("Read initialization file %s."), filename
);
1449 CustomMacro
*FindCustomMacro(wxChar
*name
)
1451 wxNode
*node
= CustomMacroList
.Find(name
);
1454 CustomMacro
*macro
= (CustomMacro
*)node
->GetData();
1460 // Display custom macros
1461 void ShowCustomMacros(void)
1463 wxNode
*node
= CustomMacroList
.GetFirst();
1466 OnInform(_T("No custom macros loaded.\n"));
1473 CustomMacro
*macro
= (CustomMacro
*)node
->GetData();
1474 wxSnprintf(buf
, sizeof(buf
), _T("\\%s[%d]\n {%s}"), macro
->macroName
, macro
->noArgs
,
1475 macro
->macroBody
? macro
->macroBody
: _T(""));
1477 node
= node
->GetNext();
1481 // Parse a string into several comma-separated fields
1482 wxChar
*ParseMultifieldString(wxChar
*allFields
, int *pos
)
1484 static wxChar buffer
[300];
1486 int fieldIndex
= *pos
;
1487 int len
= wxStrlen(allFields
);
1489 bool keepGoing
= true;
1490 while ((fieldIndex
<= len
) && keepGoing
)
1492 if (allFields
[fieldIndex
] == _T(' '))
1497 else if (allFields
[fieldIndex
] == _T(','))
1499 *pos
= fieldIndex
+ 1;
1502 else if (allFields
[fieldIndex
] == 0)
1504 *pos
= fieldIndex
+ 1;
1509 buffer
[i
] = allFields
[fieldIndex
];
1515 if (oldPos
== (*pos
))
1529 ColourTableEntry::ColourTableEntry(const wxChar
*theName
, unsigned int r
, unsigned int g
, unsigned int b
)
1531 name
= copystring(theName
);
1537 ColourTableEntry::~ColourTableEntry(void)
1542 void AddColour(const wxChar
*theName
, unsigned int r
, unsigned int g
, unsigned int b
)
1544 wxNode
*node
= ColourTable
.Find(theName
);
1547 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->GetData();
1548 if (entry
->red
== r
|| entry
->green
== g
|| entry
->blue
== b
)
1556 ColourTableEntry
*entry
= new ColourTableEntry(theName
, r
, g
, b
);
1557 ColourTable
.Append(theName
, entry
);
1560 int FindColourPosition(wxChar
*theName
)
1563 wxNode
*node
= ColourTable
.GetFirst();
1566 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->GetData();
1567 if (wxStrcmp(theName
, entry
->name
) == 0)
1570 node
= node
->GetNext();
1575 // Converts e.g. "red" -> "#FF0000"
1576 extern void DecToHex(int, wxChar
*);
1577 bool FindColourHTMLString(wxChar
*theName
, wxChar
*buf
)
1579 wxNode
*node
= ColourTable
.GetFirst();
1582 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->GetData();
1583 if (wxStrcmp(theName
, entry
->name
) == 0)
1585 wxStrcpy(buf
, _T("#"));
1588 DecToHex(entry
->red
, buf2
);
1589 wxStrcat(buf
, buf2
);
1590 DecToHex(entry
->green
, buf2
);
1591 wxStrcat(buf
, buf2
);
1592 DecToHex(entry
->blue
, buf2
);
1593 wxStrcat(buf
, buf2
);
1597 node
= node
->GetNext();
1603 void InitialiseColourTable(void)
1605 // \\red0\\green0\\blue0;
1606 AddColour(_T("black"), 0,0,0);
1608 // \\red0\\green0\\blue255;\\red0\\green255\\blue255;\n");
1609 AddColour(_T("cyan"), 0,255,255);
1611 // \\red0\\green255\\blue0;
1612 AddColour(_T("green"), 0,255,0);
1614 // \\red255\\green0\\blue255;
1615 AddColour(_T("magenta"), 255,0,255);
1617 // \\red255\\green0\\blue0;
1618 AddColour(_T("red"), 255,0,0);
1620 // \\red255\\green255\\blue0;
1621 AddColour(_T("yellow"), 255,255,0);
1623 // \\red255\\green255\\blue255;}");
1624 AddColour(_T("white"), 255,255,255);
1628 * The purpose of this is to reduce the number of times wxYield is
1629 * called, since under Windows this can slow things down.
1632 void Tex2RTFYield(bool force
)
1635 static int yieldCount
= 0;
1642 if (yieldCount
== 0)
1654 // In both RTF generation and HTML generation for wxHelp version 2,
1655 // we need to associate \indexed keywords with the current filename/topics.
1657 // Hash table for lists of keywords for topics (WinHelp).
1658 wxHashTable
TopicTable(wxKEY_STRING
);
1659 void AddKeyWordForTopic(wxChar
*topic
, wxChar
*entry
, wxChar
*filename
)
1661 TexTopic
*texTopic
= (TexTopic
*)TopicTable
.Get(topic
);
1664 texTopic
= new TexTopic(filename
);
1665 texTopic
->keywords
= new wxStringList
;
1666 TopicTable
.Put(topic
, texTopic
);
1669 if (!texTopic
->keywords
->Member(entry
))
1670 texTopic
->keywords
->Add(entry
);
1673 void ClearKeyWordTable(void)
1675 TopicTable
.BeginFind();
1676 wxHashTable::Node
*node
= TopicTable
.Next();
1679 TexTopic
*texTopic
= (TexTopic
*)node
->GetData();
1681 node
= TopicTable
.Next();
1688 * TexTopic structure
1691 TexTopic::TexTopic(wxChar
*f
)
1694 filename
= copystring(f
);
1697 hasChildren
= false;
1701 TexTopic::~TexTopic(void)
1709 // Convert case, according to upperCaseNames setting.
1710 wxChar
*ConvertCase(wxChar
*s
)
1712 static wxChar buf
[256];
1713 int len
= wxStrlen(s
);
1716 for (i
= 0; i
< len
; i
++)
1717 buf
[i
] = (wxChar
)wxToupper(s
[i
]);
1719 for (i
= 0; i
< len
; i
++)
1720 buf
[i
] = (wxChar
)wxTolower(s
[i
]);
1725 // if substring is true, search for str1 in str2
1726 bool StringMatch(const wxChar
*str1
, const wxChar
*str2
, bool subString
,
1731 wxString
Sstr1(str1
);
1732 wxString
Sstr2(str2
);
1738 return Sstr2
.Index(Sstr1
) != (size_t)wxNOT_FOUND
;
1741 return exact
? wxString(str2
).Cmp(str1
) == 0 :
1742 wxString(str2
).CmpNoCase(str1
) == 0;