1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Miscellaneous utilities
4 // Author: Julian Smart
5 // Modified by: Wlodzimiez ABX Skiba 2003/2004 Unicode support
9 // Copyright: (c) Julian Smart
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
14 #pragma implementation
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
47 #if !WXWIN_COMPATIBILITY_2_4
48 static inline wxChar
* copystring(const wxChar
* s
)
49 { return wxStrcpy(new wxChar
[wxStrlen(s
) + 1], s
); }
50 static inline void StringToInt (const wxChar
*s
, int *number
)
52 if (s
&& *s
&& number
)
53 *number
= (int) wxStrtol (s
, (wxChar
**) NULL
, 10);
57 wxHashTable
TexReferences(wxKEY_STRING
);
58 wxList
BibList(wxKEY_STRING
);
59 wxStringList CitationList
;
60 wxList
ColourTable(wxKEY_STRING
);
61 wxHashTable
BibStringTable(wxKEY_STRING
);
62 wxList
CustomMacroList(wxKEY_STRING
);
63 TexChunk
*currentSection
= NULL
;
64 wxChar
*fakeCurrentSection
= NULL
;
66 static long BibLine
= 1;
68 void OutputCurrentSection(void)
70 if (fakeCurrentSection
)
71 TexOutput(fakeCurrentSection
);
72 else if (currentSection
)
73 TraverseChildrenFromChunk(currentSection
);
76 // Nasty but the way things are done now, necessary,
77 // in order to output a chunk properly to a string (macros and all).
78 void OutputCurrentSectionToString(wxChar
*buf
)
80 if (fakeCurrentSection
)
81 wxStrcpy(buf
, fakeCurrentSection
);
83 OutputChunkToString(currentSection
, buf
);
86 void OutputChunkToString(TexChunk
*chunk
, wxChar
*buf
)
88 FILE *tempfd
= wxFopen(_T("tmp.tmp"), _T("w"));
92 FILE *old1
= CurrentOutput1
;
93 FILE *old2
= CurrentOutput2
;
95 CurrentOutput1
= tempfd
;
96 CurrentOutput2
= NULL
;
98 TraverseChildrenFromChunk(chunk
);
100 CurrentOutput1
= old1
;
101 CurrentOutput2
= old2
;
105 // Read from file into string
106 tempfd
= wxFopen(_T("tmp.tmp"), _T("r"));
125 wxRemoveFile(_T("tmp.tmp"));
128 // Called by Tex2Any to simulate a section
129 void FakeCurrentSection(wxChar
*fakeSection
, bool addToContents
)
131 currentSection
= NULL
;
132 if (fakeCurrentSection
) delete[] fakeCurrentSection
;
133 fakeCurrentSection
= copystring(fakeSection
);
135 if (DocumentStyle
== LATEX_ARTICLE
)
137 int mac
= ltSECTIONHEADING
;
139 mac
= ltSECTIONHEADINGSTAR
;
140 OnMacro(mac
, 0, true);
141 OnMacro(mac
, 0, false);
145 int mac
= ltCHAPTERHEADING
;
147 mac
= ltCHAPTERHEADINGSTAR
;
148 OnMacro(mac
, 0, true);
149 OnMacro(mac
, 0, false);
151 if (fakeCurrentSection
) delete[] fakeCurrentSection
;
152 fakeCurrentSection
= NULL
;
155 // Look for \label macro, use this ref name if found or
156 // make up a topic name otherwise.
157 static long topicCounter
= 0;
159 void ResetTopicCounter(void)
164 static wxChar
*forceTopicName
= NULL
;
166 void ForceTopicName(const wxChar
*name
)
169 delete[] forceTopicName
;
171 forceTopicName
= copystring(name
);
173 forceTopicName
= NULL
;
176 wxChar
*FindTopicName(TexChunk
*chunk
)
179 return forceTopicName
;
181 wxChar
*topicName
= NULL
;
182 static wxChar topicBuf
[100];
184 if (chunk
&& (chunk
->type
== CHUNK_TYPE_MACRO
) &&
185 (chunk
->macroId
== ltLABEL
))
187 wxNode
*node
= chunk
->children
.GetFirst();
190 TexChunk
*child
= (TexChunk
*)node
->GetData();
191 if (child
->type
== CHUNK_TYPE_ARG
)
193 wxNode
*snode
= child
->children
.GetFirst();
196 TexChunk
*schunk
= (TexChunk
*)snode
->GetData();
197 if (schunk
->type
== CHUNK_TYPE_STRING
)
198 topicName
= schunk
->value
;
207 wxSnprintf(topicBuf
, sizeof(topicBuf
), _T("topic%ld"), topicCounter
);
214 * Simulate argument data, so we can 'drive' clients which implement
215 * certain basic formatting behaviour.
216 * Snag is that some save a TexChunk, so don't use yet...
220 void StartSimulateArgument(wxChar
*data
)
222 wxStrcpy(currentArgData
, data
);
226 void EndSimulateArgument(void)
232 * Parse and convert unit arguments to points
236 int ParseUnitArgument(wxChar
*unitArg
)
238 float conversionFactor
= 1.0;
239 float unitValue
= 0.0;
240 int len
= wxStrlen(unitArg
);
241 // Get rid of any accidentally embedded commands
242 for (int i
= 0; i
< len
; i
++)
243 if (unitArg
[i
] == '\\')
245 len
= wxStrlen(unitArg
);
247 if (unitArg
&& (len
> 0) && (isdigit(unitArg
[0]) || unitArg
[0] == '-'))
249 wxSscanf(unitArg
, _T("%f"), &unitValue
);
253 units
[0] = unitArg
[len
-2];
254 units
[1] = unitArg
[len
-1];
256 if (wxStrcmp(units
, _T("in")) == 0)
257 conversionFactor
= 72.0;
258 else if (wxStrcmp(units
, _T("cm")) == 0)
259 conversionFactor
= (float)72.0/(float)2.51;
260 else if (wxStrcmp(units
, _T("mm")) == 0)
261 conversionFactor
= (float)72.0/(float)25.1;
262 else if (wxStrcmp(units
, _T("pt")) == 0)
263 conversionFactor
= 1;
265 return (int)(unitValue
*conversionFactor
);
271 * Strip off any extension (dot something) from end of file,
272 * IF one exists. Inserts zero into buffer.
276 void StripExtension(wxChar
*buffer
)
278 int len
= wxStrlen(buffer
);
282 if (buffer
[i
] == '.')
296 void SetFontSizes(int pointSize
)
348 void AddTexRef(wxChar
*name
, wxChar
*file
, wxChar
*sectionName
,
349 int chapter
, int section
, int subsection
, int subsubsection
)
351 TexRef
*texRef
= (TexRef
*)TexReferences
.Get(name
);
352 if (texRef
) TexReferences
.Delete(name
);
359 wxStrcat(buf, sectionName);
366 wxSnprintf(buf2
, sizeof(buf2
), _T("%d"), chapter
);
373 wxStrcat(buf
, _T("."));
375 wxSnprintf(buf2
, sizeof(buf2
), _T("%d"), section
);
381 wxStrcat(buf
, _T("."));
382 wxSnprintf(buf2
, sizeof(buf2
), _T("%d"), subsection
);
388 wxStrcat(buf
, _T("."));
389 wxSnprintf(buf2
, sizeof(buf2
), _T("%d"), subsubsection
);
392 wxChar
*tmp
= ((wxStrlen(buf
) > 0) ? buf
: (wxChar
*)NULL
);
393 TexReferences
.Put(name
, new TexRef(name
, file
, tmp
, sectionName
));
396 void WriteTexReferences(wxChar
*filename
)
399 wxString name
= filename
;
400 wxSTD ofstream
ostr((char const *)name
.fn_str());
401 if (ostr
.bad()) return;
403 TexReferences
.BeginFind();
404 wxHashTable::Node
*node
= TexReferences
.Next();
408 TexRef
*ref
= (TexRef
*)node
->GetData();
409 converter
= ref
->refLabel
;
410 ostr
<< converter
.mb_str();
412 converter
= (ref
->refFile
? ref
->refFile
: _T("??"));
413 ostr
<< converter
.mb_str();
415 converter
= (ref
->sectionName
? ref
->sectionName
: _T("??")) ;
416 ostr
<< converter
.mb_str();
418 converter
= (ref
->sectionNumber
? ref
->sectionNumber
: _T("??")) ;
419 ostr
<< converter
.mb_str();
421 if (!ref
->sectionNumber
|| (wxStrcmp(ref
->sectionNumber
, _T("??")) == 0 && wxStrcmp(ref
->sectionName
, _T("??")) == 0))
424 wxSnprintf(buf
, sizeof(buf
), _T("Warning: reference %s not resolved."), ref
->refLabel
);
427 node
= TexReferences
.Next();
431 void ReadTexReferences(wxChar
*filename
)
433 if (!wxFileExists(filename
))
436 wxString name
= filename
;
437 wxSTD ifstream
istr((char const *)name
.fn_str(), wxSTD
ios::in
);
439 if (istr
.bad()) return;
444 char sectionName
[100];
454 istr
.get(ch
); // Read past space
457 while (ch
!= '\n' && !istr
.eof())
465 wxString label_string
= wxString::FromAscii(label
);
466 wxString file_string
= wxString::FromAscii(file
);
467 wxString sectionName_string
= wxString::FromAscii(sectionName
);
468 wxString section_string
= wxString::FromAscii(section
);
470 // gt - needed to trick the hash table "TexReferences" into deleting the key
471 // strings it creates in the Put() function, but not the item that is
472 // created here, as that is destroyed elsewhere. Without doing this, there
473 // were massive memory leaks
474 TexReferences
.DeleteContents(true);
476 label_string
.c_str(),
478 label_string
.c_str(),
480 section_string
.c_str(),
481 sectionName_string
.c_str()
484 TexReferences
.DeleteContents(false);
491 * Bibliography-handling code
495 void BibEatWhiteSpace(wxSTD istream
& str
)
497 char ch
= (char)str
.peek();
499 while (!str
.eof() && (ch
== ' ' || ch
== '\t' || ch
== 13 || ch
== 10 || ch
== (char)EOF
))
504 if ((ch
== (char)EOF
) || str
.eof()) return;
505 ch
= (char)str
.peek();
508 // Ignore end-of-line comments
509 if (ch
== '%' || ch
== ';' || ch
== '#')
512 ch
= (char)str
.peek();
513 while (ch
!= 10 && ch
!= 13 && !str
.eof())
516 ch
= (char)str
.peek();
518 BibEatWhiteSpace(str
);
522 // Read word up to { or , or space
523 void BibReadWord(wxSTD istream
& istr
, wxChar
*buffer
)
527 char ch
= (char)istr
.peek();
528 while (!istr
.eof() && ch
!= ' ' && ch
!= '{' && ch
!= '(' && ch
!= 13 && ch
!= 10 && ch
!= '\t' &&
529 ch
!= ',' && ch
!= '=')
534 ch
= (char)istr
.peek();
539 // Read string (double-quoted or not) to end quote or EOL
540 void BibReadToEOL(wxSTD istream
& istr
, wxChar
*buffer
)
544 char ch
= (char)istr
.peek();
545 bool inQuotes
= false;
549 ch
= (char)istr
.peek();
552 // If in quotes, read white space too. If not,
553 // stop at white space or comment.
554 while (!istr
.eof() && ch
!= 13 && ch
!= 10 && ch
!= _T('"') &&
555 (inQuotes
|| ((ch
!= _T(' ')) && (ch
!= 9) &&
556 (ch
!= _T(';')) && (ch
!= _T('%')) && (ch
!= _T('#')))))
561 ch
= (char)istr
.peek();
568 // Read }-terminated value, taking nested braces into account.
569 void BibReadValue(wxSTD istream
& istr
, wxChar
*buffer
, bool ignoreBraces
= true,
570 bool quotesMayTerminate
= true)
575 char ch
= (char)istr
.peek();
576 bool stopping
= false;
577 while (!istr
.eof() && !stopping
)
583 wxSnprintf(buf
, sizeof(buf
), _T("Sorry, value > 4000 chars in bib file at line %ld."), BibLine
);
584 wxLogError(buf
, "Tex2RTF Fatal Error");
601 else if (quotesMayTerminate
&& ch
== '"')
608 if (!ignoreBraces
|| (ch
!= '{' && ch
!= '}'))
618 wxUnusedVar(stopping
);
621 bool ReadBib(wxChar
*filename
)
623 if (!wxFileExists(filename
))
626 wxString name
= filename
;
628 wxSTD ifstream
istr((char const *)name
.fn_str(), wxSTD
ios::in
);
629 if (istr
.bad()) return false;
633 OnInform(_T("Reading .bib file..."));
636 wxChar fieldValue
[4000];
637 wxChar recordType
[100];
638 wxChar recordKey
[100];
639 wxChar recordField
[100];
644 BibEatWhiteSpace(istr
);
648 wxSnprintf(buf
, sizeof(buf
), _T("Expected @: malformed bib file at line %ld (%s)"), BibLine
, filename
);
652 BibReadWord(istr
, recordType
);
653 BibEatWhiteSpace(istr
);
655 if (ch
!= '{' && ch
!= '(')
657 wxSnprintf(buf
, sizeof(buf
), _T("Expected { or ( after record type: malformed .bib file at line %ld (%s)"), BibLine
, filename
);
661 BibEatWhiteSpace(istr
);
662 if (StringMatch(recordType
, _T("string"), false, true))
664 BibReadWord(istr
, recordType
);
665 BibEatWhiteSpace(istr
);
669 wxSnprintf(buf
, sizeof(buf
), _T("Expected = after string key: malformed .bib file at line %ld (%s)"), BibLine
, filename
);
673 BibEatWhiteSpace(istr
);
675 if (ch
!= '"' && ch
!= '{')
677 wxSnprintf(buf
, sizeof(buf
), _T("Expected = after string key: malformed .bib file at line %ld (%s)"), BibLine
, filename
);
681 BibReadValue(istr
, fieldValue
);
683 // Now put in hash table if necesary
684 if (!BibStringTable
.Get(recordType
))
685 BibStringTable
.Put(recordType
, (wxObject
*)copystring(fieldValue
));
687 // Read closing ) or }
688 BibEatWhiteSpace(istr
);
690 BibEatWhiteSpace(istr
);
694 BibReadWord(istr
, recordKey
);
696 BibEntry
*bibEntry
= new BibEntry
;
697 bibEntry
->key
= copystring(recordKey
);
698 bibEntry
->type
= copystring(recordType
);
700 bool moreRecords
= true;
701 while (moreRecords
&& !istr
.eof())
703 BibEatWhiteSpace(istr
);
705 if (ch
== '}' || ch
== ')')
711 BibEatWhiteSpace(istr
);
712 BibReadWord(istr
, recordField
);
713 BibEatWhiteSpace(istr
);
717 wxSnprintf(buf
, sizeof(buf
), _T("Expected = after field type: malformed .bib file at line %ld (%s)"), BibLine
, filename
);
721 BibEatWhiteSpace(istr
);
723 if (ch
!= '{' && ch
!= '"')
726 BibReadWord(istr
, fieldValue
+1);
728 // If in the table of strings, replace with string from table.
729 wxChar
*s
= (wxChar
*)BibStringTable
.Get(fieldValue
);
732 wxStrcpy(fieldValue
, s
);
736 BibReadValue(istr
, fieldValue
, true, (ch
== _T('"') ? true : false));
738 // Now we can add a field
739 if (StringMatch(recordField
, _T("author"), false, true))
740 bibEntry
->author
= copystring(fieldValue
);
741 else if (StringMatch(recordField
, _T("key"), false, true))
743 else if (StringMatch(recordField
, _T("annotate"), false, true))
745 else if (StringMatch(recordField
, _T("abstract"), false, true))
747 else if (StringMatch(recordField
, _T("edition"), false, true))
749 else if (StringMatch(recordField
, _T("howpublished"), false, true))
751 else if (StringMatch(recordField
, _T("note"), false, true) || StringMatch(recordField
, _T("notes"), false, true))
753 else if (StringMatch(recordField
, _T("series"), false, true))
755 else if (StringMatch(recordField
, _T("type"), false, true))
757 else if (StringMatch(recordField
, _T("keywords"), false, true))
759 else if (StringMatch(recordField
, _T("editor"), false, true) || StringMatch(recordField
, _T("editors"), false, true))
760 bibEntry
->editor
= copystring(fieldValue
);
761 else if (StringMatch(recordField
, _T("title"), false, true))
762 bibEntry
->title
= copystring(fieldValue
);
763 else if (StringMatch(recordField
, _T("booktitle"), false, true))
764 bibEntry
->booktitle
= copystring(fieldValue
);
765 else if (StringMatch(recordField
, _T("journal"), false, true))
766 bibEntry
->journal
= copystring(fieldValue
);
767 else if (StringMatch(recordField
, _T("volume"), false, true))
768 bibEntry
->volume
= copystring(fieldValue
);
769 else if (StringMatch(recordField
, _T("number"), false, true))
770 bibEntry
->number
= copystring(fieldValue
);
771 else if (StringMatch(recordField
, _T("year"), false, true))
772 bibEntry
->year
= copystring(fieldValue
);
773 else if (StringMatch(recordField
, _T("month"), false, true))
774 bibEntry
->month
= copystring(fieldValue
);
775 else if (StringMatch(recordField
, _T("pages"), false, true))
776 bibEntry
->pages
= copystring(fieldValue
);
777 else if (StringMatch(recordField
, _T("publisher"), false, true))
778 bibEntry
->publisher
= copystring(fieldValue
);
779 else if (StringMatch(recordField
, _T("address"), false, true))
780 bibEntry
->address
= copystring(fieldValue
);
781 else if (StringMatch(recordField
, _T("institution"), false, true) || StringMatch(recordField
, _T("school"), false, true))
782 bibEntry
->institution
= copystring(fieldValue
);
783 else if (StringMatch(recordField
, _T("organization"), false, true) || StringMatch(recordField
, _T("organisation"), false, true))
784 bibEntry
->organization
= copystring(fieldValue
);
785 else if (StringMatch(recordField
, _T("comment"), false, true) || StringMatch(recordField
, _T("comments"), false, true))
786 bibEntry
->comment
= copystring(fieldValue
);
787 else if (StringMatch(recordField
, _T("annote"), false, true))
788 bibEntry
->comment
= copystring(fieldValue
);
789 else if (StringMatch(recordField
, _T("chapter"), false, true))
790 bibEntry
->chapter
= copystring(fieldValue
);
793 wxSnprintf(buf
, sizeof(buf
), _T("Unrecognised bib field type %s at line %ld (%s)"), recordField
, BibLine
, filename
);
798 BibList
.Append(recordKey
, bibEntry
);
799 BibEatWhiteSpace(istr
);
805 void OutputBibItem(TexRef
*ref
, BibEntry
*bib
)
809 OnMacro(ltNUMBEREDBIBITEM
, 2, true);
810 OnArgument(ltNUMBEREDBIBITEM
, 1, true);
811 TexOutput(ref
->sectionNumber
);
812 OnArgument(ltNUMBEREDBIBITEM
, 1, false);
813 OnArgument(ltNUMBEREDBIBITEM
, 2, true);
816 OnMacro(ltBF
, 1, true);
817 OnArgument(ltBF
, 1, true);
819 TexOutput(bib
->author
);
820 OnArgument(ltBF
, 1, false);
821 OnMacro(ltBF
, 1, false);
822 if (bib
->author
&& (wxStrlen(bib
->author
) > 0) && (bib
->author
[wxStrlen(bib
->author
) - 1] != '.'))
829 TexOutput(bib
->year
);
834 TexOutput(bib
->month
);
837 if (bib
->year
|| bib
->month
)
840 if (StringMatch(bib
->type
, _T("article"), false, true))
844 TexOutput(bib
->title
);
849 OnMacro(ltIT
, 1, true);
850 OnArgument(ltIT
, 1, true);
851 TexOutput(bib
->journal
);
852 OnArgument(ltIT
, 1, false);
853 OnMacro(ltIT
, 1, false);
858 OnMacro(ltBF
, 1, true);
859 OnArgument(ltBF
, 1, true);
860 TexOutput(bib
->volume
);
861 OnArgument(ltBF
, 1, false);
862 OnMacro(ltBF
, 1, false);
867 TexOutput(bib
->number
);
872 TexOutput(_T(", pages "));
873 TexOutput(bib
->pages
);
877 else if (StringMatch(bib
->type
, _T("book"), false, true) ||
878 StringMatch(bib
->type
, _T("unpublished"), false, true) ||
879 StringMatch(bib
->type
, _T("manual"), false, true) ||
880 StringMatch(bib
->type
, _T("phdthesis"), false, true) ||
881 StringMatch(bib
->type
, _T("mastersthesis"), false, true) ||
882 StringMatch(bib
->type
, _T("misc"), false, true) ||
883 StringMatch(bib
->type
, _T("techreport"), false, true) ||
884 StringMatch(bib
->type
, _T("booklet"), false, true))
886 if (bib
->title
|| bib
->booktitle
)
888 OnMacro(ltIT
, 1, true);
889 OnArgument(ltIT
, 1, true);
890 TexOutput(bib
->title
? bib
->title
: bib
->booktitle
);
892 OnArgument(ltIT
, 1, false);
893 OnMacro(ltIT
, 1, false);
895 if (StringMatch(bib
->type
, _T("phdthesis"), false, true))
896 TexOutput(_T("PhD thesis. "));
897 if (StringMatch(bib
->type
, _T("techreport"), false, true))
898 TexOutput(_T("Technical report. "));
901 TexOutput(_T("Ed. "));
902 TexOutput(bib
->editor
);
905 if (bib
->institution
)
907 TexOutput(bib
->institution
);
910 if (bib
->organization
)
912 TexOutput(bib
->organization
);
917 TexOutput(bib
->publisher
);
922 TexOutput(bib
->address
);
926 else if (StringMatch(bib
->type
, _T("inbook"), false, true) ||
927 StringMatch(bib
->type
, _T("inproceedings"), false, true) ||
928 StringMatch(bib
->type
, _T("incollection"), false, true) ||
929 StringMatch(bib
->type
, _T("conference"), false, true))
933 TexOutput(bib
->title
);
937 TexOutput(_T(", from "));
938 OnMacro(ltIT
, 1, true);
939 OnArgument(ltIT
, 1, true);
940 TexOutput(bib
->booktitle
);
942 OnArgument(ltIT
, 1, false);
943 OnMacro(ltIT
, 1, false);
947 TexOutput(_T(", ed. "));
948 TexOutput(bib
->editor
);
953 TexOutput(bib
->publisher
);
957 if (bib
->publisher
) TexOutput(_T(", "));
958 else TexOutput(_T(" "));
959 TexOutput(bib
->address
);
961 if (bib
->publisher
|| bib
->address
)
967 OnMacro(ltBF
, 1, true);
968 OnArgument(ltBF
, 1, true);
969 TexOutput(bib
->volume
);
970 OnArgument(ltBF
, 1, false);
971 OnMacro(ltBF
, 1, false);
978 TexOutput(bib
->number
);
983 TexOutput(_T(" Number "));
984 TexOutput(bib
->number
);
990 TexOutput(_T(" Chap. "));
991 TexOutput(bib
->chapter
);
995 if (bib
->chapter
) TexOutput(_T(", pages "));
996 else TexOutput(_T(" Pages "));
997 TexOutput(bib
->pages
);
1001 OnArgument(ltNUMBEREDBIBITEM
, 2, false);
1002 OnMacro(ltNUMBEREDBIBITEM
, 2, false);
1005 void OutputBib(void)
1007 // Write the heading
1008 ForceTopicName(_T("bibliography"));
1009 FakeCurrentSection(ReferencesNameString
);
1010 ForceTopicName(NULL
);
1012 OnMacro(ltPAR
, 0, true);
1013 OnMacro(ltPAR
, 0, false);
1015 if ((convertMode
== TEX_RTF
) && !winHelp
)
1017 OnMacro(ltPAR
, 0, true);
1018 OnMacro(ltPAR
, 0, false);
1021 wxStringListNode
*node
= CitationList
.GetFirst();
1024 wxChar
*citeKey
= (wxChar
*)node
->GetData();
1025 // wxNode *texNode = TexReferences.Find(citeKey);
1026 TexRef
*ref
= (TexRef
*)TexReferences
.Get(citeKey
);
1027 wxNode
*bibNode
= BibList
.Find(citeKey
);
1030 BibEntry
*entry
= (BibEntry
*)bibNode
->GetData();
1031 OutputBibItem(ref
, entry
);
1033 node
= node
->GetNext();
1037 static int citeCount
= 1;
1039 void ResolveBibReferences(void)
1041 if (CitationList
.GetCount() > 0)
1042 OnInform(_T("Resolving bibliographic references..."));
1046 wxStringListNode
*node
= CitationList
.GetFirst();
1050 wxChar
*citeKey
= (wxChar
*)node
->GetData();
1051 // wxNode *texNode = TexReferences.Find(citeKey);
1052 TexRef
*ref
= (TexRef
*)TexReferences
.Get(citeKey
);
1053 wxNode
*bibNode
= BibList
.Find(citeKey
);
1057 //BibEntry *entry = (BibEntry *)bibNode->GetData();
1058 if (ref
->sectionNumber
) delete[] ref
->sectionNumber
;
1059 wxSnprintf(buf
, sizeof(buf
), _T("[%d]"), citeCount
);
1060 ref
->sectionNumber
= copystring(buf
);
1065 wxSnprintf(buf
, sizeof(buf
), _T("Warning: bib ref %s not resolved."), citeKey
);
1068 node
= node
->GetNext();
1072 // Remember we need to resolve this citation
1073 void AddCitation(wxChar
*citeKey
)
1075 if (!CitationList
.Member(citeKey
))
1076 CitationList
.Add(citeKey
);
1078 if (!TexReferences
.Get(citeKey
))
1080 TexReferences
.Put(citeKey
, new TexRef(citeKey
, _T("??"), NULL
));
1084 TexRef
*FindReference(wxChar
*key
)
1086 return (TexRef
*)TexReferences
.Get(key
);
1090 * Custom macro stuff
1094 bool StringTobool(wxChar
*val
)
1096 if (wxStrncmp(val
, _T("yes"), 3) == 0 || wxStrncmp(val
, _T("YES"), 3) == 0 ||
1097 wxStrncmp(val
, _T("on"), 2) == 0 || wxStrncmp(val
, _T("ON"), 2) == 0 ||
1098 wxStrncmp(val
, _T("true"), 4) == 0 || wxStrncmp(val
, _T("true"), 4) == 0 ||
1099 wxStrncmp(val
, _T("ok"), 2) == 0 || wxStrncmp(val
, _T("OK"), 2) == 0 ||
1100 wxStrncmp(val
, _T("1"), 1) == 0)
1106 // Define a variable value from the .ini file
1107 wxChar
*RegisterSetting(wxChar
*settingName
, wxChar
*settingValue
, bool interactive
)
1109 static wxChar errorCode
[100];
1110 wxStrcpy(errorCode
, _T("OK"));
1111 if (StringMatch(settingName
, _T("chapterName"), false, true))
1113 delete[] ChapterNameString
;
1114 ChapterNameString
= copystring(settingValue
);
1116 else if (StringMatch(settingName
, _T("sectionName"), false, true))
1118 delete[] SectionNameString
;
1119 SectionNameString
= copystring(settingValue
);
1121 else if (StringMatch(settingName
, _T("subsectionName"), false, true))
1123 delete[] SubsectionNameString
;
1124 SubsectionNameString
= copystring(settingValue
);
1126 else if (StringMatch(settingName
, _T("subsubsectionName"), false, true))
1128 delete[] SubsubsectionNameString
;
1129 SubsubsectionNameString
= copystring(settingValue
);
1131 else if (StringMatch(settingName
, _T("indexName"), false, true))
1133 delete[] IndexNameString
;
1134 IndexNameString
= copystring(settingValue
);
1136 else if (StringMatch(settingName
, _T("contentsName"), false, true))
1138 delete[] ContentsNameString
;
1139 ContentsNameString
= copystring(settingValue
);
1141 else if (StringMatch(settingName
, _T("glossaryName"), false, true))
1143 delete[] GlossaryNameString
;
1144 GlossaryNameString
= copystring(settingValue
);
1146 else if (StringMatch(settingName
, _T("referencesName"), false, true))
1148 delete[] ReferencesNameString
;
1149 ReferencesNameString
= copystring(settingValue
);
1151 else if (StringMatch(settingName
, _T("tablesName"), false, true))
1153 delete[] TablesNameString
;
1154 TablesNameString
= copystring(settingValue
);
1156 else if (StringMatch(settingName
, _T("figuresName"), false, true))
1158 delete[] FiguresNameString
;
1159 FiguresNameString
= copystring(settingValue
);
1161 else if (StringMatch(settingName
, _T("tableName"), false, true))
1163 delete[] TableNameString
;
1164 TableNameString
= copystring(settingValue
);
1166 else if (StringMatch(settingName
, _T("figureName"), false, true))
1168 delete[] FigureNameString
;
1169 FigureNameString
= copystring(settingValue
);
1171 else if (StringMatch(settingName
, _T("abstractName"), false, true))
1173 delete[] AbstractNameString
;
1174 AbstractNameString
= copystring(settingValue
);
1176 else if (StringMatch(settingName
, _T("chapterFontSize"), false, true))
1177 StringToInt(settingValue
, &chapterFont
);
1178 else if (StringMatch(settingName
, _T("sectionFontSize"), false, true))
1179 StringToInt(settingValue
, §ionFont
);
1180 else if (StringMatch(settingName
, _T("subsectionFontSize"), false, true))
1181 StringToInt(settingValue
, &subsectionFont
);
1182 else if (StringMatch(settingName
, _T("titleFontSize"), false, true))
1183 StringToInt(settingValue
, &titleFont
);
1184 else if (StringMatch(settingName
, _T("authorFontSize"), false, true))
1185 StringToInt(settingValue
, &authorFont
);
1186 else if (StringMatch(settingName
, _T("ignoreInput"), false, true))
1187 IgnorableInputFiles
.Add(wxFileNameFromPath(settingValue
));
1188 else if (StringMatch(settingName
, _T("mirrorMargins"), false, true))
1189 mirrorMargins
= StringTobool(settingValue
);
1190 else if (StringMatch(settingName
, _T("runTwice"), false, true))
1191 runTwice
= StringTobool(settingValue
);
1192 else if (StringMatch(settingName
, _T("isInteractive"), false, true))
1193 isInteractive
= StringTobool(settingValue
);
1194 else if (StringMatch(settingName
, _T("headerRule"), false, true))
1195 headerRule
= StringTobool(settingValue
);
1196 else if (StringMatch(settingName
, _T("footerRule"), false, true))
1197 footerRule
= StringTobool(settingValue
);
1198 else if (StringMatch(settingName
, _T("combineSubSections"), false, true))
1199 combineSubSections
= StringTobool(settingValue
);
1200 else if (StringMatch(settingName
, _T("listLabelIndent"), false, true))
1201 StringToInt(settingValue
, &labelIndentTab
);
1202 else if (StringMatch(settingName
, _T("listItemIndent"), false, true))
1203 StringToInt(settingValue
, &itemIndentTab
);
1204 else if (StringMatch(settingName
, _T("useUpButton"), false, true))
1205 useUpButton
= StringTobool(settingValue
);
1206 else if (StringMatch(settingName
, _T("useHeadingStyles"), false, true))
1207 useHeadingStyles
= StringTobool(settingValue
);
1208 else if (StringMatch(settingName
, _T("useWord"), false, true))
1209 useWord
= StringTobool(settingValue
);
1210 else if (StringMatch(settingName
, _T("contentsDepth"), false, true))
1211 StringToInt(settingValue
, &contentsDepth
);
1212 else if (StringMatch(settingName
, _T("generateHPJ"), false, true))
1213 generateHPJ
= StringTobool(settingValue
);
1214 else if (StringMatch(settingName
, _T("truncateFilenames"), false, true))
1215 truncateFilenames
= StringTobool(settingValue
);
1216 else if (StringMatch(settingName
, _T("winHelpVersion"), false, true))
1217 StringToInt(settingValue
, &winHelpVersion
);
1218 else if (StringMatch(settingName
, _T("winHelpContents"), false, true))
1219 winHelpContents
= StringTobool(settingValue
);
1220 else if (StringMatch(settingName
, _T("htmlIndex"), false, true))
1221 htmlIndex
= StringTobool(settingValue
);
1222 else if (StringMatch(settingName
, _T("htmlWorkshopFiles"), false, true))
1223 htmlWorkshopFiles
= StringTobool(settingValue
);
1224 else if (StringMatch(settingName
, _T("htmlFrameContents"), false, true))
1225 htmlFrameContents
= StringTobool(settingValue
);
1226 else if (StringMatch(settingName
, _T("htmlStylesheet"), false, true))
1228 if (htmlStylesheet
) delete[] htmlStylesheet
;
1229 htmlStylesheet
= copystring(settingValue
);
1231 else if (StringMatch(settingName
, _T("upperCaseNames"), false, true))
1232 upperCaseNames
= StringTobool(settingValue
);
1233 else if (StringMatch(settingName
, _T("ignoreBadRefs"), false, true))
1234 ignoreBadRefs
= StringTobool(settingValue
);
1235 else if (StringMatch(settingName
, _T("htmlFaceName"), false, true))
1237 delete[] htmlFaceName
;
1238 htmlFaceName
= copystring(settingValue
);
1240 else if (StringMatch(settingName
, _T("winHelpTitle"), false, true))
1243 delete[] winHelpTitle
;
1244 winHelpTitle
= copystring(settingValue
);
1246 else if (StringMatch(settingName
, _T("indexSubsections"), false, true))
1247 indexSubsections
= StringTobool(settingValue
);
1248 else if (StringMatch(settingName
, _T("compatibility"), false, true))
1249 compatibilityMode
= StringTobool(settingValue
);
1250 else if (StringMatch(settingName
, _T("defaultColumnWidth"), false, true))
1252 StringToInt(settingValue
, &defaultTableColumnWidth
);
1253 defaultTableColumnWidth
= 20*defaultTableColumnWidth
;
1255 else if (StringMatch(settingName
, _T("bitmapMethod"), false, true))
1257 if ((wxStrcmp(settingValue
, _T("includepicture")) != 0) && (wxStrcmp(settingValue
, _T("hex")) != 0) &&
1258 (wxStrcmp(settingValue
, _T("import")) != 0))
1261 OnError(_T("Unknown bitmapMethod"));
1262 wxStrcpy(errorCode
, _T("Unknown bitmapMethod"));
1266 delete[] bitmapMethod
;
1267 bitmapMethod
= copystring(settingValue
);
1270 else if (StringMatch(settingName
, _T("htmlBrowseButtons"), false, true))
1272 if (wxStrcmp(settingValue
, _T("none")) == 0)
1273 htmlBrowseButtons
= HTML_BUTTONS_NONE
;
1274 else if (wxStrcmp(settingValue
, _T("bitmap")) == 0)
1275 htmlBrowseButtons
= HTML_BUTTONS_BITMAP
;
1276 else if (wxStrcmp(settingValue
, _T("text")) == 0)
1277 htmlBrowseButtons
= HTML_BUTTONS_TEXT
;
1281 OnInform(_T("Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text."));
1282 wxStrcpy(errorCode
, _T("Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text."));
1285 else if (StringMatch(settingName
, _T("backgroundImage"), false, true))
1287 backgroundImageString
= copystring(settingValue
);
1289 else if (StringMatch(settingName
, _T("backgroundColour"), false, true))
1291 delete[] backgroundColourString
;
1292 backgroundColourString
= copystring(settingValue
);
1294 else if (StringMatch(settingName
, _T("textColour"), false, true))
1296 textColourString
= copystring(settingValue
);
1298 else if (StringMatch(settingName
, _T("linkColour"), false, true))
1300 linkColourString
= copystring(settingValue
);
1302 else if (StringMatch(settingName
, _T("followedLinkColour"), false, true))
1304 followedLinkColourString
= copystring(settingValue
);
1306 else if (StringMatch(settingName
, _T("conversionMode"), false, true))
1308 if (StringMatch(settingValue
, _T("RTF"), false, true))
1310 winHelp
= false; convertMode
= TEX_RTF
;
1312 else if (StringMatch(settingValue
, _T("WinHelp"), false, true))
1314 winHelp
= true; convertMode
= TEX_RTF
;
1316 else if (StringMatch(settingValue
, _T("XLP"), false, true) ||
1317 StringMatch(settingValue
, _T("wxHelp"), false, true))
1319 convertMode
= TEX_XLP
;
1321 else if (StringMatch(settingValue
, _T("HTML"), false, true))
1323 convertMode
= TEX_HTML
;
1328 OnInform(_T("Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML."));
1329 wxStrcpy(errorCode
, _T("Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML."));
1332 else if (StringMatch(settingName
, _T("documentFontSize"), false, true))
1335 StringToInt(settingValue
, &n
);
1336 if (n
== 10 || n
== 11 || n
== 12)
1341 wxSnprintf(buf
, sizeof(buf
), _T("Initialisation file error: nonstandard document font size %d."), n
);
1344 wxStrcpy(errorCode
, buf
);
1350 wxSnprintf(buf
, sizeof(buf
), _T("Initialisation file error: unrecognised setting %s."), settingName
);
1353 wxStrcpy(errorCode
, buf
);
1358 bool ReadCustomMacros(wxChar
*filename
)
1360 if (!wxFileExists(filename
))
1363 wxString name
= filename
;
1364 wxSTD ifstream
istr((char const *)name
.fn_str(), wxSTD
ios::in
);
1366 if (istr
.bad()) return false;
1368 CustomMacroList
.Clear();
1370 wxChar macroName
[100];
1371 wxChar macroBody
[1000];
1376 BibEatWhiteSpace(istr
);
1381 if (ch
!= '\\') // Not a macro definition, so must be NAME=VALUE
1383 wxChar settingName
[100];
1384 settingName
[0] = ch
;
1385 BibReadWord(istr
, (settingName
+1));
1386 BibEatWhiteSpace(istr
);
1390 OnError(_T("Expected = following name: malformed tex2rtf.ini file."));
1395 wxChar settingValue
[200];
1396 BibEatWhiteSpace(istr
);
1397 BibReadToEOL(istr
, settingValue
);
1398 RegisterSetting(settingName
, settingValue
);
1403 BibReadWord(istr
, macroName
);
1404 BibEatWhiteSpace(istr
);
1408 OnError(_T("Expected [ followed by number of arguments: malformed tex2rtf.ini file."));
1415 OnError(_T("Expected ] following number of arguments: malformed tex2rtf.ini file."));
1418 BibEatWhiteSpace(istr
);
1422 OnError(_T("Expected { followed by macro body: malformed tex2rtf.ini file."));
1425 CustomMacro
*macro
= new CustomMacro(macroName
, noArgs
, NULL
);
1426 BibReadValue(istr
, macroBody
, false, false); // Don't ignore extra braces
1427 if (wxStrlen(macroBody
) > 0)
1428 macro
->macroBody
= copystring(macroBody
);
1430 BibEatWhiteSpace(istr
);
1431 CustomMacroList
.Append(macroName
, macro
);
1432 AddMacroDef(ltCUSTOM_MACRO
, macroName
, noArgs
);
1436 wxSnprintf(mbuf
, sizeof(mbuf
), _T("Read initialization file %s."), filename
);
1441 CustomMacro
*FindCustomMacro(wxChar
*name
)
1443 wxNode
*node
= CustomMacroList
.Find(name
);
1446 CustomMacro
*macro
= (CustomMacro
*)node
->GetData();
1452 // Display custom macros
1453 void ShowCustomMacros(void)
1455 wxNode
*node
= CustomMacroList
.GetFirst();
1458 OnInform(_T("No custom macros loaded.\n"));
1465 CustomMacro
*macro
= (CustomMacro
*)node
->GetData();
1466 wxSnprintf(buf
, sizeof(buf
), _T("\\%s[%d]\n {%s}"), macro
->macroName
, macro
->noArgs
,
1467 macro
->macroBody
? macro
->macroBody
: _T(""));
1469 node
= node
->GetNext();
1473 // Parse a string into several comma-separated fields
1474 wxChar
*ParseMultifieldString(wxChar
*allFields
, int *pos
)
1476 static wxChar buffer
[300];
1478 int fieldIndex
= *pos
;
1479 int len
= wxStrlen(allFields
);
1481 bool keepGoing
= true;
1482 while ((fieldIndex
<= len
) && keepGoing
)
1484 if (allFields
[fieldIndex
] == _T(' '))
1489 else if (allFields
[fieldIndex
] == _T(','))
1491 *pos
= fieldIndex
+ 1;
1494 else if (allFields
[fieldIndex
] == 0)
1496 *pos
= fieldIndex
+ 1;
1501 buffer
[i
] = allFields
[fieldIndex
];
1507 if (oldPos
== (*pos
))
1521 ColourTableEntry::ColourTableEntry(const wxChar
*theName
, unsigned int r
, unsigned int g
, unsigned int b
)
1523 name
= copystring(theName
);
1529 ColourTableEntry::~ColourTableEntry(void)
1534 void AddColour(const wxChar
*theName
, unsigned int r
, unsigned int g
, unsigned int b
)
1536 wxNode
*node
= ColourTable
.Find(theName
);
1539 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->GetData();
1540 if (entry
->red
== r
|| entry
->green
== g
|| entry
->blue
== b
)
1548 ColourTableEntry
*entry
= new ColourTableEntry(theName
, r
, g
, b
);
1549 ColourTable
.Append(theName
, entry
);
1552 int FindColourPosition(wxChar
*theName
)
1555 wxNode
*node
= ColourTable
.GetFirst();
1558 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->GetData();
1559 if (wxStrcmp(theName
, entry
->name
) == 0)
1562 node
= node
->GetNext();
1567 // Converts e.g. "red" -> "#FF0000"
1568 extern void DecToHex(int, wxChar
*);
1569 bool FindColourHTMLString(wxChar
*theName
, wxChar
*buf
)
1571 wxNode
*node
= ColourTable
.GetFirst();
1574 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->GetData();
1575 if (wxStrcmp(theName
, entry
->name
) == 0)
1577 wxStrcpy(buf
, _T("#"));
1580 DecToHex(entry
->red
, buf2
);
1581 wxStrcat(buf
, buf2
);
1582 DecToHex(entry
->green
, buf2
);
1583 wxStrcat(buf
, buf2
);
1584 DecToHex(entry
->blue
, buf2
);
1585 wxStrcat(buf
, buf2
);
1589 node
= node
->GetNext();
1595 void InitialiseColourTable(void)
1597 // \\red0\\green0\\blue0;
1598 AddColour(_T("black"), 0,0,0);
1600 // \\red0\\green0\\blue255;\\red0\\green255\\blue255;\n");
1601 AddColour(_T("cyan"), 0,255,255);
1603 // \\red0\\green255\\blue0;
1604 AddColour(_T("green"), 0,255,0);
1606 // \\red255\\green0\\blue255;
1607 AddColour(_T("magenta"), 255,0,255);
1609 // \\red255\\green0\\blue0;
1610 AddColour(_T("red"), 255,0,0);
1612 // \\red255\\green255\\blue0;
1613 AddColour(_T("yellow"), 255,255,0);
1615 // \\red255\\green255\\blue255;}");
1616 AddColour(_T("white"), 255,255,255);
1620 * The purpose of this is to reduce the number of times wxYield is
1621 * called, since under Windows this can slow things down.
1624 void Tex2RTFYield(bool force
)
1627 static int yieldCount
= 0;
1634 if (yieldCount
== 0)
1644 // In both RTF generation and HTML generation for wxHelp version 2,
1645 // we need to associate \indexed keywords with the current filename/topics.
1647 // Hash table for lists of keywords for topics (WinHelp).
1648 wxHashTable
TopicTable(wxKEY_STRING
);
1649 void AddKeyWordForTopic(wxChar
*topic
, wxChar
*entry
, wxChar
*filename
)
1651 TexTopic
*texTopic
= (TexTopic
*)TopicTable
.Get(topic
);
1654 texTopic
= new TexTopic(filename
);
1655 texTopic
->keywords
= new wxStringList
;
1656 TopicTable
.Put(topic
, texTopic
);
1659 if (!texTopic
->keywords
->Member(entry
))
1660 texTopic
->keywords
->Add(entry
);
1663 void ClearKeyWordTable(void)
1665 TopicTable
.BeginFind();
1666 wxHashTable::Node
*node
= TopicTable
.Next();
1669 TexTopic
*texTopic
= (TexTopic
*)node
->GetData();
1671 node
= TopicTable
.Next();
1678 * TexTopic structure
1681 TexTopic::TexTopic(wxChar
*f
)
1684 filename
= copystring(f
);
1687 hasChildren
= false;
1691 TexTopic::~TexTopic(void)
1699 // Convert case, according to upperCaseNames setting.
1700 wxChar
*ConvertCase(wxChar
*s
)
1702 static wxChar buf
[256];
1703 int len
= wxStrlen(s
);
1706 for (i
= 0; i
< len
; i
++)
1707 buf
[i
] = (wxChar
)wxToupper(s
[i
]);
1709 for (i
= 0; i
< len
; i
++)
1710 buf
[i
] = (wxChar
)wxTolower(s
[i
]);
1715 #if !WXWIN_COMPATIBILITY_2
1716 // if substring is true, search for str1 in str2
1717 bool StringMatch(const wxChar
*str1
, const wxChar
*str2
, bool subString
,
1722 wxString
Sstr1(str1
);
1723 wxString
Sstr2(str2
);
1729 return Sstr2
.Index(Sstr1
) != (size_t)wxNOT_FOUND
;
1732 return exact
? wxString(str2
).Cmp(str1
) == 0 :
1733 wxString(str2
).CmpNoCase(str1
) == 0;