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 #if !WXWIN_COMPATIBILITY_2_4
45 static inline wxChar
* copystring(const wxChar
* s
)
46 { return wxStrcpy(new wxChar
[wxStrlen(s
) + 1], s
); }
49 wxHashTable
TexReferences(wxKEY_STRING
);
50 wxList
BibList(wxKEY_STRING
);
51 wxStringList CitationList
;
52 wxList
ColourTable(wxKEY_STRING
);
53 wxHashTable
BibStringTable(wxKEY_STRING
);
54 wxList
CustomMacroList(wxKEY_STRING
);
55 TexChunk
*currentSection
= NULL
;
56 wxChar
*fakeCurrentSection
= NULL
;
58 static long BibLine
= 1;
60 void OutputCurrentSection(void)
62 if (fakeCurrentSection
)
63 TexOutput(fakeCurrentSection
);
64 else if (currentSection
)
65 TraverseChildrenFromChunk(currentSection
);
68 // Nasty but the way things are done now, necessary,
69 // in order to output a chunk properly to a string (macros and all).
70 void OutputCurrentSectionToString(wxChar
*buf
)
72 if (fakeCurrentSection
)
73 wxStrcpy(buf
, fakeCurrentSection
);
75 OutputChunkToString(currentSection
, buf
);
78 void OutputChunkToString(TexChunk
*chunk
, wxChar
*buf
)
80 FILE *tempfd
= wxFopen(_T("tmp.tmp"), _T("w"));
84 FILE *old1
= CurrentOutput1
;
85 FILE *old2
= CurrentOutput2
;
87 CurrentOutput1
= tempfd
;
88 CurrentOutput2
= NULL
;
90 TraverseChildrenFromChunk(chunk
);
92 CurrentOutput1
= old1
;
93 CurrentOutput2
= old2
;
97 // Read from file into string
98 tempfd
= wxFopen(_T("tmp.tmp"), _T("r"));
117 wxRemoveFile(_T("tmp.tmp"));
120 // Called by Tex2Any to simulate a section
121 void FakeCurrentSection(wxChar
*fakeSection
, bool addToContents
)
123 currentSection
= NULL
;
124 if (fakeCurrentSection
) delete[] fakeCurrentSection
;
125 fakeCurrentSection
= copystring(fakeSection
);
127 if (DocumentStyle
== LATEX_ARTICLE
)
129 int mac
= ltSECTIONHEADING
;
131 mac
= ltSECTIONHEADINGSTAR
;
132 OnMacro(mac
, 0, true);
133 OnMacro(mac
, 0, false);
137 int mac
= ltCHAPTERHEADING
;
139 mac
= ltCHAPTERHEADINGSTAR
;
140 OnMacro(mac
, 0, true);
141 OnMacro(mac
, 0, false);
143 if (fakeCurrentSection
) delete[] fakeCurrentSection
;
144 fakeCurrentSection
= NULL
;
147 // Look for \label macro, use this ref name if found or
148 // make up a topic name otherwise.
149 static long topicCounter
= 0;
151 void ResetTopicCounter(void)
156 static wxChar
*forceTopicName
= NULL
;
158 void ForceTopicName(const wxChar
*name
)
161 delete[] forceTopicName
;
163 forceTopicName
= copystring(name
);
165 forceTopicName
= NULL
;
168 wxChar
*FindTopicName(TexChunk
*chunk
)
171 return forceTopicName
;
173 wxChar
*topicName
= NULL
;
174 static wxChar topicBuf
[100];
176 if (chunk
&& (chunk
->type
== CHUNK_TYPE_MACRO
) &&
177 (chunk
->macroId
== ltLABEL
))
179 wxNode
*node
= chunk
->children
.GetFirst();
182 TexChunk
*child
= (TexChunk
*)node
->GetData();
183 if (child
->type
== CHUNK_TYPE_ARG
)
185 wxNode
*snode
= child
->children
.GetFirst();
188 TexChunk
*schunk
= (TexChunk
*)snode
->GetData();
189 if (schunk
->type
== CHUNK_TYPE_STRING
)
190 topicName
= schunk
->value
;
199 wxSnprintf(topicBuf
, sizeof(topicBuf
), _T("topic%ld"), topicCounter
);
206 * Simulate argument data, so we can 'drive' clients which implement
207 * certain basic formatting behaviour.
208 * Snag is that some save a TexChunk, so don't use yet...
212 void StartSimulateArgument(wxChar
*data
)
214 wxStrcpy(currentArgData
, data
);
218 void EndSimulateArgument(void)
224 * Parse and convert unit arguments to points
228 int ParseUnitArgument(wxChar
*unitArg
)
230 float conversionFactor
= 1.0;
231 float unitValue
= 0.0;
232 int len
= wxStrlen(unitArg
);
233 // Get rid of any accidentally embedded commands
234 for (int i
= 0; i
< len
; i
++)
235 if (unitArg
[i
] == '\\')
237 len
= wxStrlen(unitArg
);
239 if (unitArg
&& (len
> 0) && (isdigit(unitArg
[0]) || unitArg
[0] == '-'))
241 wxSscanf(unitArg
, _T("%f"), &unitValue
);
245 units
[0] = unitArg
[len
-2];
246 units
[1] = unitArg
[len
-1];
248 if (wxStrcmp(units
, _T("in")) == 0)
249 conversionFactor
= 72.0;
250 else if (wxStrcmp(units
, _T("cm")) == 0)
251 conversionFactor
= (float)72.0/(float)2.51;
252 else if (wxStrcmp(units
, _T("mm")) == 0)
253 conversionFactor
= (float)72.0/(float)25.1;
254 else if (wxStrcmp(units
, _T("pt")) == 0)
255 conversionFactor
= 1;
257 return (int)(unitValue
*conversionFactor
);
263 * Strip off any extension (dot something) from end of file,
264 * IF one exists. Inserts zero into buffer.
268 void StripExtension(wxChar
*buffer
)
270 int len
= wxStrlen(buffer
);
274 if (buffer
[i
] == '.')
288 void SetFontSizes(int pointSize
)
340 void AddTexRef(wxChar
*name
, wxChar
*file
, wxChar
*sectionName
,
341 int chapter
, int section
, int subsection
, int subsubsection
)
343 TexRef
*texRef
= (TexRef
*)TexReferences
.Get(name
);
344 if (texRef
) TexReferences
.Delete(name
);
351 wxStrcat(buf, sectionName);
358 wxSnprintf(buf2
, sizeof(buf2
), _T("%d"), chapter
);
365 wxStrcat(buf
, _T("."));
367 wxSnprintf(buf2
, sizeof(buf2
), _T("%d"), section
);
373 wxStrcat(buf
, _T("."));
374 wxSnprintf(buf2
, sizeof(buf2
), _T("%d"), subsection
);
380 wxStrcat(buf
, _T("."));
381 wxSnprintf(buf2
, sizeof(buf2
), _T("%d"), subsubsection
);
384 wxChar
*tmp
= ((wxStrlen(buf
) > 0) ? buf
: (wxChar
*)NULL
);
385 TexReferences
.Put(name
, new TexRef(name
, file
, tmp
, sectionName
));
388 void WriteTexReferences(wxChar
*filename
)
390 wxString name
= filename
;
393 if (!(wxFileExists(name
)?file
.Open(name
):file
.Create(name
)))
398 TexReferences
.BeginFind();
399 wxHashTable::Node
*node
= TexReferences
.Next();
403 TexRef
*ref
= (TexRef
*)node
->GetData();
404 wxString converter
= ref
->refLabel
;
405 converter
<< wxT(" ");
406 converter
<< (ref
->refFile
? ref
->refFile
: _T("??"));
407 converter
<< wxT(" ");
408 converter
<< (ref
->sectionName
? ref
->sectionName
: _T("??")) ;
409 converter
<< wxT(" ");
410 converter
<< (ref
->sectionNumber
? ref
->sectionNumber
: _T("??")) ;
411 file
.AddLine(converter
);
413 if (!ref
->sectionNumber
|| (wxStrcmp(ref
->sectionNumber
, _T("??")) == 0 && wxStrcmp(ref
->sectionName
, _T("??")) == 0))
416 wxSnprintf(buf
, sizeof(buf
), _T("Warning: reference %s not resolved."), ref
->refLabel
);
419 node
= TexReferences
.Next();
426 void ReadTexReferences(wxChar
*filename
)
428 wxString name
= filename
;
430 if (!wxFileExists(name
))
434 if (!file
.Open(name
))
438 for ( line
= file
.GetFirstLine(); !file
.Eof(); line
= file
.GetNextLine() )
440 wxString labelStr
= line
.BeforeFirst(wxT(' '));
441 line
= line
.AfterFirst(wxT(' '));
442 wxString fileStr
= line
.BeforeFirst(wxT(' '));
443 line
= line
.AfterFirst(wxT(' '));
444 wxString sectionNameStr
= line
.BeforeFirst(wxT(' '));
445 wxString sectionStr
= line
.AfterFirst(wxT(' '));
447 // gt - needed to trick the hash table "TexReferences" into deleting the key
448 // strings it creates in the Put() function, but not the item that is
449 // created here, as that is destroyed elsewhere. Without doing this, there
450 // were massive memory leaks
451 TexReferences
.DeleteContents(true);
458 sectionNameStr
.c_str()
461 TexReferences
.DeleteContents(false);
467 * Bibliography-handling code
471 void BibEatWhiteSpace(wxString
& line
)
473 while(!line
.empty() && (line
[0] == _T(' ') || line
[0] == _T('\t') || line
[0] == (wxChar
)EOF
))
477 line
= line
.substr(1);
480 // Ignore end-of-line comments
481 if (line
[0] == _T('%') || line
[0] == _T(';') || line
[0] == _T('#'))
483 line
= wxEmptyString
;
487 void BibEatWhiteSpace(wxSTD istream
& str
)
489 char ch
= (char)str
.peek();
491 while (!str
.eof() && (ch
== ' ' || ch
== '\t' || ch
== 13 || ch
== 10 || ch
== (char)EOF
))
496 if ((ch
== (char)EOF
) || str
.eof()) return;
497 ch
= (char)str
.peek();
500 // Ignore end-of-line comments
501 if (ch
== '%' || ch
== ';' || ch
== '#')
504 ch
= (char)str
.peek();
505 while (ch
!= 10 && ch
!= 13 && !str
.eof())
508 ch
= (char)str
.peek();
510 BibEatWhiteSpace(str
);
514 // Read word up to { or , or space
515 wxString
BibReadWord(wxString
& line
)
519 while (!line
.empty() &&
520 line
[0] != _T('\t') &&
521 line
[0] != _T(' ') &&
522 line
[0] != _T('{') &&
523 line
[0] != _T('(') &&
524 line
[0] != _T(',') &&
528 line
= line
.substr(1);
533 void BibReadWord(wxSTD istream
& istr
, wxChar
*buffer
)
537 char ch
= (char)istr
.peek();
538 while (!istr
.eof() && ch
!= ' ' && ch
!= '{' && ch
!= '(' && ch
!= 13 && ch
!= 10 && ch
!= '\t' &&
539 ch
!= ',' && ch
!= '=')
544 ch
= (char)istr
.peek();
549 // Read string (double-quoted or not) to end quote or EOL
550 wxString
BibReadToEOL(wxString
& line
)
553 return wxEmptyString
;
556 bool inQuotes
= false;
557 if (line
[0] == _T('"'))
559 line
= line
.substr(1);
562 // If in quotes, read white space too. If not,
563 // stop at white space or comment.
564 while (!line
.empty() && line
[0] != _T('"') &&
565 (inQuotes
|| ((line
[0] != _T(' ')) && (line
[0] != 9) &&
566 (line
[0] != _T(';')) && (line
[0] != _T('%')) && (line
[0] != _T('#')))))
569 line
= line
.substr(1);
572 line
= line
.substr(1);
577 void BibReadToEOL(wxSTD istream
& istr
, wxChar
*buffer
)
581 char ch
= (char)istr
.peek();
582 bool inQuotes
= false;
586 ch
= (char)istr
.peek();
589 // If in quotes, read white space too. If not,
590 // stop at white space or comment.
591 while (!istr
.eof() && ch
!= 13 && ch
!= 10 && ch
!= _T('"') &&
592 (inQuotes
|| ((ch
!= _T(' ')) && (ch
!= 9) &&
593 (ch
!= _T(';')) && (ch
!= _T('%')) && (ch
!= _T('#')))))
598 ch
= (char)istr
.peek();
605 // Read }-terminated value, taking nested braces into account.
606 wxString
BibReadValue(wxString
& line
,
607 bool ignoreBraces
= true,
608 bool quotesMayTerminate
= true)
612 bool stopping
= false;
614 if (line
.length() >= 4000)
617 wxSnprintf(buf
, sizeof(buf
), _T("Sorry, value > 4000 chars in bib file at line %ld."), BibLine
);
618 wxLogError(buf
, "Tex2RTF Fatal Error");
619 return wxEmptyString
;
622 while (!line
.empty() && !stopping
)
625 line
= line
.substr(1);
639 else if (quotesMayTerminate
&& ch
== _T('"'))
647 if (!ignoreBraces
|| (ch
!= _T('{') && ch
!= _T('}')))
657 void BibReadValue(wxSTD istream
& istr
, wxChar
*buffer
, bool ignoreBraces
= true,
658 bool quotesMayTerminate
= true)
663 char ch
= (char)istr
.peek();
664 bool stopping
= false;
665 while (!istr
.eof() && !stopping
)
671 wxSnprintf(buf
, sizeof(buf
), _T("Sorry, value > 4000 chars in bib file at line %ld."), BibLine
);
672 wxLogError(buf
, "Tex2RTF Fatal Error");
689 else if (quotesMayTerminate
&& ch
== '"')
696 if (!ignoreBraces
|| (ch
!= '{' && ch
!= '}'))
706 wxUnusedVar(stopping
);
709 bool ReadBib(wxChar
*filename
)
711 if (!wxFileExists(filename
))
714 wxString name
= filename
;
716 wxSTD ifstream
istr((char const *)name
.fn_str(), wxSTD
ios::in
);
717 if (istr
.bad()) return false;
721 OnInform(_T("Reading .bib file..."));
724 wxChar fieldValue
[4000];
725 wxChar recordType
[100];
726 wxChar recordKey
[100];
727 wxChar recordField
[100];
732 BibEatWhiteSpace(istr
);
736 wxSnprintf(buf
, sizeof(buf
), _T("Expected @: malformed bib file at line %ld (%s)"), BibLine
, filename
);
740 BibReadWord(istr
, recordType
);
741 BibEatWhiteSpace(istr
);
743 if (ch
!= '{' && ch
!= '(')
745 wxSnprintf(buf
, sizeof(buf
), _T("Expected { or ( after record type: malformed .bib file at line %ld (%s)"), BibLine
, filename
);
749 BibEatWhiteSpace(istr
);
750 if (StringMatch(recordType
, _T("string"), false, true))
752 BibReadWord(istr
, recordType
);
753 BibEatWhiteSpace(istr
);
757 wxSnprintf(buf
, sizeof(buf
), _T("Expected = after string key: malformed .bib file at line %ld (%s)"), BibLine
, filename
);
761 BibEatWhiteSpace(istr
);
763 if (ch
!= '"' && ch
!= '{')
765 wxSnprintf(buf
, sizeof(buf
), _T("Expected = after string key: malformed .bib file at line %ld (%s)"), BibLine
, filename
);
769 BibReadValue(istr
, fieldValue
);
771 // Now put in hash table if necesary
772 if (!BibStringTable
.Get(recordType
))
773 BibStringTable
.Put(recordType
, (wxObject
*)copystring(fieldValue
));
775 // Read closing ) or }
776 BibEatWhiteSpace(istr
);
778 BibEatWhiteSpace(istr
);
782 BibReadWord(istr
, recordKey
);
784 BibEntry
*bibEntry
= new BibEntry
;
785 bibEntry
->key
= copystring(recordKey
);
786 bibEntry
->type
= copystring(recordType
);
788 bool moreRecords
= true;
789 while (moreRecords
&& !istr
.eof())
791 BibEatWhiteSpace(istr
);
793 if (ch
== '}' || ch
== ')')
799 BibEatWhiteSpace(istr
);
800 BibReadWord(istr
, recordField
);
801 BibEatWhiteSpace(istr
);
805 wxSnprintf(buf
, sizeof(buf
), _T("Expected = after field type: malformed .bib file at line %ld (%s)"), BibLine
, filename
);
809 BibEatWhiteSpace(istr
);
811 if (ch
!= '{' && ch
!= '"')
814 BibReadWord(istr
, fieldValue
+1);
816 // If in the table of strings, replace with string from table.
817 wxChar
*s
= (wxChar
*)BibStringTable
.Get(fieldValue
);
820 wxStrcpy(fieldValue
, s
);
824 BibReadValue(istr
, fieldValue
, true, (ch
== _T('"') ? true : false));
826 // Now we can add a field
827 if (StringMatch(recordField
, _T("author"), false, true))
828 bibEntry
->author
= copystring(fieldValue
);
829 else if (StringMatch(recordField
, _T("key"), false, true))
831 else if (StringMatch(recordField
, _T("annotate"), false, true))
833 else if (StringMatch(recordField
, _T("abstract"), false, true))
835 else if (StringMatch(recordField
, _T("edition"), false, true))
837 else if (StringMatch(recordField
, _T("howpublished"), false, true))
839 else if (StringMatch(recordField
, _T("note"), false, true) || StringMatch(recordField
, _T("notes"), false, true))
841 else if (StringMatch(recordField
, _T("series"), false, true))
843 else if (StringMatch(recordField
, _T("type"), false, true))
845 else if (StringMatch(recordField
, _T("keywords"), false, true))
847 else if (StringMatch(recordField
, _T("editor"), false, true) || StringMatch(recordField
, _T("editors"), false, true))
848 bibEntry
->editor
= copystring(fieldValue
);
849 else if (StringMatch(recordField
, _T("title"), false, true))
850 bibEntry
->title
= copystring(fieldValue
);
851 else if (StringMatch(recordField
, _T("booktitle"), false, true))
852 bibEntry
->booktitle
= copystring(fieldValue
);
853 else if (StringMatch(recordField
, _T("journal"), false, true))
854 bibEntry
->journal
= copystring(fieldValue
);
855 else if (StringMatch(recordField
, _T("volume"), false, true))
856 bibEntry
->volume
= copystring(fieldValue
);
857 else if (StringMatch(recordField
, _T("number"), false, true))
858 bibEntry
->number
= copystring(fieldValue
);
859 else if (StringMatch(recordField
, _T("year"), false, true))
860 bibEntry
->year
= copystring(fieldValue
);
861 else if (StringMatch(recordField
, _T("month"), false, true))
862 bibEntry
->month
= copystring(fieldValue
);
863 else if (StringMatch(recordField
, _T("pages"), false, true))
864 bibEntry
->pages
= copystring(fieldValue
);
865 else if (StringMatch(recordField
, _T("publisher"), false, true))
866 bibEntry
->publisher
= copystring(fieldValue
);
867 else if (StringMatch(recordField
, _T("address"), false, true))
868 bibEntry
->address
= copystring(fieldValue
);
869 else if (StringMatch(recordField
, _T("institution"), false, true) || StringMatch(recordField
, _T("school"), false, true))
870 bibEntry
->institution
= copystring(fieldValue
);
871 else if (StringMatch(recordField
, _T("organization"), false, true) || StringMatch(recordField
, _T("organisation"), false, true))
872 bibEntry
->organization
= copystring(fieldValue
);
873 else if (StringMatch(recordField
, _T("comment"), false, true) || StringMatch(recordField
, _T("comments"), false, true))
874 bibEntry
->comment
= copystring(fieldValue
);
875 else if (StringMatch(recordField
, _T("annote"), false, true))
876 bibEntry
->comment
= copystring(fieldValue
);
877 else if (StringMatch(recordField
, _T("chapter"), false, true))
878 bibEntry
->chapter
= copystring(fieldValue
);
881 wxSnprintf(buf
, sizeof(buf
), _T("Unrecognised bib field type %s at line %ld (%s)"), recordField
, BibLine
, filename
);
886 BibList
.Append(recordKey
, bibEntry
);
887 BibEatWhiteSpace(istr
);
893 void OutputBibItem(TexRef
*ref
, BibEntry
*bib
)
897 OnMacro(ltNUMBEREDBIBITEM
, 2, true);
898 OnArgument(ltNUMBEREDBIBITEM
, 1, true);
899 TexOutput(ref
->sectionNumber
);
900 OnArgument(ltNUMBEREDBIBITEM
, 1, false);
901 OnArgument(ltNUMBEREDBIBITEM
, 2, true);
904 OnMacro(ltBF
, 1, true);
905 OnArgument(ltBF
, 1, true);
907 TexOutput(bib
->author
);
908 OnArgument(ltBF
, 1, false);
909 OnMacro(ltBF
, 1, false);
910 if (bib
->author
&& (wxStrlen(bib
->author
) > 0) && (bib
->author
[wxStrlen(bib
->author
) - 1] != '.'))
917 TexOutput(bib
->year
);
922 TexOutput(bib
->month
);
925 if (bib
->year
|| bib
->month
)
928 if (StringMatch(bib
->type
, _T("article"), false, true))
932 TexOutput(bib
->title
);
937 OnMacro(ltIT
, 1, true);
938 OnArgument(ltIT
, 1, true);
939 TexOutput(bib
->journal
);
940 OnArgument(ltIT
, 1, false);
941 OnMacro(ltIT
, 1, false);
946 OnMacro(ltBF
, 1, true);
947 OnArgument(ltBF
, 1, true);
948 TexOutput(bib
->volume
);
949 OnArgument(ltBF
, 1, false);
950 OnMacro(ltBF
, 1, false);
955 TexOutput(bib
->number
);
960 TexOutput(_T(", pages "));
961 TexOutput(bib
->pages
);
965 else if (StringMatch(bib
->type
, _T("book"), false, true) ||
966 StringMatch(bib
->type
, _T("unpublished"), false, true) ||
967 StringMatch(bib
->type
, _T("manual"), false, true) ||
968 StringMatch(bib
->type
, _T("phdthesis"), false, true) ||
969 StringMatch(bib
->type
, _T("mastersthesis"), false, true) ||
970 StringMatch(bib
->type
, _T("misc"), false, true) ||
971 StringMatch(bib
->type
, _T("techreport"), false, true) ||
972 StringMatch(bib
->type
, _T("booklet"), false, true))
974 if (bib
->title
|| bib
->booktitle
)
976 OnMacro(ltIT
, 1, true);
977 OnArgument(ltIT
, 1, true);
978 TexOutput(bib
->title
? bib
->title
: bib
->booktitle
);
980 OnArgument(ltIT
, 1, false);
981 OnMacro(ltIT
, 1, false);
983 if (StringMatch(bib
->type
, _T("phdthesis"), false, true))
984 TexOutput(_T("PhD thesis. "));
985 if (StringMatch(bib
->type
, _T("techreport"), false, true))
986 TexOutput(_T("Technical report. "));
989 TexOutput(_T("Ed. "));
990 TexOutput(bib
->editor
);
993 if (bib
->institution
)
995 TexOutput(bib
->institution
);
998 if (bib
->organization
)
1000 TexOutput(bib
->organization
);
1001 TexOutput(_T(". "));
1005 TexOutput(bib
->publisher
);
1006 TexOutput(_T(". "));
1010 TexOutput(bib
->address
);
1011 TexOutput(_T(". "));
1014 else if (StringMatch(bib
->type
, _T("inbook"), false, true) ||
1015 StringMatch(bib
->type
, _T("inproceedings"), false, true) ||
1016 StringMatch(bib
->type
, _T("incollection"), false, true) ||
1017 StringMatch(bib
->type
, _T("conference"), false, true))
1021 TexOutput(bib
->title
);
1025 TexOutput(_T(", from "));
1026 OnMacro(ltIT
, 1, true);
1027 OnArgument(ltIT
, 1, true);
1028 TexOutput(bib
->booktitle
);
1030 OnArgument(ltIT
, 1, false);
1031 OnMacro(ltIT
, 1, false);
1035 TexOutput(_T(", ed. "));
1036 TexOutput(bib
->editor
);
1041 TexOutput(bib
->publisher
);
1045 if (bib
->publisher
) TexOutput(_T(", "));
1046 else TexOutput(_T(" "));
1047 TexOutput(bib
->address
);
1049 if (bib
->publisher
|| bib
->address
)
1055 OnMacro(ltBF
, 1, true);
1056 OnArgument(ltBF
, 1, true);
1057 TexOutput(bib
->volume
);
1058 OnArgument(ltBF
, 1, false);
1059 OnMacro(ltBF
, 1, false);
1066 TexOutput(bib
->number
);
1067 TexOutput(_T(")."));
1071 TexOutput(_T(" Number "));
1072 TexOutput(bib
->number
);
1078 TexOutput(_T(" Chap. "));
1079 TexOutput(bib
->chapter
);
1083 if (bib
->chapter
) TexOutput(_T(", pages "));
1084 else TexOutput(_T(" Pages "));
1085 TexOutput(bib
->pages
);
1089 OnArgument(ltNUMBEREDBIBITEM
, 2, false);
1090 OnMacro(ltNUMBEREDBIBITEM
, 2, false);
1093 void OutputBib(void)
1095 // Write the heading
1096 ForceTopicName(_T("bibliography"));
1097 FakeCurrentSection(ReferencesNameString
);
1098 ForceTopicName(NULL
);
1100 OnMacro(ltPAR
, 0, true);
1101 OnMacro(ltPAR
, 0, false);
1103 if ((convertMode
== TEX_RTF
) && !winHelp
)
1105 OnMacro(ltPAR
, 0, true);
1106 OnMacro(ltPAR
, 0, false);
1109 wxStringListNode
*node
= CitationList
.GetFirst();
1112 wxChar
*citeKey
= (wxChar
*)node
->GetData();
1113 // wxNode *texNode = TexReferences.Find(citeKey);
1114 TexRef
*ref
= (TexRef
*)TexReferences
.Get(citeKey
);
1115 wxNode
*bibNode
= BibList
.Find(citeKey
);
1118 BibEntry
*entry
= (BibEntry
*)bibNode
->GetData();
1119 OutputBibItem(ref
, entry
);
1121 node
= node
->GetNext();
1125 static int citeCount
= 1;
1127 void ResolveBibReferences(void)
1129 if (CitationList
.GetCount() > 0)
1130 OnInform(_T("Resolving bibliographic references..."));
1134 wxStringListNode
*node
= CitationList
.GetFirst();
1138 wxChar
*citeKey
= (wxChar
*)node
->GetData();
1139 // wxNode *texNode = TexReferences.Find(citeKey);
1140 TexRef
*ref
= (TexRef
*)TexReferences
.Get(citeKey
);
1141 wxNode
*bibNode
= BibList
.Find(citeKey
);
1145 //BibEntry *entry = (BibEntry *)bibNode->GetData();
1146 if (ref
->sectionNumber
) delete[] ref
->sectionNumber
;
1147 wxSnprintf(buf
, sizeof(buf
), _T("[%d]"), citeCount
);
1148 ref
->sectionNumber
= copystring(buf
);
1153 wxSnprintf(buf
, sizeof(buf
), _T("Warning: bib ref %s not resolved."), citeKey
);
1156 node
= node
->GetNext();
1160 // Remember we need to resolve this citation
1161 void AddCitation(wxChar
*citeKey
)
1163 if (!CitationList
.Member(citeKey
))
1164 CitationList
.Add(citeKey
);
1166 if (!TexReferences
.Get(citeKey
))
1168 TexReferences
.Put(citeKey
, new TexRef(citeKey
, _T("??"), NULL
));
1172 TexRef
*FindReference(wxChar
*key
)
1174 return (TexRef
*)TexReferences
.Get(key
);
1178 * Custom macro stuff
1182 bool StringTobool(const wxString
& val
)
1187 if (up
.IsSameAs(_T("YES")) ||
1188 up
.IsSameAs(_T("TRUE")) ||
1189 up
.IsSameAs(_T("ON")) ||
1190 up
.IsSameAs(_T("OK")) |
1191 up
.IsSameAs(_T("1")))
1197 void RegisterIntSetting (const wxString
& s
, int *number
)
1207 // Define a variable value from the .ini file
1208 wxChar
*RegisterSetting(const wxString
& settingName
, const wxString
& settingValue
, bool interactive
)
1210 wxString
settingValueStr( settingValue
);
1212 static wxChar errorCode
[100];
1213 wxStrcpy(errorCode
, _T("OK"));
1214 if (StringMatch(settingName
, _T("chapterName"), false, true))
1216 delete[] ChapterNameString
;
1217 ChapterNameString
= copystring(settingValue
);
1219 else if (StringMatch(settingName
, _T("sectionName"), false, true))
1221 delete[] SectionNameString
;
1222 SectionNameString
= copystring(settingValue
);
1224 else if (StringMatch(settingName
, _T("subsectionName"), false, true))
1226 delete[] SubsectionNameString
;
1227 SubsectionNameString
= copystring(settingValue
);
1229 else if (StringMatch(settingName
, _T("subsubsectionName"), false, true))
1231 delete[] SubsubsectionNameString
;
1232 SubsubsectionNameString
= copystring(settingValue
);
1234 else if (StringMatch(settingName
, _T("indexName"), false, true))
1236 delete[] IndexNameString
;
1237 IndexNameString
= copystring(settingValue
);
1239 else if (StringMatch(settingName
, _T("contentsName"), false, true))
1241 delete[] ContentsNameString
;
1242 ContentsNameString
= copystring(settingValue
);
1244 else if (StringMatch(settingName
, _T("glossaryName"), false, true))
1246 delete[] GlossaryNameString
;
1247 GlossaryNameString
= copystring(settingValue
);
1249 else if (StringMatch(settingName
, _T("referencesName"), false, true))
1251 delete[] ReferencesNameString
;
1252 ReferencesNameString
= copystring(settingValue
);
1254 else if (StringMatch(settingName
, _T("tablesName"), false, true))
1256 delete[] TablesNameString
;
1257 TablesNameString
= copystring(settingValue
);
1259 else if (StringMatch(settingName
, _T("figuresName"), false, true))
1261 delete[] FiguresNameString
;
1262 FiguresNameString
= copystring(settingValue
);
1264 else if (StringMatch(settingName
, _T("tableName"), false, true))
1266 delete[] TableNameString
;
1267 TableNameString
= copystring(settingValue
);
1269 else if (StringMatch(settingName
, _T("figureName"), false, true))
1271 delete[] FigureNameString
;
1272 FigureNameString
= copystring(settingValue
);
1274 else if (StringMatch(settingName
, _T("abstractName"), false, true))
1276 delete[] AbstractNameString
;
1277 AbstractNameString
= copystring(settingValue
);
1279 else if (StringMatch(settingName
, _T("chapterFontSize"), false, true))
1280 RegisterIntSetting(settingValueStr
, &chapterFont
);
1281 else if (StringMatch(settingName
, _T("sectionFontSize"), false, true))
1282 RegisterIntSetting(settingValueStr
, §ionFont
);
1283 else if (StringMatch(settingName
, _T("subsectionFontSize"), false, true))
1284 RegisterIntSetting(settingValueStr
, &subsectionFont
);
1285 else if (StringMatch(settingName
, _T("titleFontSize"), false, true))
1286 RegisterIntSetting(settingValueStr
, &titleFont
);
1287 else if (StringMatch(settingName
, _T("authorFontSize"), false, true))
1288 RegisterIntSetting(settingValueStr
, &authorFont
);
1289 else if (StringMatch(settingName
, _T("ignoreInput"), false, true))
1290 IgnorableInputFiles
.Add(wxFileNameFromPath(settingValue
));
1291 else if (StringMatch(settingName
, _T("mirrorMargins"), false, true))
1292 mirrorMargins
= StringTobool(settingValue
);
1293 else if (StringMatch(settingName
, _T("runTwice"), false, true))
1294 runTwice
= StringTobool(settingValue
);
1295 else if (StringMatch(settingName
, _T("isInteractive"), false, true))
1296 isInteractive
= StringTobool(settingValue
);
1297 else if (StringMatch(settingName
, _T("headerRule"), false, true))
1298 headerRule
= StringTobool(settingValue
);
1299 else if (StringMatch(settingName
, _T("footerRule"), false, true))
1300 footerRule
= StringTobool(settingValue
);
1301 else if (StringMatch(settingName
, _T("combineSubSections"), false, true))
1302 combineSubSections
= StringTobool(settingValue
);
1303 else if (StringMatch(settingName
, _T("listLabelIndent"), false, true))
1304 RegisterIntSetting(settingValueStr
, &labelIndentTab
);
1305 else if (StringMatch(settingName
, _T("listItemIndent"), false, true))
1306 RegisterIntSetting(settingValueStr
, &itemIndentTab
);
1307 else if (StringMatch(settingName
, _T("useUpButton"), false, true))
1308 useUpButton
= StringTobool(settingValue
);
1309 else if (StringMatch(settingName
, _T("useHeadingStyles"), false, true))
1310 useHeadingStyles
= StringTobool(settingValue
);
1311 else if (StringMatch(settingName
, _T("useWord"), false, true))
1312 useWord
= StringTobool(settingValue
);
1313 else if (StringMatch(settingName
, _T("contentsDepth"), false, true))
1314 RegisterIntSetting(settingValueStr
, &contentsDepth
);
1315 else if (StringMatch(settingName
, _T("generateHPJ"), false, true))
1316 generateHPJ
= StringTobool(settingValue
);
1317 else if (StringMatch(settingName
, _T("truncateFilenames"), false, true))
1318 truncateFilenames
= StringTobool(settingValue
);
1319 else if (StringMatch(settingName
, _T("winHelpVersion"), false, true))
1320 RegisterIntSetting(settingValueStr
, &winHelpVersion
);
1321 else if (StringMatch(settingName
, _T("winHelpContents"), false, true))
1322 winHelpContents
= StringTobool(settingValue
);
1323 else if (StringMatch(settingName
, _T("htmlIndex"), false, true))
1324 htmlIndex
= StringTobool(settingValue
);
1325 else if (StringMatch(settingName
, _T("htmlWorkshopFiles"), false, true))
1326 htmlWorkshopFiles
= StringTobool(settingValue
);
1327 else if (StringMatch(settingName
, _T("htmlFrameContents"), false, true))
1328 htmlFrameContents
= StringTobool(settingValue
);
1329 else if (StringMatch(settingName
, _T("htmlStylesheet"), false, true))
1332 delete[] htmlStylesheet
;
1333 htmlStylesheet
= copystring(settingValue
);
1335 else if (StringMatch(settingName
, _T("upperCaseNames"), false, true))
1336 upperCaseNames
= StringTobool(settingValue
);
1337 else if (StringMatch(settingName
, _T("ignoreBadRefs"), false, true))
1338 ignoreBadRefs
= StringTobool(settingValue
);
1339 else if (StringMatch(settingName
, _T("htmlFaceName"), false, true))
1341 delete[] htmlFaceName
;
1342 htmlFaceName
= copystring(settingValue
);
1344 else if (StringMatch(settingName
, _T("winHelpTitle"), false, true))
1347 delete[] winHelpTitle
;
1348 winHelpTitle
= copystring(settingValue
);
1350 else if (StringMatch(settingName
, _T("indexSubsections"), false, true))
1351 indexSubsections
= StringTobool(settingValue
);
1352 else if (StringMatch(settingName
, _T("compatibility"), false, true))
1353 compatibilityMode
= StringTobool(settingValue
);
1354 else if (StringMatch(settingName
, _T("defaultColumnWidth"), false, true))
1356 RegisterIntSetting(settingValueStr
, &defaultTableColumnWidth
);
1357 defaultTableColumnWidth
= 20*defaultTableColumnWidth
;
1359 else if (StringMatch(settingName
, _T("bitmapMethod"), false, true))
1361 if ((wxStrcmp(settingValue
, _T("includepicture")) != 0) && (wxStrcmp(settingValue
, _T("hex")) != 0) &&
1362 (wxStrcmp(settingValue
, _T("import")) != 0))
1365 OnError(_T("Unknown bitmapMethod"));
1366 wxStrcpy(errorCode
, _T("Unknown bitmapMethod"));
1370 delete[] bitmapMethod
;
1371 bitmapMethod
= copystring(settingValue
);
1374 else if (StringMatch(settingName
, _T("htmlBrowseButtons"), false, true))
1376 if (wxStrcmp(settingValue
, _T("none")) == 0)
1377 htmlBrowseButtons
= HTML_BUTTONS_NONE
;
1378 else if (wxStrcmp(settingValue
, _T("bitmap")) == 0)
1379 htmlBrowseButtons
= HTML_BUTTONS_BITMAP
;
1380 else if (wxStrcmp(settingValue
, _T("text")) == 0)
1381 htmlBrowseButtons
= HTML_BUTTONS_TEXT
;
1385 OnInform(_T("Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text."));
1386 wxStrcpy(errorCode
, _T("Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text."));
1389 else if (StringMatch(settingName
, _T("backgroundImage"), false, true))
1391 backgroundImageString
= copystring(settingValue
);
1393 else if (StringMatch(settingName
, _T("backgroundColour"), false, true))
1395 delete[] backgroundColourString
;
1396 backgroundColourString
= copystring(settingValue
);
1398 else if (StringMatch(settingName
, _T("textColour"), false, true))
1400 textColourString
= copystring(settingValue
);
1402 else if (StringMatch(settingName
, _T("linkColour"), false, true))
1404 linkColourString
= copystring(settingValue
);
1406 else if (StringMatch(settingName
, _T("followedLinkColour"), false, true))
1408 followedLinkColourString
= copystring(settingValue
);
1410 else if (StringMatch(settingName
, _T("conversionMode"), false, true))
1412 if (StringMatch(settingValue
, _T("RTF"), false, true))
1414 winHelp
= false; convertMode
= TEX_RTF
;
1416 else if (StringMatch(settingValue
, _T("WinHelp"), false, true))
1418 winHelp
= true; convertMode
= TEX_RTF
;
1420 else if (StringMatch(settingValue
, _T("XLP"), false, true) ||
1421 StringMatch(settingValue
, _T("wxHelp"), false, true))
1423 convertMode
= TEX_XLP
;
1425 else if (StringMatch(settingValue
, _T("HTML"), false, true))
1427 convertMode
= TEX_HTML
;
1432 OnInform(_T("Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML."));
1433 wxStrcpy(errorCode
, _T("Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML."));
1436 else if (StringMatch(settingName
, _T("documentFontSize"), false, true))
1439 RegisterIntSetting(settingValueStr
, &n
);
1440 if (n
== 10 || n
== 11 || n
== 12)
1445 wxSnprintf(buf
, sizeof(buf
), _T("Initialisation file error: nonstandard document font size %d."), n
);
1448 wxStrcpy(errorCode
, buf
);
1454 wxSnprintf(buf
, sizeof(buf
), _T("Initialisation file error: unrecognised setting %s."), settingName
.c_str());
1457 wxStrcpy(errorCode
, buf
);
1462 bool ReadCustomMacros(const wxString
& filename
)
1464 if (!wxFileExists(filename
))
1467 wxFileInputStream
input( filename
);
1468 if(!input
.Ok()) return false;
1469 wxTextInputStream
ini( input
);
1471 CustomMacroList
.Clear();
1473 while (!input
.Eof())
1475 wxString line
= ini
.ReadLine();
1476 BibEatWhiteSpace(line
);
1477 if (line
.empty()) continue;
1479 if (line
[0] != _T('\\')) // Not a macro definition, so must be NAME=VALUE
1481 wxString settingName
= BibReadWord(line
);
1482 BibEatWhiteSpace(line
);
1483 if (line
.empty() || line
[0] != _T('='))
1485 OnError(_T("Expected = following name: malformed tex2rtf.ini file."));
1490 line
= line
.substr(1);
1491 BibEatWhiteSpace(line
);
1492 wxString settingValue
= BibReadToEOL(line
);
1493 RegisterSetting(settingName
, settingValue
);
1498 line
= line
.substr(1);
1499 wxString macroName
= BibReadWord(line
);
1500 BibEatWhiteSpace(line
);
1501 if (line
[0] != _T('['))
1503 OnError(_T("Expected [ followed by number of arguments: malformed tex2rtf.ini file."));
1506 line
= line
.substr(1);
1507 wxString noAargStr
= line
.BeforeFirst(_T(']'));
1508 line
= line
.AfterFirst(_T(']'));
1510 if (!noAargStr
.ToLong(&noArgs
) || line
.empty())
1512 OnError(_T("Expected ] following number of arguments: malformed tex2rtf.ini file."));
1515 BibEatWhiteSpace(line
);
1516 if (line
[0] != _T('{'))
1518 OnError(_T("Expected { followed by macro body: malformed tex2rtf.ini file."));
1522 CustomMacro
*macro
= new CustomMacro(macroName
.c_str(), noArgs
, NULL
);
1523 wxString macroBody
= BibReadValue(line
, false, false); // Don't ignore extra braces
1524 if (!macroBody
.empty())
1525 macro
->macroBody
= copystring(macroBody
.c_str());
1527 BibEatWhiteSpace(line
);
1528 CustomMacroList
.Append(macroName
.c_str(), macro
);
1529 AddMacroDef(ltCUSTOM_MACRO
, macroName
.c_str(), noArgs
);
1534 wxSnprintf(mbuf
, sizeof(mbuf
), _T("Read initialization file %s."), filename
.c_str());
1539 CustomMacro
*FindCustomMacro(wxChar
*name
)
1541 wxNode
*node
= CustomMacroList
.Find(name
);
1544 CustomMacro
*macro
= (CustomMacro
*)node
->GetData();
1550 // Display custom macros
1551 void ShowCustomMacros(void)
1553 wxNode
*node
= CustomMacroList
.GetFirst();
1556 OnInform(_T("No custom macros loaded.\n"));
1563 CustomMacro
*macro
= (CustomMacro
*)node
->GetData();
1564 wxSnprintf(buf
, sizeof(buf
), _T("\\%s[%d]\n {%s}"), macro
->macroName
, macro
->noArgs
,
1565 macro
->macroBody
? macro
->macroBody
: _T(""));
1567 node
= node
->GetNext();
1571 // Parse a string into several comma-separated fields
1572 wxChar
*ParseMultifieldString(wxChar
*allFields
, int *pos
)
1574 static wxChar buffer
[300];
1576 int fieldIndex
= *pos
;
1577 int len
= wxStrlen(allFields
);
1579 bool keepGoing
= true;
1580 while ((fieldIndex
<= len
) && keepGoing
)
1582 if (allFields
[fieldIndex
] == _T(' '))
1587 else if (allFields
[fieldIndex
] == _T(','))
1589 *pos
= fieldIndex
+ 1;
1592 else if (allFields
[fieldIndex
] == 0)
1594 *pos
= fieldIndex
+ 1;
1599 buffer
[i
] = allFields
[fieldIndex
];
1605 if (oldPos
== (*pos
))
1619 ColourTableEntry::ColourTableEntry(const wxChar
*theName
, unsigned int r
, unsigned int g
, unsigned int b
)
1621 name
= copystring(theName
);
1627 ColourTableEntry::~ColourTableEntry(void)
1632 void AddColour(const wxChar
*theName
, unsigned int r
, unsigned int g
, unsigned int b
)
1634 wxNode
*node
= ColourTable
.Find(theName
);
1637 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->GetData();
1638 if (entry
->red
== r
|| entry
->green
== g
|| entry
->blue
== b
)
1646 ColourTableEntry
*entry
= new ColourTableEntry(theName
, r
, g
, b
);
1647 ColourTable
.Append(theName
, entry
);
1650 int FindColourPosition(wxChar
*theName
)
1653 wxNode
*node
= ColourTable
.GetFirst();
1656 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->GetData();
1657 if (wxStrcmp(theName
, entry
->name
) == 0)
1660 node
= node
->GetNext();
1665 // Converts e.g. "red" -> "#FF0000"
1666 extern void DecToHex(int, wxChar
*);
1667 bool FindColourHTMLString(wxChar
*theName
, wxChar
*buf
)
1669 wxNode
*node
= ColourTable
.GetFirst();
1672 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->GetData();
1673 if (wxStrcmp(theName
, entry
->name
) == 0)
1675 wxStrcpy(buf
, _T("#"));
1678 DecToHex(entry
->red
, buf2
);
1679 wxStrcat(buf
, buf2
);
1680 DecToHex(entry
->green
, buf2
);
1681 wxStrcat(buf
, buf2
);
1682 DecToHex(entry
->blue
, buf2
);
1683 wxStrcat(buf
, buf2
);
1687 node
= node
->GetNext();
1693 void InitialiseColourTable(void)
1695 // \\red0\\green0\\blue0;
1696 AddColour(_T("black"), 0,0,0);
1698 // \\red0\\green0\\blue255;\\red0\\green255\\blue255;\n");
1699 AddColour(_T("cyan"), 0,255,255);
1701 // \\red0\\green255\\blue0;
1702 AddColour(_T("green"), 0,255,0);
1704 // \\red255\\green0\\blue255;
1705 AddColour(_T("magenta"), 255,0,255);
1707 // \\red255\\green0\\blue0;
1708 AddColour(_T("red"), 255,0,0);
1710 // \\red255\\green255\\blue0;
1711 AddColour(_T("yellow"), 255,255,0);
1713 // \\red255\\green255\\blue255;}");
1714 AddColour(_T("white"), 255,255,255);
1718 * The purpose of this is to reduce the number of times wxYield is
1719 * called, since under Windows this can slow things down.
1722 void Tex2RTFYield(bool force
)
1725 static int yieldCount
= 0;
1732 if (yieldCount
== 0)
1744 // In both RTF generation and HTML generation for wxHelp version 2,
1745 // we need to associate \indexed keywords with the current filename/topics.
1747 // Hash table for lists of keywords for topics (WinHelp).
1748 wxHashTable
TopicTable(wxKEY_STRING
);
1749 void AddKeyWordForTopic(wxChar
*topic
, wxChar
*entry
, wxChar
*filename
)
1751 TexTopic
*texTopic
= (TexTopic
*)TopicTable
.Get(topic
);
1754 texTopic
= new TexTopic(filename
);
1755 texTopic
->keywords
= new wxStringList
;
1756 TopicTable
.Put(topic
, texTopic
);
1759 if (!texTopic
->keywords
->Member(entry
))
1760 texTopic
->keywords
->Add(entry
);
1763 void ClearKeyWordTable(void)
1765 TopicTable
.BeginFind();
1766 wxHashTable::Node
*node
= TopicTable
.Next();
1769 TexTopic
*texTopic
= (TexTopic
*)node
->GetData();
1771 node
= TopicTable
.Next();
1778 * TexTopic structure
1781 TexTopic::TexTopic(wxChar
*f
)
1784 filename
= copystring(f
);
1787 hasChildren
= false;
1791 TexTopic::~TexTopic(void)
1799 // Convert case, according to upperCaseNames setting.
1800 wxChar
*ConvertCase(wxChar
*s
)
1802 static wxChar buf
[256];
1803 int len
= wxStrlen(s
);
1806 for (i
= 0; i
< len
; i
++)
1807 buf
[i
] = (wxChar
)wxToupper(s
[i
]);
1809 for (i
= 0; i
< len
; i
++)
1810 buf
[i
] = (wxChar
)wxTolower(s
[i
]);
1815 // if substring is true, search for str1 in str2
1816 bool StringMatch(const wxChar
*str1
, const wxChar
*str2
, bool subString
,
1821 wxString
Sstr1(str1
);
1822 wxString
Sstr2(str2
);
1828 return Sstr2
.Index(Sstr1
) != (size_t)wxNOT_FOUND
;
1831 return exact
? wxString(str2
).Cmp(str1
) == 0 :
1832 wxString(str2
).CmpNoCase(str1
) == 0;