]> git.saurik.com Git - wxWidgets.git/blame - utils/tex2rtf/src/texutils.cpp
Fixed silly error (what was Bool = int is now bool = 1/0)
[wxWidgets.git] / utils / tex2rtf / src / texutils.cpp
CommitLineData
9a29912f
JS
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{
eb7aa89b
UU
405#if !wxUSE_IOSTREAMH && __WXMSW__
406 ifstream istr(filename, ios::in);
407#else
9a29912f 408 ifstream istr(filename, ios::nocreate | ios::in);
eb7aa89b 409#endif
9a29912f
JS
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 char buf[300];
eb7aa89b
UU
573#if !wxUSE_IOSTREAMH && __WXMSW__
574 ifstream istr(filename, ios::in);
575#else
9a29912f 576 ifstream istr(filename, ios::nocreate | ios::in);
eb7aa89b 577#endif
9a29912f
JS
578 if (istr.bad()) return FALSE;
579
580 BibLine = 1;
581
582 OnInform("Reading .bib file...");
583
584 char ch;
585 char fieldValue[2000];
586 char recordType[100];
587 char recordKey[100];
588 char recordField[100];
589 while (!istr.eof())
590 {
591 Tex2RTFYield();
592
593 BibEatWhiteSpace(istr);
594 istr.get(ch);
595 if (ch != '@')
596 {
597 sprintf(buf, "Expected @: malformed bib file at line %ld (%s)", BibLine, filename);
598 OnError(buf);
599 return FALSE;
600 }
601 BibReadWord(istr, recordType);
602 BibEatWhiteSpace(istr);
603 istr.get(ch);
604 if (ch != '{' && ch != '(')
605 {
606 sprintf(buf, "Expected { or ( after record type: malformed .bib file at line %ld (%s)", BibLine, filename);
607 OnError(buf);
608 return FALSE;
609 }
610 BibEatWhiteSpace(istr);
611 if (StringMatch(recordType, "string", FALSE, TRUE))
612 {
613 BibReadWord(istr, recordType);
614 BibEatWhiteSpace(istr);
615 istr.get(ch);
616 if (ch != '=')
617 {
618 sprintf(buf, "Expected = after string key: malformed .bib file at line %ld (%s)", BibLine, filename);
619 OnError(buf);
620 return FALSE;
621 }
622 BibEatWhiteSpace(istr);
623 istr.get(ch);
624 if (ch != '"' && ch != '{')
625 {
626 sprintf(buf, "Expected = after string key: malformed .bib file at line %ld (%s)", BibLine, filename);
627 OnError(buf);
628 return FALSE;
629 }
630 BibReadValue(istr, fieldValue);
631
632 // Now put in hash table if necesary
633 if (!BibStringTable.Get(recordType))
634 BibStringTable.Put(recordType, (wxObject *)copystring(fieldValue));
635
636 // Read closing ) or }
637 BibEatWhiteSpace(istr);
638 istr.get(ch);
639 BibEatWhiteSpace(istr);
640 }
641 else
642 {
643 BibReadWord(istr, recordKey);
644
645 BibEntry *bibEntry = new BibEntry;
646 bibEntry->key = copystring(recordKey);
647 bibEntry->type = copystring(recordType);
648
649 bool moreRecords = TRUE;
650 while (moreRecords && !istr.eof())
651 {
652 BibEatWhiteSpace(istr);
653 istr.get(ch);
654 if (ch == '}' || ch == ')')
655 {
656 moreRecords = FALSE;
657 }
658 else if (ch == ',')
659 {
660 BibEatWhiteSpace(istr);
661 BibReadWord(istr, recordField);
662 BibEatWhiteSpace(istr);
663 istr.get(ch);
664 if (ch != '=')
665 {
666 sprintf(buf, "Expected = after field type: malformed .bib file at line %ld (%s)", BibLine, filename);
667 OnError(buf);
668 return FALSE;
669 }
670 BibEatWhiteSpace(istr);
671 istr.get(ch);
672 if (ch != '{' && ch != '"')
673 {
674 fieldValue[0] = ch;
675 BibReadWord(istr, fieldValue+1);
676
677 // If in the table of strings, replace with string from table.
678 char *s = (char *)BibStringTable.Get(fieldValue);
679 if (s)
680 {
681 strcpy(fieldValue, s);
682 }
683 }
684 else
685 BibReadValue(istr, fieldValue, TRUE, (ch == '"' ? TRUE : FALSE));
686
687 // Now we can add a field
688 if (StringMatch(recordField, "author", FALSE, TRUE))
689 bibEntry->author = copystring(fieldValue);
690 else if (StringMatch(recordField, "key", FALSE, TRUE))
691 {}
692 else if (StringMatch(recordField, "annotate", FALSE, TRUE))
693 {}
694 else if (StringMatch(recordField, "abstract", FALSE, TRUE))
695 {}
696 else if (StringMatch(recordField, "edition", FALSE, TRUE))
697 {}
698 else if (StringMatch(recordField, "howpublished", FALSE, TRUE))
699 {}
700 else if (StringMatch(recordField, "note", FALSE, TRUE) || StringMatch(recordField, "notes", FALSE, TRUE))
701 {}
702 else if (StringMatch(recordField, "series", FALSE, TRUE))
703 {}
704 else if (StringMatch(recordField, "type", FALSE, TRUE))
705 {}
706 else if (StringMatch(recordField, "keywords", FALSE, TRUE))
707 {}
708 else if (StringMatch(recordField, "editor", FALSE, TRUE) || StringMatch(recordField, "editors", FALSE, TRUE))
709 bibEntry->editor= copystring(fieldValue);
710 else if (StringMatch(recordField, "title", FALSE, TRUE))
711 bibEntry->title= copystring(fieldValue);
712 else if (StringMatch(recordField, "booktitle", FALSE, TRUE))
713 bibEntry->booktitle= copystring(fieldValue);
714 else if (StringMatch(recordField, "journal", FALSE, TRUE))
715 bibEntry->journal= copystring(fieldValue);
716 else if (StringMatch(recordField, "volume", FALSE, TRUE))
717 bibEntry->volume= copystring(fieldValue);
718 else if (StringMatch(recordField, "number", FALSE, TRUE))
719 bibEntry->number= copystring(fieldValue);
720 else if (StringMatch(recordField, "year", FALSE, TRUE))
721 bibEntry->year= copystring(fieldValue);
722 else if (StringMatch(recordField, "month", FALSE, TRUE))
723 bibEntry->month= copystring(fieldValue);
724 else if (StringMatch(recordField, "pages", FALSE, TRUE))
725 bibEntry->pages= copystring(fieldValue);
726 else if (StringMatch(recordField, "publisher", FALSE, TRUE))
727 bibEntry->publisher= copystring(fieldValue);
728 else if (StringMatch(recordField, "address", FALSE, TRUE))
729 bibEntry->address= copystring(fieldValue);
730 else if (StringMatch(recordField, "institution", FALSE, TRUE) || StringMatch(recordField, "school", FALSE, TRUE))
731 bibEntry->institution= copystring(fieldValue);
732 else if (StringMatch(recordField, "organization", FALSE, TRUE) || StringMatch(recordField, "organisation", FALSE, TRUE))
733 bibEntry->organization= copystring(fieldValue);
734 else if (StringMatch(recordField, "comment", FALSE, TRUE) || StringMatch(recordField, "comments", FALSE, TRUE))
735 bibEntry->comment= copystring(fieldValue);
736 else if (StringMatch(recordField, "annote", FALSE, TRUE))
737 bibEntry->comment= copystring(fieldValue);
738 else if (StringMatch(recordField, "chapter", FALSE, TRUE))
739 bibEntry->chapter= copystring(fieldValue);
740 else
741 {
742 sprintf(buf, "Unrecognised bib field type %s at line %ld (%s)", recordField, BibLine, filename);
743 OnError(buf);
744 }
745 }
746 }
747 BibList.Append(recordKey, bibEntry);
748 BibEatWhiteSpace(istr);
749 }
750 }
751 return TRUE;
752}
753
754void OutputBibItem(TexRef *ref, BibEntry *bib)
755{
756 Tex2RTFYield();
757
758 OnMacro(ltNUMBEREDBIBITEM, 2, TRUE);
759 OnArgument(ltNUMBEREDBIBITEM, 1, TRUE);
760 TexOutput(ref->sectionNumber);
761 OnArgument(ltNUMBEREDBIBITEM, 1, FALSE);
762 OnArgument(ltNUMBEREDBIBITEM, 2, TRUE);
763
764 TexOutput(" ");
765 OnMacro(ltBF, 1, TRUE);
766 OnArgument(ltBF, 1, TRUE);
767 if (bib->author)
768 TexOutput(bib->author);
769 OnArgument(ltBF, 1, FALSE);
770 OnMacro(ltBF, 1, FALSE);
771 if (bib->author && (strlen(bib->author) > 0) && (bib->author[strlen(bib->author) - 1] != '.'))
772 TexOutput(". ");
773 else
774 TexOutput(" ");
775
776 if (bib->year)
777 {
778 TexOutput(bib->year);
779 }
780 if (bib->month)
781 {
782 TexOutput(" (");
783 TexOutput(bib->month);
784 TexOutput(")");
785 }
786 if (bib->year || bib->month)
787 TexOutput(". ");
788
789 if (StringMatch(bib->type, "article", FALSE, TRUE))
790 {
791 if (bib->title)
792 {
793 TexOutput(bib->title);
794 TexOutput(". ");
795 }
796 if (bib->journal)
797 {
798 OnMacro(ltIT, 1, TRUE);
799 OnArgument(ltIT, 1, TRUE);
800 TexOutput(bib->journal);
801 OnArgument(ltIT, 1, FALSE);
802 OnMacro(ltIT, 1, FALSE);
803 }
804 if (bib->volume)
805 {
806 TexOutput(", ");
807 OnMacro(ltBF, 1, TRUE);
808 OnArgument(ltBF, 1, TRUE);
809 TexOutput(bib->volume);
810 OnArgument(ltBF, 1, FALSE);
811 OnMacro(ltBF, 1, FALSE);
812 }
813 if (bib->number)
814 {
815 TexOutput("(");
816 TexOutput(bib->number);
817 TexOutput(")");
818 }
819 if (bib->pages)
820 {
821 TexOutput(", pages ");
822 TexOutput(bib->pages);
823 }
824 TexOutput(".");
825 }
826 else if (StringMatch(bib->type, "book", FALSE, TRUE) ||
827 StringMatch(bib->type, "unpublished", FALSE, TRUE) ||
828 StringMatch(bib->type, "manual", FALSE, TRUE) ||
829 StringMatch(bib->type, "phdthesis", FALSE, TRUE) ||
830 StringMatch(bib->type, "mastersthesis", FALSE, TRUE) ||
831 StringMatch(bib->type, "misc", FALSE, TRUE) ||
832 StringMatch(bib->type, "techreport", FALSE, TRUE) ||
833 StringMatch(bib->type, "booklet", FALSE, TRUE))
834 {
835 if (bib->title || bib->booktitle)
836 {
837 OnMacro(ltIT, 1, TRUE);
838 OnArgument(ltIT, 1, TRUE);
839 TexOutput(bib->title ? bib->title : bib->booktitle);
840 TexOutput(". ");
841 OnArgument(ltIT, 1, FALSE);
842 OnMacro(ltIT, 1, FALSE);
843 }
844 if (StringMatch(bib->type, "phdthesis", FALSE, TRUE))
845 TexOutput("PhD thesis. ");
846 if (StringMatch(bib->type, "techreport", FALSE, TRUE))
847 TexOutput("Technical report. ");
848 if (bib->editor)
849 {
850 TexOutput("Ed. ");
851 TexOutput(bib->editor);
852 TexOutput(". ");
853 }
854 if (bib->institution)
855 {
856 TexOutput(bib->institution);
857 TexOutput(". ");
858 }
859 if (bib->organization)
860 {
861 TexOutput(bib->organization);
862 TexOutput(". ");
863 }
864 if (bib->publisher)
865 {
866 TexOutput(bib->publisher);
867 TexOutput(". ");
868 }
869 if (bib->address)
870 {
871 TexOutput(bib->address);
872 TexOutput(". ");
873 }
874 }
875 else if (StringMatch(bib->type, "inbook", FALSE, TRUE) ||
876 StringMatch(bib->type, "inproceedings", FALSE, TRUE) ||
877 StringMatch(bib->type, "incollection", FALSE, TRUE) ||
878 StringMatch(bib->type, "conference", FALSE, TRUE))
879 {
880 if (bib->title)
881 {
882 TexOutput(bib->title);
883 }
884 if (bib->booktitle)
885 {
886 TexOutput(", from ");
887 OnMacro(ltIT, 1, TRUE);
888 OnArgument(ltIT, 1, TRUE);
889 TexOutput(bib->booktitle);
890 TexOutput(".");
891 OnArgument(ltIT, 1, FALSE);
892 OnMacro(ltIT, 1, FALSE);
893 }
894 if (bib->editor)
895 {
896 TexOutput(", ed. ");
897 TexOutput(bib->editor);
898 }
899 if (bib->publisher)
900 {
901 TexOutput(" ");
902 TexOutput(bib->publisher);
903 }
904 if (bib->address)
905 {
906 if (bib->publisher) TexOutput(", ");
907 else TexOutput(" ");
908 TexOutput(bib->address);
909 }
910 if (bib->publisher || bib->address)
911 TexOutput(".");
912
913 if (bib->volume)
914 {
915 TexOutput(" ");
916 OnMacro(ltBF, 1, TRUE);
917 OnArgument(ltBF, 1, TRUE);
918 TexOutput(bib->volume);
919 OnArgument(ltBF, 1, FALSE);
920 OnMacro(ltBF, 1, FALSE);
921 }
922 if (bib->number)
923 {
924 if (bib->volume)
925 {
926 TexOutput("(");
927 TexOutput(bib->number);
928 TexOutput(").");
929 }
930 else
931 {
932 TexOutput(" Number ");
933 TexOutput(bib->number);
934 TexOutput(".");
935 }
936 }
937 if (bib->chapter)
938 {
939 TexOutput(" Chap. "); TexOutput(bib->chapter);
940 }
941 if (bib->pages)
942 {
943 if (bib->chapter) TexOutput(", pages ");
944 else TexOutput(" Pages ");
945 TexOutput(bib->pages);
946 TexOutput(".");
947 }
948 }
949 OnArgument(ltNUMBEREDBIBITEM, 2, FALSE);
950 OnMacro(ltNUMBEREDBIBITEM, 2, FALSE);
951}
952
953void OutputBib(void)
954{
955 // Write the heading
956 ForceTopicName("bibliography");
957 FakeCurrentSection(ReferencesNameString);
958 ForceTopicName(NULL);
959
960 OnMacro(ltPAR, 0, TRUE);
961 OnMacro(ltPAR, 0, FALSE);
962
963 if ((convertMode == TEX_RTF) && !winHelp)
964 {
965 OnMacro(ltPAR, 0, TRUE);
966 OnMacro(ltPAR, 0, FALSE);
967 }
968
969 wxNode *node = CitationList.First();
970 while (node)
971 {
972 char *citeKey = (char *)node->Data();
973// wxNode *texNode = TexReferences.Find(citeKey);
974 TexRef *ref = (TexRef *)TexReferences.Get(citeKey);
975 wxNode *bibNode = BibList.Find(citeKey);
976 if (bibNode && ref)
977 {
978 BibEntry *entry = (BibEntry *)bibNode->Data();
979 OutputBibItem(ref, entry);
980 }
981 node = node->Next();
982 }
983}
984
985static int citeCount = 1;
986
987void ResolveBibReferences(void)
988{
989 if (CitationList.Number() > 0)
990 OnInform("Resolving bibliographic references...");
991
992 citeCount = 1;
993 char buf[200];
994 wxNode *node = CitationList.First();
995 while (node)
996 {
997 Tex2RTFYield();
998 char *citeKey = (char *)node->Data();
999// wxNode *texNode = TexReferences.Find(citeKey);
1000 TexRef *ref = (TexRef *)TexReferences.Get(citeKey);
1001 wxNode *bibNode = BibList.Find(citeKey);
1002 if (bibNode && ref)
1003 {
1004 // Unused Variable
1005 //BibEntry *entry = (BibEntry *)bibNode->Data();
1006 if (ref->sectionNumber) delete[] ref->sectionNumber;
1007 sprintf(buf, "[%d]", citeCount);
1008 ref->sectionNumber = copystring(buf);
1009 citeCount ++;
1010 }
1011 else
1012 {
1013 sprintf(buf, "Warning: bib ref %s not resolved.", citeKey);
1014 OnInform(buf);
1015 }
1016 node = node->Next();
1017 }
1018}
1019
1020// Remember we need to resolve this citation
1021void AddCitation(char *citeKey)
1022{
1023 if (!CitationList.Member(citeKey))
1024 CitationList.Add(citeKey);
1025
1026 if (!TexReferences.Get(citeKey))
1027 {
1028 TexReferences.Put(citeKey, new TexRef(citeKey, "??", NULL));
1029 }
1030}
1031
1032TexRef *FindReference(char *key)
1033{
1034 return (TexRef *)TexReferences.Get(key);
1035}
1036
1037/*
1038 * Custom macro stuff
1039 *
1040 */
1041
1042bool StringTobool(char *val)
1043{
1044 if (strncmp(val, "yes", 3) == 0 || strncmp(val, "YES", 3) == 0 ||
1045 strncmp(val, "on", 2) == 0 || strncmp(val, "ON", 2) == 0 ||
1046 strncmp(val, "true", 4) == 0 || strncmp(val, "TRUE", 4) == 0 ||
1047 strncmp(val, "ok", 2) == 0 || strncmp(val, "OK", 2) == 0 ||
1048 strncmp(val, "1", 1) == 0)
1049 return TRUE;
1050 else
1051 return FALSE;
1052}
1053
1054// Define a variable value from the .ini file
1055char *RegisterSetting(char *settingName, char *settingValue, bool interactive)
1056{
1057 static char errorCode[100];
1058 strcpy(errorCode, "OK");
1059 if (StringMatch(settingName, "chapterName", FALSE, TRUE))
1060 {
1061 delete[] ChapterNameString;
1062 ChapterNameString = copystring(settingValue);
1063 }
1064 else if (StringMatch(settingName, "sectionName", FALSE, TRUE))
1065 {
1066 delete[] SectionNameString;
1067 SectionNameString = copystring(settingValue);
1068 }
1069 else if (StringMatch(settingName, "subsectionName", FALSE, TRUE))
1070 {
1071 delete[] SubsectionNameString;
1072 SubsectionNameString = copystring(settingValue);
1073 }
1074 else if (StringMatch(settingName, "subsubsectionName", FALSE, TRUE))
1075 {
1076 delete[] SubsubsectionNameString;
1077 SubsubsectionNameString = copystring(settingValue);
1078 }
1079 else if (StringMatch(settingName, "indexName", FALSE, TRUE))
1080 {
1081 delete[] IndexNameString;
1082 IndexNameString = copystring(settingValue);
1083 }
1084 else if (StringMatch(settingName, "contentsName", FALSE, TRUE))
1085 {
1086 delete[] ContentsNameString;
1087 ContentsNameString = copystring(settingValue);
1088 }
1089 else if (StringMatch(settingName, "glossaryName", FALSE, TRUE))
1090 {
1091 delete[] GlossaryNameString;
1092 GlossaryNameString = copystring(settingValue);
1093 }
1094 else if (StringMatch(settingName, "referencesName", FALSE, TRUE))
1095 {
1096 delete[] ReferencesNameString;
1097 ReferencesNameString = copystring(settingValue);
1098 }
1099 else if (StringMatch(settingName, "tablesName", FALSE, TRUE))
1100 {
1101 delete[] TablesNameString;
1102 TablesNameString = copystring(settingValue);
1103 }
1104 else if (StringMatch(settingName, "figuresName", FALSE, TRUE))
1105 {
1106 delete[] FiguresNameString;
1107 FiguresNameString = copystring(settingValue);
1108 }
1109 else if (StringMatch(settingName, "tableName", FALSE, TRUE))
1110 {
1111 delete[] TableNameString;
1112 TableNameString = copystring(settingValue);
1113 }
1114 else if (StringMatch(settingName, "figureName", FALSE, TRUE))
1115 {
1116 delete[] FigureNameString;
1117 FigureNameString = copystring(settingValue);
1118 }
1119 else if (StringMatch(settingName, "abstractName", FALSE, TRUE))
1120 {
1121 delete[] AbstractNameString;
1122 AbstractNameString = copystring(settingValue);
1123 }
1124 else if (StringMatch(settingName, "chapterFontSize", FALSE, TRUE))
1125 StringToInt(settingValue, &chapterFont);
1126 else if (StringMatch(settingName, "sectionFontSize", FALSE, TRUE))
1127 StringToInt(settingValue, &sectionFont);
1128 else if (StringMatch(settingName, "subsectionFontSize", FALSE, TRUE))
1129 StringToInt(settingValue, &subsectionFont);
1130 else if (StringMatch(settingName, "titleFontSize", FALSE, TRUE))
1131 StringToInt(settingValue, &titleFont);
1132 else if (StringMatch(settingName, "authorFontSize", FALSE, TRUE))
1133 StringToInt(settingValue, &authorFont);
1134 else if (StringMatch(settingName, "ignoreInput", FALSE, TRUE))
1135 IgnorableInputFiles.Add(FileNameFromPath(settingValue));
1136 else if (StringMatch(settingName, "mirrorMargins", FALSE, TRUE))
1137 mirrorMargins = StringTobool(settingValue);
1138 else if (StringMatch(settingName, "runTwice", FALSE, TRUE))
1139 runTwice = StringTobool(settingValue);
1140 else if (StringMatch(settingName, "isInteractive", FALSE, TRUE))
1141 isInteractive = StringTobool(settingValue);
1142 else if (StringMatch(settingName, "headerRule", FALSE, TRUE))
1143 headerRule = StringTobool(settingValue);
1144 else if (StringMatch(settingName, "footerRule", FALSE, TRUE))
1145 footerRule = StringTobool(settingValue);
1146 else if (StringMatch(settingName, "combineSubSections", FALSE, TRUE))
1147 combineSubSections = StringTobool(settingValue);
1148 else if (StringMatch(settingName, "listLabelIndent", FALSE, TRUE))
1149 StringToInt(settingValue, &labelIndentTab);
1150 else if (StringMatch(settingName, "listItemIndent", FALSE, TRUE))
1151 StringToInt(settingValue, &itemIndentTab);
1152 else if (StringMatch(settingName, "useUpButton", FALSE, TRUE))
1153 useUpButton = StringTobool(settingValue);
1154 else if (StringMatch(settingName, "useHeadingStyles", FALSE, TRUE))
1155 useHeadingStyles = StringTobool(settingValue);
1156 else if (StringMatch(settingName, "useWord", FALSE, TRUE))
1157 useWord = StringTobool(settingValue);
1158 else if (StringMatch(settingName, "contentsDepth", FALSE, TRUE))
1159 StringToInt(settingValue, &contentsDepth);
1160 else if (StringMatch(settingName, "generateHPJ", FALSE, TRUE))
1161 generateHPJ = StringTobool(settingValue);
1162 else if (StringMatch(settingName, "truncateFilenames", FALSE, TRUE))
1163 truncateFilenames = StringTobool(settingValue);
1164 else if (StringMatch(settingName, "winHelpVersion", FALSE, TRUE))
1165 StringToInt(settingValue, &winHelpVersion);
1166 else if (StringMatch(settingName, "winHelpContents", FALSE, TRUE))
1167 winHelpContents = StringTobool(settingValue);
1168 else if (StringMatch(settingName, "htmlIndex", FALSE, TRUE))
1169 htmlIndex = StringTobool(settingValue);
1170 else if (StringMatch(settingName, "htmlFrameContents", FALSE, TRUE))
1171 htmlFrameContents = StringTobool(settingValue);
1172 else if (StringMatch(settingName, "upperCaseNames", FALSE, TRUE))
1173 upperCaseNames = StringTobool(settingValue);
1174 else if (StringMatch(settingName, "winHelpTitle", FALSE, TRUE))
1175 {
1176 if (winHelpTitle)
1177 delete[] winHelpTitle;
1178 winHelpTitle = copystring(settingValue);
1179 }
1180 else if (StringMatch(settingName, "indexSubsections", FALSE, TRUE))
1181 indexSubsections = StringTobool(settingValue);
1182 else if (StringMatch(settingName, "compatibility", FALSE, TRUE))
1183 compatibilityMode = StringTobool(settingValue);
1184 else if (StringMatch(settingName, "defaultColumnWidth", FALSE, TRUE))
1185 {
1186 StringToInt(settingValue, &defaultTableColumnWidth);
1187 defaultTableColumnWidth = 20*defaultTableColumnWidth;
1188 }
1189 else if (StringMatch(settingName, "bitmapMethod", FALSE, TRUE))
1190 {
1191 if ((strcmp(settingValue, "includepicture") != 0) && (strcmp(settingValue, "hex") != 0) &&
1192 (strcmp(settingValue, "import") != 0))
1193 {
1194 if (interactive)
1195 OnError("Unknown bitmapMethod");
1196 strcpy(errorCode, "Unknown bitmapMethod");
1197 }
1198 else
1199 {
1200 delete[] bitmapMethod;
1201 bitmapMethod = copystring(settingValue);
1202 }
1203 }
1204 else if (StringMatch(settingName, "htmlBrowseButtons", FALSE, TRUE))
1205 {
1206 if (strcmp(settingValue, "none") == 0)
1207 htmlBrowseButtons = HTML_BUTTONS_NONE;
1208 else if (strcmp(settingValue, "bitmap") == 0)
1209 htmlBrowseButtons = HTML_BUTTONS_BITMAP;
1210 else if (strcmp(settingValue, "text") == 0)
1211 htmlBrowseButtons = HTML_BUTTONS_TEXT;
1212 else
1213 {
1214 if (interactive)
1215 OnInform("Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text.");
1216 strcpy(errorCode, "Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text.");
1217 }
1218 }
1219 else if (StringMatch(settingName, "backgroundImage", FALSE, TRUE))
1220 {
1221 backgroundImageString = copystring(settingValue);
1222 }
1223 else if (StringMatch(settingName, "backgroundColour", FALSE, TRUE))
1224 {
1225 delete[] backgroundColourString;
1226 backgroundColourString = copystring(settingValue);
1227 }
1228 else if (StringMatch(settingName, "textColour", FALSE, TRUE))
1229 {
1230 textColourString = copystring(settingValue);
1231 }
1232 else if (StringMatch(settingName, "linkColour", FALSE, TRUE))
1233 {
1234 linkColourString = copystring(settingValue);
1235 }
1236 else if (StringMatch(settingName, "followedLinkColour", FALSE, TRUE))
1237 {
1238 followedLinkColourString = copystring(settingValue);
1239 }
1240 else if (StringMatch(settingName, "conversionMode", FALSE, TRUE))
1241 {
1242 if (StringMatch(settingValue, "RTF", FALSE, TRUE))
1243 {
1244 winHelp = FALSE; convertMode = TEX_RTF;
1245 }
1246 else if (StringMatch(settingValue, "WinHelp", FALSE, TRUE))
1247 {
1248 winHelp = TRUE; convertMode = TEX_RTF;
1249 }
1250 else if (StringMatch(settingValue, "XLP", FALSE, TRUE) ||
1251 StringMatch(settingValue, "wxHelp", FALSE, TRUE))
1252 {
1253 convertMode = TEX_XLP;
1254 }
1255 else if (StringMatch(settingValue, "HTML", FALSE, TRUE))
1256 {
1257 convertMode = TEX_HTML;
1258 }
1259 else
1260 {
1261 if (interactive)
1262 OnInform("Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML.");
1263 strcpy(errorCode, "Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML.");
1264 }
1265 }
1266 else if (StringMatch(settingName, "documentFontSize", FALSE, TRUE))
1267 {
1268 int n;
1269 StringToInt(settingValue, &n);
1270 if (n == 10 || n == 11 || n == 12)
1271 SetFontSizes(n);
1272 else
1273 {
1274 char buf[200];
1275 sprintf(buf, "Initialisation file error: nonstandard document font size %d.", n);
1276 if (interactive)
1277 OnInform(buf);
1278 strcpy(errorCode, buf);
1279 }
1280 }
1281 else
1282 {
1283 char buf[200];
1284 sprintf(buf, "Initialisation file error: unrecognised setting %s.", settingName);
1285 if (interactive)
1286 OnInform(buf);
1287 strcpy(errorCode, buf);
1288 }
1289 return errorCode;
1290}
1291
1292bool ReadCustomMacros(char *filename)
1293{
eb7aa89b
UU
1294#if !wxUSE_IOSTREAMH && __WXMSW__
1295 ifstream istr(filename, ios::in);
1296#else
9a29912f 1297 ifstream istr(filename, ios::nocreate | ios::in);
eb7aa89b 1298#endif
9a29912f
JS
1299 if (istr.bad()) return FALSE;
1300
1301 CustomMacroList.Clear();
1302 char ch;
1303 char macroName[100];
1304 char macroBody[1000];
1305 int noArgs;
1306
1307 while (!istr.eof())
1308 {
1309 BibEatWhiteSpace(istr);
1310 istr.get(ch);
1311 if (istr.eof())
1312 break;
1313
1314 if (ch != '\\') // Not a macro definition, so must be NAME=VALUE
1315 {
1316 char settingName[100];
1317 settingName[0] = ch;
1318 BibReadWord(istr, (settingName+1));
1319 BibEatWhiteSpace(istr);
1320 istr.get(ch);
1321 if (ch != '=')
1322 {
1323 OnError("Expected = following name: malformed tex2rtf.ini file.");
1324 return FALSE;
1325 }
1326 else
1327 {
1328 char settingValue[200];
1329 BibEatWhiteSpace(istr);
1330 BibReadToEOL(istr, settingValue);
1331 RegisterSetting(settingName, settingValue);
1332 }
1333 }
1334 else
1335 {
1336 BibReadWord(istr, macroName);
1337 BibEatWhiteSpace(istr);
1338 istr.get(ch);
1339 if (ch != '[')
1340 {
1341 OnError("Expected [ followed by number of arguments: malformed tex2rtf.ini file.");
1342 return FALSE;
1343 }
1344 istr >> noArgs;
1345 istr.get(ch);
1346 if (ch != ']')
1347 {
1348 OnError("Expected ] following number of arguments: malformed tex2rtf.ini file.");
1349 return FALSE;
1350 }
1351 BibEatWhiteSpace(istr);
1352 istr.get(ch);
1353 if (ch != '{')
1354 {
1355 OnError("Expected { followed by macro body: malformed tex2rtf.ini file.");
1356 return FALSE;
1357 }
1358 CustomMacro *macro = new CustomMacro(macroName, noArgs, NULL);
1359 BibReadValue(istr, macroBody, FALSE, FALSE); // Don't ignore extra braces
1360 if (strlen(macroBody) > 0)
1361 macro->macroBody = copystring(macroBody);
1362
1363 BibEatWhiteSpace(istr);
1364 CustomMacroList.Append(macroName, macro);
1365 AddMacroDef(ltCUSTOM_MACRO, macroName, noArgs);
1366 }
1367 }
1368 char mbuf[200];
1369 sprintf(mbuf, "Read initialization file %s.", filename);
1370 OnInform(mbuf);
1371 return TRUE;
1372}
1373
1374CustomMacro *FindCustomMacro(char *name)
1375{
1376 wxNode *node = CustomMacroList.Find(name);
1377 if (node)
1378 {
1379 CustomMacro *macro = (CustomMacro *)node->Data();
1380 return macro;
1381 }
1382 return NULL;
1383}
1384
1385// Display custom macros
1386void ShowCustomMacros(void)
1387{
1388 wxNode *node = CustomMacroList.First();
1389 if (!node)
1390 {
1391 OnInform("No custom macros loaded.\n");
1392 return;
1393 }
1394
1395 char buf[400];
1396 while (node)
1397 {
1398 CustomMacro *macro = (CustomMacro *)node->Data();
1399 sprintf(buf, "\\%s[%d]\n {%s}", macro->macroName, macro->noArgs,
1400 macro->macroBody ? macro->macroBody : "");
1401 OnInform(buf);
1402 node = node->Next();
1403 }
1404}
1405
1406// Parse a string into several comma-separated fields
1407char *ParseMultifieldString(char *allFields, int *pos)
1408{
1409 static char buffer[300];
1410 int i = 0;
1411 int fieldIndex = *pos;
1412 int len = strlen(allFields);
1413 int oldPos = *pos;
1414 bool keepGoing = TRUE;
1415 while ((fieldIndex <= len) && keepGoing)
1416 {
1417 if (allFields[fieldIndex] == ' ')
1418 {
1419 // Skip
1420 fieldIndex ++;
1421 }
1422 else if (allFields[fieldIndex] == ',')
1423 {
1424 *pos = fieldIndex + 1;
1425 keepGoing = FALSE;
1426 }
1427 else if (allFields[fieldIndex] == 0)
1428 {
1429 *pos = fieldIndex + 1;
1430 keepGoing = FALSE;
1431 }
1432 else
1433 {
1434 buffer[i] = allFields[fieldIndex];
1435 fieldIndex ++;
1436 i++;
1437 }
1438 }
1439 buffer[i] = 0;
1440 if (oldPos == (*pos))
1441 *pos = len + 1;
1442
1443 if (i == 0)
1444 return NULL;
1445 else
1446 return buffer;
1447}
1448
1449/*
1450 * Colour tables
1451 *
1452 */
1453
1454ColourTableEntry::ColourTableEntry(char *theName, unsigned int r, unsigned int g, unsigned int b)
1455{
1456 name = copystring(theName);
1457 red = r;
1458 green = g;
1459 blue = b;
1460}
1461
1462ColourTableEntry::~ColourTableEntry(void)
1463{
1464 delete[] name;
1465}
1466
1467void AddColour(char *theName, unsigned int r, unsigned int g, unsigned int b)
1468{
1469 wxNode *node = ColourTable.Find(theName);
1470 if (node)
1471 {
1472 ColourTableEntry *entry = (ColourTableEntry *)node->Data();
1473 if (entry->red == r || entry->green == g || entry->blue == b)
1474 return;
1475 else
1476 {
1477 delete entry;
1478 delete node;
1479 }
1480 }
1481 ColourTableEntry *entry = new ColourTableEntry(theName, r, g, b);
1482 ColourTable.Append(theName, entry);
1483}
1484
1485int FindColourPosition(char *theName)
1486{
1487 int i = 0;
1488 wxNode *node = ColourTable.First();
1489 while (node)
1490 {
1491 ColourTableEntry *entry = (ColourTableEntry *)node->Data();
1492 if (strcmp(theName, entry->name) == 0)
1493 return i;
1494 i ++;
1495 node = node->Next();
1496 }
1497 return -1;
1498}
1499
1500// Converts e.g. "red" -> "#FF0000"
1501extern void DecToHex(int, char *);
1502bool FindColourHTMLString(char *theName, char *buf)
1503{
1504 int i = 0;
1505 wxNode *node = ColourTable.First();
1506 while (node)
1507 {
1508 ColourTableEntry *entry = (ColourTableEntry *)node->Data();
1509 if (strcmp(theName, entry->name) == 0)
1510 {
1511 strcpy(buf, "#");
1512
1513 char buf2[3];
1514 DecToHex(entry->red, buf2);
1515 strcat(buf, buf2);
1516 DecToHex(entry->green, buf2);
1517 strcat(buf, buf2);
1518 DecToHex(entry->blue, buf2);
1519 strcat(buf, buf2);
1520
1521 return TRUE;
1522 }
1523 i ++;
1524 node = node->Next();
1525 }
1526 return FALSE;
1527}
1528
1529
1530void InitialiseColourTable(void)
1531{
1532 // \\red0\\green0\\blue0;
1533 AddColour("black", 0,0,0);
1534
1535 // \\red0\\green0\\blue255;\\red0\\green255\\blue255;\n");
1536 AddColour("cyan", 0,255,255);
1537
1538 // \\red0\\green255\\blue0;
1539 AddColour("green", 0,255,0);
1540
1541 // \\red255\\green0\\blue255;
1542 AddColour("magenta", 255,0,255);
1543
1544 // \\red255\\green0\\blue0;
1545 AddColour("red", 255,0,0);
1546
1547 // \\red255\\green255\\blue0;
1548 AddColour("yellow", 255,255,0);
1549
1550 // \\red255\\green255\\blue255;}");
1551 AddColour("white", 255,255,255);
1552}
1553
1554/*
1555 * The purpose of this is to reduce the number of times wxYield is
1556 * called, since under Windows this can slow things down.
1557 */
1558
1559static int yieldCount = 0;
1560
1561void Tex2RTFYield(bool force)
1562{
1563#ifdef __WXMSW__
1564 if (isSync)
1565 return;
1566
1567 if (force)
1568 yieldCount = 0;
1569 if (yieldCount == 0)
1570 {
1571 wxYield();
1572 yieldCount = 10;
1573 }
1574 yieldCount --;
1575#endif
1576}
1577
1578// In both RTF generation and HTML generation for wxHelp version 2,
1579// we need to associate \indexed keywords with the current filename/topics.
1580
1581// Hash table for lists of keywords for topics (WinHelp).
1582wxHashTable TopicTable(wxKEY_STRING);
1583void AddKeyWordForTopic(char *topic, char *entry, char *filename)
1584{
1585 TexTopic *texTopic = (TexTopic *)TopicTable.Get(topic);
1586 if (!texTopic)
1587 {
1588 texTopic = new TexTopic(filename);
1589 texTopic->keywords = new wxStringList;
1590 TopicTable.Put(topic, texTopic);
1591 }
1592
1593 if (!texTopic->keywords->Member(entry))
1594 texTopic->keywords->Add(entry);
1595}
1596
1597void ClearKeyWordTable(void)
1598{
1599 TopicTable.BeginFind();
1600 wxNode *node = TopicTable.Next();
1601 while (node)
1602 {
1603 TexTopic *texTopic = (TexTopic *)node->Data();
1604 delete texTopic;
1605 node = TopicTable.Next();
1606 }
1607 TopicTable.Clear();
1608}
1609
1610
1611/*
1612 * TexTopic structure
1613 */
1614
1615TexTopic::TexTopic(char *f)
1616{
1617 if (f)
1618 filename = copystring(f);
1619 else
1620 filename = NULL;
1621 hasChildren = FALSE;
1622 keywords = NULL;
1623}
1624
1625TexTopic::~TexTopic(void)
1626{
1627 if (keywords)
1628 delete keywords;
1629 if (filename)
1630 delete[] filename;
1631}
1632
1633// Convert case, according to upperCaseNames setting.
1634char *ConvertCase(char *s)
1635{
1636 static char buf[256];
1637 int len = strlen(s);
1638 int i;
1639 if (upperCaseNames)
1640 for (i = 0; i < len; i ++)
1641 buf[i] = wxToUpper(s[i]);
1642 else
1643 for (i = 0; i < len; i ++)
1644 buf[i] = wxToLower(s[i]);
1645 buf[i] = 0;
1646 return buf;
1647}