]> git.saurik.com Git - wxWidgets.git/blame_incremental - utils/tex2rtf/src/texutils.cpp
corrected a type in the constructor from two points
[wxWidgets.git] / utils / tex2rtf / src / texutils.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: texutils.cpp
3// Purpose: Miscellaneous utilities
4// Author: Julian Smart
5// Modified by:
6// Created: 7.9.93
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#ifndef WX_PRECOMP
24#include "wx/wx.h"
25#endif
26
27#include <wx/hash.h>
28
29#if wxUSE_IOSTREAMH
30#include <iostream.h>
31#include <fstream.h>
32#else
33#include <iostream>
34#include <fstream>
35#endif
36
37#include <ctype.h>
38#include "tex2any.h"
39
40wxHashTable TexReferences(wxKEY_STRING);
41wxList BibList(wxKEY_STRING);
42wxStringList CitationList;
43wxList ColourTable(wxKEY_STRING);
44wxHashTable BibStringTable(wxKEY_STRING);
45wxList CustomMacroList(wxKEY_STRING);
46TexChunk *currentSection = NULL;
47char *fakeCurrentSection = NULL;
48
49static long BibLine = 1;
50
51void OutputCurrentSection(void)
52{
53 if (fakeCurrentSection)
54 TexOutput(fakeCurrentSection);
55 else if (currentSection)
56 TraverseChildrenFromChunk(currentSection);
57}
58
59// Nasty but the way things are done now, necessary,
60// in order to output a chunk properly to a string (macros and all).
61void OutputCurrentSectionToString(char *buf)
62{
63 if (fakeCurrentSection)
64 strcpy(buf, fakeCurrentSection);
65 else
66 OutputChunkToString(currentSection, buf);
67}
68
69void OutputChunkToString(TexChunk *chunk, char *buf)
70{
71 FILE *tempfd = fopen("tmp.tmp", "w");
72 if (!tempfd)
73 return;
74
75 FILE *old1 = CurrentOutput1;
76 FILE *old2 = CurrentOutput2;
77
78 CurrentOutput1 = tempfd;
79 CurrentOutput2 = NULL;
80
81 TraverseChildrenFromChunk(chunk);
82
83 CurrentOutput1 = old1;
84 CurrentOutput2 = old2;
85
86 fclose(tempfd);
87
88 // Read from file into string
89 tempfd = fopen("tmp.tmp", "r");
90 if (!tempfd)
91 return;
92
93 buf[0] = 0;
94 int ch = -2;
95 int i = 0;
96 while (ch != EOF)
97 {
98 ch = getc(tempfd);
99 if (ch == EOF)
100 buf[i] = 0;
101 else
102 {
103 buf[i] = ch;
104 i ++;
105 }
106 }
107 fclose(tempfd);
108 wxRemoveFile("tmp.tmp");
109}
110
111// Called by Tex2Any to simulate a section
112void FakeCurrentSection(char *fakeSection, bool addToContents)
113{
114 currentSection = NULL;
115 if (fakeCurrentSection) delete[] fakeCurrentSection;
116 fakeCurrentSection = copystring(fakeSection);
117
118 if (DocumentStyle == LATEX_ARTICLE)
119 {
120 int mac = ltSECTIONHEADING;
121 if (!addToContents)
122 mac = ltSECTIONHEADINGSTAR;
123 OnMacro(mac, 0, TRUE);
124 OnMacro(mac, 0, FALSE);
125 }
126 else
127 {
128 int mac = ltCHAPTERHEADING;
129 if (!addToContents)
130 mac = ltCHAPTERHEADINGSTAR;
131 OnMacro(mac, 0, TRUE);
132 OnMacro(mac, 0, FALSE);
133 }
134 if (fakeCurrentSection) delete[] fakeCurrentSection;
135 fakeCurrentSection = NULL;
136}
137
138// Look for \label macro, use this ref name if found or
139// make up a topic name otherwise.
140static long topicCounter = 0;
141
142void ResetTopicCounter(void)
143{
144 topicCounter = 0;
145}
146
147static char *forceTopicName = NULL;
148
149void ForceTopicName(char *name)
150{
151 if (forceTopicName)
152 delete[] forceTopicName;
153 if (name)
154 forceTopicName = copystring(name);
155 else
156 forceTopicName = NULL;
157}
158
159char *FindTopicName(TexChunk *chunk)
160{
161 if (forceTopicName)
162 return forceTopicName;
163
164 char *topicName = NULL;
165 static char topicBuf[100];
166
167 if (chunk && (chunk->type == CHUNK_TYPE_MACRO) &&
168 (chunk->macroId == ltLABEL))
169 {
170 wxNode *node = chunk->children.First();
171 if (node)
172 {
173 TexChunk *child = (TexChunk *)node->Data();
174 if (child->type == CHUNK_TYPE_ARG)
175 {
176 wxNode *snode = child->children.First();
177 if (snode)
178 {
179 TexChunk *schunk = (TexChunk *)snode->Data();
180 if (schunk->type == CHUNK_TYPE_STRING)
181 topicName = schunk->value;
182 }
183 }
184 }
185 }
186 if (topicName)
187 return topicName;
188 else
189 {
190 sprintf(topicBuf, "topic%ld", topicCounter);
191 topicCounter ++;
192 return topicBuf;
193 }
194}
195
196/*
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...
200 *
201 */
202
203void StartSimulateArgument(char *data)
204{
205 strcpy(currentArgData, data);
206 haveArgData = TRUE;
207}
208
209void EndSimulateArgument(void)
210{
211 haveArgData = FALSE;
212}
213
214/*
215 * Parse and convert unit arguments to points
216 *
217 */
218
219int ParseUnitArgument(char *unitArg)
220{
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] == '\\')
227 unitArg[i] = 0;
228 len = strlen(unitArg);
229
230 if (unitArg && (len > 0) && (isdigit(unitArg[0]) || unitArg[0] == '-'))
231 {
232 sscanf(unitArg, "%f", &unitValue);
233 if (len > 1)
234 {
235 char units[3];
236 units[0] = unitArg[len-2];
237 units[1] = unitArg[len-1];
238 units[2] = 0;
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;
247 }
248 return (int)(unitValue*conversionFactor);
249 }
250 else return 0;
251}
252
253/*
254 * Strip off any extension (dot something) from end of file,
255 * IF one exists. Inserts zero into buffer.
256 *
257 */
258
259void StripExtension(char *buffer)
260{
261 int len = strlen(buffer);
262 int i = len-1;
263 while (i > 0)
264 {
265 if (buffer[i] == '.')
266 {
267 buffer[i] = 0;
268 break;
269 }
270 i --;
271 }
272}
273
274/*
275 * Latex font setting
276 *
277 */
278
279void SetFontSizes(int pointSize)
280{
281 switch (pointSize)
282 {
283 case 12:
284 {
285 normalFont = 12;
286 smallFont = 10;
287 tinyFont = 8;
288 largeFont1 = 14;
289 LargeFont2 = 16;
290 LARGEFont3 = 20;
291 hugeFont1 = 24;
292 HugeFont2 = 28;
293 HUGEFont3 = 32;
294 break;
295 }
296 case 11:
297 {
298 normalFont = 11;
299 smallFont = 9;
300 tinyFont = 7;
301 largeFont1 = 13;
302 LargeFont2 = 16;
303 LARGEFont3 = 19;
304 hugeFont1 = 22;
305 HugeFont2 = 26;
306 HUGEFont3 = 30;
307 break;
308 }
309 case 10:
310 {
311 normalFont = 10;
312 smallFont = 8;
313 tinyFont = 6;
314 largeFont1 = 12;
315 LargeFont2 = 14;
316 LARGEFont3 = 18;
317 hugeFont1 = 20;
318 HugeFont2 = 24;
319 HUGEFont3 = 28;
320 break;
321 }
322 }
323}
324
325
326/*
327 * Latex references
328 *
329 */
330
331void AddTexRef(char *name, char *file, char *sectionName,
332 int chapter, int section, int subsection, int subsubsection)
333{
334 TexRef *texRef = (TexRef *)TexReferences.Get(name);
335 if (texRef) TexReferences.Delete(name);
336
337 char buf[100];
338 buf[0] = 0;
339/*
340 if (sectionName)
341 {
342 strcat(buf, sectionName);
343 strcat(buf, " ");
344 }
345*/
346 if (chapter)
347 {
348 char buf2[10];
349 sprintf(buf2, "%d", chapter);
350 strcat(buf, buf2);
351 }
352 if (section)
353 {
354 char buf2[10];
355 if (chapter)
356 strcat(buf, ".");
357
358 sprintf(buf2, "%d", section);
359 strcat(buf, buf2);
360 }
361 if (subsection)
362 {
363 char buf2[10];
364 strcat(buf, ".");
365 sprintf(buf2, "%d", subsection);
366 strcat(buf, buf2);
367 }
368 if (subsubsection)
369 {
370 char buf2[10];
371 strcat(buf, ".");
372 sprintf(buf2, "%d", subsubsection);
373 strcat(buf, buf2);
374 }
375 char *tmp = ((strlen(buf) > 0) ? buf : (char *)NULL);
376 TexReferences.Put(name, new TexRef(name, file, tmp, sectionName));
377}
378
379void WriteTexReferences(char *filename)
380{
381 ofstream ostr(filename);
382 if (ostr.bad()) return;
383 char buf[200];
384
385 TexReferences.BeginFind();
386 wxNode *node = TexReferences.Next();
387 while (node)
388 {
389 Tex2RTFYield();
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))
395 {
396 sprintf(buf, "Warning: reference %s not resolved.", ref->refLabel);
397 OnInform(buf);
398 }
399 node = TexReferences.Next();
400 }
401}
402
403void ReadTexReferences(char *filename)
404{
405 if (!wxFileExists(filename))
406 return;
407
408 ifstream istr(filename, ios::in);
409
410 if (istr.bad()) return;
411
412 char label[100];
413 char file[400];
414 char section[100];
415 char sectionName[100];
416
417 while (!istr.eof())
418 {
419 istr >> label;
420 if (!istr.eof())
421 {
422 istr >> file;
423 istr >> sectionName;
424 char ch;
425 istr.get(ch); // Read past space
426 istr.get(ch);
427 int i = 0;
428 while (ch != '\n' && !istr.eof())
429 {
430 section[i] = ch;
431 i ++;
432 istr.get(ch);
433 }
434 section[i] = 0;
435 TexReferences.Put(label, new TexRef(label, file, section, sectionName));
436 }
437 }
438}
439
440
441/*
442 * Bibliography-handling code
443 *
444 */
445
446void BibEatWhiteSpace(istream& str)
447{
448 char ch = str.peek();
449
450 while (!str.eof() && (ch == ' ' || ch == '\t' || ch == 13 || ch == 10 || ch == EOF))
451 {
452 if (ch == 10)
453 BibLine ++;
454 str.get(ch);
455 if ((ch == EOF) || str.eof()) return;
456 ch = str.peek();
457 }
458
459 // Ignore end-of-line comments
460 if (ch == '%' || ch == ';' || ch == '#')
461 {
462 str.get(ch);
463 ch = str.peek();
464 while (ch != 10 && ch != 13 && !str.eof())
465 {
466 str.get(ch);
467 ch = str.peek();
468 }
469 BibEatWhiteSpace(str);
470 }
471}
472
473// Read word up to { or , or space
474void BibReadWord(istream& istr, char *buffer)
475{
476 int i = 0;
477 buffer[i] = 0;
478 char ch = istr.peek();
479 while (!istr.eof() && ch != ' ' && ch != '{' && ch != '(' && ch != 13 && ch != 10 && ch != '\t' &&
480 ch != ',' && ch != '=')
481 {
482 istr.get(ch);
483 buffer[i] = ch;
484 i ++;
485 ch = istr.peek();
486 }
487 buffer[i] = 0;
488}
489
490// Read string (double-quoted or not) to end quote or EOL
491void BibReadToEOL(istream& istr, char *buffer)
492{
493 int i = 0;
494 buffer[i] = 0;
495 char ch = istr.peek();
496 bool inQuotes = FALSE;
497 if (ch == '"')
498 {
499 istr.get(ch);
500 ch = istr.peek();
501 inQuotes = TRUE;
502 }
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 != '#'))))
508 {
509 istr.get(ch);
510 buffer[i] = ch;
511 i ++;
512 ch = istr.peek();
513 }
514 if (ch == '"')
515 istr.get(ch);
516 buffer[i] = 0;
517}
518
519// Read }-terminated value, taking nested braces into account.
520void BibReadValue(istream& istr, char *buffer, bool ignoreBraces = TRUE,
521 bool quotesMayTerminate = TRUE)
522{
523 int braceCount = 1;
524 int i = 0;
525 buffer[i] = 0;
526 char ch = istr.peek();
527 bool stopping = FALSE;
528 while (!istr.eof() && !stopping)
529 {
530// i ++;
531 if (i >= 2000)
532 {
533 char buf[100];
534 sprintf(buf, "Sorry, value > 2000 chars in bib file at line %ld, terminating.", BibLine);
535 wxFatalError(buf, "Tex2RTF Fatal Error");
536 }
537 istr.get(ch);
538
539 if (ch == '{')
540 braceCount ++;
541
542 if (ch == '}')
543 {
544 braceCount --;
545 if (braceCount == 0)
546 {
547 stopping = TRUE;
548 break;
549 }
550 }
551 else if (quotesMayTerminate && ch == '"')
552 {
553 stopping = TRUE;
554 break;
555 }
556 if (!stopping)
557 {
558 if (!ignoreBraces || (ch != '{' && ch != '}'))
559 {
560 buffer[i] = ch;
561 i ++;
562 }
563 }
564 if (ch == 10)
565 BibLine ++;
566 }
567 buffer[i] = 0;
568}
569
570bool ReadBib(char *filename)
571{
572 if (!wxFileExists(filename))
573 return FALSE;
574
575 char buf[300];
576 ifstream istr(filename, ios::in);
577 if (istr.bad()) return FALSE;
578
579 BibLine = 1;
580
581 OnInform("Reading .bib file...");
582
583 char ch;
584 char fieldValue[2000];
585 char recordType[100];
586 char recordKey[100];
587 char recordField[100];
588 while (!istr.eof())
589 {
590 Tex2RTFYield();
591
592 BibEatWhiteSpace(istr);
593 istr.get(ch);
594 if (ch != '@')
595 {
596 sprintf(buf, "Expected @: malformed bib file at line %ld (%s)", BibLine, filename);
597 OnError(buf);
598 return FALSE;
599 }
600 BibReadWord(istr, recordType);
601 BibEatWhiteSpace(istr);
602 istr.get(ch);
603 if (ch != '{' && ch != '(')
604 {
605 sprintf(buf, "Expected { or ( after record type: malformed .bib file at line %ld (%s)", BibLine, filename);
606 OnError(buf);
607 return FALSE;
608 }
609 BibEatWhiteSpace(istr);
610 if (StringMatch(recordType, "string", FALSE, TRUE))
611 {
612 BibReadWord(istr, recordType);
613 BibEatWhiteSpace(istr);
614 istr.get(ch);
615 if (ch != '=')
616 {
617 sprintf(buf, "Expected = after string key: malformed .bib file at line %ld (%s)", BibLine, filename);
618 OnError(buf);
619 return FALSE;
620 }
621 BibEatWhiteSpace(istr);
622 istr.get(ch);
623 if (ch != '"' && ch != '{')
624 {
625 sprintf(buf, "Expected = after string key: malformed .bib file at line %ld (%s)", BibLine, filename);
626 OnError(buf);
627 return FALSE;
628 }
629 BibReadValue(istr, fieldValue);
630
631 // Now put in hash table if necesary
632 if (!BibStringTable.Get(recordType))
633 BibStringTable.Put(recordType, (wxObject *)copystring(fieldValue));
634
635 // Read closing ) or }
636 BibEatWhiteSpace(istr);
637 istr.get(ch);
638 BibEatWhiteSpace(istr);
639 }
640 else
641 {
642 BibReadWord(istr, recordKey);
643
644 BibEntry *bibEntry = new BibEntry;
645 bibEntry->key = copystring(recordKey);
646 bibEntry->type = copystring(recordType);
647
648 bool moreRecords = TRUE;
649 while (moreRecords && !istr.eof())
650 {
651 BibEatWhiteSpace(istr);
652 istr.get(ch);
653 if (ch == '}' || ch == ')')
654 {
655 moreRecords = FALSE;
656 }
657 else if (ch == ',')
658 {
659 BibEatWhiteSpace(istr);
660 BibReadWord(istr, recordField);
661 BibEatWhiteSpace(istr);
662 istr.get(ch);
663 if (ch != '=')
664 {
665 sprintf(buf, "Expected = after field type: malformed .bib file at line %ld (%s)", BibLine, filename);
666 OnError(buf);
667 return FALSE;
668 }
669 BibEatWhiteSpace(istr);
670 istr.get(ch);
671 if (ch != '{' && ch != '"')
672 {
673 fieldValue[0] = ch;
674 BibReadWord(istr, fieldValue+1);
675
676 // If in the table of strings, replace with string from table.
677 char *s = (char *)BibStringTable.Get(fieldValue);
678 if (s)
679 {
680 strcpy(fieldValue, s);
681 }
682 }
683 else
684 BibReadValue(istr, fieldValue, TRUE, (ch == '"' ? TRUE : FALSE));
685
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))
690 {}
691 else if (StringMatch(recordField, "annotate", FALSE, TRUE))
692 {}
693 else if (StringMatch(recordField, "abstract", FALSE, TRUE))
694 {}
695 else if (StringMatch(recordField, "edition", FALSE, TRUE))
696 {}
697 else if (StringMatch(recordField, "howpublished", FALSE, TRUE))
698 {}
699 else if (StringMatch(recordField, "note", FALSE, TRUE) || StringMatch(recordField, "notes", FALSE, TRUE))
700 {}
701 else if (StringMatch(recordField, "series", FALSE, TRUE))
702 {}
703 else if (StringMatch(recordField, "type", FALSE, TRUE))
704 {}
705 else if (StringMatch(recordField, "keywords", FALSE, TRUE))
706 {}
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);
739 else
740 {
741 sprintf(buf, "Unrecognised bib field type %s at line %ld (%s)", recordField, BibLine, filename);
742 OnError(buf);
743 }
744 }
745 }
746 BibList.Append(recordKey, bibEntry);
747 BibEatWhiteSpace(istr);
748 }
749 }
750 return TRUE;
751}
752
753void OutputBibItem(TexRef *ref, BibEntry *bib)
754{
755 Tex2RTFYield();
756
757 OnMacro(ltNUMBEREDBIBITEM, 2, TRUE);
758 OnArgument(ltNUMBEREDBIBITEM, 1, TRUE);
759 TexOutput(ref->sectionNumber);
760 OnArgument(ltNUMBEREDBIBITEM, 1, FALSE);
761 OnArgument(ltNUMBEREDBIBITEM, 2, TRUE);
762
763 TexOutput(" ");
764 OnMacro(ltBF, 1, TRUE);
765 OnArgument(ltBF, 1, TRUE);
766 if (bib->author)
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] != '.'))
771 TexOutput(". ");
772 else
773 TexOutput(" ");
774
775 if (bib->year)
776 {
777 TexOutput(bib->year);
778 }
779 if (bib->month)
780 {
781 TexOutput(" (");
782 TexOutput(bib->month);
783 TexOutput(")");
784 }
785 if (bib->year || bib->month)
786 TexOutput(". ");
787
788 if (StringMatch(bib->type, "article", FALSE, TRUE))
789 {
790 if (bib->title)
791 {
792 TexOutput(bib->title);
793 TexOutput(". ");
794 }
795 if (bib->journal)
796 {
797 OnMacro(ltIT, 1, TRUE);
798 OnArgument(ltIT, 1, TRUE);
799 TexOutput(bib->journal);
800 OnArgument(ltIT, 1, FALSE);
801 OnMacro(ltIT, 1, FALSE);
802 }
803 if (bib->volume)
804 {
805 TexOutput(", ");
806 OnMacro(ltBF, 1, TRUE);
807 OnArgument(ltBF, 1, TRUE);
808 TexOutput(bib->volume);
809 OnArgument(ltBF, 1, FALSE);
810 OnMacro(ltBF, 1, FALSE);
811 }
812 if (bib->number)
813 {
814 TexOutput("(");
815 TexOutput(bib->number);
816 TexOutput(")");
817 }
818 if (bib->pages)
819 {
820 TexOutput(", pages ");
821 TexOutput(bib->pages);
822 }
823 TexOutput(".");
824 }
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))
833 {
834 if (bib->title || bib->booktitle)
835 {
836 OnMacro(ltIT, 1, TRUE);
837 OnArgument(ltIT, 1, TRUE);
838 TexOutput(bib->title ? bib->title : bib->booktitle);
839 TexOutput(". ");
840 OnArgument(ltIT, 1, FALSE);
841 OnMacro(ltIT, 1, FALSE);
842 }
843 if (StringMatch(bib->type, "phdthesis", FALSE, TRUE))
844 TexOutput("PhD thesis. ");
845 if (StringMatch(bib->type, "techreport", FALSE, TRUE))
846 TexOutput("Technical report. ");
847 if (bib->editor)
848 {
849 TexOutput("Ed. ");
850 TexOutput(bib->editor);
851 TexOutput(". ");
852 }
853 if (bib->institution)
854 {
855 TexOutput(bib->institution);
856 TexOutput(". ");
857 }
858 if (bib->organization)
859 {
860 TexOutput(bib->organization);
861 TexOutput(". ");
862 }
863 if (bib->publisher)
864 {
865 TexOutput(bib->publisher);
866 TexOutput(". ");
867 }
868 if (bib->address)
869 {
870 TexOutput(bib->address);
871 TexOutput(". ");
872 }
873 }
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))
878 {
879 if (bib->title)
880 {
881 TexOutput(bib->title);
882 }
883 if (bib->booktitle)
884 {
885 TexOutput(", from ");
886 OnMacro(ltIT, 1, TRUE);
887 OnArgument(ltIT, 1, TRUE);
888 TexOutput(bib->booktitle);
889 TexOutput(".");
890 OnArgument(ltIT, 1, FALSE);
891 OnMacro(ltIT, 1, FALSE);
892 }
893 if (bib->editor)
894 {
895 TexOutput(", ed. ");
896 TexOutput(bib->editor);
897 }
898 if (bib->publisher)
899 {
900 TexOutput(" ");
901 TexOutput(bib->publisher);
902 }
903 if (bib->address)
904 {
905 if (bib->publisher) TexOutput(", ");
906 else TexOutput(" ");
907 TexOutput(bib->address);
908 }
909 if (bib->publisher || bib->address)
910 TexOutput(".");
911
912 if (bib->volume)
913 {
914 TexOutput(" ");
915 OnMacro(ltBF, 1, TRUE);
916 OnArgument(ltBF, 1, TRUE);
917 TexOutput(bib->volume);
918 OnArgument(ltBF, 1, FALSE);
919 OnMacro(ltBF, 1, FALSE);
920 }
921 if (bib->number)
922 {
923 if (bib->volume)
924 {
925 TexOutput("(");
926 TexOutput(bib->number);
927 TexOutput(").");
928 }
929 else
930 {
931 TexOutput(" Number ");
932 TexOutput(bib->number);
933 TexOutput(".");
934 }
935 }
936 if (bib->chapter)
937 {
938 TexOutput(" Chap. "); TexOutput(bib->chapter);
939 }
940 if (bib->pages)
941 {
942 if (bib->chapter) TexOutput(", pages ");
943 else TexOutput(" Pages ");
944 TexOutput(bib->pages);
945 TexOutput(".");
946 }
947 }
948 OnArgument(ltNUMBEREDBIBITEM, 2, FALSE);
949 OnMacro(ltNUMBEREDBIBITEM, 2, FALSE);
950}
951
952void OutputBib(void)
953{
954 // Write the heading
955 ForceTopicName("bibliography");
956 FakeCurrentSection(ReferencesNameString);
957 ForceTopicName(NULL);
958
959 OnMacro(ltPAR, 0, TRUE);
960 OnMacro(ltPAR, 0, FALSE);
961
962 if ((convertMode == TEX_RTF) && !winHelp)
963 {
964 OnMacro(ltPAR, 0, TRUE);
965 OnMacro(ltPAR, 0, FALSE);
966 }
967
968 wxNode *node = CitationList.First();
969 while (node)
970 {
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);
975 if (bibNode && ref)
976 {
977 BibEntry *entry = (BibEntry *)bibNode->Data();
978 OutputBibItem(ref, entry);
979 }
980 node = node->Next();
981 }
982}
983
984static int citeCount = 1;
985
986void ResolveBibReferences(void)
987{
988 if (CitationList.Number() > 0)
989 OnInform("Resolving bibliographic references...");
990
991 citeCount = 1;
992 char buf[200];
993 wxNode *node = CitationList.First();
994 while (node)
995 {
996 Tex2RTFYield();
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);
1001 if (bibNode && ref)
1002 {
1003 // Unused Variable
1004 //BibEntry *entry = (BibEntry *)bibNode->Data();
1005 if (ref->sectionNumber) delete[] ref->sectionNumber;
1006 sprintf(buf, "[%d]", citeCount);
1007 ref->sectionNumber = copystring(buf);
1008 citeCount ++;
1009 }
1010 else
1011 {
1012 sprintf(buf, "Warning: bib ref %s not resolved.", citeKey);
1013 OnInform(buf);
1014 }
1015 node = node->Next();
1016 }
1017}
1018
1019// Remember we need to resolve this citation
1020void AddCitation(char *citeKey)
1021{
1022 if (!CitationList.Member(citeKey))
1023 CitationList.Add(citeKey);
1024
1025 if (!TexReferences.Get(citeKey))
1026 {
1027 TexReferences.Put(citeKey, new TexRef(citeKey, "??", NULL));
1028 }
1029}
1030
1031TexRef *FindReference(char *key)
1032{
1033 return (TexRef *)TexReferences.Get(key);
1034}
1035
1036/*
1037 * Custom macro stuff
1038 *
1039 */
1040
1041bool StringTobool(char *val)
1042{
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)
1048 return TRUE;
1049 else
1050 return FALSE;
1051}
1052
1053// Define a variable value from the .ini file
1054char *RegisterSetting(char *settingName, char *settingValue, bool interactive)
1055{
1056 static char errorCode[100];
1057 strcpy(errorCode, "OK");
1058 if (StringMatch(settingName, "chapterName", FALSE, TRUE))
1059 {
1060 delete[] ChapterNameString;
1061 ChapterNameString = copystring(settingValue);
1062 }
1063 else if (StringMatch(settingName, "sectionName", FALSE, TRUE))
1064 {
1065 delete[] SectionNameString;
1066 SectionNameString = copystring(settingValue);
1067 }
1068 else if (StringMatch(settingName, "subsectionName", FALSE, TRUE))
1069 {
1070 delete[] SubsectionNameString;
1071 SubsectionNameString = copystring(settingValue);
1072 }
1073 else if (StringMatch(settingName, "subsubsectionName", FALSE, TRUE))
1074 {
1075 delete[] SubsubsectionNameString;
1076 SubsubsectionNameString = copystring(settingValue);
1077 }
1078 else if (StringMatch(settingName, "indexName", FALSE, TRUE))
1079 {
1080 delete[] IndexNameString;
1081 IndexNameString = copystring(settingValue);
1082 }
1083 else if (StringMatch(settingName, "contentsName", FALSE, TRUE))
1084 {
1085 delete[] ContentsNameString;
1086 ContentsNameString = copystring(settingValue);
1087 }
1088 else if (StringMatch(settingName, "glossaryName", FALSE, TRUE))
1089 {
1090 delete[] GlossaryNameString;
1091 GlossaryNameString = copystring(settingValue);
1092 }
1093 else if (StringMatch(settingName, "referencesName", FALSE, TRUE))
1094 {
1095 delete[] ReferencesNameString;
1096 ReferencesNameString = copystring(settingValue);
1097 }
1098 else if (StringMatch(settingName, "tablesName", FALSE, TRUE))
1099 {
1100 delete[] TablesNameString;
1101 TablesNameString = copystring(settingValue);
1102 }
1103 else if (StringMatch(settingName, "figuresName", FALSE, TRUE))
1104 {
1105 delete[] FiguresNameString;
1106 FiguresNameString = copystring(settingValue);
1107 }
1108 else if (StringMatch(settingName, "tableName", FALSE, TRUE))
1109 {
1110 delete[] TableNameString;
1111 TableNameString = copystring(settingValue);
1112 }
1113 else if (StringMatch(settingName, "figureName", FALSE, TRUE))
1114 {
1115 delete[] FigureNameString;
1116 FigureNameString = copystring(settingValue);
1117 }
1118 else if (StringMatch(settingName, "abstractName", FALSE, TRUE))
1119 {
1120 delete[] AbstractNameString;
1121 AbstractNameString = copystring(settingValue);
1122 }
1123 else if (StringMatch(settingName, "chapterFontSize", FALSE, TRUE))
1124 StringToInt(settingValue, &chapterFont);
1125 else if (StringMatch(settingName, "sectionFontSize", FALSE, TRUE))
1126 StringToInt(settingValue, &sectionFont);
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, "htmlFrameContents", FALSE, TRUE))
1170 htmlFrameContents = StringTobool(settingValue);
1171 else if (StringMatch(settingName, "upperCaseNames", FALSE, TRUE))
1172 upperCaseNames = StringTobool(settingValue);
1173 else if (StringMatch(settingName, "winHelpTitle", FALSE, TRUE))
1174 {
1175 if (winHelpTitle)
1176 delete[] winHelpTitle;
1177 winHelpTitle = copystring(settingValue);
1178 }
1179 else if (StringMatch(settingName, "indexSubsections", FALSE, TRUE))
1180 indexSubsections = StringTobool(settingValue);
1181 else if (StringMatch(settingName, "compatibility", FALSE, TRUE))
1182 compatibilityMode = StringTobool(settingValue);
1183 else if (StringMatch(settingName, "defaultColumnWidth", FALSE, TRUE))
1184 {
1185 StringToInt(settingValue, &defaultTableColumnWidth);
1186 defaultTableColumnWidth = 20*defaultTableColumnWidth;
1187 }
1188 else if (StringMatch(settingName, "bitmapMethod", FALSE, TRUE))
1189 {
1190 if ((strcmp(settingValue, "includepicture") != 0) && (strcmp(settingValue, "hex") != 0) &&
1191 (strcmp(settingValue, "import") != 0))
1192 {
1193 if (interactive)
1194 OnError("Unknown bitmapMethod");
1195 strcpy(errorCode, "Unknown bitmapMethod");
1196 }
1197 else
1198 {
1199 delete[] bitmapMethod;
1200 bitmapMethod = copystring(settingValue);
1201 }
1202 }
1203 else if (StringMatch(settingName, "htmlBrowseButtons", FALSE, TRUE))
1204 {
1205 if (strcmp(settingValue, "none") == 0)
1206 htmlBrowseButtons = HTML_BUTTONS_NONE;
1207 else if (strcmp(settingValue, "bitmap") == 0)
1208 htmlBrowseButtons = HTML_BUTTONS_BITMAP;
1209 else if (strcmp(settingValue, "text") == 0)
1210 htmlBrowseButtons = HTML_BUTTONS_TEXT;
1211 else
1212 {
1213 if (interactive)
1214 OnInform("Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text.");
1215 strcpy(errorCode, "Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text.");
1216 }
1217 }
1218 else if (StringMatch(settingName, "backgroundImage", FALSE, TRUE))
1219 {
1220 backgroundImageString = copystring(settingValue);
1221 }
1222 else if (StringMatch(settingName, "backgroundColour", FALSE, TRUE))
1223 {
1224 delete[] backgroundColourString;
1225 backgroundColourString = copystring(settingValue);
1226 }
1227 else if (StringMatch(settingName, "textColour", FALSE, TRUE))
1228 {
1229 textColourString = copystring(settingValue);
1230 }
1231 else if (StringMatch(settingName, "linkColour", FALSE, TRUE))
1232 {
1233 linkColourString = copystring(settingValue);
1234 }
1235 else if (StringMatch(settingName, "followedLinkColour", FALSE, TRUE))
1236 {
1237 followedLinkColourString = copystring(settingValue);
1238 }
1239 else if (StringMatch(settingName, "conversionMode", FALSE, TRUE))
1240 {
1241 if (StringMatch(settingValue, "RTF", FALSE, TRUE))
1242 {
1243 winHelp = FALSE; convertMode = TEX_RTF;
1244 }
1245 else if (StringMatch(settingValue, "WinHelp", FALSE, TRUE))
1246 {
1247 winHelp = TRUE; convertMode = TEX_RTF;
1248 }
1249 else if (StringMatch(settingValue, "XLP", FALSE, TRUE) ||
1250 StringMatch(settingValue, "wxHelp", FALSE, TRUE))
1251 {
1252 convertMode = TEX_XLP;
1253 }
1254 else if (StringMatch(settingValue, "HTML", FALSE, TRUE))
1255 {
1256 convertMode = TEX_HTML;
1257 }
1258 else
1259 {
1260 if (interactive)
1261 OnInform("Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML.");
1262 strcpy(errorCode, "Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML.");
1263 }
1264 }
1265 else if (StringMatch(settingName, "documentFontSize", FALSE, TRUE))
1266 {
1267 int n;
1268 StringToInt(settingValue, &n);
1269 if (n == 10 || n == 11 || n == 12)
1270 SetFontSizes(n);
1271 else
1272 {
1273 char buf[200];
1274 sprintf(buf, "Initialisation file error: nonstandard document font size %d.", n);
1275 if (interactive)
1276 OnInform(buf);
1277 strcpy(errorCode, buf);
1278 }
1279 }
1280 else
1281 {
1282 char buf[200];
1283 sprintf(buf, "Initialisation file error: unrecognised setting %s.", settingName);
1284 if (interactive)
1285 OnInform(buf);
1286 strcpy(errorCode, buf);
1287 }
1288 return errorCode;
1289}
1290
1291bool ReadCustomMacros(char *filename)
1292{
1293 if (!wxFileExists(filename))
1294 return FALSE;
1295
1296 ifstream istr(filename, ios::in);
1297
1298 if (istr.bad()) return FALSE;
1299
1300 CustomMacroList.Clear();
1301 char ch;
1302 char macroName[100];
1303 char macroBody[1000];
1304 int noArgs;
1305
1306 while (!istr.eof())
1307 {
1308 BibEatWhiteSpace(istr);
1309 istr.get(ch);
1310 if (istr.eof())
1311 break;
1312
1313 if (ch != '\\') // Not a macro definition, so must be NAME=VALUE
1314 {
1315 char settingName[100];
1316 settingName[0] = ch;
1317 BibReadWord(istr, (settingName+1));
1318 BibEatWhiteSpace(istr);
1319 istr.get(ch);
1320 if (ch != '=')
1321 {
1322 OnError("Expected = following name: malformed tex2rtf.ini file.");
1323 return FALSE;
1324 }
1325 else
1326 {
1327 char settingValue[200];
1328 BibEatWhiteSpace(istr);
1329 BibReadToEOL(istr, settingValue);
1330 RegisterSetting(settingName, settingValue);
1331 }
1332 }
1333 else
1334 {
1335 BibReadWord(istr, macroName);
1336 BibEatWhiteSpace(istr);
1337 istr.get(ch);
1338 if (ch != '[')
1339 {
1340 OnError("Expected [ followed by number of arguments: malformed tex2rtf.ini file.");
1341 return FALSE;
1342 }
1343 istr >> noArgs;
1344 istr.get(ch);
1345 if (ch != ']')
1346 {
1347 OnError("Expected ] following number of arguments: malformed tex2rtf.ini file.");
1348 return FALSE;
1349 }
1350 BibEatWhiteSpace(istr);
1351 istr.get(ch);
1352 if (ch != '{')
1353 {
1354 OnError("Expected { followed by macro body: malformed tex2rtf.ini file.");
1355 return FALSE;
1356 }
1357 CustomMacro *macro = new CustomMacro(macroName, noArgs, NULL);
1358 BibReadValue(istr, macroBody, FALSE, FALSE); // Don't ignore extra braces
1359 if (strlen(macroBody) > 0)
1360 macro->macroBody = copystring(macroBody);
1361
1362 BibEatWhiteSpace(istr);
1363 CustomMacroList.Append(macroName, macro);
1364 AddMacroDef(ltCUSTOM_MACRO, macroName, noArgs);
1365 }
1366 }
1367 char mbuf[200];
1368 sprintf(mbuf, "Read initialization file %s.", filename);
1369 OnInform(mbuf);
1370 return TRUE;
1371}
1372
1373CustomMacro *FindCustomMacro(char *name)
1374{
1375 wxNode *node = CustomMacroList.Find(name);
1376 if (node)
1377 {
1378 CustomMacro *macro = (CustomMacro *)node->Data();
1379 return macro;
1380 }
1381 return NULL;
1382}
1383
1384// Display custom macros
1385void ShowCustomMacros(void)
1386{
1387 wxNode *node = CustomMacroList.First();
1388 if (!node)
1389 {
1390 OnInform("No custom macros loaded.\n");
1391 return;
1392 }
1393
1394 char buf[400];
1395 while (node)
1396 {
1397 CustomMacro *macro = (CustomMacro *)node->Data();
1398 sprintf(buf, "\\%s[%d]\n {%s}", macro->macroName, macro->noArgs,
1399 macro->macroBody ? macro->macroBody : "");
1400 OnInform(buf);
1401 node = node->Next();
1402 }
1403}
1404
1405// Parse a string into several comma-separated fields
1406char *ParseMultifieldString(char *allFields, int *pos)
1407{
1408 static char buffer[300];
1409 int i = 0;
1410 int fieldIndex = *pos;
1411 int len = strlen(allFields);
1412 int oldPos = *pos;
1413 bool keepGoing = TRUE;
1414 while ((fieldIndex <= len) && keepGoing)
1415 {
1416 if (allFields[fieldIndex] == ' ')
1417 {
1418 // Skip
1419 fieldIndex ++;
1420 }
1421 else if (allFields[fieldIndex] == ',')
1422 {
1423 *pos = fieldIndex + 1;
1424 keepGoing = FALSE;
1425 }
1426 else if (allFields[fieldIndex] == 0)
1427 {
1428 *pos = fieldIndex + 1;
1429 keepGoing = FALSE;
1430 }
1431 else
1432 {
1433 buffer[i] = allFields[fieldIndex];
1434 fieldIndex ++;
1435 i++;
1436 }
1437 }
1438 buffer[i] = 0;
1439 if (oldPos == (*pos))
1440 *pos = len + 1;
1441
1442 if (i == 0)
1443 return NULL;
1444 else
1445 return buffer;
1446}
1447
1448/*
1449 * Colour tables
1450 *
1451 */
1452
1453ColourTableEntry::ColourTableEntry(char *theName, unsigned int r, unsigned int g, unsigned int b)
1454{
1455 name = copystring(theName);
1456 red = r;
1457 green = g;
1458 blue = b;
1459}
1460
1461ColourTableEntry::~ColourTableEntry(void)
1462{
1463 delete[] name;
1464}
1465
1466void AddColour(char *theName, unsigned int r, unsigned int g, unsigned int b)
1467{
1468 wxNode *node = ColourTable.Find(theName);
1469 if (node)
1470 {
1471 ColourTableEntry *entry = (ColourTableEntry *)node->Data();
1472 if (entry->red == r || entry->green == g || entry->blue == b)
1473 return;
1474 else
1475 {
1476 delete entry;
1477 delete node;
1478 }
1479 }
1480 ColourTableEntry *entry = new ColourTableEntry(theName, r, g, b);
1481 ColourTable.Append(theName, entry);
1482}
1483
1484int FindColourPosition(char *theName)
1485{
1486 int i = 0;
1487 wxNode *node = ColourTable.First();
1488 while (node)
1489 {
1490 ColourTableEntry *entry = (ColourTableEntry *)node->Data();
1491 if (strcmp(theName, entry->name) == 0)
1492 return i;
1493 i ++;
1494 node = node->Next();
1495 }
1496 return -1;
1497}
1498
1499// Converts e.g. "red" -> "#FF0000"
1500extern void DecToHex(int, char *);
1501bool FindColourHTMLString(char *theName, char *buf)
1502{
1503 int i = 0;
1504 wxNode *node = ColourTable.First();
1505 while (node)
1506 {
1507 ColourTableEntry *entry = (ColourTableEntry *)node->Data();
1508 if (strcmp(theName, entry->name) == 0)
1509 {
1510 strcpy(buf, "#");
1511
1512 char buf2[3];
1513 DecToHex(entry->red, buf2);
1514 strcat(buf, buf2);
1515 DecToHex(entry->green, buf2);
1516 strcat(buf, buf2);
1517 DecToHex(entry->blue, buf2);
1518 strcat(buf, buf2);
1519
1520 return TRUE;
1521 }
1522 i ++;
1523 node = node->Next();
1524 }
1525 return FALSE;
1526}
1527
1528
1529void InitialiseColourTable(void)
1530{
1531 // \\red0\\green0\\blue0;
1532 AddColour("black", 0,0,0);
1533
1534 // \\red0\\green0\\blue255;\\red0\\green255\\blue255;\n");
1535 AddColour("cyan", 0,255,255);
1536
1537 // \\red0\\green255\\blue0;
1538 AddColour("green", 0,255,0);
1539
1540 // \\red255\\green0\\blue255;
1541 AddColour("magenta", 255,0,255);
1542
1543 // \\red255\\green0\\blue0;
1544 AddColour("red", 255,0,0);
1545
1546 // \\red255\\green255\\blue0;
1547 AddColour("yellow", 255,255,0);
1548
1549 // \\red255\\green255\\blue255;}");
1550 AddColour("white", 255,255,255);
1551}
1552
1553/*
1554 * The purpose of this is to reduce the number of times wxYield is
1555 * called, since under Windows this can slow things down.
1556 */
1557
1558static int yieldCount = 0;
1559
1560void Tex2RTFYield(bool force)
1561{
1562#ifdef __WXMSW__
1563 if (isSync)
1564 return;
1565
1566 if (force)
1567 yieldCount = 0;
1568 if (yieldCount == 0)
1569 {
1570 wxYield();
1571 yieldCount = 10;
1572 }
1573 yieldCount --;
1574#endif
1575}
1576
1577// In both RTF generation and HTML generation for wxHelp version 2,
1578// we need to associate \indexed keywords with the current filename/topics.
1579
1580// Hash table for lists of keywords for topics (WinHelp).
1581wxHashTable TopicTable(wxKEY_STRING);
1582void AddKeyWordForTopic(char *topic, char *entry, char *filename)
1583{
1584 TexTopic *texTopic = (TexTopic *)TopicTable.Get(topic);
1585 if (!texTopic)
1586 {
1587 texTopic = new TexTopic(filename);
1588 texTopic->keywords = new wxStringList;
1589 TopicTable.Put(topic, texTopic);
1590 }
1591
1592 if (!texTopic->keywords->Member(entry))
1593 texTopic->keywords->Add(entry);
1594}
1595
1596void ClearKeyWordTable(void)
1597{
1598 TopicTable.BeginFind();
1599 wxNode *node = TopicTable.Next();
1600 while (node)
1601 {
1602 TexTopic *texTopic = (TexTopic *)node->Data();
1603 delete texTopic;
1604 node = TopicTable.Next();
1605 }
1606 TopicTable.Clear();
1607}
1608
1609
1610/*
1611 * TexTopic structure
1612 */
1613
1614TexTopic::TexTopic(char *f)
1615{
1616 if (f)
1617 filename = copystring(f);
1618 else
1619 filename = NULL;
1620 hasChildren = FALSE;
1621 keywords = NULL;
1622}
1623
1624TexTopic::~TexTopic(void)
1625{
1626 if (keywords)
1627 delete keywords;
1628 if (filename)
1629 delete[] filename;
1630}
1631
1632// Convert case, according to upperCaseNames setting.
1633char *ConvertCase(char *s)
1634{
1635 static char buf[256];
1636 int len = strlen(s);
1637 int i;
1638 if (upperCaseNames)
1639 for (i = 0; i < len; i ++)
1640 buf[i] = wxToUpper(s[i]);
1641 else
1642 for (i = 0; i < len; i ++)
1643 buf[i] = wxToLower(s[i]);
1644 buf[i] = 0;
1645 return buf;
1646}