1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Miscellaneous utilities
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
40 wxHashTable
TexReferences(wxKEY_STRING
);
41 wxList
BibList(wxKEY_STRING
);
42 wxStringList CitationList
;
43 wxList
ColourTable(wxKEY_STRING
);
44 wxHashTable
BibStringTable(wxKEY_STRING
);
45 wxList
CustomMacroList(wxKEY_STRING
);
46 TexChunk
*currentSection
= NULL
;
47 char *fakeCurrentSection
= NULL
;
49 static long BibLine
= 1;
51 void OutputCurrentSection(void)
53 if (fakeCurrentSection
)
54 TexOutput(fakeCurrentSection
);
55 else if (currentSection
)
56 TraverseChildrenFromChunk(currentSection
);
59 // Nasty but the way things are done now, necessary,
60 // in order to output a chunk properly to a string (macros and all).
61 void OutputCurrentSectionToString(char *buf
)
63 if (fakeCurrentSection
)
64 strcpy(buf
, fakeCurrentSection
);
66 OutputChunkToString(currentSection
, buf
);
69 void OutputChunkToString(TexChunk
*chunk
, char *buf
)
71 FILE *tempfd
= fopen("tmp.tmp", "w");
75 FILE *old1
= CurrentOutput1
;
76 FILE *old2
= CurrentOutput2
;
78 CurrentOutput1
= tempfd
;
79 CurrentOutput2
= NULL
;
81 TraverseChildrenFromChunk(chunk
);
83 CurrentOutput1
= old1
;
84 CurrentOutput2
= old2
;
88 // Read from file into string
89 tempfd
= fopen("tmp.tmp", "r");
108 wxRemoveFile("tmp.tmp");
111 // Called by Tex2Any to simulate a section
112 void FakeCurrentSection(char *fakeSection
, bool addToContents
)
114 currentSection
= NULL
;
115 if (fakeCurrentSection
) delete[] fakeCurrentSection
;
116 fakeCurrentSection
= copystring(fakeSection
);
118 if (DocumentStyle
== LATEX_ARTICLE
)
120 int mac
= ltSECTIONHEADING
;
122 mac
= ltSECTIONHEADINGSTAR
;
123 OnMacro(mac
, 0, TRUE
);
124 OnMacro(mac
, 0, FALSE
);
128 int mac
= ltCHAPTERHEADING
;
130 mac
= ltCHAPTERHEADINGSTAR
;
131 OnMacro(mac
, 0, TRUE
);
132 OnMacro(mac
, 0, FALSE
);
134 if (fakeCurrentSection
) delete[] fakeCurrentSection
;
135 fakeCurrentSection
= NULL
;
138 // Look for \label macro, use this ref name if found or
139 // make up a topic name otherwise.
140 static long topicCounter
= 0;
142 void ResetTopicCounter(void)
147 static char *forceTopicName
= NULL
;
149 void ForceTopicName(char *name
)
152 delete[] forceTopicName
;
154 forceTopicName
= copystring(name
);
156 forceTopicName
= NULL
;
159 char *FindTopicName(TexChunk
*chunk
)
162 return forceTopicName
;
164 char *topicName
= NULL
;
165 static char topicBuf
[100];
167 if (chunk
&& (chunk
->type
== CHUNK_TYPE_MACRO
) &&
168 (chunk
->macroId
== ltLABEL
))
170 wxNode
*node
= chunk
->children
.First();
173 TexChunk
*child
= (TexChunk
*)node
->Data();
174 if (child
->type
== CHUNK_TYPE_ARG
)
176 wxNode
*snode
= child
->children
.First();
179 TexChunk
*schunk
= (TexChunk
*)snode
->Data();
180 if (schunk
->type
== CHUNK_TYPE_STRING
)
181 topicName
= schunk
->value
;
190 sprintf(topicBuf
, "topic%ld", topicCounter
);
197 * Simulate argument data, so we can 'drive' clients which implement
198 * certain basic formatting behaviour.
199 * Snag is that some save a TexChunk, so don't use yet...
203 void StartSimulateArgument(char *data
)
205 strcpy(currentArgData
, data
);
209 void EndSimulateArgument(void)
215 * Parse and convert unit arguments to points
219 int ParseUnitArgument(char *unitArg
)
221 float conversionFactor
= 1.0;
222 float unitValue
= 0.0;
223 int len
= strlen(unitArg
);
224 // Get rid of any accidentally embedded commands
225 for (int i
= 0; i
< len
; i
++)
226 if (unitArg
[i
] == '\\')
228 len
= strlen(unitArg
);
230 if (unitArg
&& (len
> 0) && (isdigit(unitArg
[0]) || unitArg
[0] == '-'))
232 sscanf(unitArg
, "%f", &unitValue
);
236 units
[0] = unitArg
[len
-2];
237 units
[1] = unitArg
[len
-1];
239 if (strcmp(units
, "in") == 0)
240 conversionFactor
= 72.0;
241 else if (strcmp(units
, "cm") == 0)
242 conversionFactor
= 72.0/2.51;
243 else if (strcmp(units
, "mm") == 0)
244 conversionFactor
= 72.0/25.1;
245 else if (strcmp(units
, "pt") == 0)
246 conversionFactor
= 1;
248 return (int)(unitValue
*conversionFactor
);
254 * Strip off any extension (dot something) from end of file,
255 * IF one exists. Inserts zero into buffer.
259 void StripExtension(char *buffer
)
261 int len
= strlen(buffer
);
265 if (buffer
[i
] == '.')
279 void SetFontSizes(int pointSize
)
331 void AddTexRef(char *name
, char *file
, char *sectionName
,
332 int chapter
, int section
, int subsection
, int subsubsection
)
334 TexRef
*texRef
= (TexRef
*)TexReferences
.Get(name
);
335 if (texRef
) TexReferences
.Delete(name
);
342 strcat(buf, sectionName);
349 sprintf(buf2
, "%d", chapter
);
358 sprintf(buf2
, "%d", section
);
365 sprintf(buf2
, "%d", subsection
);
372 sprintf(buf2
, "%d", subsubsection
);
375 char *tmp
= ((strlen(buf
) > 0) ? buf
: (char *)NULL
);
376 TexReferences
.Put(name
, new TexRef(name
, file
, tmp
, sectionName
));
379 void WriteTexReferences(char *filename
)
381 ofstream
ostr(filename
);
382 if (ostr
.bad()) return;
385 TexReferences
.BeginFind();
386 wxNode
*node
= TexReferences
.Next();
390 TexRef
*ref
= (TexRef
*)node
->Data();
391 ostr
<< ref
->refLabel
<< " " << (ref
->refFile
? ref
->refFile
: "??") << " ";
392 ostr
<< (ref
->sectionName
? ref
->sectionName
: "??") << " ";
393 ostr
<< (ref
->sectionNumber
? ref
->sectionNumber
: "??") << "\n";
394 if (!ref
->sectionNumber
|| (strcmp(ref
->sectionNumber
, "??") == 0 && strcmp(ref
->sectionName
, "??") == 0))
396 sprintf(buf
, "Warning: reference %s not resolved.", ref
->refLabel
);
399 node
= TexReferences
.Next();
403 void ReadTexReferences(char *filename
)
405 if (!wxFileExists(filename
))
408 ifstream
istr(filename
, ios::in
);
410 if (istr
.bad()) return;
415 char sectionName
[100];
425 istr
.get(ch
); // Read past space
428 while (ch
!= '\n' && !istr
.eof())
435 TexReferences
.Put(label
, new TexRef(label
, file
, section
, sectionName
));
442 * Bibliography-handling code
446 void BibEatWhiteSpace(istream
& str
)
448 char ch
= str
.peek();
450 while (!str
.eof() && (ch
== ' ' || ch
== '\t' || ch
== 13 || ch
== 10 || ch
== EOF
))
455 if ((ch
== EOF
) || str
.eof()) return;
459 // Ignore end-of-line comments
460 if (ch
== '%' || ch
== ';' || ch
== '#')
464 while (ch
!= 10 && ch
!= 13 && !str
.eof())
469 BibEatWhiteSpace(str
);
473 // Read word up to { or , or space
474 void BibReadWord(istream
& istr
, char *buffer
)
478 char ch
= istr
.peek();
479 while (!istr
.eof() && ch
!= ' ' && ch
!= '{' && ch
!= '(' && ch
!= 13 && ch
!= 10 && ch
!= '\t' &&
480 ch
!= ',' && ch
!= '=')
490 // Read string (double-quoted or not) to end quote or EOL
491 void BibReadToEOL(istream
& istr
, char *buffer
)
495 char ch
= istr
.peek();
496 bool inQuotes
= FALSE
;
503 // If in quotes, read white space too. If not,
504 // stop at white space or comment.
505 while (!istr
.eof() && ch
!= 13 && ch
!= 10 && ch
!= '"' &&
506 (inQuotes
|| ((ch
!= ' ') && (ch
!= 9) &&
507 (ch
!= ';') && (ch
!= '%') && (ch
!= '#'))))
519 // Read }-terminated value, taking nested braces into account.
520 void BibReadValue(istream
& istr
, char *buffer
, bool ignoreBraces
= TRUE
,
521 bool quotesMayTerminate
= TRUE
)
526 char ch
= istr
.peek();
527 bool stopping
= FALSE
;
528 while (!istr
.eof() && !stopping
)
534 sprintf(buf
, "Sorry, value > 2000 chars in bib file at line %ld, terminating.", BibLine
);
535 wxFatalError(buf
, "Tex2RTF Fatal Error");
551 else if (quotesMayTerminate
&& ch
== '"')
558 if (!ignoreBraces
|| (ch
!= '{' && ch
!= '}'))
570 bool ReadBib(char *filename
)
572 if (!wxFileExists(filename
))
576 ifstream
istr(filename
, ios::in
);
577 if (istr
.bad()) return FALSE
;
581 OnInform("Reading .bib file...");
584 char fieldValue
[2000];
585 char recordType
[100];
587 char recordField
[100];
592 BibEatWhiteSpace(istr
);
596 sprintf(buf
, "Expected @: malformed bib file at line %ld (%s)", BibLine
, filename
);
600 BibReadWord(istr
, recordType
);
601 BibEatWhiteSpace(istr
);
603 if (ch
!= '{' && ch
!= '(')
605 sprintf(buf
, "Expected { or ( after record type: malformed .bib file at line %ld (%s)", BibLine
, filename
);
609 BibEatWhiteSpace(istr
);
610 if (StringMatch(recordType
, "string", FALSE
, TRUE
))
612 BibReadWord(istr
, recordType
);
613 BibEatWhiteSpace(istr
);
617 sprintf(buf
, "Expected = after string key: malformed .bib file at line %ld (%s)", BibLine
, filename
);
621 BibEatWhiteSpace(istr
);
623 if (ch
!= '"' && ch
!= '{')
625 sprintf(buf
, "Expected = after string key: malformed .bib file at line %ld (%s)", BibLine
, filename
);
629 BibReadValue(istr
, fieldValue
);
631 // Now put in hash table if necesary
632 if (!BibStringTable
.Get(recordType
))
633 BibStringTable
.Put(recordType
, (wxObject
*)copystring(fieldValue
));
635 // Read closing ) or }
636 BibEatWhiteSpace(istr
);
638 BibEatWhiteSpace(istr
);
642 BibReadWord(istr
, recordKey
);
644 BibEntry
*bibEntry
= new BibEntry
;
645 bibEntry
->key
= copystring(recordKey
);
646 bibEntry
->type
= copystring(recordType
);
648 bool moreRecords
= TRUE
;
649 while (moreRecords
&& !istr
.eof())
651 BibEatWhiteSpace(istr
);
653 if (ch
== '}' || ch
== ')')
659 BibEatWhiteSpace(istr
);
660 BibReadWord(istr
, recordField
);
661 BibEatWhiteSpace(istr
);
665 sprintf(buf
, "Expected = after field type: malformed .bib file at line %ld (%s)", BibLine
, filename
);
669 BibEatWhiteSpace(istr
);
671 if (ch
!= '{' && ch
!= '"')
674 BibReadWord(istr
, fieldValue
+1);
676 // If in the table of strings, replace with string from table.
677 char *s
= (char *)BibStringTable
.Get(fieldValue
);
680 strcpy(fieldValue
, s
);
684 BibReadValue(istr
, fieldValue
, TRUE
, (ch
== '"' ? TRUE
: FALSE
));
686 // Now we can add a field
687 if (StringMatch(recordField
, "author", FALSE
, TRUE
))
688 bibEntry
->author
= copystring(fieldValue
);
689 else if (StringMatch(recordField
, "key", FALSE
, TRUE
))
691 else if (StringMatch(recordField
, "annotate", FALSE
, TRUE
))
693 else if (StringMatch(recordField
, "abstract", FALSE
, TRUE
))
695 else if (StringMatch(recordField
, "edition", FALSE
, TRUE
))
697 else if (StringMatch(recordField
, "howpublished", FALSE
, TRUE
))
699 else if (StringMatch(recordField
, "note", FALSE
, TRUE
) || StringMatch(recordField
, "notes", FALSE
, TRUE
))
701 else if (StringMatch(recordField
, "series", FALSE
, TRUE
))
703 else if (StringMatch(recordField
, "type", FALSE
, TRUE
))
705 else if (StringMatch(recordField
, "keywords", FALSE
, TRUE
))
707 else if (StringMatch(recordField
, "editor", FALSE
, TRUE
) || StringMatch(recordField
, "editors", FALSE
, TRUE
))
708 bibEntry
->editor
= copystring(fieldValue
);
709 else if (StringMatch(recordField
, "title", FALSE
, TRUE
))
710 bibEntry
->title
= copystring(fieldValue
);
711 else if (StringMatch(recordField
, "booktitle", FALSE
, TRUE
))
712 bibEntry
->booktitle
= copystring(fieldValue
);
713 else if (StringMatch(recordField
, "journal", FALSE
, TRUE
))
714 bibEntry
->journal
= copystring(fieldValue
);
715 else if (StringMatch(recordField
, "volume", FALSE
, TRUE
))
716 bibEntry
->volume
= copystring(fieldValue
);
717 else if (StringMatch(recordField
, "number", FALSE
, TRUE
))
718 bibEntry
->number
= copystring(fieldValue
);
719 else if (StringMatch(recordField
, "year", FALSE
, TRUE
))
720 bibEntry
->year
= copystring(fieldValue
);
721 else if (StringMatch(recordField
, "month", FALSE
, TRUE
))
722 bibEntry
->month
= copystring(fieldValue
);
723 else if (StringMatch(recordField
, "pages", FALSE
, TRUE
))
724 bibEntry
->pages
= copystring(fieldValue
);
725 else if (StringMatch(recordField
, "publisher", FALSE
, TRUE
))
726 bibEntry
->publisher
= copystring(fieldValue
);
727 else if (StringMatch(recordField
, "address", FALSE
, TRUE
))
728 bibEntry
->address
= copystring(fieldValue
);
729 else if (StringMatch(recordField
, "institution", FALSE
, TRUE
) || StringMatch(recordField
, "school", FALSE
, TRUE
))
730 bibEntry
->institution
= copystring(fieldValue
);
731 else if (StringMatch(recordField
, "organization", FALSE
, TRUE
) || StringMatch(recordField
, "organisation", FALSE
, TRUE
))
732 bibEntry
->organization
= copystring(fieldValue
);
733 else if (StringMatch(recordField
, "comment", FALSE
, TRUE
) || StringMatch(recordField
, "comments", FALSE
, TRUE
))
734 bibEntry
->comment
= copystring(fieldValue
);
735 else if (StringMatch(recordField
, "annote", FALSE
, TRUE
))
736 bibEntry
->comment
= copystring(fieldValue
);
737 else if (StringMatch(recordField
, "chapter", FALSE
, TRUE
))
738 bibEntry
->chapter
= copystring(fieldValue
);
741 sprintf(buf
, "Unrecognised bib field type %s at line %ld (%s)", recordField
, BibLine
, filename
);
746 BibList
.Append(recordKey
, bibEntry
);
747 BibEatWhiteSpace(istr
);
753 void OutputBibItem(TexRef
*ref
, BibEntry
*bib
)
757 OnMacro(ltNUMBEREDBIBITEM
, 2, TRUE
);
758 OnArgument(ltNUMBEREDBIBITEM
, 1, TRUE
);
759 TexOutput(ref
->sectionNumber
);
760 OnArgument(ltNUMBEREDBIBITEM
, 1, FALSE
);
761 OnArgument(ltNUMBEREDBIBITEM
, 2, TRUE
);
764 OnMacro(ltBF
, 1, TRUE
);
765 OnArgument(ltBF
, 1, TRUE
);
767 TexOutput(bib
->author
);
768 OnArgument(ltBF
, 1, FALSE
);
769 OnMacro(ltBF
, 1, FALSE
);
770 if (bib
->author
&& (strlen(bib
->author
) > 0) && (bib
->author
[strlen(bib
->author
) - 1] != '.'))
777 TexOutput(bib
->year
);
782 TexOutput(bib
->month
);
785 if (bib
->year
|| bib
->month
)
788 if (StringMatch(bib
->type
, "article", FALSE
, TRUE
))
792 TexOutput(bib
->title
);
797 OnMacro(ltIT
, 1, TRUE
);
798 OnArgument(ltIT
, 1, TRUE
);
799 TexOutput(bib
->journal
);
800 OnArgument(ltIT
, 1, FALSE
);
801 OnMacro(ltIT
, 1, FALSE
);
806 OnMacro(ltBF
, 1, TRUE
);
807 OnArgument(ltBF
, 1, TRUE
);
808 TexOutput(bib
->volume
);
809 OnArgument(ltBF
, 1, FALSE
);
810 OnMacro(ltBF
, 1, FALSE
);
815 TexOutput(bib
->number
);
820 TexOutput(", pages ");
821 TexOutput(bib
->pages
);
825 else if (StringMatch(bib
->type
, "book", FALSE
, TRUE
) ||
826 StringMatch(bib
->type
, "unpublished", FALSE
, TRUE
) ||
827 StringMatch(bib
->type
, "manual", FALSE
, TRUE
) ||
828 StringMatch(bib
->type
, "phdthesis", FALSE
, TRUE
) ||
829 StringMatch(bib
->type
, "mastersthesis", FALSE
, TRUE
) ||
830 StringMatch(bib
->type
, "misc", FALSE
, TRUE
) ||
831 StringMatch(bib
->type
, "techreport", FALSE
, TRUE
) ||
832 StringMatch(bib
->type
, "booklet", FALSE
, TRUE
))
834 if (bib
->title
|| bib
->booktitle
)
836 OnMacro(ltIT
, 1, TRUE
);
837 OnArgument(ltIT
, 1, TRUE
);
838 TexOutput(bib
->title
? bib
->title
: bib
->booktitle
);
840 OnArgument(ltIT
, 1, FALSE
);
841 OnMacro(ltIT
, 1, FALSE
);
843 if (StringMatch(bib
->type
, "phdthesis", FALSE
, TRUE
))
844 TexOutput("PhD thesis. ");
845 if (StringMatch(bib
->type
, "techreport", FALSE
, TRUE
))
846 TexOutput("Technical report. ");
850 TexOutput(bib
->editor
);
853 if (bib
->institution
)
855 TexOutput(bib
->institution
);
858 if (bib
->organization
)
860 TexOutput(bib
->organization
);
865 TexOutput(bib
->publisher
);
870 TexOutput(bib
->address
);
874 else if (StringMatch(bib
->type
, "inbook", FALSE
, TRUE
) ||
875 StringMatch(bib
->type
, "inproceedings", FALSE
, TRUE
) ||
876 StringMatch(bib
->type
, "incollection", FALSE
, TRUE
) ||
877 StringMatch(bib
->type
, "conference", FALSE
, TRUE
))
881 TexOutput(bib
->title
);
885 TexOutput(", from ");
886 OnMacro(ltIT
, 1, TRUE
);
887 OnArgument(ltIT
, 1, TRUE
);
888 TexOutput(bib
->booktitle
);
890 OnArgument(ltIT
, 1, FALSE
);
891 OnMacro(ltIT
, 1, FALSE
);
896 TexOutput(bib
->editor
);
901 TexOutput(bib
->publisher
);
905 if (bib
->publisher
) TexOutput(", ");
907 TexOutput(bib
->address
);
909 if (bib
->publisher
|| bib
->address
)
915 OnMacro(ltBF
, 1, TRUE
);
916 OnArgument(ltBF
, 1, TRUE
);
917 TexOutput(bib
->volume
);
918 OnArgument(ltBF
, 1, FALSE
);
919 OnMacro(ltBF
, 1, FALSE
);
926 TexOutput(bib
->number
);
931 TexOutput(" Number ");
932 TexOutput(bib
->number
);
938 TexOutput(" Chap. "); TexOutput(bib
->chapter
);
942 if (bib
->chapter
) TexOutput(", pages ");
943 else TexOutput(" Pages ");
944 TexOutput(bib
->pages
);
948 OnArgument(ltNUMBEREDBIBITEM
, 2, FALSE
);
949 OnMacro(ltNUMBEREDBIBITEM
, 2, FALSE
);
955 ForceTopicName("bibliography");
956 FakeCurrentSection(ReferencesNameString
);
957 ForceTopicName(NULL
);
959 OnMacro(ltPAR
, 0, TRUE
);
960 OnMacro(ltPAR
, 0, FALSE
);
962 if ((convertMode
== TEX_RTF
) && !winHelp
)
964 OnMacro(ltPAR
, 0, TRUE
);
965 OnMacro(ltPAR
, 0, FALSE
);
968 wxNode
*node
= CitationList
.First();
971 char *citeKey
= (char *)node
->Data();
972 // wxNode *texNode = TexReferences.Find(citeKey);
973 TexRef
*ref
= (TexRef
*)TexReferences
.Get(citeKey
);
974 wxNode
*bibNode
= BibList
.Find(citeKey
);
977 BibEntry
*entry
= (BibEntry
*)bibNode
->Data();
978 OutputBibItem(ref
, entry
);
984 static int citeCount
= 1;
986 void ResolveBibReferences(void)
988 if (CitationList
.Number() > 0)
989 OnInform("Resolving bibliographic references...");
993 wxNode
*node
= CitationList
.First();
997 char *citeKey
= (char *)node
->Data();
998 // wxNode *texNode = TexReferences.Find(citeKey);
999 TexRef
*ref
= (TexRef
*)TexReferences
.Get(citeKey
);
1000 wxNode
*bibNode
= BibList
.Find(citeKey
);
1004 //BibEntry *entry = (BibEntry *)bibNode->Data();
1005 if (ref
->sectionNumber
) delete[] ref
->sectionNumber
;
1006 sprintf(buf
, "[%d]", citeCount
);
1007 ref
->sectionNumber
= copystring(buf
);
1012 sprintf(buf
, "Warning: bib ref %s not resolved.", citeKey
);
1015 node
= node
->Next();
1019 // Remember we need to resolve this citation
1020 void AddCitation(char *citeKey
)
1022 if (!CitationList
.Member(citeKey
))
1023 CitationList
.Add(citeKey
);
1025 if (!TexReferences
.Get(citeKey
))
1027 TexReferences
.Put(citeKey
, new TexRef(citeKey
, "??", NULL
));
1031 TexRef
*FindReference(char *key
)
1033 return (TexRef
*)TexReferences
.Get(key
);
1037 * Custom macro stuff
1041 bool StringTobool(char *val
)
1043 if (strncmp(val
, "yes", 3) == 0 || strncmp(val
, "YES", 3) == 0 ||
1044 strncmp(val
, "on", 2) == 0 || strncmp(val
, "ON", 2) == 0 ||
1045 strncmp(val
, "true", 4) == 0 || strncmp(val
, "TRUE", 4) == 0 ||
1046 strncmp(val
, "ok", 2) == 0 || strncmp(val
, "OK", 2) == 0 ||
1047 strncmp(val
, "1", 1) == 0)
1053 // Define a variable value from the .ini file
1054 char *RegisterSetting(char *settingName
, char *settingValue
, bool interactive
)
1056 static char errorCode
[100];
1057 strcpy(errorCode
, "OK");
1058 if (StringMatch(settingName
, "chapterName", FALSE
, TRUE
))
1060 delete[] ChapterNameString
;
1061 ChapterNameString
= copystring(settingValue
);
1063 else if (StringMatch(settingName
, "sectionName", FALSE
, TRUE
))
1065 delete[] SectionNameString
;
1066 SectionNameString
= copystring(settingValue
);
1068 else if (StringMatch(settingName
, "subsectionName", FALSE
, TRUE
))
1070 delete[] SubsectionNameString
;
1071 SubsectionNameString
= copystring(settingValue
);
1073 else if (StringMatch(settingName
, "subsubsectionName", FALSE
, TRUE
))
1075 delete[] SubsubsectionNameString
;
1076 SubsubsectionNameString
= copystring(settingValue
);
1078 else if (StringMatch(settingName
, "indexName", FALSE
, TRUE
))
1080 delete[] IndexNameString
;
1081 IndexNameString
= copystring(settingValue
);
1083 else if (StringMatch(settingName
, "contentsName", FALSE
, TRUE
))
1085 delete[] ContentsNameString
;
1086 ContentsNameString
= copystring(settingValue
);
1088 else if (StringMatch(settingName
, "glossaryName", FALSE
, TRUE
))
1090 delete[] GlossaryNameString
;
1091 GlossaryNameString
= copystring(settingValue
);
1093 else if (StringMatch(settingName
, "referencesName", FALSE
, TRUE
))
1095 delete[] ReferencesNameString
;
1096 ReferencesNameString
= copystring(settingValue
);
1098 else if (StringMatch(settingName
, "tablesName", FALSE
, TRUE
))
1100 delete[] TablesNameString
;
1101 TablesNameString
= copystring(settingValue
);
1103 else if (StringMatch(settingName
, "figuresName", FALSE
, TRUE
))
1105 delete[] FiguresNameString
;
1106 FiguresNameString
= copystring(settingValue
);
1108 else if (StringMatch(settingName
, "tableName", FALSE
, TRUE
))
1110 delete[] TableNameString
;
1111 TableNameString
= copystring(settingValue
);
1113 else if (StringMatch(settingName
, "figureName", FALSE
, TRUE
))
1115 delete[] FigureNameString
;
1116 FigureNameString
= copystring(settingValue
);
1118 else if (StringMatch(settingName
, "abstractName", FALSE
, TRUE
))
1120 delete[] AbstractNameString
;
1121 AbstractNameString
= copystring(settingValue
);
1123 else if (StringMatch(settingName
, "chapterFontSize", FALSE
, TRUE
))
1124 StringToInt(settingValue
, &chapterFont
);
1125 else if (StringMatch(settingName
, "sectionFontSize", FALSE
, TRUE
))
1126 StringToInt(settingValue
, §ionFont
);
1127 else if (StringMatch(settingName
, "subsectionFontSize", FALSE
, TRUE
))
1128 StringToInt(settingValue
, &subsectionFont
);
1129 else if (StringMatch(settingName
, "titleFontSize", FALSE
, TRUE
))
1130 StringToInt(settingValue
, &titleFont
);
1131 else if (StringMatch(settingName
, "authorFontSize", FALSE
, TRUE
))
1132 StringToInt(settingValue
, &authorFont
);
1133 else if (StringMatch(settingName
, "ignoreInput", FALSE
, TRUE
))
1134 IgnorableInputFiles
.Add(FileNameFromPath(settingValue
));
1135 else if (StringMatch(settingName
, "mirrorMargins", FALSE
, TRUE
))
1136 mirrorMargins
= StringTobool(settingValue
);
1137 else if (StringMatch(settingName
, "runTwice", FALSE
, TRUE
))
1138 runTwice
= StringTobool(settingValue
);
1139 else if (StringMatch(settingName
, "isInteractive", FALSE
, TRUE
))
1140 isInteractive
= StringTobool(settingValue
);
1141 else if (StringMatch(settingName
, "headerRule", FALSE
, TRUE
))
1142 headerRule
= StringTobool(settingValue
);
1143 else if (StringMatch(settingName
, "footerRule", FALSE
, TRUE
))
1144 footerRule
= StringTobool(settingValue
);
1145 else if (StringMatch(settingName
, "combineSubSections", FALSE
, TRUE
))
1146 combineSubSections
= StringTobool(settingValue
);
1147 else if (StringMatch(settingName
, "listLabelIndent", FALSE
, TRUE
))
1148 StringToInt(settingValue
, &labelIndentTab
);
1149 else if (StringMatch(settingName
, "listItemIndent", FALSE
, TRUE
))
1150 StringToInt(settingValue
, &itemIndentTab
);
1151 else if (StringMatch(settingName
, "useUpButton", FALSE
, TRUE
))
1152 useUpButton
= StringTobool(settingValue
);
1153 else if (StringMatch(settingName
, "useHeadingStyles", FALSE
, TRUE
))
1154 useHeadingStyles
= StringTobool(settingValue
);
1155 else if (StringMatch(settingName
, "useWord", FALSE
, TRUE
))
1156 useWord
= StringTobool(settingValue
);
1157 else if (StringMatch(settingName
, "contentsDepth", FALSE
, TRUE
))
1158 StringToInt(settingValue
, &contentsDepth
);
1159 else if (StringMatch(settingName
, "generateHPJ", FALSE
, TRUE
))
1160 generateHPJ
= StringTobool(settingValue
);
1161 else if (StringMatch(settingName
, "truncateFilenames", FALSE
, TRUE
))
1162 truncateFilenames
= StringTobool(settingValue
);
1163 else if (StringMatch(settingName
, "winHelpVersion", FALSE
, TRUE
))
1164 StringToInt(settingValue
, &winHelpVersion
);
1165 else if (StringMatch(settingName
, "winHelpContents", FALSE
, TRUE
))
1166 winHelpContents
= StringTobool(settingValue
);
1167 else if (StringMatch(settingName
, "htmlIndex", FALSE
, TRUE
))
1168 htmlIndex
= StringTobool(settingValue
);
1169 else if (StringMatch(settingName
, "htmlWorkshopFiles", FALSE
, TRUE
))
1170 htmlWorkshopFiles
= StringTobool(settingValue
);
1171 else if (StringMatch(settingName
, "htmlFrameContents", FALSE
, TRUE
))
1172 htmlFrameContents
= StringTobool(settingValue
);
1173 else if (StringMatch(settingName
, "upperCaseNames", FALSE
, TRUE
))
1174 upperCaseNames
= StringTobool(settingValue
);
1175 else if (StringMatch(settingName
, "winHelpTitle", FALSE
, TRUE
))
1178 delete[] winHelpTitle
;
1179 winHelpTitle
= copystring(settingValue
);
1181 else if (StringMatch(settingName
, "indexSubsections", FALSE
, TRUE
))
1182 indexSubsections
= StringTobool(settingValue
);
1183 else if (StringMatch(settingName
, "compatibility", FALSE
, TRUE
))
1184 compatibilityMode
= StringTobool(settingValue
);
1185 else if (StringMatch(settingName
, "defaultColumnWidth", FALSE
, TRUE
))
1187 StringToInt(settingValue
, &defaultTableColumnWidth
);
1188 defaultTableColumnWidth
= 20*defaultTableColumnWidth
;
1190 else if (StringMatch(settingName
, "bitmapMethod", FALSE
, TRUE
))
1192 if ((strcmp(settingValue
, "includepicture") != 0) && (strcmp(settingValue
, "hex") != 0) &&
1193 (strcmp(settingValue
, "import") != 0))
1196 OnError("Unknown bitmapMethod");
1197 strcpy(errorCode
, "Unknown bitmapMethod");
1201 delete[] bitmapMethod
;
1202 bitmapMethod
= copystring(settingValue
);
1205 else if (StringMatch(settingName
, "htmlBrowseButtons", FALSE
, TRUE
))
1207 if (strcmp(settingValue
, "none") == 0)
1208 htmlBrowseButtons
= HTML_BUTTONS_NONE
;
1209 else if (strcmp(settingValue
, "bitmap") == 0)
1210 htmlBrowseButtons
= HTML_BUTTONS_BITMAP
;
1211 else if (strcmp(settingValue
, "text") == 0)
1212 htmlBrowseButtons
= HTML_BUTTONS_TEXT
;
1216 OnInform("Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text.");
1217 strcpy(errorCode
, "Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text.");
1220 else if (StringMatch(settingName
, "backgroundImage", FALSE
, TRUE
))
1222 backgroundImageString
= copystring(settingValue
);
1224 else if (StringMatch(settingName
, "backgroundColour", FALSE
, TRUE
))
1226 delete[] backgroundColourString
;
1227 backgroundColourString
= copystring(settingValue
);
1229 else if (StringMatch(settingName
, "textColour", FALSE
, TRUE
))
1231 textColourString
= copystring(settingValue
);
1233 else if (StringMatch(settingName
, "linkColour", FALSE
, TRUE
))
1235 linkColourString
= copystring(settingValue
);
1237 else if (StringMatch(settingName
, "followedLinkColour", FALSE
, TRUE
))
1239 followedLinkColourString
= copystring(settingValue
);
1241 else if (StringMatch(settingName
, "conversionMode", FALSE
, TRUE
))
1243 if (StringMatch(settingValue
, "RTF", FALSE
, TRUE
))
1245 winHelp
= FALSE
; convertMode
= TEX_RTF
;
1247 else if (StringMatch(settingValue
, "WinHelp", FALSE
, TRUE
))
1249 winHelp
= TRUE
; convertMode
= TEX_RTF
;
1251 else if (StringMatch(settingValue
, "XLP", FALSE
, TRUE
) ||
1252 StringMatch(settingValue
, "wxHelp", FALSE
, TRUE
))
1254 convertMode
= TEX_XLP
;
1256 else if (StringMatch(settingValue
, "HTML", FALSE
, TRUE
))
1258 convertMode
= TEX_HTML
;
1263 OnInform("Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML.");
1264 strcpy(errorCode
, "Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML.");
1267 else if (StringMatch(settingName
, "documentFontSize", FALSE
, TRUE
))
1270 StringToInt(settingValue
, &n
);
1271 if (n
== 10 || n
== 11 || n
== 12)
1276 sprintf(buf
, "Initialisation file error: nonstandard document font size %d.", n
);
1279 strcpy(errorCode
, buf
);
1285 sprintf(buf
, "Initialisation file error: unrecognised setting %s.", settingName
);
1288 strcpy(errorCode
, buf
);
1293 bool ReadCustomMacros(char *filename
)
1295 if (!wxFileExists(filename
))
1298 ifstream
istr(filename
, ios::in
);
1300 if (istr
.bad()) return FALSE
;
1302 CustomMacroList
.Clear();
1304 char macroName
[100];
1305 char macroBody
[1000];
1310 BibEatWhiteSpace(istr
);
1315 if (ch
!= '\\') // Not a macro definition, so must be NAME=VALUE
1317 char settingName
[100];
1318 settingName
[0] = ch
;
1319 BibReadWord(istr
, (settingName
+1));
1320 BibEatWhiteSpace(istr
);
1324 OnError("Expected = following name: malformed tex2rtf.ini file.");
1329 char settingValue
[200];
1330 BibEatWhiteSpace(istr
);
1331 BibReadToEOL(istr
, settingValue
);
1332 RegisterSetting(settingName
, settingValue
);
1337 BibReadWord(istr
, macroName
);
1338 BibEatWhiteSpace(istr
);
1342 OnError("Expected [ followed by number of arguments: malformed tex2rtf.ini file.");
1349 OnError("Expected ] following number of arguments: malformed tex2rtf.ini file.");
1352 BibEatWhiteSpace(istr
);
1356 OnError("Expected { followed by macro body: malformed tex2rtf.ini file.");
1359 CustomMacro
*macro
= new CustomMacro(macroName
, noArgs
, NULL
);
1360 BibReadValue(istr
, macroBody
, FALSE
, FALSE
); // Don't ignore extra braces
1361 if (strlen(macroBody
) > 0)
1362 macro
->macroBody
= copystring(macroBody
);
1364 BibEatWhiteSpace(istr
);
1365 CustomMacroList
.Append(macroName
, macro
);
1366 AddMacroDef(ltCUSTOM_MACRO
, macroName
, noArgs
);
1370 sprintf(mbuf
, "Read initialization file %s.", filename
);
1375 CustomMacro
*FindCustomMacro(char *name
)
1377 wxNode
*node
= CustomMacroList
.Find(name
);
1380 CustomMacro
*macro
= (CustomMacro
*)node
->Data();
1386 // Display custom macros
1387 void ShowCustomMacros(void)
1389 wxNode
*node
= CustomMacroList
.First();
1392 OnInform("No custom macros loaded.\n");
1399 CustomMacro
*macro
= (CustomMacro
*)node
->Data();
1400 sprintf(buf
, "\\%s[%d]\n {%s}", macro
->macroName
, macro
->noArgs
,
1401 macro
->macroBody
? macro
->macroBody
: "");
1403 node
= node
->Next();
1407 // Parse a string into several comma-separated fields
1408 char *ParseMultifieldString(char *allFields
, int *pos
)
1410 static char buffer
[300];
1412 int fieldIndex
= *pos
;
1413 int len
= strlen(allFields
);
1415 bool keepGoing
= TRUE
;
1416 while ((fieldIndex
<= len
) && keepGoing
)
1418 if (allFields
[fieldIndex
] == ' ')
1423 else if (allFields
[fieldIndex
] == ',')
1425 *pos
= fieldIndex
+ 1;
1428 else if (allFields
[fieldIndex
] == 0)
1430 *pos
= fieldIndex
+ 1;
1435 buffer
[i
] = allFields
[fieldIndex
];
1441 if (oldPos
== (*pos
))
1455 ColourTableEntry::ColourTableEntry(char *theName
, unsigned int r
, unsigned int g
, unsigned int b
)
1457 name
= copystring(theName
);
1463 ColourTableEntry::~ColourTableEntry(void)
1468 void AddColour(char *theName
, unsigned int r
, unsigned int g
, unsigned int b
)
1470 wxNode
*node
= ColourTable
.Find(theName
);
1473 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->Data();
1474 if (entry
->red
== r
|| entry
->green
== g
|| entry
->blue
== b
)
1482 ColourTableEntry
*entry
= new ColourTableEntry(theName
, r
, g
, b
);
1483 ColourTable
.Append(theName
, entry
);
1486 int FindColourPosition(char *theName
)
1489 wxNode
*node
= ColourTable
.First();
1492 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->Data();
1493 if (strcmp(theName
, entry
->name
) == 0)
1496 node
= node
->Next();
1501 // Converts e.g. "red" -> "#FF0000"
1502 extern void DecToHex(int, char *);
1503 bool FindColourHTMLString(char *theName
, char *buf
)
1506 wxNode
*node
= ColourTable
.First();
1509 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->Data();
1510 if (strcmp(theName
, entry
->name
) == 0)
1515 DecToHex(entry
->red
, buf2
);
1517 DecToHex(entry
->green
, buf2
);
1519 DecToHex(entry
->blue
, buf2
);
1525 node
= node
->Next();
1531 void InitialiseColourTable(void)
1533 // \\red0\\green0\\blue0;
1534 AddColour("black", 0,0,0);
1536 // \\red0\\green0\\blue255;\\red0\\green255\\blue255;\n");
1537 AddColour("cyan", 0,255,255);
1539 // \\red0\\green255\\blue0;
1540 AddColour("green", 0,255,0);
1542 // \\red255\\green0\\blue255;
1543 AddColour("magenta", 255,0,255);
1545 // \\red255\\green0\\blue0;
1546 AddColour("red", 255,0,0);
1548 // \\red255\\green255\\blue0;
1549 AddColour("yellow", 255,255,0);
1551 // \\red255\\green255\\blue255;}");
1552 AddColour("white", 255,255,255);
1556 * The purpose of this is to reduce the number of times wxYield is
1557 * called, since under Windows this can slow things down.
1560 static int yieldCount
= 0;
1562 void Tex2RTFYield(bool force
)
1570 if (yieldCount
== 0)
1579 // In both RTF generation and HTML generation for wxHelp version 2,
1580 // we need to associate \indexed keywords with the current filename/topics.
1582 // Hash table for lists of keywords for topics (WinHelp).
1583 wxHashTable
TopicTable(wxKEY_STRING
);
1584 void AddKeyWordForTopic(char *topic
, char *entry
, char *filename
)
1586 TexTopic
*texTopic
= (TexTopic
*)TopicTable
.Get(topic
);
1589 texTopic
= new TexTopic(filename
);
1590 texTopic
->keywords
= new wxStringList
;
1591 TopicTable
.Put(topic
, texTopic
);
1594 if (!texTopic
->keywords
->Member(entry
))
1595 texTopic
->keywords
->Add(entry
);
1598 void ClearKeyWordTable(void)
1600 TopicTable
.BeginFind();
1601 wxNode
*node
= TopicTable
.Next();
1604 TexTopic
*texTopic
= (TexTopic
*)node
->Data();
1606 node
= TopicTable
.Next();
1613 * TexTopic structure
1616 TexTopic::TexTopic(char *f
)
1619 filename
= copystring(f
);
1622 hasChildren
= FALSE
;
1626 TexTopic::~TexTopic(void)
1634 // Convert case, according to upperCaseNames setting.
1635 char *ConvertCase(char *s
)
1637 static char buf
[256];
1638 int len
= strlen(s
);
1641 for (i
= 0; i
< len
; i
++)
1642 buf
[i
] = toupper(s
[i
]);
1644 for (i
= 0; i
< len
; i
++)
1645 buf
[i
] = tolower(s
[i
]);