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"
46 #if !WXWIN_COMPATIBILITY_2_4
47 static inline wxChar
* copystring(const wxChar
* s
)
48 { return wxStrcpy(new wxChar
[wxStrlen(s
) + 1], s
); }
49 static inline void StringToInt (const wxChar
*s
, int *number
)
51 if (s
&& *s
&& number
)
52 *number
= (int) wxStrtol (s
, (wxChar
**) NULL
, 10);
56 wxHashTable
TexReferences(wxKEY_STRING
);
57 wxList
BibList(wxKEY_STRING
);
58 wxStringList CitationList
;
59 wxList
ColourTable(wxKEY_STRING
);
60 wxHashTable
BibStringTable(wxKEY_STRING
);
61 wxList
CustomMacroList(wxKEY_STRING
);
62 TexChunk
*currentSection
= NULL
;
63 char *fakeCurrentSection
= NULL
;
65 static long BibLine
= 1;
67 void OutputCurrentSection(void)
69 if (fakeCurrentSection
)
70 TexOutput(fakeCurrentSection
);
71 else if (currentSection
)
72 TraverseChildrenFromChunk(currentSection
);
75 // Nasty but the way things are done now, necessary,
76 // in order to output a chunk properly to a string (macros and all).
77 void OutputCurrentSectionToString(char *buf
)
79 if (fakeCurrentSection
)
80 strcpy(buf
, fakeCurrentSection
);
82 OutputChunkToString(currentSection
, buf
);
85 void OutputChunkToString(TexChunk
*chunk
, char *buf
)
87 FILE *tempfd
= fopen("tmp.tmp", "w");
91 FILE *old1
= CurrentOutput1
;
92 FILE *old2
= CurrentOutput2
;
94 CurrentOutput1
= tempfd
;
95 CurrentOutput2
= NULL
;
97 TraverseChildrenFromChunk(chunk
);
99 CurrentOutput1
= old1
;
100 CurrentOutput2
= old2
;
104 // Read from file into string
105 tempfd
= fopen("tmp.tmp", "r");
124 wxRemoveFile("tmp.tmp");
127 // Called by Tex2Any to simulate a section
128 void FakeCurrentSection(char *fakeSection
, bool addToContents
)
130 currentSection
= NULL
;
131 if (fakeCurrentSection
) delete[] fakeCurrentSection
;
132 fakeCurrentSection
= copystring(fakeSection
);
134 if (DocumentStyle
== LATEX_ARTICLE
)
136 int mac
= ltSECTIONHEADING
;
138 mac
= ltSECTIONHEADINGSTAR
;
139 OnMacro(mac
, 0, TRUE
);
140 OnMacro(mac
, 0, FALSE
);
144 int mac
= ltCHAPTERHEADING
;
146 mac
= ltCHAPTERHEADINGSTAR
;
147 OnMacro(mac
, 0, TRUE
);
148 OnMacro(mac
, 0, FALSE
);
150 if (fakeCurrentSection
) delete[] fakeCurrentSection
;
151 fakeCurrentSection
= NULL
;
154 // Look for \label macro, use this ref name if found or
155 // make up a topic name otherwise.
156 static long topicCounter
= 0;
158 void ResetTopicCounter(void)
163 static char *forceTopicName
= NULL
;
165 void ForceTopicName(const char *name
)
168 delete[] forceTopicName
;
170 forceTopicName
= copystring(name
);
172 forceTopicName
= NULL
;
175 char *FindTopicName(TexChunk
*chunk
)
178 return forceTopicName
;
180 char *topicName
= NULL
;
181 static char topicBuf
[100];
183 if (chunk
&& (chunk
->type
== CHUNK_TYPE_MACRO
) &&
184 (chunk
->macroId
== ltLABEL
))
186 wxNode
*node
= chunk
->children
.GetFirst();
189 TexChunk
*child
= (TexChunk
*)node
->GetData();
190 if (child
->type
== CHUNK_TYPE_ARG
)
192 wxNode
*snode
= child
->children
.GetFirst();
195 TexChunk
*schunk
= (TexChunk
*)snode
->GetData();
196 if (schunk
->type
== CHUNK_TYPE_STRING
)
197 topicName
= schunk
->value
;
206 sprintf(topicBuf
, "topic%ld", topicCounter
);
213 * Simulate argument data, so we can 'drive' clients which implement
214 * certain basic formatting behaviour.
215 * Snag is that some save a TexChunk, so don't use yet...
219 void StartSimulateArgument(char *data
)
221 strcpy(currentArgData
, data
);
225 void EndSimulateArgument(void)
231 * Parse and convert unit arguments to points
235 int ParseUnitArgument(char *unitArg
)
237 float conversionFactor
= 1.0;
238 float unitValue
= 0.0;
239 int len
= strlen(unitArg
);
240 // Get rid of any accidentally embedded commands
241 for (int i
= 0; i
< len
; i
++)
242 if (unitArg
[i
] == '\\')
244 len
= strlen(unitArg
);
246 if (unitArg
&& (len
> 0) && (isdigit(unitArg
[0]) || unitArg
[0] == '-'))
248 sscanf(unitArg
, "%f", &unitValue
);
252 units
[0] = unitArg
[len
-2];
253 units
[1] = unitArg
[len
-1];
255 if (strcmp(units
, "in") == 0)
256 conversionFactor
= 72.0;
257 else if (strcmp(units
, "cm") == 0)
258 conversionFactor
= (float)72.0/(float)2.51;
259 else if (strcmp(units
, "mm") == 0)
260 conversionFactor
= (float)72.0/(float)25.1;
261 else if (strcmp(units
, "pt") == 0)
262 conversionFactor
= 1;
264 return (int)(unitValue
*conversionFactor
);
270 * Strip off any extension (dot something) from end of file,
271 * IF one exists. Inserts zero into buffer.
275 void StripExtension(char *buffer
)
277 int len
= strlen(buffer
);
281 if (buffer
[i
] == '.')
295 void SetFontSizes(int pointSize
)
347 void AddTexRef(char *name
, char *file
, char *sectionName
,
348 int chapter
, int section
, int subsection
, int subsubsection
)
350 TexRef
*texRef
= (TexRef
*)TexReferences
.Get(name
);
351 if (texRef
) TexReferences
.Delete(name
);
358 strcat(buf, sectionName);
365 sprintf(buf2
, "%d", chapter
);
374 sprintf(buf2
, "%d", section
);
381 sprintf(buf2
, "%d", subsection
);
388 sprintf(buf2
, "%d", subsubsection
);
391 char *tmp
= ((strlen(buf
) > 0) ? buf
: (char *)NULL
);
392 TexReferences
.Put(name
, new TexRef(name
, file
, tmp
, sectionName
));
395 void WriteTexReferences(char *filename
)
397 wxSTD ofstream
ostr(filename
);
398 if (ostr
.bad()) return;
401 TexReferences
.BeginFind();
402 wxNode
*node
= TexReferences
.Next();
406 TexRef
*ref
= (TexRef
*)node
->GetData();
407 ostr
<< ref
->refLabel
<< " " << (ref
->refFile
? ref
->refFile
: "??") << " ";
408 ostr
<< (ref
->sectionName
? ref
->sectionName
: "??") << " ";
409 ostr
<< (ref
->sectionNumber
? ref
->sectionNumber
: "??") << "\n";
410 if (!ref
->sectionNumber
|| (strcmp(ref
->sectionNumber
, "??") == 0 && strcmp(ref
->sectionName
, "??") == 0))
412 sprintf(buf
, "Warning: reference %s not resolved.", ref
->refLabel
);
415 node
= TexReferences
.Next();
419 void ReadTexReferences(char *filename
)
421 if (!wxFileExists(filename
))
424 wxSTD ifstream
istr(filename
, wxSTD
ios::in
);
426 if (istr
.bad()) return;
431 char sectionName
[100];
441 istr
.get(ch
); // Read past space
444 while (ch
!= '\n' && !istr
.eof())
452 // gt - needed to trick the hash table "TexReferences" into deleting the key
453 // strings it creates in the Put() function, but not the item that is
454 // created here, as that is destroyed elsewhere. Without doing this, there
455 // were massive memory leaks
456 TexReferences
.DeleteContents(TRUE
);
457 TexReferences
.Put(label
, new TexRef(label
, file
, section
, sectionName
));
458 TexReferences
.DeleteContents(FALSE
);
465 * Bibliography-handling code
469 void BibEatWhiteSpace(wxSTD istream
& str
)
471 char ch
= str
.peek();
473 while (!str
.eof() && (ch
== ' ' || ch
== '\t' || ch
== 13 || ch
== 10 || ch
== EOF
))
478 if ((ch
== EOF
) || str
.eof()) return;
482 // Ignore end-of-line comments
483 if (ch
== '%' || ch
== ';' || ch
== '#')
487 while (ch
!= 10 && ch
!= 13 && !str
.eof())
492 BibEatWhiteSpace(str
);
496 // Read word up to { or , or space
497 void BibReadWord(wxSTD istream
& istr
, char *buffer
)
501 char ch
= istr
.peek();
502 while (!istr
.eof() && ch
!= ' ' && ch
!= '{' && ch
!= '(' && ch
!= 13 && ch
!= 10 && ch
!= '\t' &&
503 ch
!= ',' && ch
!= '=')
513 // Read string (double-quoted or not) to end quote or EOL
514 void BibReadToEOL(wxSTD istream
& istr
, char *buffer
)
518 char ch
= istr
.peek();
519 bool inQuotes
= FALSE
;
526 // If in quotes, read white space too. If not,
527 // stop at white space or comment.
528 while (!istr
.eof() && ch
!= 13 && ch
!= 10 && ch
!= '"' &&
529 (inQuotes
|| ((ch
!= ' ') && (ch
!= 9) &&
530 (ch
!= ';') && (ch
!= '%') && (ch
!= '#'))))
542 // Read }-terminated value, taking nested braces into account.
543 void BibReadValue(wxSTD istream
& istr
, char *buffer
, bool ignoreBraces
= TRUE
,
544 bool quotesMayTerminate
= TRUE
)
549 char ch
= istr
.peek();
550 bool stopping
= FALSE
;
551 while (!istr
.eof() && !stopping
)
557 sprintf(buf
, "Sorry, value > 4000 chars in bib file at line %ld.", BibLine
);
558 wxLogError(buf
, "Tex2RTF Fatal Error");
575 else if (quotesMayTerminate
&& ch
== '"')
582 if (!ignoreBraces
|| (ch
!= '{' && ch
!= '}'))
594 bool ReadBib(char *filename
)
596 if (!wxFileExists(filename
))
600 wxSTD ifstream
istr(filename
, wxSTD
ios::in
);
601 if (istr
.bad()) return FALSE
;
605 OnInform("Reading .bib file...");
608 char fieldValue
[4000];
609 char recordType
[100];
611 char recordField
[100];
616 BibEatWhiteSpace(istr
);
620 sprintf(buf
, "Expected @: malformed bib file at line %ld (%s)", BibLine
, filename
);
624 BibReadWord(istr
, recordType
);
625 BibEatWhiteSpace(istr
);
627 if (ch
!= '{' && ch
!= '(')
629 sprintf(buf
, "Expected { or ( after record type: malformed .bib file at line %ld (%s)", BibLine
, filename
);
633 BibEatWhiteSpace(istr
);
634 if (StringMatch(recordType
, "string", FALSE
, TRUE
))
636 BibReadWord(istr
, recordType
);
637 BibEatWhiteSpace(istr
);
641 sprintf(buf
, "Expected = after string key: malformed .bib file at line %ld (%s)", BibLine
, filename
);
645 BibEatWhiteSpace(istr
);
647 if (ch
!= '"' && ch
!= '{')
649 sprintf(buf
, "Expected = after string key: malformed .bib file at line %ld (%s)", BibLine
, filename
);
653 BibReadValue(istr
, fieldValue
);
655 // Now put in hash table if necesary
656 if (!BibStringTable
.Get(recordType
))
657 BibStringTable
.Put(recordType
, (wxObject
*)copystring(fieldValue
));
659 // Read closing ) or }
660 BibEatWhiteSpace(istr
);
662 BibEatWhiteSpace(istr
);
666 BibReadWord(istr
, recordKey
);
668 BibEntry
*bibEntry
= new BibEntry
;
669 bibEntry
->key
= copystring(recordKey
);
670 bibEntry
->type
= copystring(recordType
);
672 bool moreRecords
= TRUE
;
673 while (moreRecords
&& !istr
.eof())
675 BibEatWhiteSpace(istr
);
677 if (ch
== '}' || ch
== ')')
683 BibEatWhiteSpace(istr
);
684 BibReadWord(istr
, recordField
);
685 BibEatWhiteSpace(istr
);
689 sprintf(buf
, "Expected = after field type: malformed .bib file at line %ld (%s)", BibLine
, filename
);
693 BibEatWhiteSpace(istr
);
695 if (ch
!= '{' && ch
!= '"')
698 BibReadWord(istr
, fieldValue
+1);
700 // If in the table of strings, replace with string from table.
701 char *s
= (char *)BibStringTable
.Get(fieldValue
);
704 strcpy(fieldValue
, s
);
708 BibReadValue(istr
, fieldValue
, TRUE
, (ch
== '"' ? TRUE
: FALSE
));
710 // Now we can add a field
711 if (StringMatch(recordField
, "author", FALSE
, TRUE
))
712 bibEntry
->author
= copystring(fieldValue
);
713 else if (StringMatch(recordField
, "key", FALSE
, TRUE
))
715 else if (StringMatch(recordField
, "annotate", FALSE
, TRUE
))
717 else if (StringMatch(recordField
, "abstract", FALSE
, TRUE
))
719 else if (StringMatch(recordField
, "edition", FALSE
, TRUE
))
721 else if (StringMatch(recordField
, "howpublished", FALSE
, TRUE
))
723 else if (StringMatch(recordField
, "note", FALSE
, TRUE
) || StringMatch(recordField
, "notes", FALSE
, TRUE
))
725 else if (StringMatch(recordField
, "series", FALSE
, TRUE
))
727 else if (StringMatch(recordField
, "type", FALSE
, TRUE
))
729 else if (StringMatch(recordField
, "keywords", FALSE
, TRUE
))
731 else if (StringMatch(recordField
, "editor", FALSE
, TRUE
) || StringMatch(recordField
, "editors", FALSE
, TRUE
))
732 bibEntry
->editor
= copystring(fieldValue
);
733 else if (StringMatch(recordField
, "title", FALSE
, TRUE
))
734 bibEntry
->title
= copystring(fieldValue
);
735 else if (StringMatch(recordField
, "booktitle", FALSE
, TRUE
))
736 bibEntry
->booktitle
= copystring(fieldValue
);
737 else if (StringMatch(recordField
, "journal", FALSE
, TRUE
))
738 bibEntry
->journal
= copystring(fieldValue
);
739 else if (StringMatch(recordField
, "volume", FALSE
, TRUE
))
740 bibEntry
->volume
= copystring(fieldValue
);
741 else if (StringMatch(recordField
, "number", FALSE
, TRUE
))
742 bibEntry
->number
= copystring(fieldValue
);
743 else if (StringMatch(recordField
, "year", FALSE
, TRUE
))
744 bibEntry
->year
= copystring(fieldValue
);
745 else if (StringMatch(recordField
, "month", FALSE
, TRUE
))
746 bibEntry
->month
= copystring(fieldValue
);
747 else if (StringMatch(recordField
, "pages", FALSE
, TRUE
))
748 bibEntry
->pages
= copystring(fieldValue
);
749 else if (StringMatch(recordField
, "publisher", FALSE
, TRUE
))
750 bibEntry
->publisher
= copystring(fieldValue
);
751 else if (StringMatch(recordField
, "address", FALSE
, TRUE
))
752 bibEntry
->address
= copystring(fieldValue
);
753 else if (StringMatch(recordField
, "institution", FALSE
, TRUE
) || StringMatch(recordField
, "school", FALSE
, TRUE
))
754 bibEntry
->institution
= copystring(fieldValue
);
755 else if (StringMatch(recordField
, "organization", FALSE
, TRUE
) || StringMatch(recordField
, "organisation", FALSE
, TRUE
))
756 bibEntry
->organization
= copystring(fieldValue
);
757 else if (StringMatch(recordField
, "comment", FALSE
, TRUE
) || StringMatch(recordField
, "comments", FALSE
, TRUE
))
758 bibEntry
->comment
= copystring(fieldValue
);
759 else if (StringMatch(recordField
, "annote", FALSE
, TRUE
))
760 bibEntry
->comment
= copystring(fieldValue
);
761 else if (StringMatch(recordField
, "chapter", FALSE
, TRUE
))
762 bibEntry
->chapter
= copystring(fieldValue
);
765 sprintf(buf
, "Unrecognised bib field type %s at line %ld (%s)", recordField
, BibLine
, filename
);
770 BibList
.Append(recordKey
, bibEntry
);
771 BibEatWhiteSpace(istr
);
777 void OutputBibItem(TexRef
*ref
, BibEntry
*bib
)
781 OnMacro(ltNUMBEREDBIBITEM
, 2, TRUE
);
782 OnArgument(ltNUMBEREDBIBITEM
, 1, TRUE
);
783 TexOutput(ref
->sectionNumber
);
784 OnArgument(ltNUMBEREDBIBITEM
, 1, FALSE
);
785 OnArgument(ltNUMBEREDBIBITEM
, 2, TRUE
);
788 OnMacro(ltBF
, 1, TRUE
);
789 OnArgument(ltBF
, 1, TRUE
);
791 TexOutput(bib
->author
);
792 OnArgument(ltBF
, 1, FALSE
);
793 OnMacro(ltBF
, 1, FALSE
);
794 if (bib
->author
&& (strlen(bib
->author
) > 0) && (bib
->author
[strlen(bib
->author
) - 1] != '.'))
801 TexOutput(bib
->year
);
806 TexOutput(bib
->month
);
809 if (bib
->year
|| bib
->month
)
812 if (StringMatch(bib
->type
, "article", FALSE
, TRUE
))
816 TexOutput(bib
->title
);
821 OnMacro(ltIT
, 1, TRUE
);
822 OnArgument(ltIT
, 1, TRUE
);
823 TexOutput(bib
->journal
);
824 OnArgument(ltIT
, 1, FALSE
);
825 OnMacro(ltIT
, 1, FALSE
);
830 OnMacro(ltBF
, 1, TRUE
);
831 OnArgument(ltBF
, 1, TRUE
);
832 TexOutput(bib
->volume
);
833 OnArgument(ltBF
, 1, FALSE
);
834 OnMacro(ltBF
, 1, FALSE
);
839 TexOutput(bib
->number
);
844 TexOutput(", pages ");
845 TexOutput(bib
->pages
);
849 else if (StringMatch(bib
->type
, "book", FALSE
, TRUE
) ||
850 StringMatch(bib
->type
, "unpublished", FALSE
, TRUE
) ||
851 StringMatch(bib
->type
, "manual", FALSE
, TRUE
) ||
852 StringMatch(bib
->type
, "phdthesis", FALSE
, TRUE
) ||
853 StringMatch(bib
->type
, "mastersthesis", FALSE
, TRUE
) ||
854 StringMatch(bib
->type
, "misc", FALSE
, TRUE
) ||
855 StringMatch(bib
->type
, "techreport", FALSE
, TRUE
) ||
856 StringMatch(bib
->type
, "booklet", FALSE
, TRUE
))
858 if (bib
->title
|| bib
->booktitle
)
860 OnMacro(ltIT
, 1, TRUE
);
861 OnArgument(ltIT
, 1, TRUE
);
862 TexOutput(bib
->title
? bib
->title
: bib
->booktitle
);
864 OnArgument(ltIT
, 1, FALSE
);
865 OnMacro(ltIT
, 1, FALSE
);
867 if (StringMatch(bib
->type
, "phdthesis", FALSE
, TRUE
))
868 TexOutput("PhD thesis. ");
869 if (StringMatch(bib
->type
, "techreport", FALSE
, TRUE
))
870 TexOutput("Technical report. ");
874 TexOutput(bib
->editor
);
877 if (bib
->institution
)
879 TexOutput(bib
->institution
);
882 if (bib
->organization
)
884 TexOutput(bib
->organization
);
889 TexOutput(bib
->publisher
);
894 TexOutput(bib
->address
);
898 else if (StringMatch(bib
->type
, "inbook", FALSE
, TRUE
) ||
899 StringMatch(bib
->type
, "inproceedings", FALSE
, TRUE
) ||
900 StringMatch(bib
->type
, "incollection", FALSE
, TRUE
) ||
901 StringMatch(bib
->type
, "conference", FALSE
, TRUE
))
905 TexOutput(bib
->title
);
909 TexOutput(", from ");
910 OnMacro(ltIT
, 1, TRUE
);
911 OnArgument(ltIT
, 1, TRUE
);
912 TexOutput(bib
->booktitle
);
914 OnArgument(ltIT
, 1, FALSE
);
915 OnMacro(ltIT
, 1, FALSE
);
920 TexOutput(bib
->editor
);
925 TexOutput(bib
->publisher
);
929 if (bib
->publisher
) TexOutput(", ");
931 TexOutput(bib
->address
);
933 if (bib
->publisher
|| bib
->address
)
939 OnMacro(ltBF
, 1, TRUE
);
940 OnArgument(ltBF
, 1, TRUE
);
941 TexOutput(bib
->volume
);
942 OnArgument(ltBF
, 1, FALSE
);
943 OnMacro(ltBF
, 1, FALSE
);
950 TexOutput(bib
->number
);
955 TexOutput(" Number ");
956 TexOutput(bib
->number
);
962 TexOutput(" Chap. "); TexOutput(bib
->chapter
);
966 if (bib
->chapter
) TexOutput(", pages ");
967 else TexOutput(" Pages ");
968 TexOutput(bib
->pages
);
972 OnArgument(ltNUMBEREDBIBITEM
, 2, FALSE
);
973 OnMacro(ltNUMBEREDBIBITEM
, 2, FALSE
);
979 ForceTopicName("bibliography");
980 FakeCurrentSection(ReferencesNameString
);
981 ForceTopicName(NULL
);
983 OnMacro(ltPAR
, 0, TRUE
);
984 OnMacro(ltPAR
, 0, FALSE
);
986 if ((convertMode
== TEX_RTF
) && !winHelp
)
988 OnMacro(ltPAR
, 0, TRUE
);
989 OnMacro(ltPAR
, 0, FALSE
);
992 wxStringListNode
*node
= CitationList
.GetFirst();
995 char *citeKey
= (char *)node
->GetData();
996 // wxNode *texNode = TexReferences.Find(citeKey);
997 TexRef
*ref
= (TexRef
*)TexReferences
.Get(citeKey
);
998 wxNode
*bibNode
= BibList
.Find(citeKey
);
1001 BibEntry
*entry
= (BibEntry
*)bibNode
->GetData();
1002 OutputBibItem(ref
, entry
);
1004 node
= node
->GetNext();
1008 static int citeCount
= 1;
1010 void ResolveBibReferences(void)
1012 if (CitationList
.GetCount() > 0)
1013 OnInform("Resolving bibliographic references...");
1017 wxStringListNode
*node
= CitationList
.GetFirst();
1021 char *citeKey
= (char *)node
->GetData();
1022 // wxNode *texNode = TexReferences.Find(citeKey);
1023 TexRef
*ref
= (TexRef
*)TexReferences
.Get(citeKey
);
1024 wxNode
*bibNode
= BibList
.Find(citeKey
);
1028 //BibEntry *entry = (BibEntry *)bibNode->GetData();
1029 if (ref
->sectionNumber
) delete[] ref
->sectionNumber
;
1030 sprintf(buf
, "[%d]", citeCount
);
1031 ref
->sectionNumber
= copystring(buf
);
1036 sprintf(buf
, "Warning: bib ref %s not resolved.", citeKey
);
1039 node
= node
->GetNext();
1043 // Remember we need to resolve this citation
1044 void AddCitation(char *citeKey
)
1046 if (!CitationList
.Member(citeKey
))
1047 CitationList
.Add(citeKey
);
1049 if (!TexReferences
.Get(citeKey
))
1051 TexReferences
.Put(citeKey
, new TexRef(citeKey
, "??", NULL
));
1055 TexRef
*FindReference(char *key
)
1057 return (TexRef
*)TexReferences
.Get(key
);
1061 * Custom macro stuff
1065 bool StringTobool(char *val
)
1067 if (strncmp(val
, "yes", 3) == 0 || strncmp(val
, "YES", 3) == 0 ||
1068 strncmp(val
, "on", 2) == 0 || strncmp(val
, "ON", 2) == 0 ||
1069 strncmp(val
, "true", 4) == 0 || strncmp(val
, "TRUE", 4) == 0 ||
1070 strncmp(val
, "ok", 2) == 0 || strncmp(val
, "OK", 2) == 0 ||
1071 strncmp(val
, "1", 1) == 0)
1077 // Define a variable value from the .ini file
1078 char *RegisterSetting(char *settingName
, char *settingValue
, bool interactive
)
1080 static char errorCode
[100];
1081 strcpy(errorCode
, "OK");
1082 if (StringMatch(settingName
, "chapterName", FALSE
, TRUE
))
1084 delete[] ChapterNameString
;
1085 ChapterNameString
= copystring(settingValue
);
1087 else if (StringMatch(settingName
, "sectionName", FALSE
, TRUE
))
1089 delete[] SectionNameString
;
1090 SectionNameString
= copystring(settingValue
);
1092 else if (StringMatch(settingName
, "subsectionName", FALSE
, TRUE
))
1094 delete[] SubsectionNameString
;
1095 SubsectionNameString
= copystring(settingValue
);
1097 else if (StringMatch(settingName
, "subsubsectionName", FALSE
, TRUE
))
1099 delete[] SubsubsectionNameString
;
1100 SubsubsectionNameString
= copystring(settingValue
);
1102 else if (StringMatch(settingName
, "indexName", FALSE
, TRUE
))
1104 delete[] IndexNameString
;
1105 IndexNameString
= copystring(settingValue
);
1107 else if (StringMatch(settingName
, "contentsName", FALSE
, TRUE
))
1109 delete[] ContentsNameString
;
1110 ContentsNameString
= copystring(settingValue
);
1112 else if (StringMatch(settingName
, "glossaryName", FALSE
, TRUE
))
1114 delete[] GlossaryNameString
;
1115 GlossaryNameString
= copystring(settingValue
);
1117 else if (StringMatch(settingName
, "referencesName", FALSE
, TRUE
))
1119 delete[] ReferencesNameString
;
1120 ReferencesNameString
= copystring(settingValue
);
1122 else if (StringMatch(settingName
, "tablesName", FALSE
, TRUE
))
1124 delete[] TablesNameString
;
1125 TablesNameString
= copystring(settingValue
);
1127 else if (StringMatch(settingName
, "figuresName", FALSE
, TRUE
))
1129 delete[] FiguresNameString
;
1130 FiguresNameString
= copystring(settingValue
);
1132 else if (StringMatch(settingName
, "tableName", FALSE
, TRUE
))
1134 delete[] TableNameString
;
1135 TableNameString
= copystring(settingValue
);
1137 else if (StringMatch(settingName
, "figureName", FALSE
, TRUE
))
1139 delete[] FigureNameString
;
1140 FigureNameString
= copystring(settingValue
);
1142 else if (StringMatch(settingName
, "abstractName", FALSE
, TRUE
))
1144 delete[] AbstractNameString
;
1145 AbstractNameString
= copystring(settingValue
);
1147 else if (StringMatch(settingName
, "chapterFontSize", FALSE
, TRUE
))
1148 StringToInt(settingValue
, &chapterFont
);
1149 else if (StringMatch(settingName
, "sectionFontSize", FALSE
, TRUE
))
1150 StringToInt(settingValue
, §ionFont
);
1151 else if (StringMatch(settingName
, "subsectionFontSize", FALSE
, TRUE
))
1152 StringToInt(settingValue
, &subsectionFont
);
1153 else if (StringMatch(settingName
, "titleFontSize", FALSE
, TRUE
))
1154 StringToInt(settingValue
, &titleFont
);
1155 else if (StringMatch(settingName
, "authorFontSize", FALSE
, TRUE
))
1156 StringToInt(settingValue
, &authorFont
);
1157 else if (StringMatch(settingName
, "ignoreInput", FALSE
, TRUE
))
1158 IgnorableInputFiles
.Add(wxFileNameFromPath(settingValue
));
1159 else if (StringMatch(settingName
, "mirrorMargins", FALSE
, TRUE
))
1160 mirrorMargins
= StringTobool(settingValue
);
1161 else if (StringMatch(settingName
, "runTwice", FALSE
, TRUE
))
1162 runTwice
= StringTobool(settingValue
);
1163 else if (StringMatch(settingName
, "isInteractive", FALSE
, TRUE
))
1164 isInteractive
= StringTobool(settingValue
);
1165 else if (StringMatch(settingName
, "headerRule", FALSE
, TRUE
))
1166 headerRule
= StringTobool(settingValue
);
1167 else if (StringMatch(settingName
, "footerRule", FALSE
, TRUE
))
1168 footerRule
= StringTobool(settingValue
);
1169 else if (StringMatch(settingName
, "combineSubSections", FALSE
, TRUE
))
1170 combineSubSections
= StringTobool(settingValue
);
1171 else if (StringMatch(settingName
, "listLabelIndent", FALSE
, TRUE
))
1172 StringToInt(settingValue
, &labelIndentTab
);
1173 else if (StringMatch(settingName
, "listItemIndent", FALSE
, TRUE
))
1174 StringToInt(settingValue
, &itemIndentTab
);
1175 else if (StringMatch(settingName
, "useUpButton", FALSE
, TRUE
))
1176 useUpButton
= StringTobool(settingValue
);
1177 else if (StringMatch(settingName
, "useHeadingStyles", FALSE
, TRUE
))
1178 useHeadingStyles
= StringTobool(settingValue
);
1179 else if (StringMatch(settingName
, "useWord", FALSE
, TRUE
))
1180 useWord
= StringTobool(settingValue
);
1181 else if (StringMatch(settingName
, "contentsDepth", FALSE
, TRUE
))
1182 StringToInt(settingValue
, &contentsDepth
);
1183 else if (StringMatch(settingName
, "generateHPJ", FALSE
, TRUE
))
1184 generateHPJ
= StringTobool(settingValue
);
1185 else if (StringMatch(settingName
, "truncateFilenames", FALSE
, TRUE
))
1186 truncateFilenames
= StringTobool(settingValue
);
1187 else if (StringMatch(settingName
, "winHelpVersion", FALSE
, TRUE
))
1188 StringToInt(settingValue
, &winHelpVersion
);
1189 else if (StringMatch(settingName
, "winHelpContents", FALSE
, TRUE
))
1190 winHelpContents
= StringTobool(settingValue
);
1191 else if (StringMatch(settingName
, "htmlIndex", FALSE
, TRUE
))
1192 htmlIndex
= StringTobool(settingValue
);
1193 else if (StringMatch(settingName
, "htmlWorkshopFiles", FALSE
, TRUE
))
1194 htmlWorkshopFiles
= StringTobool(settingValue
);
1195 else if (StringMatch(settingName
, "htmlFrameContents", FALSE
, TRUE
))
1196 htmlFrameContents
= StringTobool(settingValue
);
1197 else if (StringMatch(settingName
, "htmlStylesheet", FALSE
, TRUE
))
1199 if (htmlStylesheet
) delete[] htmlStylesheet
;
1200 htmlStylesheet
= copystring(settingValue
);
1202 else if (StringMatch(settingName
, "upperCaseNames", FALSE
, TRUE
))
1203 upperCaseNames
= StringTobool(settingValue
);
1204 else if (StringMatch(settingName
, "ignoreBadRefs", FALSE
, TRUE
))
1205 ignoreBadRefs
= StringTobool(settingValue
);
1206 else if (StringMatch(settingName
, "htmlFaceName", FALSE
, TRUE
))
1208 delete[] htmlFaceName
;
1209 htmlFaceName
= copystring(settingValue
);
1211 else if (StringMatch(settingName
, "winHelpTitle", FALSE
, TRUE
))
1214 delete[] winHelpTitle
;
1215 winHelpTitle
= copystring(settingValue
);
1217 else if (StringMatch(settingName
, "indexSubsections", FALSE
, TRUE
))
1218 indexSubsections
= StringTobool(settingValue
);
1219 else if (StringMatch(settingName
, "compatibility", FALSE
, TRUE
))
1220 compatibilityMode
= StringTobool(settingValue
);
1221 else if (StringMatch(settingName
, "defaultColumnWidth", FALSE
, TRUE
))
1223 StringToInt(settingValue
, &defaultTableColumnWidth
);
1224 defaultTableColumnWidth
= 20*defaultTableColumnWidth
;
1226 else if (StringMatch(settingName
, "bitmapMethod", FALSE
, TRUE
))
1228 if ((strcmp(settingValue
, "includepicture") != 0) && (strcmp(settingValue
, "hex") != 0) &&
1229 (strcmp(settingValue
, "import") != 0))
1232 OnError("Unknown bitmapMethod");
1233 strcpy(errorCode
, "Unknown bitmapMethod");
1237 delete[] bitmapMethod
;
1238 bitmapMethod
= copystring(settingValue
);
1241 else if (StringMatch(settingName
, "htmlBrowseButtons", FALSE
, TRUE
))
1243 if (strcmp(settingValue
, "none") == 0)
1244 htmlBrowseButtons
= HTML_BUTTONS_NONE
;
1245 else if (strcmp(settingValue
, "bitmap") == 0)
1246 htmlBrowseButtons
= HTML_BUTTONS_BITMAP
;
1247 else if (strcmp(settingValue
, "text") == 0)
1248 htmlBrowseButtons
= HTML_BUTTONS_TEXT
;
1252 OnInform("Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text.");
1253 strcpy(errorCode
, "Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text.");
1256 else if (StringMatch(settingName
, "backgroundImage", FALSE
, TRUE
))
1258 backgroundImageString
= copystring(settingValue
);
1260 else if (StringMatch(settingName
, "backgroundColour", FALSE
, TRUE
))
1262 delete[] backgroundColourString
;
1263 backgroundColourString
= copystring(settingValue
);
1265 else if (StringMatch(settingName
, "textColour", FALSE
, TRUE
))
1267 textColourString
= copystring(settingValue
);
1269 else if (StringMatch(settingName
, "linkColour", FALSE
, TRUE
))
1271 linkColourString
= copystring(settingValue
);
1273 else if (StringMatch(settingName
, "followedLinkColour", FALSE
, TRUE
))
1275 followedLinkColourString
= copystring(settingValue
);
1277 else if (StringMatch(settingName
, "conversionMode", FALSE
, TRUE
))
1279 if (StringMatch(settingValue
, "RTF", FALSE
, TRUE
))
1281 winHelp
= FALSE
; convertMode
= TEX_RTF
;
1283 else if (StringMatch(settingValue
, "WinHelp", FALSE
, TRUE
))
1285 winHelp
= TRUE
; convertMode
= TEX_RTF
;
1287 else if (StringMatch(settingValue
, "XLP", FALSE
, TRUE
) ||
1288 StringMatch(settingValue
, "wxHelp", FALSE
, TRUE
))
1290 convertMode
= TEX_XLP
;
1292 else if (StringMatch(settingValue
, "HTML", FALSE
, TRUE
))
1294 convertMode
= TEX_HTML
;
1299 OnInform("Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML.");
1300 strcpy(errorCode
, "Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML.");
1303 else if (StringMatch(settingName
, "documentFontSize", FALSE
, TRUE
))
1306 StringToInt(settingValue
, &n
);
1307 if (n
== 10 || n
== 11 || n
== 12)
1312 sprintf(buf
, "Initialisation file error: nonstandard document font size %d.", n
);
1315 strcpy(errorCode
, buf
);
1321 sprintf(buf
, "Initialisation file error: unrecognised setting %s.", settingName
);
1324 strcpy(errorCode
, buf
);
1329 bool ReadCustomMacros(char *filename
)
1331 if (!wxFileExists(filename
))
1334 wxSTD ifstream
istr(filename
, wxSTD
ios::in
);
1336 if (istr
.bad()) return FALSE
;
1338 CustomMacroList
.Clear();
1340 char macroName
[100];
1341 char macroBody
[1000];
1346 BibEatWhiteSpace(istr
);
1351 if (ch
!= '\\') // Not a macro definition, so must be NAME=VALUE
1353 char settingName
[100];
1354 settingName
[0] = ch
;
1355 BibReadWord(istr
, (settingName
+1));
1356 BibEatWhiteSpace(istr
);
1360 OnError("Expected = following name: malformed tex2rtf.ini file.");
1365 char settingValue
[200];
1366 BibEatWhiteSpace(istr
);
1367 BibReadToEOL(istr
, settingValue
);
1368 RegisterSetting(settingName
, settingValue
);
1373 BibReadWord(istr
, macroName
);
1374 BibEatWhiteSpace(istr
);
1378 OnError("Expected [ followed by number of arguments: malformed tex2rtf.ini file.");
1385 OnError("Expected ] following number of arguments: malformed tex2rtf.ini file.");
1388 BibEatWhiteSpace(istr
);
1392 OnError("Expected { followed by macro body: malformed tex2rtf.ini file.");
1395 CustomMacro
*macro
= new CustomMacro(macroName
, noArgs
, NULL
);
1396 BibReadValue(istr
, macroBody
, FALSE
, FALSE
); // Don't ignore extra braces
1397 if (strlen(macroBody
) > 0)
1398 macro
->macroBody
= copystring(macroBody
);
1400 BibEatWhiteSpace(istr
);
1401 CustomMacroList
.Append(macroName
, macro
);
1402 AddMacroDef(ltCUSTOM_MACRO
, macroName
, noArgs
);
1406 sprintf(mbuf
, "Read initialization file %s.", filename
);
1411 CustomMacro
*FindCustomMacro(char *name
)
1413 wxNode
*node
= CustomMacroList
.Find(name
);
1416 CustomMacro
*macro
= (CustomMacro
*)node
->GetData();
1422 // Display custom macros
1423 void ShowCustomMacros(void)
1425 wxNode
*node
= CustomMacroList
.GetFirst();
1428 OnInform("No custom macros loaded.\n");
1435 CustomMacro
*macro
= (CustomMacro
*)node
->GetData();
1436 sprintf(buf
, "\\%s[%d]\n {%s}", macro
->macroName
, macro
->noArgs
,
1437 macro
->macroBody
? macro
->macroBody
: "");
1439 node
= node
->GetNext();
1443 // Parse a string into several comma-separated fields
1444 char *ParseMultifieldString(char *allFields
, int *pos
)
1446 static char buffer
[300];
1448 int fieldIndex
= *pos
;
1449 int len
= strlen(allFields
);
1451 bool keepGoing
= TRUE
;
1452 while ((fieldIndex
<= len
) && keepGoing
)
1454 if (allFields
[fieldIndex
] == ' ')
1459 else if (allFields
[fieldIndex
] == ',')
1461 *pos
= fieldIndex
+ 1;
1464 else if (allFields
[fieldIndex
] == 0)
1466 *pos
= fieldIndex
+ 1;
1471 buffer
[i
] = allFields
[fieldIndex
];
1477 if (oldPos
== (*pos
))
1491 ColourTableEntry::ColourTableEntry(const char *theName
, unsigned int r
, unsigned int g
, unsigned int b
)
1493 name
= copystring(theName
);
1499 ColourTableEntry::~ColourTableEntry(void)
1504 void AddColour(const char *theName
, unsigned int r
, unsigned int g
, unsigned int b
)
1506 wxNode
*node
= ColourTable
.Find(theName
);
1509 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->GetData();
1510 if (entry
->red
== r
|| entry
->green
== g
|| entry
->blue
== b
)
1518 ColourTableEntry
*entry
= new ColourTableEntry(theName
, r
, g
, b
);
1519 ColourTable
.Append(theName
, entry
);
1522 int FindColourPosition(char *theName
)
1525 wxNode
*node
= ColourTable
.GetFirst();
1528 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->GetData();
1529 if (strcmp(theName
, entry
->name
) == 0)
1532 node
= node
->GetNext();
1537 // Converts e.g. "red" -> "#FF0000"
1538 extern void DecToHex(int, char *);
1539 bool FindColourHTMLString(char *theName
, char *buf
)
1542 wxNode
*node
= ColourTable
.GetFirst();
1545 ColourTableEntry
*entry
= (ColourTableEntry
*)node
->GetData();
1546 if (strcmp(theName
, entry
->name
) == 0)
1551 DecToHex(entry
->red
, buf2
);
1553 DecToHex(entry
->green
, buf2
);
1555 DecToHex(entry
->blue
, buf2
);
1561 node
= node
->GetNext();
1567 void InitialiseColourTable(void)
1569 // \\red0\\green0\\blue0;
1570 AddColour("black", 0,0,0);
1572 // \\red0\\green0\\blue255;\\red0\\green255\\blue255;\n");
1573 AddColour("cyan", 0,255,255);
1575 // \\red0\\green255\\blue0;
1576 AddColour("green", 0,255,0);
1578 // \\red255\\green0\\blue255;
1579 AddColour("magenta", 255,0,255);
1581 // \\red255\\green0\\blue0;
1582 AddColour("red", 255,0,0);
1584 // \\red255\\green255\\blue0;
1585 AddColour("yellow", 255,255,0);
1587 // \\red255\\green255\\blue255;}");
1588 AddColour("white", 255,255,255);
1592 * The purpose of this is to reduce the number of times wxYield is
1593 * called, since under Windows this can slow things down.
1596 void Tex2RTFYield(bool force
)
1599 static int yieldCount
= 0;
1606 if (yieldCount
== 0)
1616 // In both RTF generation and HTML generation for wxHelp version 2,
1617 // we need to associate \indexed keywords with the current filename/topics.
1619 // Hash table for lists of keywords for topics (WinHelp).
1620 wxHashTable
TopicTable(wxKEY_STRING
);
1621 void AddKeyWordForTopic(char *topic
, char *entry
, char *filename
)
1623 TexTopic
*texTopic
= (TexTopic
*)TopicTable
.Get(topic
);
1626 texTopic
= new TexTopic(filename
);
1627 texTopic
->keywords
= new wxStringList
;
1628 TopicTable
.Put(topic
, texTopic
);
1631 if (!texTopic
->keywords
->Member(entry
))
1632 texTopic
->keywords
->Add(entry
);
1635 void ClearKeyWordTable(void)
1637 TopicTable
.BeginFind();
1638 wxNode
*node
= TopicTable
.Next();
1641 TexTopic
*texTopic
= (TexTopic
*)node
->GetData();
1643 node
= TopicTable
.Next();
1650 * TexTopic structure
1653 TexTopic::TexTopic(char *f
)
1656 filename
= copystring(f
);
1659 hasChildren
= FALSE
;
1663 TexTopic::~TexTopic(void)
1671 // Convert case, according to upperCaseNames setting.
1672 char *ConvertCase(char *s
)
1674 static char buf
[256];
1675 int len
= strlen(s
);
1678 for (i
= 0; i
< len
; i
++)
1679 buf
[i
] = toupper(s
[i
]);
1681 for (i
= 0; i
< len
; i
++)
1682 buf
[i
] = tolower(s
[i
]);
1687 #if !WXWIN_COMPATIBILITY_2
1688 // if substring is TRUE, search for str1 in str2
1689 bool StringMatch(const wxChar
*str1
, const wxChar
*str2
, bool subString
,
1694 wxString
Sstr1(str1
);
1695 wxString
Sstr2(str2
);
1701 return Sstr2
.Index(Sstr1
) != (size_t)wxNOT_FOUND
;
1704 return exact
? wxString(str2
).Cmp(str1
) == 0 :
1705 wxString(str2
).CmpNoCase(str1
) == 0;