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