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"
43 #if !WXWIN_COMPATIBILITY_2_4
44 static inline wxChar
* copystring(const wxChar
* s
)
45 { return wxStrcpy(new wxChar
[wxStrlen(s
) + 1], s
); }
48 wxHashTable
TexReferences(wxKEY_STRING
);
49 wxList
BibList(wxKEY_STRING
);
50 wxStringList CitationList
;
51 wxList
ColourTable(wxKEY_STRING
);
52 wxHashTable
BibStringTable(wxKEY_STRING
);
53 wxList
CustomMacroList(wxKEY_STRING
);
54 TexChunk
*currentSection
= NULL
;
55 wxChar
*fakeCurrentSection
= NULL
;
57 static long BibLine
= 1;
59 void OutputCurrentSection(void)
61 if (fakeCurrentSection
)
62 TexOutput(fakeCurrentSection
);
63 else if (currentSection
)
64 TraverseChildrenFromChunk(currentSection
);
67 // Nasty but the way things are done now, necessary,
68 // in order to output a chunk properly to a string (macros and all).
69 void OutputCurrentSectionToString(wxChar
*buf
)
71 if (fakeCurrentSection
)
72 wxStrcpy(buf
, fakeCurrentSection
);
74 OutputChunkToString(currentSection
, buf
);
77 void OutputChunkToString(TexChunk
*chunk
, wxChar
*buf
)
79 FILE *tempfd
= wxFopen(_T("tmp.tmp"), _T("w"));
83 FILE *old1
= CurrentOutput1
;
84 FILE *old2
= CurrentOutput2
;
86 CurrentOutput1
= tempfd
;
87 CurrentOutput2
= NULL
;
89 TraverseChildrenFromChunk(chunk
);
91 CurrentOutput1
= old1
;
92 CurrentOutput2
= old2
;
96 // Read from file into string
97 tempfd
= wxFopen(_T("tmp.tmp"), _T("r"));
116 wxRemoveFile(_T("tmp.tmp"));
119 // Called by Tex2Any to simulate a section
120 void FakeCurrentSection(wxChar
*fakeSection
, bool addToContents
)
122 currentSection
= NULL
;
123 if (fakeCurrentSection
) delete[] fakeCurrentSection
;
124 fakeCurrentSection
= copystring(fakeSection
);
126 if (DocumentStyle
== LATEX_ARTICLE
)
128 int mac
= ltSECTIONHEADING
;
130 mac
= ltSECTIONHEADINGSTAR
;
131 OnMacro(mac
, 0, true);
132 OnMacro(mac
, 0, false);
136 int mac
= ltCHAPTERHEADING
;
138 mac
= ltCHAPTERHEADINGSTAR
;
139 OnMacro(mac
, 0, true);
140 OnMacro(mac
, 0, false);
142 if (fakeCurrentSection
) delete[] fakeCurrentSection
;
143 fakeCurrentSection
= NULL
;
146 // Look for \label macro, use this ref name if found or
147 // make up a topic name otherwise.
148 static long topicCounter
= 0;
150 void ResetTopicCounter(void)
155 static wxChar
*forceTopicName
= NULL
;
157 void ForceTopicName(const wxChar
*name
)
160 delete[] forceTopicName
;
162 forceTopicName
= copystring(name
);
164 forceTopicName
= NULL
;
167 wxChar
*FindTopicName(TexChunk
*chunk
)
170 return forceTopicName
;
172 wxChar
*topicName
= NULL
;
173 static wxChar topicBuf
[100];
175 if (chunk
&& (chunk
->type
== CHUNK_TYPE_MACRO
) &&
176 (chunk
->macroId
== ltLABEL
))
178 wxNode
*node
= chunk
->children
.GetFirst();
181 TexChunk
*child
= (TexChunk
*)node
->GetData();
182 if (child
->type
== CHUNK_TYPE_ARG
)
184 wxNode
*snode
= child
->children
.GetFirst();
187 TexChunk
*schunk
= (TexChunk
*)snode
->GetData();
188 if (schunk
->type
== CHUNK_TYPE_STRING
)
189 topicName
= schunk
->value
;
198 wxSnprintf(topicBuf
, sizeof(topicBuf
), _T("topic%ld"), topicCounter
);
205 * Simulate argument data, so we can 'drive' clients which implement
206 * certain basic formatting behaviour.
207 * Snag is that some save a TexChunk, so don't use yet...
211 void StartSimulateArgument(wxChar
*data
)
213 wxStrcpy(currentArgData
, data
);
217 void EndSimulateArgument(void)
223 * Parse and convert unit arguments to points
227 int ParseUnitArgument(wxChar
*unitArg
)
229 float conversionFactor
= 1.0;
230 float unitValue
= 0.0;
231 int len
= wxStrlen(unitArg
);
232 // Get rid of any accidentally embedded commands
233 for (int i
= 0; i
< len
; i
++)
234 if (unitArg
[i
] == '\\')
236 len
= wxStrlen(unitArg
);
238 if (unitArg
&& (len
> 0) && (isdigit(unitArg
[0]) || unitArg
[0] == '-'))
240 wxSscanf(unitArg
, _T("%f"), &unitValue
);
244 units
[0] = unitArg
[len
-2];
245 units
[1] = unitArg
[len
-1];
247 if (wxStrcmp(units
, _T("in")) == 0)
248 conversionFactor
= 72.0;
249 else if (wxStrcmp(units
, _T("cm")) == 0)
250 conversionFactor
= (float)72.0/(float)2.51;
251 else if (wxStrcmp(units
, _T("mm")) == 0)
252 conversionFactor
= (float)72.0/(float)25.1;
253 else if (wxStrcmp(units
, _T("pt")) == 0)
254 conversionFactor
= 1;
256 return (int)(unitValue
*conversionFactor
);
262 * Strip off any extension (dot something) from end of file,
263 * IF one exists. Inserts zero into buffer.
267 void StripExtension(wxChar
*buffer
)
269 int len
= wxStrlen(buffer
);
273 if (buffer
[i
] == '.')
287 void SetFontSizes(int pointSize
)
339 void AddTexRef(wxChar
*name
, wxChar
*file
, wxChar
*sectionName
,
340 int chapter
, int section
, int subsection
, int subsubsection
)
342 TexRef
*texRef
= (TexRef
*)TexReferences
.Get(name
);
343 if (texRef
) TexReferences
.Delete(name
);
350 wxStrcat(buf, sectionName);
357 wxSnprintf(buf2
, sizeof(buf2
), _T("%d"), chapter
);
364 wxStrcat(buf
, _T("."));
366 wxSnprintf(buf2
, sizeof(buf2
), _T("%d"), section
);
372 wxStrcat(buf
, _T("."));
373 wxSnprintf(buf2
, sizeof(buf2
), _T("%d"), subsection
);
379 wxStrcat(buf
, _T("."));
380 wxSnprintf(buf2
, sizeof(buf2
), _T("%d"), subsubsection
);
383 wxChar
*tmp
= ((wxStrlen(buf
) > 0) ? buf
: (wxChar
*)NULL
);
384 TexReferences
.Put(name
, new TexRef(name
, file
, tmp
, sectionName
));
387 void WriteTexReferences(wxChar
*filename
)
390 wxString name
= filename
;
391 wxSTD ofstream
ostr((char const *)name
.fn_str());
392 if (ostr
.bad()) return;
394 TexReferences
.BeginFind();
395 wxHashTable::Node
*node
= TexReferences
.Next();
399 TexRef
*ref
= (TexRef
*)node
->GetData();
400 converter
= ref
->refLabel
;
401 ostr
<< converter
.mb_str();
403 converter
= (ref
->refFile
? ref
->refFile
: _T("??"));
404 ostr
<< converter
.mb_str();
406 converter
= (ref
->sectionName
? ref
->sectionName
: _T("??")) ;
407 ostr
<< converter
.mb_str();
409 converter
= (ref
->sectionNumber
? ref
->sectionNumber
: _T("??")) ;
410 ostr
<< converter
.mb_str();
412 if (!ref
->sectionNumber
|| (wxStrcmp(ref
->sectionNumber
, _T("??")) == 0 && wxStrcmp(ref
->sectionName
, _T("??")) == 0))
415 wxSnprintf(buf
, sizeof(buf
), _T("Warning: reference %s not resolved."), ref
->refLabel
);
418 node
= TexReferences
.Next();
422 void ReadTexReferences(wxChar
*filename
)
424 if (!wxFileExists(filename
))
427 wxString name
= filename
;
428 wxSTD ifstream
istr((char const *)name
.fn_str(), wxSTD
ios::in
);
430 if (istr
.bad()) return;
435 char sectionName
[100];
445 istr
.get(ch
); // Read past space
448 while (ch
!= '\n' && !istr
.eof())
456 wxString label_string
= wxString::FromAscii(label
);
457 wxString file_string
= wxString::FromAscii(file
);
458 wxString sectionName_string
= wxString::FromAscii(sectionName
);
459 wxString section_string
= wxString::FromAscii(section
);
461 // gt - needed to trick the hash table "TexReferences" into deleting the key
462 // strings it creates in the Put() function, but not the item that is
463 // created here, as that is destroyed elsewhere. Without doing this, there
464 // were massive memory leaks
465 TexReferences
.DeleteContents(true);
467 label_string
.c_str(),
469 label_string
.c_str(),
471 section_string
.c_str(),
472 sectionName_string
.c_str()
475 TexReferences
.DeleteContents(false);
482 * Bibliography-handling code
486 void BibEatWhiteSpace(wxSTD istream
& str
)
488 char ch
= (char)str
.peek();
490 while (!str
.eof() && (ch
== ' ' || ch
== '\t' || ch
== 13 || ch
== 10 || ch
== (char)EOF
))
495 if ((ch
== (char)EOF
) || str
.eof()) return;
496 ch
= (char)str
.peek();
499 // Ignore end-of-line comments
500 if (ch
== '%' || ch
== ';' || ch
== '#')
503 ch
= (char)str
.peek();
504 while (ch
!= 10 && ch
!= 13 && !str
.eof())
507 ch
= (char)str
.peek();
509 BibEatWhiteSpace(str
);
513 // Read word up to { or , or space
514 void BibReadWord(wxSTD istream
& istr
, wxChar
*buffer
)
518 char ch
= (char)istr
.peek();
519 while (!istr
.eof() && ch
!= ' ' && ch
!= '{' && ch
!= '(' && ch
!= 13 && ch
!= 10 && ch
!= '\t' &&
520 ch
!= ',' && ch
!= '=')
525 ch
= (char)istr
.peek();
530 // Read string (double-quoted or not) to end quote or EOL
531 void BibReadToEOL(wxSTD istream
& istr
, wxChar
*buffer
)
535 char ch
= (char)istr
.peek();
536 bool inQuotes
= false;
540 ch
= (char)istr
.peek();
543 // If in quotes, read white space too. If not,
544 // stop at white space or comment.
545 while (!istr
.eof() && ch
!= 13 && ch
!= 10 && ch
!= _T('"') &&
546 (inQuotes
|| ((ch
!= _T(' ')) && (ch
!= 9) &&
547 (ch
!= _T(';')) && (ch
!= _T('%')) && (ch
!= _T('#')))))
552 ch
= (char)istr
.peek();
559 // Read }-terminated value, taking nested braces into account.
560 void BibReadValue(wxSTD istream
& istr
, wxChar
*buffer
, bool ignoreBraces
= true,
561 bool quotesMayTerminate
= true)
566 char ch
= (char)istr
.peek();
567 bool stopping
= false;
568 while (!istr
.eof() && !stopping
)
574 wxSnprintf(buf
, sizeof(buf
), _T("Sorry, value > 4000 chars in bib file at line %ld."), BibLine
);
575 wxLogError(buf
, "Tex2RTF Fatal Error");
592 else if (quotesMayTerminate
&& ch
== '"')
599 if (!ignoreBraces
|| (ch
!= '{' && ch
!= '}'))
609 wxUnusedVar(stopping
);
612 bool ReadBib(wxChar
*filename
)
614 if (!wxFileExists(filename
))
617 wxString name
= filename
;
619 wxSTD ifstream
istr((char const *)name
.fn_str(), wxSTD
ios::in
);
620 if (istr
.bad()) return false;
624 OnInform(_T("Reading .bib file..."));
627 wxChar fieldValue
[4000];
628 wxChar recordType
[100];
629 wxChar recordKey
[100];
630 wxChar recordField
[100];
635 BibEatWhiteSpace(istr
);
639 wxSnprintf(buf
, sizeof(buf
), _T("Expected @: malformed bib file at line %ld (%s)"), BibLine
, filename
);
643 BibReadWord(istr
, recordType
);
644 BibEatWhiteSpace(istr
);
646 if (ch
!= '{' && ch
!= '(')
648 wxSnprintf(buf
, sizeof(buf
), _T("Expected { or ( after record type: malformed .bib file at line %ld (%s)"), BibLine
, filename
);
652 BibEatWhiteSpace(istr
);
653 if (StringMatch(recordType
, _T("string"), false, true))
655 BibReadWord(istr
, recordType
);
656 BibEatWhiteSpace(istr
);
660 wxSnprintf(buf
, sizeof(buf
), _T("Expected = after string key: malformed .bib file at line %ld (%s)"), BibLine
, filename
);
664 BibEatWhiteSpace(istr
);
666 if (ch
!= '"' && ch
!= '{')
668 wxSnprintf(buf
, sizeof(buf
), _T("Expected = after string key: malformed .bib file at line %ld (%s)"), BibLine
, filename
);
672 BibReadValue(istr
, fieldValue
);
674 // Now put in hash table if necesary
675 if (!BibStringTable
.Get(recordType
))
676 BibStringTable
.Put(recordType
, (wxObject
*)copystring(fieldValue
));
678 // Read closing ) or }
679 BibEatWhiteSpace(istr
);
681 BibEatWhiteSpace(istr
);
685 BibReadWord(istr
, recordKey
);
687 BibEntry
*bibEntry
= new BibEntry
;
688 bibEntry
->key
= copystring(recordKey
);
689 bibEntry
->type
= copystring(recordType
);
691 bool moreRecords
= true;
692 while (moreRecords
&& !istr
.eof())
694 BibEatWhiteSpace(istr
);
696 if (ch
== '}' || ch
== ')')
702 BibEatWhiteSpace(istr
);
703 BibReadWord(istr
, recordField
);
704 BibEatWhiteSpace(istr
);
708 wxSnprintf(buf
, sizeof(buf
), _T("Expected = after field type: malformed .bib file at line %ld (%s)"), BibLine
, filename
);
712 BibEatWhiteSpace(istr
);
714 if (ch
!= '{' && ch
!= '"')
717 BibReadWord(istr
, fieldValue
+1);
719 // If in the table of strings, replace with string from table.
720 wxChar
*s
= (wxChar
*)BibStringTable
.Get(fieldValue
);
723 wxStrcpy(fieldValue
, s
);
727 BibReadValue(istr
, fieldValue
, true, (ch
== _T('"') ? true : false));
729 // Now we can add a field
730 if (StringMatch(recordField
, _T("author"), false, true))
731 bibEntry
->author
= copystring(fieldValue
);
732 else if (StringMatch(recordField
, _T("key"), false, true))
734 else if (StringMatch(recordField
, _T("annotate"), false, true))
736 else if (StringMatch(recordField
, _T("abstract"), false, true))
738 else if (StringMatch(recordField
, _T("edition"), false, true))
740 else if (StringMatch(recordField
, _T("howpublished"), false, true))
742 else if (StringMatch(recordField
, _T("note"), false, true) || StringMatch(recordField
, _T("notes"), false, true))
744 else if (StringMatch(recordField
, _T("series"), false, true))
746 else if (StringMatch(recordField
, _T("type"), false, true))
748 else if (StringMatch(recordField
, _T("keywords"), false, true))
750 else if (StringMatch(recordField
, _T("editor"), false, true) || StringMatch(recordField
, _T("editors"), false, true))
751 bibEntry
->editor
= copystring(fieldValue
);
752 else if (StringMatch(recordField
, _T("title"), false, true))
753 bibEntry
->title
= copystring(fieldValue
);
754 else if (StringMatch(recordField
, _T("booktitle"), false, true))
755 bibEntry
->booktitle
= copystring(fieldValue
);
756 else if (StringMatch(recordField
, _T("journal"), false, true))
757 bibEntry
->journal
= copystring(fieldValue
);
758 else if (StringMatch(recordField
, _T("volume"), false, true))
759 bibEntry
->volume
= copystring(fieldValue
);
760 else if (StringMatch(recordField
, _T("number"), false, true))
761 bibEntry
->number
= copystring(fieldValue
);
762 else if (StringMatch(recordField
, _T("year"), false, true))
763 bibEntry
->year
= copystring(fieldValue
);
764 else if (StringMatch(recordField
, _T("month"), false, true))
765 bibEntry
->month
= copystring(fieldValue
);
766 else if (StringMatch(recordField
, _T("pages"), false, true))
767 bibEntry
->pages
= copystring(fieldValue
);
768 else if (StringMatch(recordField
, _T("publisher"), false, true))
769 bibEntry
->publisher
= copystring(fieldValue
);
770 else if (StringMatch(recordField
, _T("address"), false, true))
771 bibEntry
->address
= copystring(fieldValue
);
772 else if (StringMatch(recordField
, _T("institution"), false, true) || StringMatch(recordField
, _T("school"), false, true))
773 bibEntry
->institution
= copystring(fieldValue
);
774 else if (StringMatch(recordField
, _T("organization"), false, true) || StringMatch(recordField
, _T("organisation"), false, true))
775 bibEntry
->organization
= copystring(fieldValue
);
776 else if (StringMatch(recordField
, _T("comment"), false, true) || StringMatch(recordField
, _T("comments"), false, true))
777 bibEntry
->comment
= copystring(fieldValue
);
778 else if (StringMatch(recordField
, _T("annote"), false, true))
779 bibEntry
->comment
= copystring(fieldValue
);
780 else if (StringMatch(recordField
, _T("chapter"), false, true))
781 bibEntry
->chapter
= copystring(fieldValue
);
784 wxSnprintf(buf
, sizeof(buf
), _T("Unrecognised bib field type %s at line %ld (%s)"), recordField
, BibLine
, filename
);
789 BibList
.Append(recordKey
, bibEntry
);
790 BibEatWhiteSpace(istr
);
796 void OutputBibItem(TexRef
*ref
, BibEntry
*bib
)
800 OnMacro(ltNUMBEREDBIBITEM
, 2, true);
801 OnArgument(ltNUMBEREDBIBITEM
, 1, true);
802 TexOutput(ref
->sectionNumber
);
803 OnArgument(ltNUMBEREDBIBITEM
, 1, false);
804 OnArgument(ltNUMBEREDBIBITEM
, 2, true);
807 OnMacro(ltBF
, 1, true);
808 OnArgument(ltBF
, 1, true);
810 TexOutput(bib
->author
);
811 OnArgument(ltBF
, 1, false);
812 OnMacro(ltBF
, 1, false);
813 if (bib
->author
&& (wxStrlen(bib
->author
) > 0) && (bib
->author
[wxStrlen(bib
->author
) - 1] != '.'))
820 TexOutput(bib
->year
);
825 TexOutput(bib
->month
);
828 if (bib
->year
|| bib
->month
)
831 if (StringMatch(bib
->type
, _T("article"), false, true))
835 TexOutput(bib
->title
);
840 OnMacro(ltIT
, 1, true);
841 OnArgument(ltIT
, 1, true);
842 TexOutput(bib
->journal
);
843 OnArgument(ltIT
, 1, false);
844 OnMacro(ltIT
, 1, false);
849 OnMacro(ltBF
, 1, true);
850 OnArgument(ltBF
, 1, true);
851 TexOutput(bib
->volume
);
852 OnArgument(ltBF
, 1, false);
853 OnMacro(ltBF
, 1, false);
858 TexOutput(bib
->number
);
863 TexOutput(_T(", pages "));
864 TexOutput(bib
->pages
);
868 else if (StringMatch(bib
->type
, _T("book"), false, true) ||
869 StringMatch(bib
->type
, _T("unpublished"), false, true) ||
870 StringMatch(bib
->type
, _T("manual"), false, true) ||
871 StringMatch(bib
->type
, _T("phdthesis"), false, true) ||
872 StringMatch(bib
->type
, _T("mastersthesis"), false, true) ||
873 StringMatch(bib
->type
, _T("misc"), false, true) ||
874 StringMatch(bib
->type
, _T("techreport"), false, true) ||
875 StringMatch(bib
->type
, _T("booklet"), false, true))
877 if (bib
->title
|| bib
->booktitle
)
879 OnMacro(ltIT
, 1, true);
880 OnArgument(ltIT
, 1, true);
881 TexOutput(bib
->title
? bib
->title
: bib
->booktitle
);
883 OnArgument(ltIT
, 1, false);
884 OnMacro(ltIT
, 1, false);
886 if (StringMatch(bib
->type
, _T("phdthesis"), false, true))
887 TexOutput(_T("PhD thesis. "));
888 if (StringMatch(bib
->type
, _T("techreport"), false, true))
889 TexOutput(_T("Technical report. "));
892 TexOutput(_T("Ed. "));
893 TexOutput(bib
->editor
);
896 if (bib
->institution
)
898 TexOutput(bib
->institution
);
901 if (bib
->organization
)
903 TexOutput(bib
->organization
);
908 TexOutput(bib
->publisher
);
913 TexOutput(bib
->address
);
917 else if (StringMatch(bib
->type
, _T("inbook"), false, true) ||
918 StringMatch(bib
->type
, _T("inproceedings"), false, true) ||
919 StringMatch(bib
->type
, _T("incollection"), false, true) ||
920 StringMatch(bib
->type
, _T("conference"), false, true))
924 TexOutput(bib
->title
);
928 TexOutput(_T(", from "));
929 OnMacro(ltIT
, 1, true);
930 OnArgument(ltIT
, 1, true);
931 TexOutput(bib
->booktitle
);
933 OnArgument(ltIT
, 1, false);
934 OnMacro(ltIT
, 1, false);
938 TexOutput(_T(", ed. "));
939 TexOutput(bib
->editor
);
944 TexOutput(bib
->publisher
);
948 if (bib
->publisher
) TexOutput(_T(", "));
949 else TexOutput(_T(" "));
950 TexOutput(bib
->address
);
952 if (bib
->publisher
|| bib
->address
)
958 OnMacro(ltBF
, 1, true);
959 OnArgument(ltBF
, 1, true);
960 TexOutput(bib
->volume
);
961 OnArgument(ltBF
, 1, false);
962 OnMacro(ltBF
, 1, false);
969 TexOutput(bib
->number
);
974 TexOutput(_T(" Number "));
975 TexOutput(bib
->number
);
981 TexOutput(_T(" Chap. "));
982 TexOutput(bib
->chapter
);
986 if (bib
->chapter
) TexOutput(_T(", pages "));
987 else TexOutput(_T(" Pages "));
988 TexOutput(bib
->pages
);
992 OnArgument(ltNUMBEREDBIBITEM
, 2, false);
993 OnMacro(ltNUMBEREDBIBITEM
, 2, false);
999 ForceTopicName(_T("bibliography"));
1000 FakeCurrentSection(ReferencesNameString
);
1001 ForceTopicName(NULL
);
1003 OnMacro(ltPAR
, 0, true);
1004 OnMacro(ltPAR
, 0, false);
1006 if ((convertMode
== TEX_RTF
) && !winHelp
)
1008 OnMacro(ltPAR
, 0, true);
1009 OnMacro(ltPAR
, 0, false);
1012 wxStringListNode
*node
= CitationList
.GetFirst();
1015 wxChar
*citeKey
= (wxChar
*)node
->GetData();
1016 // wxNode *texNode = TexReferences.Find(citeKey);
1017 TexRef
*ref
= (TexRef
*)TexReferences
.Get(citeKey
);
1018 wxNode
*bibNode
= BibList
.Find(citeKey
);
1021 BibEntry
*entry
= (BibEntry
*)bibNode
->GetData();
1022 OutputBibItem(ref
, entry
);
1024 node
= node
->GetNext();
1028 static int citeCount
= 1;
1030 void ResolveBibReferences(void)
1032 if (CitationList
.GetCount() > 0)
1033 OnInform(_T("Resolving bibliographic references..."));
1037 wxStringListNode
*node
= CitationList
.GetFirst();
1041 wxChar
*citeKey
= (wxChar
*)node
->GetData();
1042 // wxNode *texNode = TexReferences.Find(citeKey);
1043 TexRef
*ref
= (TexRef
*)TexReferences
.Get(citeKey
);
1044 wxNode
*bibNode
= BibList
.Find(citeKey
);
1048 //BibEntry *entry = (BibEntry *)bibNode->GetData();
1049 if (ref
->sectionNumber
) delete[] ref
->sectionNumber
;
1050 wxSnprintf(buf
, sizeof(buf
), _T("[%d]"), citeCount
);
1051 ref
->sectionNumber
= copystring(buf
);
1056 wxSnprintf(buf
, sizeof(buf
), _T("Warning: bib ref %s not resolved."), citeKey
);
1059 node
= node
->GetNext();
1063 // Remember we need to resolve this citation
1064 void AddCitation(wxChar
*citeKey
)
1066 if (!CitationList
.Member(citeKey
))
1067 CitationList
.Add(citeKey
);
1069 if (!TexReferences
.Get(citeKey
))
1071 TexReferences
.Put(citeKey
, new TexRef(citeKey
, _T("??"), NULL
));
1075 TexRef
*FindReference(wxChar
*key
)
1077 return (TexRef
*)TexReferences
.Get(key
);
1081 * Custom macro stuff
1085 bool StringTobool(wxChar
*val
)
1087 if (wxStrncmp(val
, _T("yes"), 3) == 0 || wxStrncmp(val
, _T("YES"), 3) == 0 ||
1088 wxStrncmp(val
, _T("on"), 2) == 0 || wxStrncmp(val
, _T("ON"), 2) == 0 ||
1089 wxStrncmp(val
, _T("true"), 4) == 0 || wxStrncmp(val
, _T("true"), 4) == 0 ||
1090 wxStrncmp(val
, _T("ok"), 2) == 0 || wxStrncmp(val
, _T("OK"), 2) == 0 ||
1091 wxStrncmp(val
, _T("1"), 1) == 0)
1097 void RegisterIntSetting (const wxString
& s
, int *number
)
1107 // Define a variable value from the .ini file
1108 wxChar
*RegisterSetting(wxChar
*settingName
, wxChar
*settingValue
, bool interactive
)
1110 wxString
settingValueStr( settingValue
);
1112 static wxChar errorCode
[100];
1113 wxStrcpy(errorCode
, _T("OK"));
1114 if (StringMatch(settingName
, _T("chapterName"), false, true))
1116 delete[] ChapterNameString
;
1117 ChapterNameString
= copystring(settingValue
);
1119 else if (StringMatch(settingName
, _T("sectionName"), false, true))
1121 delete[] SectionNameString
;
1122 SectionNameString
= copystring(settingValue
);
1124 else if (StringMatch(settingName
, _T("subsectionName"), false, true))
1126 delete[] SubsectionNameString
;
1127 SubsectionNameString
= copystring(settingValue
);
1129 else if (StringMatch(settingName
, _T("subsubsectionName"), false, true))
1131 delete[] SubsubsectionNameString
;
1132 SubsubsectionNameString
= copystring(settingValue
);
1134 else if (StringMatch(settingName
, _T("indexName"), false, true))
1136 delete[] IndexNameString
;
1137 IndexNameString
= copystring(settingValue
);
1139 else if (StringMatch(settingName
, _T("contentsName"), false, true))
1141 delete[] ContentsNameString
;
1142 ContentsNameString
= copystring(settingValue
);
1144 else if (StringMatch(settingName
, _T("glossaryName"), false, true))
1146 delete[] GlossaryNameString
;
1147 GlossaryNameString
= copystring(settingValue
);
1149 else if (StringMatch(settingName
, _T("referencesName"), false, true))
1151 delete[] ReferencesNameString
;
1152 ReferencesNameString
= copystring(settingValue
);
1154 else if (StringMatch(settingName
, _T("tablesName"), false, true))
1156 delete[] TablesNameString
;
1157 TablesNameString
= copystring(settingValue
);
1159 else if (StringMatch(settingName
, _T("figuresName"), false, true))
1161 delete[] FiguresNameString
;
1162 FiguresNameString
= copystring(settingValue
);
1164 else if (StringMatch(settingName
, _T("tableName"), false, true))
1166 delete[] TableNameString
;
1167 TableNameString
= copystring(settingValue
);
1169 else if (StringMatch(settingName
, _T("figureName"), false, true))
1171 delete[] FigureNameString
;
1172 FigureNameString
= copystring(settingValue
);
1174 else if (StringMatch(settingName
, _T("abstractName"), false, true))
1176 delete[] AbstractNameString
;
1177 AbstractNameString
= copystring(settingValue
);
1179 else if (StringMatch(settingName
, _T("chapterFontSize"), false, true))
1180 RegisterIntSetting(settingValueStr
, &chapterFont
);
1181 else if (StringMatch(settingName
, _T("sectionFontSize"), false, true))
1182 RegisterIntSetting(settingValueStr
, §ionFont
);
1183 else if (StringMatch(settingName
, _T("subsectionFontSize"), false, true))
1184 RegisterIntSetting(settingValueStr
, &subsectionFont
);
1185 else if (StringMatch(settingName
, _T("titleFontSize"), false, true))
1186 RegisterIntSetting(settingValueStr
, &titleFont
);
1187 else if (StringMatch(settingName
, _T("authorFontSize"), false, true))
1188 RegisterIntSetting(settingValueStr
, &authorFont
);
1189 else if (StringMatch(settingName
, _T("ignoreInput"), false, true))
1190 IgnorableInputFiles
.Add(wxFileNameFromPath(settingValue
));
1191 else if (StringMatch(settingName
, _T("mirrorMargins"), false, true))
1192 mirrorMargins
= StringTobool(settingValue
);
1193 else if (StringMatch(settingName
, _T("runTwice"), false, true))
1194 runTwice
= StringTobool(settingValue
);
1195 else if (StringMatch(settingName
, _T("isInteractive"), false, true))
1196 isInteractive
= StringTobool(settingValue
);
1197 else if (StringMatch(settingName
, _T("headerRule"), false, true))
1198 headerRule
= StringTobool(settingValue
);
1199 else if (StringMatch(settingName
, _T("footerRule"), false, true))
1200 footerRule
= StringTobool(settingValue
);
1201 else if (StringMatch(settingName
, _T("combineSubSections"), false, true))
1202 combineSubSections
= StringTobool(settingValue
);
1203 else if (StringMatch(settingName
, _T("listLabelIndent"), false, true))
1204 RegisterIntSetting(settingValueStr
, &labelIndentTab
);
1205 else if (StringMatch(settingName
, _T("listItemIndent"), false, true))
1206 RegisterIntSetting(settingValueStr
, &itemIndentTab
);
1207 else if (StringMatch(settingName
, _T("useUpButton"), false, true))
1208 useUpButton
= StringTobool(settingValue
);
1209 else if (StringMatch(settingName
, _T("useHeadingStyles"), false, true))
1210 useHeadingStyles
= StringTobool(settingValue
);
1211 else if (StringMatch(settingName
, _T("useWord"), false, true))
1212 useWord
= StringTobool(settingValue
);
1213 else if (StringMatch(settingName
, _T("contentsDepth"), false, true))
1214 RegisterIntSetting(settingValueStr
, &contentsDepth
);
1215 else if (StringMatch(settingName
, _T("generateHPJ"), false, true))
1216 generateHPJ
= StringTobool(settingValue
);
1217 else if (StringMatch(settingName
, _T("truncateFilenames"), false, true))
1218 truncateFilenames
= StringTobool(settingValue
);
1219 else if (StringMatch(settingName
, _T("winHelpVersion"), false, true))
1220 RegisterIntSetting(settingValueStr
, &winHelpVersion
);
1221 else if (StringMatch(settingName
, _T("winHelpContents"), false, true))
1222 winHelpContents
= StringTobool(settingValue
);
1223 else if (StringMatch(settingName
, _T("htmlIndex"), false, true))
1224 htmlIndex
= StringTobool(settingValue
);
1225 else if (StringMatch(settingName
, _T("htmlWorkshopFiles"), false, true))
1226 htmlWorkshopFiles
= StringTobool(settingValue
);
1227 else if (StringMatch(settingName
, _T("htmlFrameContents"), false, true))
1228 htmlFrameContents
= StringTobool(settingValue
);
1229 else if (StringMatch(settingName
, _T("htmlStylesheet"), false, true))
1232 delete[] htmlStylesheet
;
1233 htmlStylesheet
= copystring(settingValue
);
1235 else if (StringMatch(settingName
, _T("upperCaseNames"), false, true))
1236 upperCaseNames
= StringTobool(settingValue
);
1237 else if (StringMatch(settingName
, _T("ignoreBadRefs"), false, true))
1238 ignoreBadRefs
= StringTobool(settingValue
);
1239 else if (StringMatch(settingName
, _T("htmlFaceName"), false, true))
1241 delete[] htmlFaceName
;
1242 htmlFaceName
= copystring(settingValue
);
1244 else if (StringMatch(settingName
, _T("winHelpTitle"), false, true))
1247 delete[] winHelpTitle
;
1248 winHelpTitle
= copystring(settingValue
);
1250 else if (StringMatch(settingName
, _T("indexSubsections"), false, true))
1251 indexSubsections
= StringTobool(settingValue
);
1252 else if (StringMatch(settingName
, _T("compatibility"), false, true))
1253 compatibilityMode
= StringTobool(settingValue
);
1254 else if (StringMatch(settingName
, _T("defaultColumnWidth"), false, true))
1256 RegisterIntSetting(settingValueStr
, &defaultTableColumnWidth
);
1257 defaultTableColumnWidth
= 20*defaultTableColumnWidth
;
1259 else if (StringMatch(settingName
, _T("bitmapMethod"), false, true))
1261 if ((wxStrcmp(settingValue
, _T("includepicture")) != 0) && (wxStrcmp(settingValue
, _T("hex")) != 0) &&
1262 (wxStrcmp(settingValue
, _T("import")) != 0))
1265 OnError(_T("Unknown bitmapMethod"));
1266 wxStrcpy(errorCode
, _T("Unknown bitmapMethod"));
1270 delete[] bitmapMethod
;
1271 bitmapMethod
= copystring(settingValue
);
1274 else if (StringMatch(settingName
, _T("htmlBrowseButtons"), false, true))
1276 if (wxStrcmp(settingValue
, _T("none")) == 0)
1277 htmlBrowseButtons
= HTML_BUTTONS_NONE
;
1278 else if (wxStrcmp(settingValue
, _T("bitmap")) == 0)
1279 htmlBrowseButtons
= HTML_BUTTONS_BITMAP
;
1280 else if (wxStrcmp(settingValue
, _T("text")) == 0)
1281 htmlBrowseButtons
= HTML_BUTTONS_TEXT
;
1285 OnInform(_T("Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text."));
1286 wxStrcpy(errorCode
, _T("Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text."));
1289 else if (StringMatch(settingName
, _T("backgroundImage"), false, true))
1291 backgroundImageString
= copystring(settingValue
);
1293 else if (StringMatch(settingName
, _T("backgroundColour"), false, true))
1295 delete[] backgroundColourString
;
1296 backgroundColourString
= copystring(settingValue
);
1298 else if (StringMatch(settingName
, _T("textColour"), false, true))
1300 textColourString
= copystring(settingValue
);
1302 else if (StringMatch(settingName
, _T("linkColour"), false, true))
1304 linkColourString
= copystring(settingValue
);
1306 else if (StringMatch(settingName
, _T("followedLinkColour"), false, true))
1308 followedLinkColourString
= copystring(settingValue
);
1310 else if (StringMatch(settingName
, _T("conversionMode"), false, true))
1312 if (StringMatch(settingValue
, _T("RTF"), false, true))
1314 winHelp
= false; convertMode
= TEX_RTF
;
1316 else if (StringMatch(settingValue
, _T("WinHelp"), false, true))
1318 winHelp
= true; convertMode
= TEX_RTF
;
1320 else if (StringMatch(settingValue
, _T("XLP"), false, true) ||
1321 StringMatch(settingValue
, _T("wxHelp"), false, true))
1323 convertMode
= TEX_XLP
;
1325 else if (StringMatch(settingValue
, _T("HTML"), false, true))
1327 convertMode
= TEX_HTML
;
1332 OnInform(_T("Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML."));
1333 wxStrcpy(errorCode
, _T("Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML."));
1336 else if (StringMatch(settingName
, _T("documentFontSize"), false, true))
1339 RegisterIntSetting(settingValueStr
, &n
);
1340 if (n
== 10 || n
== 11 || n
== 12)
1345 wxSnprintf(buf
, sizeof(buf
), _T("Initialisation file error: nonstandard document font size %d."), n
);
1348 wxStrcpy(errorCode
, buf
);
1354 wxSnprintf(buf
, sizeof(buf
), _T("Initialisation file error: unrecognised setting %s."), settingName
);
1357 wxStrcpy(errorCode
, buf
);
1362 bool ReadCustomMacros(wxChar
*filename
)
1364 if (!wxFileExists(filename
))
1367 wxString name
= filename
;
1368 wxSTD ifstream
istr((char const *)name
.fn_str(), wxSTD
ios::in
);
1370 if (istr
.bad()) return false;
1372 CustomMacroList
.Clear();
1374 wxChar macroName
[100];
1375 wxChar macroBody
[1000];
1380 BibEatWhiteSpace(istr
);
1385 if (ch
!= '\\') // Not a macro definition, so must be NAME=VALUE
1387 wxChar settingName
[100];
1388 settingName
[0] = ch
;
1389 BibReadWord(istr
, (settingName
+1));
1390 BibEatWhiteSpace(istr
);
1394 OnError(_T("Expected = following name: malformed tex2rtf.ini file."));
1399 wxChar settingValue
[200];
1400 BibEatWhiteSpace(istr
);
1401 BibReadToEOL(istr
, settingValue
);
1402 RegisterSetting(settingName
, settingValue
);
1407 BibReadWord(istr
, macroName
);
1408 BibEatWhiteSpace(istr
);
1412 OnError(_T("Expected [ followed by number of arguments: malformed tex2rtf.ini file."));
1419 OnError(_T("Expected ] following number of arguments: malformed tex2rtf.ini file."));
1422 BibEatWhiteSpace(istr
);
1426 OnError(_T("Expected { followed by macro body: malformed tex2rtf.ini file."));
1429 CustomMacro
*macro
= new CustomMacro(macroName
, noArgs
, NULL
);
1430 BibReadValue(istr
, macroBody
, false, false); // Don't ignore extra braces
1431 if (wxStrlen(macroBody
) > 0)
1432 macro
->macroBody
= copystring(macroBody
);
1434 BibEatWhiteSpace(istr
);
1435 CustomMacroList
.Append(macroName
, macro
);
1436 AddMacroDef(ltCUSTOM_MACRO
, macroName
, noArgs
);
1440 wxSnprintf(mbuf
, sizeof(mbuf
), _T("Read initialization file %s."), filename
);
1445 CustomMacro
*FindCustomMacro(wxChar
*name
)
1447 wxNode
*node
= CustomMacroList
.Find(name
);
1450 CustomMacro
*macro
= (CustomMacro
*)node
->GetData();
1456 // Display custom macros
1457 void ShowCustomMacros(void)
1459 wxNode
*node
= CustomMacroList
.GetFirst();
1462 OnInform(_T("No custom macros loaded.\n"));
1469 CustomMacro
*macro
= (CustomMacro
*)node
->GetData();
1470 wxSnprintf(buf
, sizeof(buf
), _T("\\%s[%d]\n {%s}"), macro
->macroName
, macro
->noArgs
,
1471 macro
->macroBody
? macro
->macroBody
: _T(""));
1473 node
= node
->GetNext();
1477 // Parse a string into several comma-separated fields
1478 wxChar
*ParseMultifieldString(wxChar
*allFields
, int *pos
)
1480 static wxChar buffer
[300];
1482 int fieldIndex
= *pos
;
1483 int len
= wxStrlen(allFields
);
1485 bool keepGoing
= true;
1486 while ((fieldIndex
<= len
) && keepGoing
)
1488 if (allFields
[fieldIndex
] == _T(' '))
1493 else if (allFields
[fieldIndex
] == _T(','))
1495 *pos
= fieldIndex
+ 1;
1498 else if (allFields
[fieldIndex
] == 0)
1500 *pos
= fieldIndex
+ 1;
1505 buffer
[i
] = allFields
[fieldIndex
];
1511 if (oldPos
== (*pos
))
1525 ColourTableEntry::ColourTableEntry(const wxChar
*theName
, unsigned int r
, unsigned int g
, unsigned int b
)
1527 name
= copystring(theName
);
1533 ColourTableEntry::~ColourTableEntry(void)
1538 void AddColour(const wxChar
*theName
, unsigned int r
, unsigned int g
, unsigned int b
)
1540 wxNode
*node
= ColourTable
.Find(theName
);
1543 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->GetData();
1544 if (entry
->red
== r
|| entry
->green
== g
|| entry
->blue
== b
)
1552 ColourTableEntry
*entry
= new ColourTableEntry(theName
, r
, g
, b
);
1553 ColourTable
.Append(theName
, entry
);
1556 int FindColourPosition(wxChar
*theName
)
1559 wxNode
*node
= ColourTable
.GetFirst();
1562 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->GetData();
1563 if (wxStrcmp(theName
, entry
->name
) == 0)
1566 node
= node
->GetNext();
1571 // Converts e.g. "red" -> "#FF0000"
1572 extern void DecToHex(int, wxChar
*);
1573 bool FindColourHTMLString(wxChar
*theName
, wxChar
*buf
)
1575 wxNode
*node
= ColourTable
.GetFirst();
1578 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->GetData();
1579 if (wxStrcmp(theName
, entry
->name
) == 0)
1581 wxStrcpy(buf
, _T("#"));
1584 DecToHex(entry
->red
, buf2
);
1585 wxStrcat(buf
, buf2
);
1586 DecToHex(entry
->green
, buf2
);
1587 wxStrcat(buf
, buf2
);
1588 DecToHex(entry
->blue
, buf2
);
1589 wxStrcat(buf
, buf2
);
1593 node
= node
->GetNext();
1599 void InitialiseColourTable(void)
1601 // \\red0\\green0\\blue0;
1602 AddColour(_T("black"), 0,0,0);
1604 // \\red0\\green0\\blue255;\\red0\\green255\\blue255;\n");
1605 AddColour(_T("cyan"), 0,255,255);
1607 // \\red0\\green255\\blue0;
1608 AddColour(_T("green"), 0,255,0);
1610 // \\red255\\green0\\blue255;
1611 AddColour(_T("magenta"), 255,0,255);
1613 // \\red255\\green0\\blue0;
1614 AddColour(_T("red"), 255,0,0);
1616 // \\red255\\green255\\blue0;
1617 AddColour(_T("yellow"), 255,255,0);
1619 // \\red255\\green255\\blue255;}");
1620 AddColour(_T("white"), 255,255,255);
1624 * The purpose of this is to reduce the number of times wxYield is
1625 * called, since under Windows this can slow things down.
1628 void Tex2RTFYield(bool force
)
1631 static int yieldCount
= 0;
1638 if (yieldCount
== 0)
1650 // In both RTF generation and HTML generation for wxHelp version 2,
1651 // we need to associate \indexed keywords with the current filename/topics.
1653 // Hash table for lists of keywords for topics (WinHelp).
1654 wxHashTable
TopicTable(wxKEY_STRING
);
1655 void AddKeyWordForTopic(wxChar
*topic
, wxChar
*entry
, wxChar
*filename
)
1657 TexTopic
*texTopic
= (TexTopic
*)TopicTable
.Get(topic
);
1660 texTopic
= new TexTopic(filename
);
1661 texTopic
->keywords
= new wxStringList
;
1662 TopicTable
.Put(topic
, texTopic
);
1665 if (!texTopic
->keywords
->Member(entry
))
1666 texTopic
->keywords
->Add(entry
);
1669 void ClearKeyWordTable(void)
1671 TopicTable
.BeginFind();
1672 wxHashTable::Node
*node
= TopicTable
.Next();
1675 TexTopic
*texTopic
= (TexTopic
*)node
->GetData();
1677 node
= TopicTable
.Next();
1684 * TexTopic structure
1687 TexTopic::TexTopic(wxChar
*f
)
1690 filename
= copystring(f
);
1693 hasChildren
= false;
1697 TexTopic::~TexTopic(void)
1705 // Convert case, according to upperCaseNames setting.
1706 wxChar
*ConvertCase(wxChar
*s
)
1708 static wxChar buf
[256];
1709 int len
= wxStrlen(s
);
1712 for (i
= 0; i
< len
; i
++)
1713 buf
[i
] = (wxChar
)wxToupper(s
[i
]);
1715 for (i
= 0; i
< len
; i
++)
1716 buf
[i
] = (wxChar
)wxTolower(s
[i
]);
1721 // if substring is true, search for str1 in str2
1722 bool StringMatch(const wxChar
*str1
, const wxChar
*str2
, bool subString
,
1727 wxString
Sstr1(str1
);
1728 wxString
Sstr2(str2
);
1734 return Sstr2
.Index(Sstr1
) != (size_t)wxNOT_FOUND
;
1737 return exact
? wxString(str2
).Cmp(str1
) == 0 :
1738 wxString(str2
).CmpNoCase(str1
) == 0;