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"
45 wxHashTable
TexReferences(wxKEY_STRING
);
46 wxList
BibList(wxKEY_STRING
);
47 wxStringList CitationList
;
48 wxList
ColourTable(wxKEY_STRING
);
49 wxHashTable
BibStringTable(wxKEY_STRING
);
50 wxList
CustomMacroList(wxKEY_STRING
);
51 TexChunk
*currentSection
= NULL
;
52 char *fakeCurrentSection
= NULL
;
54 static long BibLine
= 1;
56 void OutputCurrentSection(void)
58 if (fakeCurrentSection
)
59 TexOutput(fakeCurrentSection
);
60 else if (currentSection
)
61 TraverseChildrenFromChunk(currentSection
);
64 // Nasty but the way things are done now, necessary,
65 // in order to output a chunk properly to a string (macros and all).
66 void OutputCurrentSectionToString(char *buf
)
68 if (fakeCurrentSection
)
69 strcpy(buf
, fakeCurrentSection
);
71 OutputChunkToString(currentSection
, buf
);
74 void OutputChunkToString(TexChunk
*chunk
, char *buf
)
76 FILE *tempfd
= fopen("tmp.tmp", "w");
80 FILE *old1
= CurrentOutput1
;
81 FILE *old2
= CurrentOutput2
;
83 CurrentOutput1
= tempfd
;
84 CurrentOutput2
= NULL
;
86 TraverseChildrenFromChunk(chunk
);
88 CurrentOutput1
= old1
;
89 CurrentOutput2
= old2
;
93 // Read from file into string
94 tempfd
= fopen("tmp.tmp", "r");
113 wxRemoveFile("tmp.tmp");
116 // Called by Tex2Any to simulate a section
117 void FakeCurrentSection(char *fakeSection
, bool addToContents
)
119 currentSection
= NULL
;
120 if (fakeCurrentSection
) delete[] fakeCurrentSection
;
121 fakeCurrentSection
= copystring(fakeSection
);
123 if (DocumentStyle
== LATEX_ARTICLE
)
125 int mac
= ltSECTIONHEADING
;
127 mac
= ltSECTIONHEADINGSTAR
;
128 OnMacro(mac
, 0, TRUE
);
129 OnMacro(mac
, 0, FALSE
);
133 int mac
= ltCHAPTERHEADING
;
135 mac
= ltCHAPTERHEADINGSTAR
;
136 OnMacro(mac
, 0, TRUE
);
137 OnMacro(mac
, 0, FALSE
);
139 if (fakeCurrentSection
) delete[] fakeCurrentSection
;
140 fakeCurrentSection
= NULL
;
143 // Look for \label macro, use this ref name if found or
144 // make up a topic name otherwise.
145 static long topicCounter
= 0;
147 void ResetTopicCounter(void)
152 static char *forceTopicName
= NULL
;
154 void ForceTopicName(const char *name
)
157 delete[] forceTopicName
;
159 forceTopicName
= copystring(name
);
161 forceTopicName
= NULL
;
164 char *FindTopicName(TexChunk
*chunk
)
167 return forceTopicName
;
169 char *topicName
= NULL
;
170 static char topicBuf
[100];
172 if (chunk
&& (chunk
->type
== CHUNK_TYPE_MACRO
) &&
173 (chunk
->macroId
== ltLABEL
))
175 wxNode
*node
= chunk
->children
.First();
178 TexChunk
*child
= (TexChunk
*)node
->Data();
179 if (child
->type
== CHUNK_TYPE_ARG
)
181 wxNode
*snode
= child
->children
.First();
184 TexChunk
*schunk
= (TexChunk
*)snode
->Data();
185 if (schunk
->type
== CHUNK_TYPE_STRING
)
186 topicName
= schunk
->value
;
195 sprintf(topicBuf
, "topic%ld", topicCounter
);
202 * Simulate argument data, so we can 'drive' clients which implement
203 * certain basic formatting behaviour.
204 * Snag is that some save a TexChunk, so don't use yet...
208 void StartSimulateArgument(char *data
)
210 strcpy(currentArgData
, data
);
214 void EndSimulateArgument(void)
220 * Parse and convert unit arguments to points
224 int ParseUnitArgument(char *unitArg
)
226 float conversionFactor
= 1.0;
227 float unitValue
= 0.0;
228 int len
= strlen(unitArg
);
229 // Get rid of any accidentally embedded commands
230 for (int i
= 0; i
< len
; i
++)
231 if (unitArg
[i
] == '\\')
233 len
= strlen(unitArg
);
235 if (unitArg
&& (len
> 0) && (isdigit(unitArg
[0]) || unitArg
[0] == '-'))
237 sscanf(unitArg
, "%f", &unitValue
);
241 units
[0] = unitArg
[len
-2];
242 units
[1] = unitArg
[len
-1];
244 if (strcmp(units
, "in") == 0)
245 conversionFactor
= 72.0;
246 else if (strcmp(units
, "cm") == 0)
247 conversionFactor
= (float)72.0/(float)2.51;
248 else if (strcmp(units
, "mm") == 0)
249 conversionFactor
= (float)72.0/(float)25.1;
250 else if (strcmp(units
, "pt") == 0)
251 conversionFactor
= 1;
253 return (int)(unitValue
*conversionFactor
);
259 * Strip off any extension (dot something) from end of file,
260 * IF one exists. Inserts zero into buffer.
264 void StripExtension(char *buffer
)
266 int len
= strlen(buffer
);
270 if (buffer
[i
] == '.')
284 void SetFontSizes(int pointSize
)
336 void AddTexRef(char *name
, char *file
, char *sectionName
,
337 int chapter
, int section
, int subsection
, int subsubsection
)
339 TexRef
*texRef
= (TexRef
*)TexReferences
.Get(name
);
340 if (texRef
) TexReferences
.Delete(name
);
347 strcat(buf, sectionName);
354 sprintf(buf2
, "%d", chapter
);
363 sprintf(buf2
, "%d", section
);
370 sprintf(buf2
, "%d", subsection
);
377 sprintf(buf2
, "%d", subsubsection
);
380 char *tmp
= ((strlen(buf
) > 0) ? buf
: (char *)NULL
);
381 TexReferences
.Put(name
, new TexRef(name
, file
, tmp
, sectionName
));
384 void WriteTexReferences(char *filename
)
386 wxSTD ofstream
ostr(filename
);
387 if (ostr
.bad()) return;
390 TexReferences
.BeginFind();
391 wxNode
*node
= TexReferences
.Next();
395 TexRef
*ref
= (TexRef
*)node
->Data();
396 ostr
<< ref
->refLabel
<< " " << (ref
->refFile
? ref
->refFile
: "??") << " ";
397 ostr
<< (ref
->sectionName
? ref
->sectionName
: "??") << " ";
398 ostr
<< (ref
->sectionNumber
? ref
->sectionNumber
: "??") << "\n";
399 if (!ref
->sectionNumber
|| (strcmp(ref
->sectionNumber
, "??") == 0 && strcmp(ref
->sectionName
, "??") == 0))
401 sprintf(buf
, "Warning: reference %s not resolved.", ref
->refLabel
);
404 node
= TexReferences
.Next();
408 void ReadTexReferences(char *filename
)
410 if (!wxFileExists(filename
))
413 wxSTD ifstream
istr(filename
, wxSTD
ios::in
);
415 if (istr
.bad()) return;
420 char sectionName
[100];
430 istr
.get(ch
); // Read past space
433 while (ch
!= '\n' && !istr
.eof())
441 // gt - needed to trick the hash table "TexReferences" into deleting the key
442 // strings it creates in the Put() function, but not the item that is
443 // created here, as that is destroyed elsewhere. Without doing this, there
444 // were massive memory leaks
445 TexReferences
.DeleteContents(TRUE
);
446 TexReferences
.Put(label
, new TexRef(label
, file
, section
, sectionName
));
447 TexReferences
.DeleteContents(FALSE
);
454 * Bibliography-handling code
458 void BibEatWhiteSpace(wxSTD istream
& str
)
460 char ch
= str
.peek();
462 while (!str
.eof() && (ch
== ' ' || ch
== '\t' || ch
== 13 || ch
== 10 || ch
== EOF
))
467 if ((ch
== EOF
) || str
.eof()) return;
471 // Ignore end-of-line comments
472 if (ch
== '%' || ch
== ';' || ch
== '#')
476 while (ch
!= 10 && ch
!= 13 && !str
.eof())
481 BibEatWhiteSpace(str
);
485 // Read word up to { or , or space
486 void BibReadWord(wxSTD istream
& istr
, char *buffer
)
490 char ch
= istr
.peek();
491 while (!istr
.eof() && ch
!= ' ' && ch
!= '{' && ch
!= '(' && ch
!= 13 && ch
!= 10 && ch
!= '\t' &&
492 ch
!= ',' && ch
!= '=')
502 // Read string (double-quoted or not) to end quote or EOL
503 void BibReadToEOL(wxSTD istream
& istr
, char *buffer
)
507 char ch
= istr
.peek();
508 bool inQuotes
= FALSE
;
515 // If in quotes, read white space too. If not,
516 // stop at white space or comment.
517 while (!istr
.eof() && ch
!= 13 && ch
!= 10 && ch
!= '"' &&
518 (inQuotes
|| ((ch
!= ' ') && (ch
!= 9) &&
519 (ch
!= ';') && (ch
!= '%') && (ch
!= '#'))))
531 // Read }-terminated value, taking nested braces into account.
532 void BibReadValue(wxSTD istream
& istr
, char *buffer
, bool ignoreBraces
= TRUE
,
533 bool quotesMayTerminate
= TRUE
)
538 char ch
= istr
.peek();
539 bool stopping
= FALSE
;
540 while (!istr
.eof() && !stopping
)
546 sprintf(buf
, "Sorry, value > 4000 chars in bib file at line %ld.", BibLine
);
547 wxLogError(buf
, "Tex2RTF Fatal Error");
564 else if (quotesMayTerminate
&& ch
== '"')
571 if (!ignoreBraces
|| (ch
!= '{' && ch
!= '}'))
583 bool ReadBib(char *filename
)
585 if (!wxFileExists(filename
))
589 wxSTD ifstream
istr(filename
, wxSTD
ios::in
);
590 if (istr
.bad()) return FALSE
;
594 OnInform("Reading .bib file...");
597 char fieldValue
[4000];
598 char recordType
[100];
600 char recordField
[100];
605 BibEatWhiteSpace(istr
);
609 sprintf(buf
, "Expected @: malformed bib file at line %ld (%s)", BibLine
, filename
);
613 BibReadWord(istr
, recordType
);
614 BibEatWhiteSpace(istr
);
616 if (ch
!= '{' && ch
!= '(')
618 sprintf(buf
, "Expected { or ( after record type: malformed .bib file at line %ld (%s)", BibLine
, filename
);
622 BibEatWhiteSpace(istr
);
623 if (StringMatch(recordType
, "string", FALSE
, TRUE
))
625 BibReadWord(istr
, recordType
);
626 BibEatWhiteSpace(istr
);
630 sprintf(buf
, "Expected = after string key: malformed .bib file at line %ld (%s)", BibLine
, filename
);
634 BibEatWhiteSpace(istr
);
636 if (ch
!= '"' && ch
!= '{')
638 sprintf(buf
, "Expected = after string key: malformed .bib file at line %ld (%s)", BibLine
, filename
);
642 BibReadValue(istr
, fieldValue
);
644 // Now put in hash table if necesary
645 if (!BibStringTable
.Get(recordType
))
646 BibStringTable
.Put(recordType
, (wxObject
*)copystring(fieldValue
));
648 // Read closing ) or }
649 BibEatWhiteSpace(istr
);
651 BibEatWhiteSpace(istr
);
655 BibReadWord(istr
, recordKey
);
657 BibEntry
*bibEntry
= new BibEntry
;
658 bibEntry
->key
= copystring(recordKey
);
659 bibEntry
->type
= copystring(recordType
);
661 bool moreRecords
= TRUE
;
662 while (moreRecords
&& !istr
.eof())
664 BibEatWhiteSpace(istr
);
666 if (ch
== '}' || ch
== ')')
672 BibEatWhiteSpace(istr
);
673 BibReadWord(istr
, recordField
);
674 BibEatWhiteSpace(istr
);
678 sprintf(buf
, "Expected = after field type: malformed .bib file at line %ld (%s)", BibLine
, filename
);
682 BibEatWhiteSpace(istr
);
684 if (ch
!= '{' && ch
!= '"')
687 BibReadWord(istr
, fieldValue
+1);
689 // If in the table of strings, replace with string from table.
690 char *s
= (char *)BibStringTable
.Get(fieldValue
);
693 strcpy(fieldValue
, s
);
697 BibReadValue(istr
, fieldValue
, TRUE
, (ch
== '"' ? TRUE
: FALSE
));
699 // Now we can add a field
700 if (StringMatch(recordField
, "author", FALSE
, TRUE
))
701 bibEntry
->author
= copystring(fieldValue
);
702 else if (StringMatch(recordField
, "key", FALSE
, TRUE
))
704 else if (StringMatch(recordField
, "annotate", FALSE
, TRUE
))
706 else if (StringMatch(recordField
, "abstract", FALSE
, TRUE
))
708 else if (StringMatch(recordField
, "edition", FALSE
, TRUE
))
710 else if (StringMatch(recordField
, "howpublished", FALSE
, TRUE
))
712 else if (StringMatch(recordField
, "note", FALSE
, TRUE
) || StringMatch(recordField
, "notes", FALSE
, TRUE
))
714 else if (StringMatch(recordField
, "series", FALSE
, TRUE
))
716 else if (StringMatch(recordField
, "type", FALSE
, TRUE
))
718 else if (StringMatch(recordField
, "keywords", FALSE
, TRUE
))
720 else if (StringMatch(recordField
, "editor", FALSE
, TRUE
) || StringMatch(recordField
, "editors", FALSE
, TRUE
))
721 bibEntry
->editor
= copystring(fieldValue
);
722 else if (StringMatch(recordField
, "title", FALSE
, TRUE
))
723 bibEntry
->title
= copystring(fieldValue
);
724 else if (StringMatch(recordField
, "booktitle", FALSE
, TRUE
))
725 bibEntry
->booktitle
= copystring(fieldValue
);
726 else if (StringMatch(recordField
, "journal", FALSE
, TRUE
))
727 bibEntry
->journal
= copystring(fieldValue
);
728 else if (StringMatch(recordField
, "volume", FALSE
, TRUE
))
729 bibEntry
->volume
= copystring(fieldValue
);
730 else if (StringMatch(recordField
, "number", FALSE
, TRUE
))
731 bibEntry
->number
= copystring(fieldValue
);
732 else if (StringMatch(recordField
, "year", FALSE
, TRUE
))
733 bibEntry
->year
= copystring(fieldValue
);
734 else if (StringMatch(recordField
, "month", FALSE
, TRUE
))
735 bibEntry
->month
= copystring(fieldValue
);
736 else if (StringMatch(recordField
, "pages", FALSE
, TRUE
))
737 bibEntry
->pages
= copystring(fieldValue
);
738 else if (StringMatch(recordField
, "publisher", FALSE
, TRUE
))
739 bibEntry
->publisher
= copystring(fieldValue
);
740 else if (StringMatch(recordField
, "address", FALSE
, TRUE
))
741 bibEntry
->address
= copystring(fieldValue
);
742 else if (StringMatch(recordField
, "institution", FALSE
, TRUE
) || StringMatch(recordField
, "school", FALSE
, TRUE
))
743 bibEntry
->institution
= copystring(fieldValue
);
744 else if (StringMatch(recordField
, "organization", FALSE
, TRUE
) || StringMatch(recordField
, "organisation", FALSE
, TRUE
))
745 bibEntry
->organization
= copystring(fieldValue
);
746 else if (StringMatch(recordField
, "comment", FALSE
, TRUE
) || StringMatch(recordField
, "comments", FALSE
, TRUE
))
747 bibEntry
->comment
= copystring(fieldValue
);
748 else if (StringMatch(recordField
, "annote", FALSE
, TRUE
))
749 bibEntry
->comment
= copystring(fieldValue
);
750 else if (StringMatch(recordField
, "chapter", FALSE
, TRUE
))
751 bibEntry
->chapter
= copystring(fieldValue
);
754 sprintf(buf
, "Unrecognised bib field type %s at line %ld (%s)", recordField
, BibLine
, filename
);
759 BibList
.Append(recordKey
, bibEntry
);
760 BibEatWhiteSpace(istr
);
766 void OutputBibItem(TexRef
*ref
, BibEntry
*bib
)
770 OnMacro(ltNUMBEREDBIBITEM
, 2, TRUE
);
771 OnArgument(ltNUMBEREDBIBITEM
, 1, TRUE
);
772 TexOutput(ref
->sectionNumber
);
773 OnArgument(ltNUMBEREDBIBITEM
, 1, FALSE
);
774 OnArgument(ltNUMBEREDBIBITEM
, 2, TRUE
);
777 OnMacro(ltBF
, 1, TRUE
);
778 OnArgument(ltBF
, 1, TRUE
);
780 TexOutput(bib
->author
);
781 OnArgument(ltBF
, 1, FALSE
);
782 OnMacro(ltBF
, 1, FALSE
);
783 if (bib
->author
&& (strlen(bib
->author
) > 0) && (bib
->author
[strlen(bib
->author
) - 1] != '.'))
790 TexOutput(bib
->year
);
795 TexOutput(bib
->month
);
798 if (bib
->year
|| bib
->month
)
801 if (StringMatch(bib
->type
, "article", FALSE
, TRUE
))
805 TexOutput(bib
->title
);
810 OnMacro(ltIT
, 1, TRUE
);
811 OnArgument(ltIT
, 1, TRUE
);
812 TexOutput(bib
->journal
);
813 OnArgument(ltIT
, 1, FALSE
);
814 OnMacro(ltIT
, 1, FALSE
);
819 OnMacro(ltBF
, 1, TRUE
);
820 OnArgument(ltBF
, 1, TRUE
);
821 TexOutput(bib
->volume
);
822 OnArgument(ltBF
, 1, FALSE
);
823 OnMacro(ltBF
, 1, FALSE
);
828 TexOutput(bib
->number
);
833 TexOutput(", pages ");
834 TexOutput(bib
->pages
);
838 else if (StringMatch(bib
->type
, "book", FALSE
, TRUE
) ||
839 StringMatch(bib
->type
, "unpublished", FALSE
, TRUE
) ||
840 StringMatch(bib
->type
, "manual", FALSE
, TRUE
) ||
841 StringMatch(bib
->type
, "phdthesis", FALSE
, TRUE
) ||
842 StringMatch(bib
->type
, "mastersthesis", FALSE
, TRUE
) ||
843 StringMatch(bib
->type
, "misc", FALSE
, TRUE
) ||
844 StringMatch(bib
->type
, "techreport", FALSE
, TRUE
) ||
845 StringMatch(bib
->type
, "booklet", FALSE
, TRUE
))
847 if (bib
->title
|| bib
->booktitle
)
849 OnMacro(ltIT
, 1, TRUE
);
850 OnArgument(ltIT
, 1, TRUE
);
851 TexOutput(bib
->title
? bib
->title
: bib
->booktitle
);
853 OnArgument(ltIT
, 1, FALSE
);
854 OnMacro(ltIT
, 1, FALSE
);
856 if (StringMatch(bib
->type
, "phdthesis", FALSE
, TRUE
))
857 TexOutput("PhD thesis. ");
858 if (StringMatch(bib
->type
, "techreport", FALSE
, TRUE
))
859 TexOutput("Technical report. ");
863 TexOutput(bib
->editor
);
866 if (bib
->institution
)
868 TexOutput(bib
->institution
);
871 if (bib
->organization
)
873 TexOutput(bib
->organization
);
878 TexOutput(bib
->publisher
);
883 TexOutput(bib
->address
);
887 else if (StringMatch(bib
->type
, "inbook", FALSE
, TRUE
) ||
888 StringMatch(bib
->type
, "inproceedings", FALSE
, TRUE
) ||
889 StringMatch(bib
->type
, "incollection", FALSE
, TRUE
) ||
890 StringMatch(bib
->type
, "conference", FALSE
, TRUE
))
894 TexOutput(bib
->title
);
898 TexOutput(", from ");
899 OnMacro(ltIT
, 1, TRUE
);
900 OnArgument(ltIT
, 1, TRUE
);
901 TexOutput(bib
->booktitle
);
903 OnArgument(ltIT
, 1, FALSE
);
904 OnMacro(ltIT
, 1, FALSE
);
909 TexOutput(bib
->editor
);
914 TexOutput(bib
->publisher
);
918 if (bib
->publisher
) TexOutput(", ");
920 TexOutput(bib
->address
);
922 if (bib
->publisher
|| bib
->address
)
928 OnMacro(ltBF
, 1, TRUE
);
929 OnArgument(ltBF
, 1, TRUE
);
930 TexOutput(bib
->volume
);
931 OnArgument(ltBF
, 1, FALSE
);
932 OnMacro(ltBF
, 1, FALSE
);
939 TexOutput(bib
->number
);
944 TexOutput(" Number ");
945 TexOutput(bib
->number
);
951 TexOutput(" Chap. "); TexOutput(bib
->chapter
);
955 if (bib
->chapter
) TexOutput(", pages ");
956 else TexOutput(" Pages ");
957 TexOutput(bib
->pages
);
961 OnArgument(ltNUMBEREDBIBITEM
, 2, FALSE
);
962 OnMacro(ltNUMBEREDBIBITEM
, 2, FALSE
);
968 ForceTopicName("bibliography");
969 FakeCurrentSection(ReferencesNameString
);
970 ForceTopicName(NULL
);
972 OnMacro(ltPAR
, 0, TRUE
);
973 OnMacro(ltPAR
, 0, FALSE
);
975 if ((convertMode
== TEX_RTF
) && !winHelp
)
977 OnMacro(ltPAR
, 0, TRUE
);
978 OnMacro(ltPAR
, 0, FALSE
);
981 wxNode
*node
= CitationList
.First();
984 char *citeKey
= (char *)node
->Data();
985 // wxNode *texNode = TexReferences.Find(citeKey);
986 TexRef
*ref
= (TexRef
*)TexReferences
.Get(citeKey
);
987 wxNode
*bibNode
= BibList
.Find(citeKey
);
990 BibEntry
*entry
= (BibEntry
*)bibNode
->Data();
991 OutputBibItem(ref
, entry
);
997 static int citeCount
= 1;
999 void ResolveBibReferences(void)
1001 if (CitationList
.Number() > 0)
1002 OnInform("Resolving bibliographic references...");
1006 wxNode
*node
= CitationList
.First();
1010 char *citeKey
= (char *)node
->Data();
1011 // wxNode *texNode = TexReferences.Find(citeKey);
1012 TexRef
*ref
= (TexRef
*)TexReferences
.Get(citeKey
);
1013 wxNode
*bibNode
= BibList
.Find(citeKey
);
1017 //BibEntry *entry = (BibEntry *)bibNode->Data();
1018 if (ref
->sectionNumber
) delete[] ref
->sectionNumber
;
1019 sprintf(buf
, "[%d]", citeCount
);
1020 ref
->sectionNumber
= copystring(buf
);
1025 sprintf(buf
, "Warning: bib ref %s not resolved.", citeKey
);
1028 node
= node
->Next();
1032 // Remember we need to resolve this citation
1033 void AddCitation(char *citeKey
)
1035 if (!CitationList
.Member(citeKey
))
1036 CitationList
.Add(citeKey
);
1038 if (!TexReferences
.Get(citeKey
))
1040 TexReferences
.Put(citeKey
, new TexRef(citeKey
, "??", NULL
));
1044 TexRef
*FindReference(char *key
)
1046 return (TexRef
*)TexReferences
.Get(key
);
1050 * Custom macro stuff
1054 bool StringTobool(char *val
)
1056 if (strncmp(val
, "yes", 3) == 0 || strncmp(val
, "YES", 3) == 0 ||
1057 strncmp(val
, "on", 2) == 0 || strncmp(val
, "ON", 2) == 0 ||
1058 strncmp(val
, "true", 4) == 0 || strncmp(val
, "TRUE", 4) == 0 ||
1059 strncmp(val
, "ok", 2) == 0 || strncmp(val
, "OK", 2) == 0 ||
1060 strncmp(val
, "1", 1) == 0)
1066 // Define a variable value from the .ini file
1067 char *RegisterSetting(char *settingName
, char *settingValue
, bool interactive
)
1069 static char errorCode
[100];
1070 strcpy(errorCode
, "OK");
1071 if (StringMatch(settingName
, "chapterName", FALSE
, TRUE
))
1073 delete[] ChapterNameString
;
1074 ChapterNameString
= copystring(settingValue
);
1076 else if (StringMatch(settingName
, "sectionName", FALSE
, TRUE
))
1078 delete[] SectionNameString
;
1079 SectionNameString
= copystring(settingValue
);
1081 else if (StringMatch(settingName
, "subsectionName", FALSE
, TRUE
))
1083 delete[] SubsectionNameString
;
1084 SubsectionNameString
= copystring(settingValue
);
1086 else if (StringMatch(settingName
, "subsubsectionName", FALSE
, TRUE
))
1088 delete[] SubsubsectionNameString
;
1089 SubsubsectionNameString
= copystring(settingValue
);
1091 else if (StringMatch(settingName
, "indexName", FALSE
, TRUE
))
1093 delete[] IndexNameString
;
1094 IndexNameString
= copystring(settingValue
);
1096 else if (StringMatch(settingName
, "contentsName", FALSE
, TRUE
))
1098 delete[] ContentsNameString
;
1099 ContentsNameString
= copystring(settingValue
);
1101 else if (StringMatch(settingName
, "glossaryName", FALSE
, TRUE
))
1103 delete[] GlossaryNameString
;
1104 GlossaryNameString
= copystring(settingValue
);
1106 else if (StringMatch(settingName
, "referencesName", FALSE
, TRUE
))
1108 delete[] ReferencesNameString
;
1109 ReferencesNameString
= copystring(settingValue
);
1111 else if (StringMatch(settingName
, "tablesName", FALSE
, TRUE
))
1113 delete[] TablesNameString
;
1114 TablesNameString
= copystring(settingValue
);
1116 else if (StringMatch(settingName
, "figuresName", FALSE
, TRUE
))
1118 delete[] FiguresNameString
;
1119 FiguresNameString
= copystring(settingValue
);
1121 else if (StringMatch(settingName
, "tableName", FALSE
, TRUE
))
1123 delete[] TableNameString
;
1124 TableNameString
= copystring(settingValue
);
1126 else if (StringMatch(settingName
, "figureName", FALSE
, TRUE
))
1128 delete[] FigureNameString
;
1129 FigureNameString
= copystring(settingValue
);
1131 else if (StringMatch(settingName
, "abstractName", FALSE
, TRUE
))
1133 delete[] AbstractNameString
;
1134 AbstractNameString
= copystring(settingValue
);
1136 else if (StringMatch(settingName
, "chapterFontSize", FALSE
, TRUE
))
1137 StringToInt(settingValue
, &chapterFont
);
1138 else if (StringMatch(settingName
, "sectionFontSize", FALSE
, TRUE
))
1139 StringToInt(settingValue
, §ionFont
);
1140 else if (StringMatch(settingName
, "subsectionFontSize", FALSE
, TRUE
))
1141 StringToInt(settingValue
, &subsectionFont
);
1142 else if (StringMatch(settingName
, "titleFontSize", FALSE
, TRUE
))
1143 StringToInt(settingValue
, &titleFont
);
1144 else if (StringMatch(settingName
, "authorFontSize", FALSE
, TRUE
))
1145 StringToInt(settingValue
, &authorFont
);
1146 else if (StringMatch(settingName
, "ignoreInput", FALSE
, TRUE
))
1147 IgnorableInputFiles
.Add(wxFileNameFromPath(settingValue
));
1148 else if (StringMatch(settingName
, "mirrorMargins", FALSE
, TRUE
))
1149 mirrorMargins
= StringTobool(settingValue
);
1150 else if (StringMatch(settingName
, "runTwice", FALSE
, TRUE
))
1151 runTwice
= StringTobool(settingValue
);
1152 else if (StringMatch(settingName
, "isInteractive", FALSE
, TRUE
))
1153 isInteractive
= StringTobool(settingValue
);
1154 else if (StringMatch(settingName
, "headerRule", FALSE
, TRUE
))
1155 headerRule
= StringTobool(settingValue
);
1156 else if (StringMatch(settingName
, "footerRule", FALSE
, TRUE
))
1157 footerRule
= StringTobool(settingValue
);
1158 else if (StringMatch(settingName
, "combineSubSections", FALSE
, TRUE
))
1159 combineSubSections
= StringTobool(settingValue
);
1160 else if (StringMatch(settingName
, "listLabelIndent", FALSE
, TRUE
))
1161 StringToInt(settingValue
, &labelIndentTab
);
1162 else if (StringMatch(settingName
, "listItemIndent", FALSE
, TRUE
))
1163 StringToInt(settingValue
, &itemIndentTab
);
1164 else if (StringMatch(settingName
, "useUpButton", FALSE
, TRUE
))
1165 useUpButton
= StringTobool(settingValue
);
1166 else if (StringMatch(settingName
, "useHeadingStyles", FALSE
, TRUE
))
1167 useHeadingStyles
= StringTobool(settingValue
);
1168 else if (StringMatch(settingName
, "useWord", FALSE
, TRUE
))
1169 useWord
= StringTobool(settingValue
);
1170 else if (StringMatch(settingName
, "contentsDepth", FALSE
, TRUE
))
1171 StringToInt(settingValue
, &contentsDepth
);
1172 else if (StringMatch(settingName
, "generateHPJ", FALSE
, TRUE
))
1173 generateHPJ
= StringTobool(settingValue
);
1174 else if (StringMatch(settingName
, "truncateFilenames", FALSE
, TRUE
))
1175 truncateFilenames
= StringTobool(settingValue
);
1176 else if (StringMatch(settingName
, "winHelpVersion", FALSE
, TRUE
))
1177 StringToInt(settingValue
, &winHelpVersion
);
1178 else if (StringMatch(settingName
, "winHelpContents", FALSE
, TRUE
))
1179 winHelpContents
= StringTobool(settingValue
);
1180 else if (StringMatch(settingName
, "htmlIndex", FALSE
, TRUE
))
1181 htmlIndex
= StringTobool(settingValue
);
1182 else if (StringMatch(settingName
, "htmlWorkshopFiles", FALSE
, TRUE
))
1183 htmlWorkshopFiles
= StringTobool(settingValue
);
1184 else if (StringMatch(settingName
, "htmlFrameContents", FALSE
, TRUE
))
1185 htmlFrameContents
= StringTobool(settingValue
);
1186 else if (StringMatch(settingName
, "htmlStylesheet", FALSE
, TRUE
))
1188 if (htmlStylesheet
) delete[] htmlStylesheet
;
1189 htmlStylesheet
= copystring(settingValue
);
1191 else if (StringMatch(settingName
, "upperCaseNames", FALSE
, TRUE
))
1192 upperCaseNames
= StringTobool(settingValue
);
1193 else if (StringMatch(settingName
, "ignoreBadRefs", FALSE
, TRUE
))
1194 ignoreBadRefs
= StringTobool(settingValue
);
1195 else if (StringMatch(settingName
, "htmlFaceName", FALSE
, TRUE
))
1197 delete[] htmlFaceName
;
1198 htmlFaceName
= copystring(settingValue
);
1200 else if (StringMatch(settingName
, "winHelpTitle", FALSE
, TRUE
))
1203 delete[] winHelpTitle
;
1204 winHelpTitle
= copystring(settingValue
);
1206 else if (StringMatch(settingName
, "indexSubsections", FALSE
, TRUE
))
1207 indexSubsections
= StringTobool(settingValue
);
1208 else if (StringMatch(settingName
, "compatibility", FALSE
, TRUE
))
1209 compatibilityMode
= StringTobool(settingValue
);
1210 else if (StringMatch(settingName
, "defaultColumnWidth", FALSE
, TRUE
))
1212 StringToInt(settingValue
, &defaultTableColumnWidth
);
1213 defaultTableColumnWidth
= 20*defaultTableColumnWidth
;
1215 else if (StringMatch(settingName
, "bitmapMethod", FALSE
, TRUE
))
1217 if ((strcmp(settingValue
, "includepicture") != 0) && (strcmp(settingValue
, "hex") != 0) &&
1218 (strcmp(settingValue
, "import") != 0))
1221 OnError("Unknown bitmapMethod");
1222 strcpy(errorCode
, "Unknown bitmapMethod");
1226 delete[] bitmapMethod
;
1227 bitmapMethod
= copystring(settingValue
);
1230 else if (StringMatch(settingName
, "htmlBrowseButtons", FALSE
, TRUE
))
1232 if (strcmp(settingValue
, "none") == 0)
1233 htmlBrowseButtons
= HTML_BUTTONS_NONE
;
1234 else if (strcmp(settingValue
, "bitmap") == 0)
1235 htmlBrowseButtons
= HTML_BUTTONS_BITMAP
;
1236 else if (strcmp(settingValue
, "text") == 0)
1237 htmlBrowseButtons
= HTML_BUTTONS_TEXT
;
1241 OnInform("Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text.");
1242 strcpy(errorCode
, "Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text.");
1245 else if (StringMatch(settingName
, "backgroundImage", FALSE
, TRUE
))
1247 backgroundImageString
= copystring(settingValue
);
1249 else if (StringMatch(settingName
, "backgroundColour", FALSE
, TRUE
))
1251 delete[] backgroundColourString
;
1252 backgroundColourString
= copystring(settingValue
);
1254 else if (StringMatch(settingName
, "textColour", FALSE
, TRUE
))
1256 textColourString
= copystring(settingValue
);
1258 else if (StringMatch(settingName
, "linkColour", FALSE
, TRUE
))
1260 linkColourString
= copystring(settingValue
);
1262 else if (StringMatch(settingName
, "followedLinkColour", FALSE
, TRUE
))
1264 followedLinkColourString
= copystring(settingValue
);
1266 else if (StringMatch(settingName
, "conversionMode", FALSE
, TRUE
))
1268 if (StringMatch(settingValue
, "RTF", FALSE
, TRUE
))
1270 winHelp
= FALSE
; convertMode
= TEX_RTF
;
1272 else if (StringMatch(settingValue
, "WinHelp", FALSE
, TRUE
))
1274 winHelp
= TRUE
; convertMode
= TEX_RTF
;
1276 else if (StringMatch(settingValue
, "XLP", FALSE
, TRUE
) ||
1277 StringMatch(settingValue
, "wxHelp", FALSE
, TRUE
))
1279 convertMode
= TEX_XLP
;
1281 else if (StringMatch(settingValue
, "HTML", FALSE
, TRUE
))
1283 convertMode
= TEX_HTML
;
1288 OnInform("Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML.");
1289 strcpy(errorCode
, "Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML.");
1292 else if (StringMatch(settingName
, "documentFontSize", FALSE
, TRUE
))
1295 StringToInt(settingValue
, &n
);
1296 if (n
== 10 || n
== 11 || n
== 12)
1301 sprintf(buf
, "Initialisation file error: nonstandard document font size %d.", n
);
1304 strcpy(errorCode
, buf
);
1310 sprintf(buf
, "Initialisation file error: unrecognised setting %s.", settingName
);
1313 strcpy(errorCode
, buf
);
1318 bool ReadCustomMacros(char *filename
)
1320 if (!wxFileExists(filename
))
1323 wxSTD ifstream
istr(filename
, wxSTD
ios::in
);
1325 if (istr
.bad()) return FALSE
;
1327 CustomMacroList
.Clear();
1329 char macroName
[100];
1330 char macroBody
[1000];
1335 BibEatWhiteSpace(istr
);
1340 if (ch
!= '\\') // Not a macro definition, so must be NAME=VALUE
1342 char settingName
[100];
1343 settingName
[0] = ch
;
1344 BibReadWord(istr
, (settingName
+1));
1345 BibEatWhiteSpace(istr
);
1349 OnError("Expected = following name: malformed tex2rtf.ini file.");
1354 char settingValue
[200];
1355 BibEatWhiteSpace(istr
);
1356 BibReadToEOL(istr
, settingValue
);
1357 RegisterSetting(settingName
, settingValue
);
1362 BibReadWord(istr
, macroName
);
1363 BibEatWhiteSpace(istr
);
1367 OnError("Expected [ followed by number of arguments: malformed tex2rtf.ini file.");
1374 OnError("Expected ] following number of arguments: malformed tex2rtf.ini file.");
1377 BibEatWhiteSpace(istr
);
1381 OnError("Expected { followed by macro body: malformed tex2rtf.ini file.");
1384 CustomMacro
*macro
= new CustomMacro(macroName
, noArgs
, NULL
);
1385 BibReadValue(istr
, macroBody
, FALSE
, FALSE
); // Don't ignore extra braces
1386 if (strlen(macroBody
) > 0)
1387 macro
->macroBody
= copystring(macroBody
);
1389 BibEatWhiteSpace(istr
);
1390 CustomMacroList
.Append(macroName
, macro
);
1391 AddMacroDef(ltCUSTOM_MACRO
, macroName
, noArgs
);
1395 sprintf(mbuf
, "Read initialization file %s.", filename
);
1400 CustomMacro
*FindCustomMacro(char *name
)
1402 wxNode
*node
= CustomMacroList
.Find(name
);
1405 CustomMacro
*macro
= (CustomMacro
*)node
->Data();
1411 // Display custom macros
1412 void ShowCustomMacros(void)
1414 wxNode
*node
= CustomMacroList
.First();
1417 OnInform("No custom macros loaded.\n");
1424 CustomMacro
*macro
= (CustomMacro
*)node
->Data();
1425 sprintf(buf
, "\\%s[%d]\n {%s}", macro
->macroName
, macro
->noArgs
,
1426 macro
->macroBody
? macro
->macroBody
: "");
1428 node
= node
->Next();
1432 // Parse a string into several comma-separated fields
1433 char *ParseMultifieldString(char *allFields
, int *pos
)
1435 static char buffer
[300];
1437 int fieldIndex
= *pos
;
1438 int len
= strlen(allFields
);
1440 bool keepGoing
= TRUE
;
1441 while ((fieldIndex
<= len
) && keepGoing
)
1443 if (allFields
[fieldIndex
] == ' ')
1448 else if (allFields
[fieldIndex
] == ',')
1450 *pos
= fieldIndex
+ 1;
1453 else if (allFields
[fieldIndex
] == 0)
1455 *pos
= fieldIndex
+ 1;
1460 buffer
[i
] = allFields
[fieldIndex
];
1466 if (oldPos
== (*pos
))
1480 ColourTableEntry::ColourTableEntry(const char *theName
, unsigned int r
, unsigned int g
, unsigned int b
)
1482 name
= copystring(theName
);
1488 ColourTableEntry::~ColourTableEntry(void)
1493 void AddColour(const char *theName
, unsigned int r
, unsigned int g
, unsigned int b
)
1495 wxNode
*node
= ColourTable
.Find(theName
);
1498 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->Data();
1499 if (entry
->red
== r
|| entry
->green
== g
|| entry
->blue
== b
)
1507 ColourTableEntry
*entry
= new ColourTableEntry(theName
, r
, g
, b
);
1508 ColourTable
.Append(theName
, entry
);
1511 int FindColourPosition(char *theName
)
1514 wxNode
*node
= ColourTable
.First();
1517 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->Data();
1518 if (strcmp(theName
, entry
->name
) == 0)
1521 node
= node
->Next();
1526 // Converts e.g. "red" -> "#FF0000"
1527 extern void DecToHex(int, char *);
1528 bool FindColourHTMLString(char *theName
, char *buf
)
1531 wxNode
*node
= ColourTable
.First();
1534 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->Data();
1535 if (strcmp(theName
, entry
->name
) == 0)
1540 DecToHex(entry
->red
, buf2
);
1542 DecToHex(entry
->green
, buf2
);
1544 DecToHex(entry
->blue
, buf2
);
1550 node
= node
->Next();
1556 void InitialiseColourTable(void)
1558 // \\red0\\green0\\blue0;
1559 AddColour("black", 0,0,0);
1561 // \\red0\\green0\\blue255;\\red0\\green255\\blue255;\n");
1562 AddColour("cyan", 0,255,255);
1564 // \\red0\\green255\\blue0;
1565 AddColour("green", 0,255,0);
1567 // \\red255\\green0\\blue255;
1568 AddColour("magenta", 255,0,255);
1570 // \\red255\\green0\\blue0;
1571 AddColour("red", 255,0,0);
1573 // \\red255\\green255\\blue0;
1574 AddColour("yellow", 255,255,0);
1576 // \\red255\\green255\\blue255;}");
1577 AddColour("white", 255,255,255);
1581 * The purpose of this is to reduce the number of times wxYield is
1582 * called, since under Windows this can slow things down.
1585 void Tex2RTFYield(bool force
)
1588 static int yieldCount
= 0;
1595 if (yieldCount
== 0)
1605 // In both RTF generation and HTML generation for wxHelp version 2,
1606 // we need to associate \indexed keywords with the current filename/topics.
1608 // Hash table for lists of keywords for topics (WinHelp).
1609 wxHashTable
TopicTable(wxKEY_STRING
);
1610 void AddKeyWordForTopic(char *topic
, char *entry
, char *filename
)
1612 TexTopic
*texTopic
= (TexTopic
*)TopicTable
.Get(topic
);
1615 texTopic
= new TexTopic(filename
);
1616 texTopic
->keywords
= new wxStringList
;
1617 TopicTable
.Put(topic
, texTopic
);
1620 if (!texTopic
->keywords
->Member(entry
))
1621 texTopic
->keywords
->Add(entry
);
1624 void ClearKeyWordTable(void)
1626 TopicTable
.BeginFind();
1627 wxNode
*node
= TopicTable
.Next();
1630 TexTopic
*texTopic
= (TexTopic
*)node
->Data();
1632 node
= TopicTable
.Next();
1639 * TexTopic structure
1642 TexTopic::TexTopic(char *f
)
1645 filename
= copystring(f
);
1648 hasChildren
= FALSE
;
1652 TexTopic::~TexTopic(void)
1660 // Convert case, according to upperCaseNames setting.
1661 char *ConvertCase(char *s
)
1663 static char buf
[256];
1664 int len
= strlen(s
);
1667 for (i
= 0; i
< len
; i
++)
1668 buf
[i
] = toupper(s
[i
]);
1670 for (i
= 0; i
< len
; i
++)
1671 buf
[i
] = tolower(s
[i
]);
1676 #if !WXWIN_COMPATIBILITY_2
1677 // if substring is TRUE, search for str1 in str2
1678 bool StringMatch(const wxChar
*str1
, const wxChar
*str2
, bool subString
,
1683 wxString
Sstr1(str1
);
1684 wxString
Sstr2(str2
);
1690 return Sstr2
.Index(Sstr1
) != wxNOT_FOUND
;
1693 return exact
? wxString(str2
).Cmp(str1
) == 0 :
1694 wxString(str2
).CmpNoCase(str1
) == 0;