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 /////////////////////////////////////////////////////////////////////////////
13 // For compilers that support precompilation, includes "wx.h".
14 #include "wx/wxprec.h"
26 #include "wx/textfile.h"
44 static inline wxChar
* copystring(const wxChar
* s
)
45 { return wxStrcpy(new wxChar
[wxStrlen(s
) + 1], s
); }
47 wxHashTable
TexReferences(wxKEY_STRING
);
48 wxList
BibList(wxKEY_STRING
);
49 wxStringList CitationList
;
50 wxList
ColourTable(wxKEY_STRING
);
51 wxHashTable
BibStringTable(wxKEY_STRING
);
52 wxList
CustomMacroList(wxKEY_STRING
);
53 TexChunk
*currentSection
= NULL
;
54 wxChar
*fakeCurrentSection
= NULL
;
56 static long BibLine
= 1;
58 void OutputCurrentSection(void)
60 if (fakeCurrentSection
)
61 TexOutput(fakeCurrentSection
);
62 else if (currentSection
)
63 TraverseChildrenFromChunk(currentSection
);
66 // Nasty but the way things are done now, necessary,
67 // in order to output a chunk properly to a string (macros and all).
68 void OutputCurrentSectionToString(wxChar
*buf
)
70 if (fakeCurrentSection
)
71 wxStrcpy(buf
, fakeCurrentSection
);
73 OutputChunkToString(currentSection
, buf
);
76 void OutputChunkToString(TexChunk
*chunk
, wxChar
*buf
)
78 FILE *tempfd
= wxFopen(_T("tmp.tmp"), _T("w"));
82 FILE *old1
= CurrentOutput1
;
83 FILE *old2
= CurrentOutput2
;
85 CurrentOutput1
= tempfd
;
86 CurrentOutput2
= NULL
;
88 TraverseChildrenFromChunk(chunk
);
90 CurrentOutput1
= old1
;
91 CurrentOutput2
= old2
;
95 // Read from file into string
96 tempfd
= wxFopen(_T("tmp.tmp"), _T("r"));
115 wxRemoveFile(_T("tmp.tmp"));
118 // Called by Tex2Any to simulate a section
119 void FakeCurrentSection(wxChar
*fakeSection
, bool addToContents
)
121 currentSection
= NULL
;
122 if (fakeCurrentSection
) delete[] fakeCurrentSection
;
123 fakeCurrentSection
= copystring(fakeSection
);
125 if (DocumentStyle
== LATEX_ARTICLE
)
127 int mac
= ltSECTIONHEADING
;
129 mac
= ltSECTIONHEADINGSTAR
;
130 OnMacro(mac
, 0, true);
131 OnMacro(mac
, 0, false);
135 int mac
= ltCHAPTERHEADING
;
137 mac
= ltCHAPTERHEADINGSTAR
;
138 OnMacro(mac
, 0, true);
139 OnMacro(mac
, 0, false);
141 if (fakeCurrentSection
) delete[] fakeCurrentSection
;
142 fakeCurrentSection
= NULL
;
145 // Look for \label macro, use this ref name if found or
146 // make up a topic name otherwise.
147 static long topicCounter
= 0;
149 void ResetTopicCounter(void)
154 static wxChar
*forceTopicName
= NULL
;
156 void ForceTopicName(const wxChar
*name
)
159 delete[] forceTopicName
;
161 forceTopicName
= copystring(name
);
163 forceTopicName
= NULL
;
166 wxChar
*FindTopicName(TexChunk
*chunk
)
169 return forceTopicName
;
171 wxChar
*topicName
= NULL
;
172 static wxChar topicBuf
[100];
174 if (chunk
&& (chunk
->type
== CHUNK_TYPE_MACRO
) &&
175 (chunk
->macroId
== ltLABEL
))
177 wxNode
*node
= chunk
->children
.GetFirst();
180 TexChunk
*child
= (TexChunk
*)node
->GetData();
181 if (child
->type
== CHUNK_TYPE_ARG
)
183 wxNode
*snode
= child
->children
.GetFirst();
186 TexChunk
*schunk
= (TexChunk
*)snode
->GetData();
187 if (schunk
->type
== CHUNK_TYPE_STRING
)
188 topicName
= schunk
->value
;
197 wxSnprintf(topicBuf
, sizeof(topicBuf
), _T("topic%ld"), topicCounter
);
204 * Simulate argument data, so we can 'drive' clients which implement
205 * certain basic formatting behaviour.
206 * Snag is that some save a TexChunk, so don't use yet...
210 void StartSimulateArgument(const wxChar
*data
)
212 wxStrcpy(currentArgData
, data
);
216 void EndSimulateArgument(void)
222 * Parse and convert unit arguments to points
226 int ParseUnitArgument(const wxChar
*unitArg_
)
228 wxWxCharBuffer
unitBuf(unitArg_
);
229 wxChar
*unitArg
= unitBuf
.data();
231 float conversionFactor
= 1.0;
232 float unitValue
= 0.0;
233 int len
= wxStrlen(unitArg
);
234 // Get rid of any accidentally embedded commands
235 for (int i
= 0; i
< len
; i
++)
236 if (unitArg
[i
] == '\\')
238 len
= wxStrlen(unitArg
);
240 if (unitArg
&& (len
> 0) && (isdigit(unitArg
[0]) || unitArg
[0] == '-'))
242 wxSscanf(unitArg
, _T("%f"), &unitValue
);
246 units
[0] = unitArg
[len
-2];
247 units
[1] = unitArg
[len
-1];
249 if (wxStrcmp(units
, _T("in")) == 0)
250 conversionFactor
= 72.0;
251 else if (wxStrcmp(units
, _T("cm")) == 0)
252 conversionFactor
= (float)72.0/(float)2.51;
253 else if (wxStrcmp(units
, _T("mm")) == 0)
254 conversionFactor
= (float)72.0/(float)25.1;
255 else if (wxStrcmp(units
, _T("pt")) == 0)
256 conversionFactor
= 1;
258 return (int)(unitValue
*conversionFactor
);
264 * Strip off any extension (dot something) from end of file,
265 * IF one exists. Inserts zero into buffer.
269 void StripExtension(wxChar
*buffer
)
271 int len
= wxStrlen(buffer
);
275 if (buffer
[i
] == '.')
289 void SetFontSizes(int pointSize
)
341 void AddTexRef(wxChar
*name
, wxChar
*file
, wxChar
*sectionName
,
342 int chapter
, int section
, int subsection
, int subsubsection
)
344 TexRef
*texRef
= (TexRef
*)TexReferences
.Get(name
);
345 if (texRef
) TexReferences
.Delete(name
);
352 wxStrcat(buf, sectionName);
359 wxSnprintf(buf2
, sizeof(buf2
), _T("%d"), chapter
);
366 wxStrcat(buf
, _T("."));
368 wxSnprintf(buf2
, sizeof(buf2
), _T("%d"), section
);
374 wxStrcat(buf
, _T("."));
375 wxSnprintf(buf2
, sizeof(buf2
), _T("%d"), subsection
);
381 wxStrcat(buf
, _T("."));
382 wxSnprintf(buf2
, sizeof(buf2
), _T("%d"), subsubsection
);
385 wxChar
*tmp
= ((wxStrlen(buf
) > 0) ? buf
: (wxChar
*)NULL
);
386 TexReferences
.Put(name
, new TexRef(name
, file
, tmp
, sectionName
));
389 void WriteTexReferences(wxChar
*filename
)
391 wxString name
= filename
;
394 if (!(wxFileExists(name
)?file
.Open(name
):file
.Create(name
)))
399 TexReferences
.BeginFind();
400 wxHashTable::Node
*node
= TexReferences
.Next();
404 TexRef
*ref
= (TexRef
*)node
->GetData();
405 wxString converter
= ref
->refLabel
;
406 converter
<< wxT(" ");
407 converter
<< (ref
->refFile
? ref
->refFile
: _T("??"));
408 converter
<< wxT(" ");
409 converter
<< (ref
->sectionName
? ref
->sectionName
: _T("??")) ;
410 converter
<< wxT(" ");
411 converter
<< (ref
->sectionNumber
? ref
->sectionNumber
: _T("??")) ;
412 file
.AddLine(converter
);
414 if (!ref
->sectionNumber
|| (wxStrcmp(ref
->sectionNumber
, _T("??")) == 0 && wxStrcmp(ref
->sectionName
, _T("??")) == 0))
417 wxSnprintf(buf
, sizeof(buf
), _T("Warning: reference %s not resolved."), ref
->refLabel
);
420 node
= TexReferences
.Next();
427 void ReadTexReferences(wxChar
*filename
)
429 wxString name
= filename
;
431 if (!wxFileExists(name
))
435 if (!file
.Open(name
))
439 for ( line
= file
.GetFirstLine(); !file
.Eof(); line
= file
.GetNextLine() )
441 wxString labelStr
= line
.BeforeFirst(wxT(' '));
442 line
= line
.AfterFirst(wxT(' '));
443 wxString fileStr
= line
.BeforeFirst(wxT(' '));
444 line
= line
.AfterFirst(wxT(' '));
445 wxString sectionNameStr
= line
.BeforeFirst(wxT(' '));
446 wxString sectionStr
= line
.AfterFirst(wxT(' '));
448 // gt - needed to trick the hash table "TexReferences" into deleting the key
449 // strings it creates in the Put() function, but not the item that is
450 // created here, as that is destroyed elsewhere. Without doing this, there
451 // were massive memory leaks
452 TexReferences
.DeleteContents(true);
459 sectionNameStr
.c_str()
462 TexReferences
.DeleteContents(false);
468 * Bibliography-handling code
472 void BibEatWhiteSpace(wxString
& line
)
474 while(!line
.empty() && (line
[0] == _T(' ') || line
[0] == _T('\t') || line
[0] == (wxChar
)EOF
))
478 line
= line
.substr(1);
481 // Ignore end-of-line comments
482 if (line
[0] == _T('%') || line
[0] == _T(';') || line
[0] == _T('#'))
484 line
= wxEmptyString
;
488 void BibEatWhiteSpace(wxSTD istream
& str
)
490 char ch
= (char)str
.peek();
492 while (!str
.eof() && (ch
== ' ' || ch
== '\t' || ch
== 13 || ch
== 10 || ch
== (char)EOF
))
497 if ((ch
== (char)EOF
) || str
.eof()) return;
498 ch
= (char)str
.peek();
501 // Ignore end-of-line comments
502 if (ch
== '%' || ch
== ';' || ch
== '#')
505 ch
= (char)str
.peek();
506 while (ch
!= 10 && ch
!= 13 && !str
.eof())
509 ch
= (char)str
.peek();
511 BibEatWhiteSpace(str
);
515 // Read word up to { or , or space
516 wxString
BibReadWord(wxString
& line
)
520 while (!line
.empty() &&
521 line
[0] != _T('\t') &&
522 line
[0] != _T(' ') &&
523 line
[0] != _T('{') &&
524 line
[0] != _T('(') &&
525 line
[0] != _T(',') &&
529 line
= line
.substr(1);
534 void BibReadWord(wxSTD istream
& istr
, wxChar
*buffer
)
538 char ch
= (char)istr
.peek();
539 while (!istr
.eof() && ch
!= ' ' && ch
!= '{' && ch
!= '(' && ch
!= 13 && ch
!= 10 && ch
!= '\t' &&
540 ch
!= ',' && ch
!= '=')
545 ch
= (char)istr
.peek();
550 // Read string (double-quoted or not) to end quote or EOL
551 wxString
BibReadToEOL(wxString
& line
)
554 return wxEmptyString
;
557 bool inQuotes
= false;
558 if (line
[0] == _T('"'))
560 line
= line
.substr(1);
563 // If in quotes, read white space too. If not,
564 // stop at white space or comment.
565 while (!line
.empty() && line
[0] != _T('"') &&
566 (inQuotes
|| ((line
[0] != _T(' ')) && (line
[0] != '\t') &&
567 (line
[0] != _T(';')) && (line
[0] != _T('%')) && (line
[0] != _T('#')))))
570 line
= line
.substr(1);
573 line
= line
.substr(1);
578 void BibReadToEOL(wxSTD istream
& istr
, wxChar
*buffer
)
582 char ch
= (char)istr
.peek();
583 bool inQuotes
= false;
587 ch
= (char)istr
.peek();
590 // If in quotes, read white space too. If not,
591 // stop at white space or comment.
592 while (!istr
.eof() && ch
!= 13 && ch
!= 10 && ch
!= _T('"') &&
593 (inQuotes
|| ((ch
!= _T(' ')) && (ch
!= 9) &&
594 (ch
!= _T(';')) && (ch
!= _T('%')) && (ch
!= _T('#')))))
599 ch
= (char)istr
.peek();
606 // Read }-terminated value, taking nested braces into account.
607 wxString
BibReadValue(wxString
& line
,
608 bool ignoreBraces
= true,
609 bool quotesMayTerminate
= true)
613 bool stopping
= false;
615 if (line
.length() >= 4000)
618 wxSnprintf(buf
, sizeof(buf
), _T("Sorry, value > 4000 chars in bib file at line %ld."), BibLine
);
619 wxLogError(buf
, "Tex2RTF Fatal Error");
620 return wxEmptyString
;
623 while (!line
.empty() && !stopping
)
626 line
= line
.substr(1);
640 else if (quotesMayTerminate
&& ch
== _T('"'))
648 if (!ignoreBraces
|| (ch
!= _T('{') && ch
!= _T('}')))
658 void BibReadValue(wxSTD istream
& istr
, wxChar
*buffer
, bool ignoreBraces
= true,
659 bool quotesMayTerminate
= true)
664 char ch
= (char)istr
.peek();
665 bool stopping
= false;
666 while (!istr
.eof() && !stopping
)
672 wxSnprintf(buf
, sizeof(buf
), _T("Sorry, value > 4000 chars in bib file at line %ld."), BibLine
);
673 wxLogError(buf
, "Tex2RTF Fatal Error");
690 else if (quotesMayTerminate
&& ch
== '"')
697 if (!ignoreBraces
|| (ch
!= '{' && ch
!= '}'))
707 wxUnusedVar(stopping
);
710 bool ReadBib(const wxChar
*filename
)
712 if (!wxFileExists(filename
))
715 wxString name
= filename
;
717 wxSTD ifstream
istr((char const *)name
.fn_str(), wxSTD
ios::in
);
718 if (istr
.bad()) return false;
722 OnInform(_T("Reading .bib file..."));
725 wxChar fieldValue
[4000];
726 wxChar recordType
[100];
727 wxChar recordKey
[100];
728 wxChar recordField
[100];
733 BibEatWhiteSpace(istr
);
737 wxSnprintf(buf
, sizeof(buf
), _T("Expected @: malformed bib file at line %ld (%s)"), BibLine
, filename
);
741 BibReadWord(istr
, recordType
);
742 BibEatWhiteSpace(istr
);
744 if (ch
!= '{' && ch
!= '(')
746 wxSnprintf(buf
, sizeof(buf
), _T("Expected { or ( after record type: malformed .bib file at line %ld (%s)"), BibLine
, filename
);
750 BibEatWhiteSpace(istr
);
751 if (StringMatch(recordType
, _T("string"), false, true))
753 BibReadWord(istr
, recordType
);
754 BibEatWhiteSpace(istr
);
758 wxSnprintf(buf
, sizeof(buf
), _T("Expected = after string key: malformed .bib file at line %ld (%s)"), BibLine
, filename
);
762 BibEatWhiteSpace(istr
);
764 if (ch
!= '"' && ch
!= '{')
766 wxSnprintf(buf
, sizeof(buf
), _T("Expected = after string key: malformed .bib file at line %ld (%s)"), BibLine
, filename
);
770 BibReadValue(istr
, fieldValue
);
772 // Now put in hash table if necesary
773 if (!BibStringTable
.Get(recordType
))
774 BibStringTable
.Put(recordType
, (wxObject
*)copystring(fieldValue
));
776 // Read closing ) or }
777 BibEatWhiteSpace(istr
);
779 BibEatWhiteSpace(istr
);
783 BibReadWord(istr
, recordKey
);
785 BibEntry
*bibEntry
= new BibEntry
;
786 bibEntry
->key
= copystring(recordKey
);
787 bibEntry
->type
= copystring(recordType
);
789 bool moreRecords
= true;
790 while (moreRecords
&& !istr
.eof())
792 BibEatWhiteSpace(istr
);
794 if (ch
== '}' || ch
== ')')
800 BibEatWhiteSpace(istr
);
801 BibReadWord(istr
, recordField
);
802 BibEatWhiteSpace(istr
);
806 wxSnprintf(buf
, sizeof(buf
), _T("Expected = after field type: malformed .bib file at line %ld (%s)"), BibLine
, filename
);
810 BibEatWhiteSpace(istr
);
812 if (ch
!= '{' && ch
!= '"')
815 BibReadWord(istr
, fieldValue
+1);
817 // If in the table of strings, replace with string from table.
818 wxChar
*s
= (wxChar
*)BibStringTable
.Get(fieldValue
);
821 wxStrcpy(fieldValue
, s
);
825 BibReadValue(istr
, fieldValue
, true, (ch
== _T('"') ? true : false));
827 // Now we can add a field
828 if (StringMatch(recordField
, _T("author"), false, true))
829 bibEntry
->author
= copystring(fieldValue
);
830 else if (StringMatch(recordField
, _T("key"), false, true))
832 else if (StringMatch(recordField
, _T("annotate"), false, true))
834 else if (StringMatch(recordField
, _T("abstract"), false, true))
836 else if (StringMatch(recordField
, _T("edition"), false, true))
838 else if (StringMatch(recordField
, _T("howpublished"), false, true))
840 else if (StringMatch(recordField
, _T("note"), false, true) || StringMatch(recordField
, _T("notes"), false, true))
842 else if (StringMatch(recordField
, _T("series"), false, true))
844 else if (StringMatch(recordField
, _T("type"), false, true))
846 else if (StringMatch(recordField
, _T("keywords"), false, true))
848 else if (StringMatch(recordField
, _T("editor"), false, true) || StringMatch(recordField
, _T("editors"), false, true))
849 bibEntry
->editor
= copystring(fieldValue
);
850 else if (StringMatch(recordField
, _T("title"), false, true))
851 bibEntry
->title
= copystring(fieldValue
);
852 else if (StringMatch(recordField
, _T("booktitle"), false, true))
853 bibEntry
->booktitle
= copystring(fieldValue
);
854 else if (StringMatch(recordField
, _T("journal"), false, true))
855 bibEntry
->journal
= copystring(fieldValue
);
856 else if (StringMatch(recordField
, _T("volume"), false, true))
857 bibEntry
->volume
= copystring(fieldValue
);
858 else if (StringMatch(recordField
, _T("number"), false, true))
859 bibEntry
->number
= copystring(fieldValue
);
860 else if (StringMatch(recordField
, _T("year"), false, true))
861 bibEntry
->year
= copystring(fieldValue
);
862 else if (StringMatch(recordField
, _T("month"), false, true))
863 bibEntry
->month
= copystring(fieldValue
);
864 else if (StringMatch(recordField
, _T("pages"), false, true))
865 bibEntry
->pages
= copystring(fieldValue
);
866 else if (StringMatch(recordField
, _T("publisher"), false, true))
867 bibEntry
->publisher
= copystring(fieldValue
);
868 else if (StringMatch(recordField
, _T("address"), false, true))
869 bibEntry
->address
= copystring(fieldValue
);
870 else if (StringMatch(recordField
, _T("institution"), false, true) || StringMatch(recordField
, _T("school"), false, true))
871 bibEntry
->institution
= copystring(fieldValue
);
872 else if (StringMatch(recordField
, _T("organization"), false, true) || StringMatch(recordField
, _T("organisation"), false, true))
873 bibEntry
->organization
= copystring(fieldValue
);
874 else if (StringMatch(recordField
, _T("comment"), false, true) || StringMatch(recordField
, _T("comments"), false, true))
875 bibEntry
->comment
= copystring(fieldValue
);
876 else if (StringMatch(recordField
, _T("annote"), false, true))
877 bibEntry
->comment
= copystring(fieldValue
);
878 else if (StringMatch(recordField
, _T("chapter"), false, true))
879 bibEntry
->chapter
= copystring(fieldValue
);
882 wxSnprintf(buf
, sizeof(buf
), _T("Unrecognised bib field type %s at line %ld (%s)"), recordField
, BibLine
, filename
);
887 BibList
.Append(recordKey
, bibEntry
);
888 BibEatWhiteSpace(istr
);
894 void OutputBibItem(TexRef
*ref
, BibEntry
*bib
)
898 OnMacro(ltNUMBEREDBIBITEM
, 2, true);
899 OnArgument(ltNUMBEREDBIBITEM
, 1, true);
900 TexOutput(ref
->sectionNumber
);
901 OnArgument(ltNUMBEREDBIBITEM
, 1, false);
902 OnArgument(ltNUMBEREDBIBITEM
, 2, true);
905 OnMacro(ltBF
, 1, true);
906 OnArgument(ltBF
, 1, true);
908 TexOutput(bib
->author
);
909 OnArgument(ltBF
, 1, false);
910 OnMacro(ltBF
, 1, false);
911 if (bib
->author
&& (wxStrlen(bib
->author
) > 0) && (bib
->author
[wxStrlen(bib
->author
) - 1] != '.'))
918 TexOutput(bib
->year
);
923 TexOutput(bib
->month
);
926 if (bib
->year
|| bib
->month
)
929 if (StringMatch(bib
->type
, _T("article"), false, true))
933 TexOutput(bib
->title
);
938 OnMacro(ltIT
, 1, true);
939 OnArgument(ltIT
, 1, true);
940 TexOutput(bib
->journal
);
941 OnArgument(ltIT
, 1, false);
942 OnMacro(ltIT
, 1, false);
947 OnMacro(ltBF
, 1, true);
948 OnArgument(ltBF
, 1, true);
949 TexOutput(bib
->volume
);
950 OnArgument(ltBF
, 1, false);
951 OnMacro(ltBF
, 1, false);
956 TexOutput(bib
->number
);
961 TexOutput(_T(", pages "));
962 TexOutput(bib
->pages
);
966 else if (StringMatch(bib
->type
, _T("book"), false, true) ||
967 StringMatch(bib
->type
, _T("unpublished"), false, true) ||
968 StringMatch(bib
->type
, _T("manual"), false, true) ||
969 StringMatch(bib
->type
, _T("phdthesis"), false, true) ||
970 StringMatch(bib
->type
, _T("mastersthesis"), false, true) ||
971 StringMatch(bib
->type
, _T("misc"), false, true) ||
972 StringMatch(bib
->type
, _T("techreport"), false, true) ||
973 StringMatch(bib
->type
, _T("booklet"), false, true))
975 if (bib
->title
|| bib
->booktitle
)
977 OnMacro(ltIT
, 1, true);
978 OnArgument(ltIT
, 1, true);
979 TexOutput(bib
->title
? bib
->title
: bib
->booktitle
);
981 OnArgument(ltIT
, 1, false);
982 OnMacro(ltIT
, 1, false);
984 if (StringMatch(bib
->type
, _T("phdthesis"), false, true))
985 TexOutput(_T("PhD thesis. "));
986 if (StringMatch(bib
->type
, _T("techreport"), false, true))
987 TexOutput(_T("Technical report. "));
990 TexOutput(_T("Ed. "));
991 TexOutput(bib
->editor
);
994 if (bib
->institution
)
996 TexOutput(bib
->institution
);
999 if (bib
->organization
)
1001 TexOutput(bib
->organization
);
1002 TexOutput(_T(". "));
1006 TexOutput(bib
->publisher
);
1007 TexOutput(_T(". "));
1011 TexOutput(bib
->address
);
1012 TexOutput(_T(". "));
1015 else if (StringMatch(bib
->type
, _T("inbook"), false, true) ||
1016 StringMatch(bib
->type
, _T("inproceedings"), false, true) ||
1017 StringMatch(bib
->type
, _T("incollection"), false, true) ||
1018 StringMatch(bib
->type
, _T("conference"), false, true))
1022 TexOutput(bib
->title
);
1026 TexOutput(_T(", from "));
1027 OnMacro(ltIT
, 1, true);
1028 OnArgument(ltIT
, 1, true);
1029 TexOutput(bib
->booktitle
);
1031 OnArgument(ltIT
, 1, false);
1032 OnMacro(ltIT
, 1, false);
1036 TexOutput(_T(", ed. "));
1037 TexOutput(bib
->editor
);
1042 TexOutput(bib
->publisher
);
1046 if (bib
->publisher
) TexOutput(_T(", "));
1047 else TexOutput(_T(" "));
1048 TexOutput(bib
->address
);
1050 if (bib
->publisher
|| bib
->address
)
1056 OnMacro(ltBF
, 1, true);
1057 OnArgument(ltBF
, 1, true);
1058 TexOutput(bib
->volume
);
1059 OnArgument(ltBF
, 1, false);
1060 OnMacro(ltBF
, 1, false);
1067 TexOutput(bib
->number
);
1068 TexOutput(_T(")."));
1072 TexOutput(_T(" Number "));
1073 TexOutput(bib
->number
);
1079 TexOutput(_T(" Chap. "));
1080 TexOutput(bib
->chapter
);
1084 if (bib
->chapter
) TexOutput(_T(", pages "));
1085 else TexOutput(_T(" Pages "));
1086 TexOutput(bib
->pages
);
1090 OnArgument(ltNUMBEREDBIBITEM
, 2, false);
1091 OnMacro(ltNUMBEREDBIBITEM
, 2, false);
1094 void OutputBib(void)
1096 // Write the heading
1097 ForceTopicName(_T("bibliography"));
1098 FakeCurrentSection(ReferencesNameString
);
1099 ForceTopicName(NULL
);
1101 OnMacro(ltPAR
, 0, true);
1102 OnMacro(ltPAR
, 0, false);
1104 if ((convertMode
== TEX_RTF
) && !winHelp
)
1106 OnMacro(ltPAR
, 0, true);
1107 OnMacro(ltPAR
, 0, false);
1110 wxStringListNode
*node
= CitationList
.GetFirst();
1113 wxChar
*citeKey
= (wxChar
*)node
->GetData();
1114 // wxNode *texNode = TexReferences.Find(citeKey);
1115 TexRef
*ref
= (TexRef
*)TexReferences
.Get(citeKey
);
1116 wxNode
*bibNode
= BibList
.Find(citeKey
);
1119 BibEntry
*entry
= (BibEntry
*)bibNode
->GetData();
1120 OutputBibItem(ref
, entry
);
1122 node
= node
->GetNext();
1126 static int citeCount
= 1;
1128 void ResolveBibReferences(void)
1130 if (CitationList
.GetCount() > 0)
1131 OnInform(_T("Resolving bibliographic references..."));
1135 wxStringListNode
*node
= CitationList
.GetFirst();
1139 wxChar
*citeKey
= (wxChar
*)node
->GetData();
1140 // wxNode *texNode = TexReferences.Find(citeKey);
1141 TexRef
*ref
= (TexRef
*)TexReferences
.Get(citeKey
);
1142 wxNode
*bibNode
= BibList
.Find(citeKey
);
1146 //BibEntry *entry = (BibEntry *)bibNode->GetData();
1147 if (ref
->sectionNumber
) delete[] ref
->sectionNumber
;
1148 wxSnprintf(buf
, sizeof(buf
), _T("[%d]"), citeCount
);
1149 ref
->sectionNumber
= copystring(buf
);
1154 wxSnprintf(buf
, sizeof(buf
), _T("Warning: bib ref %s not resolved."), citeKey
);
1157 node
= node
->GetNext();
1161 // Remember we need to resolve this citation
1162 void AddCitation(const wxChar
*citeKey
)
1164 if (!CitationList
.Member(citeKey
))
1165 CitationList
.Add(citeKey
);
1167 if (!TexReferences
.Get(citeKey
))
1169 TexReferences
.Put(citeKey
, new TexRef(citeKey
, _T("??"), NULL
));
1173 TexRef
*FindReference(const wxChar
*key
)
1175 return (TexRef
*)TexReferences
.Get(key
);
1179 * Custom macro stuff
1183 bool StringTobool(const wxString
& val
)
1188 if (up
.IsSameAs(_T("YES")) ||
1189 up
.IsSameAs(_T("TRUE")) ||
1190 up
.IsSameAs(_T("ON")) ||
1191 up
.IsSameAs(_T("OK")) |
1192 up
.IsSameAs(_T("1")))
1198 void RegisterIntSetting (const wxString
& s
, int *number
)
1208 // Define a variable value from the .ini file
1209 wxChar
*RegisterSetting(const wxString
& settingName
, const wxString
& settingValue
, bool interactive
)
1211 wxString
settingValueStr( settingValue
);
1213 static wxChar errorCode
[100];
1214 wxStrcpy(errorCode
, _T("OK"));
1215 if (StringMatch(settingName
, _T("chapterName"), false, true))
1217 delete[] ChapterNameString
;
1218 ChapterNameString
= copystring(settingValue
);
1220 else if (StringMatch(settingName
, _T("sectionName"), false, true))
1222 delete[] SectionNameString
;
1223 SectionNameString
= copystring(settingValue
);
1225 else if (StringMatch(settingName
, _T("subsectionName"), false, true))
1227 delete[] SubsectionNameString
;
1228 SubsectionNameString
= copystring(settingValue
);
1230 else if (StringMatch(settingName
, _T("subsubsectionName"), false, true))
1232 delete[] SubsubsectionNameString
;
1233 SubsubsectionNameString
= copystring(settingValue
);
1235 else if (StringMatch(settingName
, _T("indexName"), false, true))
1237 delete[] IndexNameString
;
1238 IndexNameString
= copystring(settingValue
);
1240 else if (StringMatch(settingName
, _T("contentsName"), false, true))
1242 delete[] ContentsNameString
;
1243 ContentsNameString
= copystring(settingValue
);
1245 else if (StringMatch(settingName
, _T("glossaryName"), false, true))
1247 delete[] GlossaryNameString
;
1248 GlossaryNameString
= copystring(settingValue
);
1250 else if (StringMatch(settingName
, _T("referencesName"), false, true))
1252 delete[] ReferencesNameString
;
1253 ReferencesNameString
= copystring(settingValue
);
1255 else if (StringMatch(settingName
, _T("tablesName"), false, true))
1257 delete[] TablesNameString
;
1258 TablesNameString
= copystring(settingValue
);
1260 else if (StringMatch(settingName
, _T("figuresName"), false, true))
1262 delete[] FiguresNameString
;
1263 FiguresNameString
= copystring(settingValue
);
1265 else if (StringMatch(settingName
, _T("tableName"), false, true))
1267 delete[] TableNameString
;
1268 TableNameString
= copystring(settingValue
);
1270 else if (StringMatch(settingName
, _T("figureName"), false, true))
1272 delete[] FigureNameString
;
1273 FigureNameString
= copystring(settingValue
);
1275 else if (StringMatch(settingName
, _T("abstractName"), false, true))
1277 delete[] AbstractNameString
;
1278 AbstractNameString
= copystring(settingValue
);
1280 else if (StringMatch(settingName
, _T("chapterFontSize"), false, true))
1281 RegisterIntSetting(settingValueStr
, &chapterFont
);
1282 else if (StringMatch(settingName
, _T("sectionFontSize"), false, true))
1283 RegisterIntSetting(settingValueStr
, §ionFont
);
1284 else if (StringMatch(settingName
, _T("subsectionFontSize"), false, true))
1285 RegisterIntSetting(settingValueStr
, &subsectionFont
);
1286 else if (StringMatch(settingName
, _T("titleFontSize"), false, true))
1287 RegisterIntSetting(settingValueStr
, &titleFont
);
1288 else if (StringMatch(settingName
, _T("authorFontSize"), false, true))
1289 RegisterIntSetting(settingValueStr
, &authorFont
);
1290 else if (StringMatch(settingName
, _T("ignoreInput"), false, true))
1291 IgnorableInputFiles
.Add(wxFileNameFromPath(settingValue
));
1292 else if (StringMatch(settingName
, _T("mirrorMargins"), false, true))
1293 mirrorMargins
= StringTobool(settingValue
);
1294 else if (StringMatch(settingName
, _T("runTwice"), false, true))
1295 runTwice
= StringTobool(settingValue
);
1296 else if (StringMatch(settingName
, _T("isInteractive"), false, true))
1297 isInteractive
= StringTobool(settingValue
);
1298 else if (StringMatch(settingName
, _T("headerRule"), false, true))
1299 headerRule
= StringTobool(settingValue
);
1300 else if (StringMatch(settingName
, _T("footerRule"), false, true))
1301 footerRule
= StringTobool(settingValue
);
1302 else if (StringMatch(settingName
, _T("combineSubSections"), false, true))
1303 combineSubSections
= StringTobool(settingValue
);
1304 else if (StringMatch(settingName
, _T("listLabelIndent"), false, true))
1305 RegisterIntSetting(settingValueStr
, &labelIndentTab
);
1306 else if (StringMatch(settingName
, _T("listItemIndent"), false, true))
1307 RegisterIntSetting(settingValueStr
, &itemIndentTab
);
1308 else if (StringMatch(settingName
, _T("useUpButton"), false, true))
1309 useUpButton
= StringTobool(settingValue
);
1310 else if (StringMatch(settingName
, _T("useHeadingStyles"), false, true))
1311 useHeadingStyles
= StringTobool(settingValue
);
1312 else if (StringMatch(settingName
, _T("useWord"), false, true))
1313 useWord
= StringTobool(settingValue
);
1314 else if (StringMatch(settingName
, _T("contentsDepth"), false, true))
1315 RegisterIntSetting(settingValueStr
, &contentsDepth
);
1316 else if (StringMatch(settingName
, _T("generateHPJ"), false, true))
1317 generateHPJ
= StringTobool(settingValue
);
1318 else if (StringMatch(settingName
, _T("truncateFilenames"), false, true))
1319 truncateFilenames
= StringTobool(settingValue
);
1320 else if (StringMatch(settingName
, _T("winHelpVersion"), false, true))
1321 RegisterIntSetting(settingValueStr
, &winHelpVersion
);
1322 else if (StringMatch(settingName
, _T("winHelpContents"), false, true))
1323 winHelpContents
= StringTobool(settingValue
);
1324 else if (StringMatch(settingName
, _T("htmlIndex"), false, true))
1325 htmlIndex
= StringTobool(settingValue
);
1326 else if (StringMatch(settingName
, _T("htmlWorkshopFiles"), false, true))
1327 htmlWorkshopFiles
= StringTobool(settingValue
);
1328 else if (StringMatch(settingName
, _T("htmlFrameContents"), false, true))
1329 htmlFrameContents
= StringTobool(settingValue
);
1330 else if (StringMatch(settingName
, _T("htmlStylesheet"), false, true))
1333 delete[] htmlStylesheet
;
1334 htmlStylesheet
= copystring(settingValue
);
1336 else if (StringMatch(settingName
, _T("upperCaseNames"), false, true))
1337 upperCaseNames
= StringTobool(settingValue
);
1338 else if (StringMatch(settingName
, _T("ignoreBadRefs"), false, true))
1339 ignoreBadRefs
= StringTobool(settingValue
);
1340 else if (StringMatch(settingName
, _T("htmlFaceName"), false, true))
1342 delete[] htmlFaceName
;
1343 htmlFaceName
= copystring(settingValue
);
1345 else if (StringMatch(settingName
, _T("winHelpTitle"), false, true))
1348 delete[] winHelpTitle
;
1349 winHelpTitle
= copystring(settingValue
);
1351 else if (StringMatch(settingName
, _T("indexSubsections"), false, true))
1352 indexSubsections
= StringTobool(settingValue
);
1353 else if (StringMatch(settingName
, _T("compatibility"), false, true))
1354 compatibilityMode
= StringTobool(settingValue
);
1355 else if (StringMatch(settingName
, _T("defaultColumnWidth"), false, true))
1357 RegisterIntSetting(settingValueStr
, &defaultTableColumnWidth
);
1358 defaultTableColumnWidth
= 20*defaultTableColumnWidth
;
1360 else if (StringMatch(settingName
, _T("bitmapMethod"), false, true))
1362 if ((wxStrcmp(settingValue
, _T("includepicture")) != 0) && (wxStrcmp(settingValue
, _T("hex")) != 0) &&
1363 (wxStrcmp(settingValue
, _T("import")) != 0))
1366 OnError(_T("Unknown bitmapMethod"));
1367 wxStrcpy(errorCode
, _T("Unknown bitmapMethod"));
1371 delete[] bitmapMethod
;
1372 bitmapMethod
= copystring(settingValue
);
1375 else if (StringMatch(settingName
, _T("htmlBrowseButtons"), false, true))
1377 if (wxStrcmp(settingValue
, _T("none")) == 0)
1378 htmlBrowseButtons
= HTML_BUTTONS_NONE
;
1379 else if (wxStrcmp(settingValue
, _T("bitmap")) == 0)
1380 htmlBrowseButtons
= HTML_BUTTONS_BITMAP
;
1381 else if (wxStrcmp(settingValue
, _T("text")) == 0)
1382 htmlBrowseButtons
= HTML_BUTTONS_TEXT
;
1386 OnInform(_T("Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text."));
1387 wxStrcpy(errorCode
, _T("Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text."));
1390 else if (StringMatch(settingName
, _T("backgroundImage"), false, true))
1392 backgroundImageString
= copystring(settingValue
);
1394 else if (StringMatch(settingName
, _T("backgroundColour"), false, true))
1396 delete[] backgroundColourString
;
1397 backgroundColourString
= copystring(settingValue
);
1399 else if (StringMatch(settingName
, _T("textColour"), false, true))
1401 textColourString
= copystring(settingValue
);
1403 else if (StringMatch(settingName
, _T("linkColour"), false, true))
1405 linkColourString
= copystring(settingValue
);
1407 else if (StringMatch(settingName
, _T("followedLinkColour"), false, true))
1409 followedLinkColourString
= copystring(settingValue
);
1411 else if (StringMatch(settingName
, _T("conversionMode"), false, true))
1413 if (StringMatch(settingValue
, _T("RTF"), false, true))
1415 winHelp
= false; convertMode
= TEX_RTF
;
1417 else if (StringMatch(settingValue
, _T("WinHelp"), false, true))
1419 winHelp
= true; convertMode
= TEX_RTF
;
1421 else if (StringMatch(settingValue
, _T("XLP"), false, true) ||
1422 StringMatch(settingValue
, _T("wxHelp"), false, true))
1424 convertMode
= TEX_XLP
;
1426 else if (StringMatch(settingValue
, _T("HTML"), false, true))
1428 convertMode
= TEX_HTML
;
1433 OnInform(_T("Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML."));
1434 wxStrcpy(errorCode
, _T("Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML."));
1437 else if (StringMatch(settingName
, _T("documentFontSize"), false, true))
1440 RegisterIntSetting(settingValueStr
, &n
);
1441 if (n
== 10 || n
== 11 || n
== 12)
1446 wxSnprintf(buf
, sizeof(buf
), _T("Initialisation file error: nonstandard document font size %d."), n
);
1449 wxStrcpy(errorCode
, buf
);
1455 wxSnprintf(buf
, sizeof(buf
), _T("Initialisation file error: unrecognised setting %s."), settingName
.c_str());
1458 wxStrcpy(errorCode
, buf
);
1463 bool ReadCustomMacros(const wxString
& filename
)
1465 if (!wxFileExists(filename
))
1468 wxFileInputStream
input( filename
);
1469 if(!input
.Ok()) return false;
1470 wxTextInputStream
ini( input
);
1472 CustomMacroList
.Clear();
1474 while (!input
.Eof())
1476 wxString line
= ini
.ReadLine();
1477 BibEatWhiteSpace(line
);
1478 if (line
.empty()) continue;
1480 if (line
[0] != _T('\\')) // Not a macro definition, so must be NAME=VALUE
1482 wxString settingName
= BibReadWord(line
);
1483 BibEatWhiteSpace(line
);
1484 if (line
.empty() || line
[0] != _T('='))
1486 OnError(_T("Expected = following name: malformed tex2rtf.ini file."));
1491 line
= line
.substr(1);
1492 BibEatWhiteSpace(line
);
1493 wxString settingValue
= BibReadToEOL(line
);
1494 RegisterSetting(settingName
, settingValue
);
1499 line
= line
.substr(1);
1500 wxString macroName
= BibReadWord(line
);
1501 BibEatWhiteSpace(line
);
1502 if (line
[0] != _T('['))
1504 OnError(_T("Expected [ followed by number of arguments: malformed tex2rtf.ini file."));
1507 line
= line
.substr(1);
1508 wxString noAargStr
= line
.BeforeFirst(_T(']'));
1509 line
= line
.AfterFirst(_T(']'));
1511 if (!noAargStr
.ToLong(&noArgs
) || line
.empty())
1513 OnError(_T("Expected ] following number of arguments: malformed tex2rtf.ini file."));
1516 BibEatWhiteSpace(line
);
1517 if (line
[0] != _T('{'))
1519 OnError(_T("Expected { followed by macro body: malformed tex2rtf.ini file."));
1523 CustomMacro
*macro
= new CustomMacro(macroName
.c_str(), noArgs
, NULL
);
1524 wxString macroBody
= BibReadValue(line
, false, false); // Don't ignore extra braces
1525 if (!macroBody
.empty())
1526 macro
->macroBody
= copystring(macroBody
.c_str());
1528 BibEatWhiteSpace(line
);
1529 CustomMacroList
.Append(macroName
, macro
);
1530 AddMacroDef(ltCUSTOM_MACRO
, macroName
.c_str(), noArgs
);
1535 wxSnprintf(mbuf
, sizeof(mbuf
), _T("Read initialization file %s."), filename
.c_str());
1540 CustomMacro
*FindCustomMacro(wxChar
*name
)
1542 wxNode
*node
= CustomMacroList
.Find(name
);
1545 CustomMacro
*macro
= (CustomMacro
*)node
->GetData();
1551 // Display custom macros
1552 void ShowCustomMacros(void)
1554 wxNode
*node
= CustomMacroList
.GetFirst();
1557 OnInform(_T("No custom macros loaded.\n"));
1564 CustomMacro
*macro
= (CustomMacro
*)node
->GetData();
1565 wxSnprintf(buf
, sizeof(buf
), _T("\\%s[%d]\n {%s}"), macro
->macroName
, macro
->noArgs
,
1566 macro
->macroBody
? macro
->macroBody
: _T(""));
1568 node
= node
->GetNext();
1572 // Parse a string into several comma-separated fields
1573 wxChar
*ParseMultifieldString(wxChar
*allFields
, int *pos
)
1575 static wxChar buffer
[300];
1577 int fieldIndex
= *pos
;
1578 int len
= wxStrlen(allFields
);
1580 bool keepGoing
= true;
1581 while ((fieldIndex
<= len
) && keepGoing
)
1583 if (allFields
[fieldIndex
] == _T(' '))
1588 else if (allFields
[fieldIndex
] == _T(','))
1590 *pos
= fieldIndex
+ 1;
1593 else if (allFields
[fieldIndex
] == 0)
1595 *pos
= fieldIndex
+ 1;
1600 buffer
[i
] = allFields
[fieldIndex
];
1606 if (oldPos
== (*pos
))
1620 ColourTableEntry::ColourTableEntry(const wxChar
*theName
, unsigned int r
, unsigned int g
, unsigned int b
)
1622 name
= copystring(theName
);
1628 ColourTableEntry::~ColourTableEntry(void)
1633 void AddColour(const wxChar
*theName
, unsigned int r
, unsigned int g
, unsigned int b
)
1635 wxNode
*node
= ColourTable
.Find(theName
);
1638 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->GetData();
1639 if (entry
->red
== r
|| entry
->green
== g
|| entry
->blue
== b
)
1647 ColourTableEntry
*entry
= new ColourTableEntry(theName
, r
, g
, b
);
1648 ColourTable
.Append(theName
, entry
);
1651 int FindColourPosition(wxChar
*theName
)
1654 wxNode
*node
= ColourTable
.GetFirst();
1657 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->GetData();
1658 if (wxStrcmp(theName
, entry
->name
) == 0)
1661 node
= node
->GetNext();
1666 // Converts e.g. "red" -> "#FF0000"
1667 extern void DecToHex(int, wxChar
*);
1668 bool FindColourHTMLString(wxChar
*theName
, wxChar
*buf
)
1670 wxNode
*node
= ColourTable
.GetFirst();
1673 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->GetData();
1674 if (wxStrcmp(theName
, entry
->name
) == 0)
1676 wxStrcpy(buf
, _T("#"));
1679 DecToHex(entry
->red
, buf2
);
1680 wxStrcat(buf
, buf2
);
1681 DecToHex(entry
->green
, buf2
);
1682 wxStrcat(buf
, buf2
);
1683 DecToHex(entry
->blue
, buf2
);
1684 wxStrcat(buf
, buf2
);
1688 node
= node
->GetNext();
1694 void InitialiseColourTable(void)
1696 // \\red0\\green0\\blue0;
1697 AddColour(_T("black"), 0,0,0);
1699 // \\red0\\green0\\blue255;\\red0\\green255\\blue255;\n");
1700 AddColour(_T("cyan"), 0,255,255);
1702 // \\red0\\green255\\blue0;
1703 AddColour(_T("green"), 0,255,0);
1705 // \\red255\\green0\\blue255;
1706 AddColour(_T("magenta"), 255,0,255);
1708 // \\red255\\green0\\blue0;
1709 AddColour(_T("red"), 255,0,0);
1711 // \\red255\\green255\\blue0;
1712 AddColour(_T("yellow"), 255,255,0);
1714 // \\red255\\green255\\blue255;}");
1715 AddColour(_T("white"), 255,255,255);
1719 * The purpose of this is to reduce the number of times wxYield is
1720 * called, since under Windows this can slow things down.
1723 void Tex2RTFYield(bool force
)
1726 static int yieldCount
= 0;
1733 if (yieldCount
== 0)
1745 // In both RTF generation and HTML generation for wxHelp version 2,
1746 // we need to associate \indexed keywords with the current filename/topics.
1748 // Hash table for lists of keywords for topics (WinHelp).
1749 wxHashTable
TopicTable(wxKEY_STRING
);
1750 void AddKeyWordForTopic(wxChar
*topic
, wxChar
*entry
, wxChar
*filename
)
1752 TexTopic
*texTopic
= (TexTopic
*)TopicTable
.Get(topic
);
1755 texTopic
= new TexTopic(filename
);
1756 texTopic
->keywords
= new wxStringList
;
1757 TopicTable
.Put(topic
, texTopic
);
1760 if (!texTopic
->keywords
->Member(entry
))
1761 texTopic
->keywords
->Add(entry
);
1764 void ClearKeyWordTable(void)
1766 TopicTable
.BeginFind();
1767 wxHashTable::Node
*node
= TopicTable
.Next();
1770 TexTopic
*texTopic
= (TexTopic
*)node
->GetData();
1772 node
= TopicTable
.Next();
1779 * TexTopic structure
1782 TexTopic::TexTopic(wxChar
*f
)
1785 filename
= copystring(f
);
1788 hasChildren
= false;
1792 TexTopic::~TexTopic(void)
1800 // Convert case, according to upperCaseNames setting.
1801 wxChar
*ConvertCase(wxChar
*s
)
1803 static wxChar buf
[256];
1804 int len
= wxStrlen(s
);
1807 for (i
= 0; i
< len
; i
++)
1808 buf
[i
] = (wxChar
)wxToupper(s
[i
]);
1810 for (i
= 0; i
< len
; i
++)
1811 buf
[i
] = (wxChar
)wxTolower(s
[i
]);
1816 // if substring is true, search for str1 in str2
1817 bool StringMatch(const wxChar
*str1
, const wxChar
*str2
, bool subString
,
1822 wxString
Sstr1(str1
);
1823 wxString
Sstr2(str2
);
1829 return Sstr2
.Index(Sstr1
) != (size_t)wxNOT_FOUND
;
1832 return exact
? wxString(str2
).Cmp(str1
) == 0 :
1833 wxString(str2
).CmpNoCase(str1
) == 0;