]> git.saurik.com Git - wxWidgets.git/blame_incremental - utils/tex2rtf/src/texutils.cpp
fix for VC6 sorry
[wxWidgets.git] / utils / tex2rtf / src / texutils.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: texutils.cpp
3// Purpose: Miscellaneous utilities
4// Author: Julian Smart
5// Modified by: Wlodzimiez ABX Skiba 2003/2004 Unicode support
6// Ron Lee
7// Created: 7.9.93
8// RCS-ID: $Id$
9// Copyright: (c) Julian Smart
10// Licence: wxWindows licence
11/////////////////////////////////////////////////////////////////////////////
12
13// For compilers that support precompilation, includes "wx.h".
14#include "wx/wxprec.h"
15
16#ifdef __BORLANDC__
17#pragma hdrstop
18#endif
19
20#ifndef WX_PRECOMP
21 #include "wx/log.h"
22#endif
23
24#include "wx/app.h"
25#include "wx/hash.h"
26#include "wx/textfile.h"
27
28#ifdef new
29#undef new
30#endif
31
32#if wxUSE_IOSTREAMH
33#include <iostream.h>
34#include <fstream.h>
35#else
36#include <iostream>
37#include <fstream>
38using namespace std;
39#endif
40
41#include <ctype.h>
42#include "tex2any.h"
43
44static inline wxChar* copystring(const wxChar* s)
45 { return wxStrcpy(new wxChar[wxStrlen(s) + 1], s); }
46
47wxHashTable TexReferences(wxKEY_STRING);
48wxList BibList(wxKEY_STRING);
49wxStringList CitationList;
50wxList ColourTable(wxKEY_STRING);
51wxHashTable BibStringTable(wxKEY_STRING);
52wxList CustomMacroList(wxKEY_STRING);
53TexChunk *currentSection = NULL;
54wxChar *fakeCurrentSection = NULL;
55
56static long BibLine = 1;
57
58void OutputCurrentSection(void)
59{
60 if (fakeCurrentSection)
61 TexOutput(fakeCurrentSection);
62 else if (currentSection)
63 TraverseChildrenFromChunk(currentSection);
64}
65
66// Nasty but the way things are done now, necessary,
67// in order to output a chunk properly to a string (macros and all).
68void OutputCurrentSectionToString(wxChar *buf)
69{
70 if (fakeCurrentSection)
71 wxStrcpy(buf, fakeCurrentSection);
72 else
73 OutputChunkToString(currentSection, buf);
74}
75
76void OutputChunkToString(TexChunk *chunk, wxChar *buf)
77{
78 FILE *tempfd = wxFopen(_T("tmp.tmp"), _T("w"));
79 if (!tempfd)
80 return;
81
82 FILE *old1 = CurrentOutput1;
83 FILE *old2 = CurrentOutput2;
84
85 CurrentOutput1 = tempfd;
86 CurrentOutput2 = NULL;
87
88 TraverseChildrenFromChunk(chunk);
89
90 CurrentOutput1 = old1;
91 CurrentOutput2 = old2;
92
93 fclose(tempfd);
94
95 // Read from file into string
96 tempfd = wxFopen(_T("tmp.tmp"), _T("r"));
97 if (!tempfd)
98 return;
99
100 buf[0] = 0;
101 int ch = -2;
102 int i = 0;
103 while (ch != EOF)
104 {
105 ch = getc(tempfd);
106 if (ch == EOF)
107 buf[i] = 0;
108 else
109 {
110 buf[i] = (wxChar)ch;
111 i ++;
112 }
113 }
114 fclose(tempfd);
115 wxRemoveFile(_T("tmp.tmp"));
116}
117
118// Called by Tex2Any to simulate a section
119void FakeCurrentSection(wxChar *fakeSection, bool addToContents)
120{
121 currentSection = NULL;
122 if (fakeCurrentSection) delete[] fakeCurrentSection;
123 fakeCurrentSection = copystring(fakeSection);
124
125 if (DocumentStyle == LATEX_ARTICLE)
126 {
127 int mac = ltSECTIONHEADING;
128 if (!addToContents)
129 mac = ltSECTIONHEADINGSTAR;
130 OnMacro(mac, 0, true);
131 OnMacro(mac, 0, false);
132 }
133 else
134 {
135 int mac = ltCHAPTERHEADING;
136 if (!addToContents)
137 mac = ltCHAPTERHEADINGSTAR;
138 OnMacro(mac, 0, true);
139 OnMacro(mac, 0, false);
140 }
141 if (fakeCurrentSection) delete[] fakeCurrentSection;
142 fakeCurrentSection = NULL;
143}
144
145// Look for \label macro, use this ref name if found or
146// make up a topic name otherwise.
147static long topicCounter = 0;
148
149void ResetTopicCounter(void)
150{
151 topicCounter = 0;
152}
153
154static wxChar *forceTopicName = NULL;
155
156void ForceTopicName(const wxChar *name)
157{
158 if (forceTopicName)
159 delete[] forceTopicName;
160 if (name)
161 forceTopicName = copystring(name);
162 else
163 forceTopicName = NULL;
164}
165
166wxChar *FindTopicName(TexChunk *chunk)
167{
168 if (forceTopicName)
169 return forceTopicName;
170
171 wxChar *topicName = NULL;
172 static wxChar topicBuf[100];
173
174 if (chunk && (chunk->type == CHUNK_TYPE_MACRO) &&
175 (chunk->macroId == ltLABEL))
176 {
177 wxNode *node = chunk->children.GetFirst();
178 if (node)
179 {
180 TexChunk *child = (TexChunk *)node->GetData();
181 if (child->type == CHUNK_TYPE_ARG)
182 {
183 wxNode *snode = child->children.GetFirst();
184 if (snode)
185 {
186 TexChunk *schunk = (TexChunk *)snode->GetData();
187 if (schunk->type == CHUNK_TYPE_STRING)
188 topicName = schunk->value;
189 }
190 }
191 }
192 }
193 if (topicName)
194 return topicName;
195 else
196 {
197 wxSnprintf(topicBuf, sizeof(topicBuf), _T("topic%ld"), topicCounter);
198 topicCounter ++;
199 return topicBuf;
200 }
201}
202
203/*
204 * Simulate argument data, so we can 'drive' clients which implement
205 * certain basic formatting behaviour.
206 * Snag is that some save a TexChunk, so don't use yet...
207 *
208 */
209
210void StartSimulateArgument(const wxChar *data)
211{
212 wxStrcpy(currentArgData, data);
213 haveArgData = true;
214}
215
216void EndSimulateArgument(void)
217{
218 haveArgData = false;
219}
220
221/*
222 * Parse and convert unit arguments to points
223 *
224 */
225
226int ParseUnitArgument(const wxChar *unitArg_)
227{
228 wxWxCharBuffer unitBuf(unitArg_);
229 wxChar *unitArg = unitBuf.data();
230
231 float conversionFactor = 1.0;
232 float unitValue = 0.0;
233 int len = wxStrlen(unitArg);
234 // Get rid of any accidentally embedded commands
235 for (int i = 0; i < len; i++)
236 if (unitArg[i] == '\\')
237 unitArg[i] = 0;
238 len = wxStrlen(unitArg);
239
240 if (unitArg && (len > 0) && (isdigit(unitArg[0]) || unitArg[0] == '-'))
241 {
242 wxSscanf(unitArg, _T("%f"), &unitValue);
243 if (len > 1)
244 {
245 wxChar units[3];
246 units[0] = unitArg[len-2];
247 units[1] = unitArg[len-1];
248 units[2] = 0;
249 if (wxStrcmp(units, _T("in")) == 0)
250 conversionFactor = 72.0;
251 else if (wxStrcmp(units, _T("cm")) == 0)
252 conversionFactor = (float)72.0/(float)2.51;
253 else if (wxStrcmp(units, _T("mm")) == 0)
254 conversionFactor = (float)72.0/(float)25.1;
255 else if (wxStrcmp(units, _T("pt")) == 0)
256 conversionFactor = 1;
257 }
258 return (int)(unitValue*conversionFactor);
259 }
260 else return 0;
261}
262
263/*
264 * Strip off any extension (dot something) from end of file,
265 * IF one exists. Inserts zero into buffer.
266 *
267 */
268
269void StripExtension(wxChar *buffer)
270{
271 int len = wxStrlen(buffer);
272 int i = len-1;
273 while (i > 0)
274 {
275 if (buffer[i] == '.')
276 {
277 buffer[i] = 0;
278 break;
279 }
280 i --;
281 }
282}
283
284/*
285 * Latex font setting
286 *
287 */
288
289void SetFontSizes(int pointSize)
290{
291 switch (pointSize)
292 {
293 case 12:
294 {
295 normalFont = 12;
296 smallFont = 10;
297 tinyFont = 8;
298 largeFont1 = 14;
299 LargeFont2 = 16;
300 LARGEFont3 = 20;
301 hugeFont1 = 24;
302 HugeFont2 = 28;
303 HUGEFont3 = 32;
304 break;
305 }
306 case 11:
307 {
308 normalFont = 11;
309 smallFont = 9;
310 tinyFont = 7;
311 largeFont1 = 13;
312 LargeFont2 = 16;
313 LARGEFont3 = 19;
314 hugeFont1 = 22;
315 HugeFont2 = 26;
316 HUGEFont3 = 30;
317 break;
318 }
319 case 10:
320 {
321 normalFont = 10;
322 smallFont = 8;
323 tinyFont = 6;
324 largeFont1 = 12;
325 LargeFont2 = 14;
326 LARGEFont3 = 18;
327 hugeFont1 = 20;
328 HugeFont2 = 24;
329 HUGEFont3 = 28;
330 break;
331 }
332 }
333}
334
335
336/*
337 * Latex references
338 *
339 */
340
341void AddTexRef(wxChar *name, wxChar *file, wxChar *sectionName,
342 int chapter, int section, int subsection, int subsubsection)
343{
344 TexRef *texRef = (TexRef *)TexReferences.Get(name);
345 if (texRef) TexReferences.Delete(name);
346
347 wxChar buf[100];
348 buf[0] = 0;
349/*
350 if (sectionName)
351 {
352 wxStrcat(buf, sectionName);
353 wxStrcat(buf, " ");
354 }
355*/
356 if (chapter)
357 {
358 wxChar buf2[10];
359 wxSnprintf(buf2, sizeof(buf2), _T("%d"), chapter);
360 wxStrcat(buf, buf2);
361 }
362 if (section)
363 {
364 wxChar buf2[10];
365 if (chapter)
366 wxStrcat(buf, _T("."));
367
368 wxSnprintf(buf2, sizeof(buf2), _T("%d"), section);
369 wxStrcat(buf, buf2);
370 }
371 if (subsection)
372 {
373 wxChar buf2[10];
374 wxStrcat(buf, _T("."));
375 wxSnprintf(buf2, sizeof(buf2), _T("%d"), subsection);
376 wxStrcat(buf, buf2);
377 }
378 if (subsubsection)
379 {
380 wxChar buf2[10];
381 wxStrcat(buf, _T("."));
382 wxSnprintf(buf2, sizeof(buf2), _T("%d"), subsubsection);
383 wxStrcat(buf, buf2);
384 }
385 wxChar *tmp = ((wxStrlen(buf) > 0) ? buf : (wxChar *)NULL);
386 TexReferences.Put(name, new TexRef(name, file, tmp, sectionName));
387}
388
389void WriteTexReferences(wxChar *filename)
390{
391 wxString name = filename;
392 wxTextFile file;
393
394 if (!(wxFileExists(name)?file.Open(name):file.Create(name)))
395 return;
396
397 file.Clear();
398
399 TexReferences.BeginFind();
400 wxHashTable::Node *node = TexReferences.Next();
401 while (node)
402 {
403 Tex2RTFYield();
404 TexRef *ref = (TexRef *)node->GetData();
405 wxString converter = ref->refLabel;
406 converter << wxT(" ");
407 converter << (ref->refFile ? ref->refFile : _T("??"));
408 converter << wxT(" ");
409 converter << (ref->sectionName ? ref->sectionName : _T("??")) ;
410 converter << wxT(" ");
411 converter << (ref->sectionNumber ? ref->sectionNumber : _T("??")) ;
412 file.AddLine(converter);
413
414 if (!ref->sectionNumber || (wxStrcmp(ref->sectionNumber, _T("??")) == 0 && wxStrcmp(ref->sectionName, _T("??")) == 0))
415 {
416 wxChar buf[200];
417 wxSnprintf(buf, sizeof(buf), _T("Warning: reference %s not resolved."), ref->refLabel);
418 OnInform(buf);
419 }
420 node = TexReferences.Next();
421 }
422
423 file.Write();
424 file.Close();
425}
426
427void ReadTexReferences(wxChar *filename)
428{
429 wxString name = filename;
430
431 if (!wxFileExists(name))
432 return;
433
434 wxTextFile file;
435 if (!file.Open(name))
436 return;
437
438 wxString line;
439 for ( line = file.GetFirstLine(); !file.Eof(); line = file.GetNextLine() )
440 {
441 wxString labelStr = line.BeforeFirst(wxT(' '));
442 line = line.AfterFirst(wxT(' '));
443 wxString fileStr = line.BeforeFirst(wxT(' '));
444 line = line.AfterFirst(wxT(' '));
445 wxString sectionNameStr = line.BeforeFirst(wxT(' '));
446 wxString sectionStr = line.AfterFirst(wxT(' '));
447
448 // gt - needed to trick the hash table "TexReferences" into deleting the key
449 // strings it creates in the Put() function, but not the item that is
450 // created here, as that is destroyed elsewhere. Without doing this, there
451 // were massive memory leaks
452 TexReferences.DeleteContents(true);
453 TexReferences.Put(
454 labelStr,
455 new TexRef(
456 labelStr.c_str(),
457 fileStr.c_str(),
458 sectionStr.c_str(),
459 sectionNameStr.c_str()
460 )
461 );
462 TexReferences.DeleteContents(false);
463 }
464}
465
466
467/*
468 * Bibliography-handling code
469 *
470 */
471
472void BibEatWhiteSpace(wxString& line)
473{
474 while(!line.empty() && (line[0] == _T(' ') || line[0] == _T('\t') || line[0] == (wxChar)EOF))
475 {
476 if (line[0] == '\r')
477 BibLine ++;
478 line = line.substr(1);
479 }
480
481 // Ignore end-of-line comments
482 if ( !line.empty() && (line[0] == _T('%') || line[0] == _T(';') || line[0] == _T('#')))
483 {
484 line.clear();
485 }
486}
487
488void BibEatWhiteSpace(wxSTD istream& str)
489{
490 char ch = (char)str.peek();
491
492 while (!str.eof() && (ch == ' ' || ch == '\t' || ch == 13 || ch == 10 || ch == (char)EOF))
493 {
494 if (ch == 10)
495 BibLine ++;
496 str.get(ch);
497 if ((ch == (char)EOF) || str.eof()) return;
498 ch = (char)str.peek();
499 }
500
501 // Ignore end-of-line comments
502 if (ch == '%' || ch == ';' || ch == '#')
503 {
504 str.get(ch);
505 ch = (char)str.peek();
506 while (ch != 10 && ch != 13 && !str.eof())
507 {
508 str.get(ch);
509 ch = (char)str.peek();
510 }
511 BibEatWhiteSpace(str);
512 }
513}
514
515// Read word up to { or , or space
516wxString BibReadWord(wxString& line)
517{
518 wxString val;
519
520 while (!line.empty() &&
521 line[0] != _T('\t') &&
522 line[0] != _T(' ') &&
523 line[0] != _T('{') &&
524 line[0] != _T('(') &&
525 line[0] != _T(',') &&
526 line[0] != _T('='))
527 {
528 val << line[0];
529 line = line.substr(1);
530 }
531 return val;
532}
533
534void BibReadWord(wxSTD istream& istr, wxChar *buffer)
535{
536 int i = 0;
537 buffer[i] = 0;
538 char ch = (char)istr.peek();
539 while (!istr.eof() && ch != ' ' && ch != '{' && ch != '(' && ch != 13 && ch != 10 && ch != '\t' &&
540 ch != ',' && ch != '=')
541 {
542 istr.get(ch);
543 buffer[i] = ch;
544 i ++;
545 ch = (char)istr.peek();
546 }
547 buffer[i] = 0;
548}
549
550// Read string (double-quoted or not) to end quote or EOL
551wxString BibReadToEOL(wxString& line)
552{
553 if(line.empty())
554 return wxEmptyString;
555
556 wxString val;
557 bool inQuotes = false;
558 if (line[0] == _T('"'))
559 {
560 line = line.substr(1);
561 inQuotes = true;
562 }
563 // If in quotes, read white space too. If not,
564 // stop at white space or comment.
565 while (!line.empty() && line[0] != _T('"') &&
566 (inQuotes || ((line[0] != _T(' ')) && (line[0] != '\t') &&
567 (line[0] != _T(';')) && (line[0] != _T('%')) && (line[0] != _T('#')))))
568 {
569 val << line[0];
570 line = line.substr(1);
571 }
572 if (!line.empty() && line[0] == '"')
573 line = line.substr(1);
574
575 return val;
576}
577
578void BibReadToEOL(wxSTD istream& istr, wxChar *buffer)
579{
580 int i = 0;
581 buffer[i] = 0;
582 char ch = (char)istr.peek();
583 bool inQuotes = false;
584 if (ch == '"')
585 {
586 istr.get(ch);
587 ch = (char)istr.peek();
588 inQuotes = true;
589 }
590 // If in quotes, read white space too. If not,
591 // stop at white space or comment.
592 while (!istr.eof() && ch != 13 && ch != 10 && ch != _T('"') &&
593 (inQuotes || ((ch != _T(' ')) && (ch != 9) &&
594 (ch != _T(';')) && (ch != _T('%')) && (ch != _T('#')))))
595 {
596 istr.get(ch);
597 buffer[i] = ch;
598 i ++;
599 ch = (char)istr.peek();
600 }
601 if (ch == '"')
602 istr.get(ch);
603 buffer[i] = 0;
604}
605
606// Read }-terminated value, taking nested braces into account.
607wxString BibReadValue(wxString& line,
608 bool ignoreBraces = true,
609 bool quotesMayTerminate = true)
610{
611 wxString val;
612 int braceCount = 1;
613 bool stopping = false;
614
615 if (line.length() >= 4000)
616 {
617 wxChar buf[100];
618 wxSnprintf(buf, sizeof(buf), _T("Sorry, value > 4000 chars in bib file at line %ld."), BibLine);
619 wxLogError(buf, "Tex2RTF Fatal Error");
620 return wxEmptyString;
621 }
622
623 while (!line.empty() && !stopping)
624 {
625 wxChar ch = line[0];
626 line = line.substr(1);
627
628 if (ch == _T('{'))
629 braceCount ++;
630
631 if (ch == _T('}'))
632 {
633 braceCount --;
634 if (braceCount == 0)
635 {
636 stopping = true;
637 break;
638 }
639 }
640 else if (quotesMayTerminate && ch == _T('"'))
641 {
642 stopping = true;
643 break;
644 }
645
646 if (!stopping)
647 {
648 if (!ignoreBraces || (ch != _T('{') && ch != _T('}')))
649 {
650 val << ch;
651 }
652 }
653 }
654
655 return val;
656}
657
658void BibReadValue(wxSTD istream& istr, wxChar *buffer, bool ignoreBraces = true,
659 bool quotesMayTerminate = true)
660{
661 int braceCount = 1;
662 int i = 0;
663 buffer[i] = 0;
664 char ch = (char)istr.peek();
665 bool stopping = false;
666 while (!istr.eof() && !stopping)
667 {
668// i ++;
669 if (i >= 4000)
670 {
671 wxChar buf[100];
672 wxSnprintf(buf, sizeof(buf), _T("Sorry, value > 4000 chars in bib file at line %ld."), BibLine);
673 wxLogError(buf, "Tex2RTF Fatal Error");
674 return;
675 }
676 istr.get(ch);
677
678 if (ch == '{')
679 braceCount ++;
680
681 if (ch == '}')
682 {
683 braceCount --;
684 if (braceCount == 0)
685 {
686 stopping = true;
687 break;
688 }
689 }
690 else if (quotesMayTerminate && ch == '"')
691 {
692 stopping = true;
693 break;
694 }
695 if (!stopping)
696 {
697 if (!ignoreBraces || (ch != '{' && ch != '}'))
698 {
699 buffer[i] = ch;
700 i ++;
701 }
702 }
703 if (ch == 10)
704 BibLine ++;
705 }
706 buffer[i] = 0;
707 wxUnusedVar(stopping);
708}
709
710bool ReadBib(const wxChar *filename)
711{
712 if (!wxFileExists(filename))
713 return false;
714
715 wxString name = filename;
716 wxChar buf[300];
717 wxSTD ifstream istr((char const *)name.fn_str(), wxSTD ios::in);
718 if (istr.bad()) return false;
719
720 BibLine = 1;
721
722 OnInform(_T("Reading .bib file..."));
723
724 char ch;
725 wxChar fieldValue[4000];
726 wxChar recordType[100];
727 wxChar recordKey[100];
728 wxChar recordField[100];
729 while (!istr.eof())
730 {
731 Tex2RTFYield();
732
733 BibEatWhiteSpace(istr);
734 istr.get(ch);
735 if (ch != '@')
736 {
737 wxSnprintf(buf, sizeof(buf), _T("Expected @: malformed bib file at line %ld (%s)"), BibLine, filename);
738 OnError(buf);
739 return false;
740 }
741 BibReadWord(istr, recordType);
742 BibEatWhiteSpace(istr);
743 istr.get(ch);
744 if (ch != '{' && ch != '(')
745 {
746 wxSnprintf(buf, sizeof(buf), _T("Expected { or ( after record type: malformed .bib file at line %ld (%s)"), BibLine, filename);
747 OnError(buf);
748 return false;
749 }
750 BibEatWhiteSpace(istr);
751 if (StringMatch(recordType, _T("string"), false, true))
752 {
753 BibReadWord(istr, recordType);
754 BibEatWhiteSpace(istr);
755 istr.get(ch);
756 if (ch != '=')
757 {
758 wxSnprintf(buf, sizeof(buf), _T("Expected = after string key: malformed .bib file at line %ld (%s)"), BibLine, filename);
759 OnError(buf);
760 return false;
761 }
762 BibEatWhiteSpace(istr);
763 istr.get(ch);
764 if (ch != '"' && ch != '{')
765 {
766 wxSnprintf(buf, sizeof(buf), _T("Expected = after string key: malformed .bib file at line %ld (%s)"), BibLine, filename);
767 OnError(buf);
768 return false;
769 }
770 BibReadValue(istr, fieldValue);
771
772 // Now put in hash table if necesary
773 if (!BibStringTable.Get(recordType))
774 BibStringTable.Put(recordType, (wxObject *)copystring(fieldValue));
775
776 // Read closing ) or }
777 BibEatWhiteSpace(istr);
778 istr.get(ch);
779 BibEatWhiteSpace(istr);
780 }
781 else
782 {
783 BibReadWord(istr, recordKey);
784
785 BibEntry *bibEntry = new BibEntry;
786 bibEntry->key = copystring(recordKey);
787 bibEntry->type = copystring(recordType);
788
789 bool moreRecords = true;
790 while (moreRecords && !istr.eof())
791 {
792 BibEatWhiteSpace(istr);
793 istr.get(ch);
794 if (ch == '}' || ch == ')')
795 {
796 moreRecords = false;
797 }
798 else if (ch == ',')
799 {
800 BibEatWhiteSpace(istr);
801 BibReadWord(istr, recordField);
802 BibEatWhiteSpace(istr);
803 istr.get(ch);
804 if (ch != '=')
805 {
806 wxSnprintf(buf, sizeof(buf), _T("Expected = after field type: malformed .bib file at line %ld (%s)"), BibLine, filename);
807 OnError(buf);
808 return false;
809 }
810 BibEatWhiteSpace(istr);
811 istr.get(ch);
812 if (ch != '{' && ch != '"')
813 {
814 fieldValue[0] = ch;
815 BibReadWord(istr, fieldValue+1);
816
817 // If in the table of strings, replace with string from table.
818 wxChar *s = (wxChar *)BibStringTable.Get(fieldValue);
819 if (s)
820 {
821 wxStrcpy(fieldValue, s);
822 }
823 }
824 else
825 BibReadValue(istr, fieldValue, true, (ch == _T('"') ? true : false));
826
827 // Now we can add a field
828 if (StringMatch(recordField, _T("author"), false, true))
829 bibEntry->author = copystring(fieldValue);
830 else if (StringMatch(recordField, _T("key"), false, true))
831 {}
832 else if (StringMatch(recordField, _T("annotate"), false, true))
833 {}
834 else if (StringMatch(recordField, _T("abstract"), false, true))
835 {}
836 else if (StringMatch(recordField, _T("edition"), false, true))
837 {}
838 else if (StringMatch(recordField, _T("howpublished"), false, true))
839 {}
840 else if (StringMatch(recordField, _T("note"), false, true) || StringMatch(recordField, _T("notes"), false, true))
841 {}
842 else if (StringMatch(recordField, _T("series"), false, true))
843 {}
844 else if (StringMatch(recordField, _T("type"), false, true))
845 {}
846 else if (StringMatch(recordField, _T("keywords"), false, true))
847 {}
848 else if (StringMatch(recordField, _T("editor"), false, true) || StringMatch(recordField, _T("editors"), false, true))
849 bibEntry->editor= copystring(fieldValue);
850 else if (StringMatch(recordField, _T("title"), false, true))
851 bibEntry->title= copystring(fieldValue);
852 else if (StringMatch(recordField, _T("booktitle"), false, true))
853 bibEntry->booktitle= copystring(fieldValue);
854 else if (StringMatch(recordField, _T("journal"), false, true))
855 bibEntry->journal= copystring(fieldValue);
856 else if (StringMatch(recordField, _T("volume"), false, true))
857 bibEntry->volume= copystring(fieldValue);
858 else if (StringMatch(recordField, _T("number"), false, true))
859 bibEntry->number= copystring(fieldValue);
860 else if (StringMatch(recordField, _T("year"), false, true))
861 bibEntry->year= copystring(fieldValue);
862 else if (StringMatch(recordField, _T("month"), false, true))
863 bibEntry->month= copystring(fieldValue);
864 else if (StringMatch(recordField, _T("pages"), false, true))
865 bibEntry->pages= copystring(fieldValue);
866 else if (StringMatch(recordField, _T("publisher"), false, true))
867 bibEntry->publisher= copystring(fieldValue);
868 else if (StringMatch(recordField, _T("address"), false, true))
869 bibEntry->address= copystring(fieldValue);
870 else if (StringMatch(recordField, _T("institution"), false, true) || StringMatch(recordField, _T("school"), false, true))
871 bibEntry->institution= copystring(fieldValue);
872 else if (StringMatch(recordField, _T("organization"), false, true) || StringMatch(recordField, _T("organisation"), false, true))
873 bibEntry->organization= copystring(fieldValue);
874 else if (StringMatch(recordField, _T("comment"), false, true) || StringMatch(recordField, _T("comments"), false, true))
875 bibEntry->comment= copystring(fieldValue);
876 else if (StringMatch(recordField, _T("annote"), false, true))
877 bibEntry->comment= copystring(fieldValue);
878 else if (StringMatch(recordField, _T("chapter"), false, true))
879 bibEntry->chapter= copystring(fieldValue);
880 else
881 {
882 wxSnprintf(buf, sizeof(buf), _T("Unrecognised bib field type %s at line %ld (%s)"), recordField, BibLine, filename);
883 OnError(buf);
884 }
885 }
886 }
887 BibList.Append(recordKey, bibEntry);
888 BibEatWhiteSpace(istr);
889 }
890 }
891 return true;
892}
893
894void OutputBibItem(TexRef *ref, BibEntry *bib)
895{
896 Tex2RTFYield();
897
898 OnMacro(ltNUMBEREDBIBITEM, 2, true);
899 OnArgument(ltNUMBEREDBIBITEM, 1, true);
900 TexOutput(ref->sectionNumber);
901 OnArgument(ltNUMBEREDBIBITEM, 1, false);
902 OnArgument(ltNUMBEREDBIBITEM, 2, true);
903
904 TexOutput(_T(" "));
905 OnMacro(ltBF, 1, true);
906 OnArgument(ltBF, 1, true);
907 if (bib->author)
908 TexOutput(bib->author);
909 OnArgument(ltBF, 1, false);
910 OnMacro(ltBF, 1, false);
911 if (bib->author && (wxStrlen(bib->author) > 0) && (bib->author[wxStrlen(bib->author) - 1] != '.'))
912 TexOutput(_T(". "));
913 else
914 TexOutput(_T(" "));
915
916 if (bib->year)
917 {
918 TexOutput(bib->year);
919 }
920 if (bib->month)
921 {
922 TexOutput(_T(" ("));
923 TexOutput(bib->month);
924 TexOutput(_T(")"));
925 }
926 if (bib->year || bib->month)
927 TexOutput(_T(". "));
928
929 if (StringMatch(bib->type, _T("article"), false, true))
930 {
931 if (bib->title)
932 {
933 TexOutput(bib->title);
934 TexOutput(_T(". "));
935 }
936 if (bib->journal)
937 {
938 OnMacro(ltIT, 1, true);
939 OnArgument(ltIT, 1, true);
940 TexOutput(bib->journal);
941 OnArgument(ltIT, 1, false);
942 OnMacro(ltIT, 1, false);
943 }
944 if (bib->volume)
945 {
946 TexOutput(_T(", "));
947 OnMacro(ltBF, 1, true);
948 OnArgument(ltBF, 1, true);
949 TexOutput(bib->volume);
950 OnArgument(ltBF, 1, false);
951 OnMacro(ltBF, 1, false);
952 }
953 if (bib->number)
954 {
955 TexOutput(_T("("));
956 TexOutput(bib->number);
957 TexOutput(_T(")"));
958 }
959 if (bib->pages)
960 {
961 TexOutput(_T(", pages "));
962 TexOutput(bib->pages);
963 }
964 TexOutput(_T("."));
965 }
966 else if (StringMatch(bib->type, _T("book"), false, true) ||
967 StringMatch(bib->type, _T("unpublished"), false, true) ||
968 StringMatch(bib->type, _T("manual"), false, true) ||
969 StringMatch(bib->type, _T("phdthesis"), false, true) ||
970 StringMatch(bib->type, _T("mastersthesis"), false, true) ||
971 StringMatch(bib->type, _T("misc"), false, true) ||
972 StringMatch(bib->type, _T("techreport"), false, true) ||
973 StringMatch(bib->type, _T("booklet"), false, true))
974 {
975 if (bib->title || bib->booktitle)
976 {
977 OnMacro(ltIT, 1, true);
978 OnArgument(ltIT, 1, true);
979 TexOutput(bib->title ? bib->title : bib->booktitle);
980 TexOutput(_T(". "));
981 OnArgument(ltIT, 1, false);
982 OnMacro(ltIT, 1, false);
983 }
984 if (StringMatch(bib->type, _T("phdthesis"), false, true))
985 TexOutput(_T("PhD thesis. "));
986 if (StringMatch(bib->type, _T("techreport"), false, true))
987 TexOutput(_T("Technical report. "));
988 if (bib->editor)
989 {
990 TexOutput(_T("Ed. "));
991 TexOutput(bib->editor);
992 TexOutput(_T(". "));
993 }
994 if (bib->institution)
995 {
996 TexOutput(bib->institution);
997 TexOutput(_T(". "));
998 }
999 if (bib->organization)
1000 {
1001 TexOutput(bib->organization);
1002 TexOutput(_T(". "));
1003 }
1004 if (bib->publisher)
1005 {
1006 TexOutput(bib->publisher);
1007 TexOutput(_T(". "));
1008 }
1009 if (bib->address)
1010 {
1011 TexOutput(bib->address);
1012 TexOutput(_T(". "));
1013 }
1014 }
1015 else if (StringMatch(bib->type, _T("inbook"), false, true) ||
1016 StringMatch(bib->type, _T("inproceedings"), false, true) ||
1017 StringMatch(bib->type, _T("incollection"), false, true) ||
1018 StringMatch(bib->type, _T("conference"), false, true))
1019 {
1020 if (bib->title)
1021 {
1022 TexOutput(bib->title);
1023 }
1024 if (bib->booktitle)
1025 {
1026 TexOutput(_T(", from "));
1027 OnMacro(ltIT, 1, true);
1028 OnArgument(ltIT, 1, true);
1029 TexOutput(bib->booktitle);
1030 TexOutput(_T("."));
1031 OnArgument(ltIT, 1, false);
1032 OnMacro(ltIT, 1, false);
1033 }
1034 if (bib->editor)
1035 {
1036 TexOutput(_T(", ed. "));
1037 TexOutput(bib->editor);
1038 }
1039 if (bib->publisher)
1040 {
1041 TexOutput(_T(" "));
1042 TexOutput(bib->publisher);
1043 }
1044 if (bib->address)
1045 {
1046 if (bib->publisher) TexOutput(_T(", "));
1047 else TexOutput(_T(" "));
1048 TexOutput(bib->address);
1049 }
1050 if (bib->publisher || bib->address)
1051 TexOutput(_T("."));
1052
1053 if (bib->volume)
1054 {
1055 TexOutput(_T(" "));
1056 OnMacro(ltBF, 1, true);
1057 OnArgument(ltBF, 1, true);
1058 TexOutput(bib->volume);
1059 OnArgument(ltBF, 1, false);
1060 OnMacro(ltBF, 1, false);
1061 }
1062 if (bib->number)
1063 {
1064 if (bib->volume)
1065 {
1066 TexOutput(_T("("));
1067 TexOutput(bib->number);
1068 TexOutput(_T(")."));
1069 }
1070 else
1071 {
1072 TexOutput(_T(" Number "));
1073 TexOutput(bib->number);
1074 TexOutput(_T("."));
1075 }
1076 }
1077 if (bib->chapter)
1078 {
1079 TexOutput(_T(" Chap. "));
1080 TexOutput(bib->chapter);
1081 }
1082 if (bib->pages)
1083 {
1084 if (bib->chapter) TexOutput(_T(", pages "));
1085 else TexOutput(_T(" Pages "));
1086 TexOutput(bib->pages);
1087 TexOutput(_T("."));
1088 }
1089 }
1090 OnArgument(ltNUMBEREDBIBITEM, 2, false);
1091 OnMacro(ltNUMBEREDBIBITEM, 2, false);
1092}
1093
1094void OutputBib(void)
1095{
1096 // Write the heading
1097 ForceTopicName(_T("bibliography"));
1098 FakeCurrentSection(ReferencesNameString);
1099 ForceTopicName(NULL);
1100
1101 OnMacro(ltPAR, 0, true);
1102 OnMacro(ltPAR, 0, false);
1103
1104 if ((convertMode == TEX_RTF) && !winHelp)
1105 {
1106 OnMacro(ltPAR, 0, true);
1107 OnMacro(ltPAR, 0, false);
1108 }
1109
1110 wxStringListNode *node = CitationList.GetFirst();
1111 while (node)
1112 {
1113 wxChar *citeKey = (wxChar *)node->GetData();
1114// wxNode *texNode = TexReferences.Find(citeKey);
1115 TexRef *ref = (TexRef *)TexReferences.Get(citeKey);
1116 wxNode *bibNode = BibList.Find(citeKey);
1117 if (bibNode && ref)
1118 {
1119 BibEntry *entry = (BibEntry *)bibNode->GetData();
1120 OutputBibItem(ref, entry);
1121 }
1122 node = node->GetNext();
1123 }
1124}
1125
1126static int citeCount = 1;
1127
1128void ResolveBibReferences(void)
1129{
1130 if (CitationList.GetCount() > 0)
1131 OnInform(_T("Resolving bibliographic references..."));
1132
1133 citeCount = 1;
1134 wxChar buf[200];
1135 wxStringListNode *node = CitationList.GetFirst();
1136 while (node)
1137 {
1138 Tex2RTFYield();
1139 wxChar *citeKey = (wxChar *)node->GetData();
1140// wxNode *texNode = TexReferences.Find(citeKey);
1141 TexRef *ref = (TexRef *)TexReferences.Get(citeKey);
1142 wxNode *bibNode = BibList.Find(citeKey);
1143 if (bibNode && ref)
1144 {
1145 // Unused Variable
1146 //BibEntry *entry = (BibEntry *)bibNode->GetData();
1147 if (ref->sectionNumber) delete[] ref->sectionNumber;
1148 wxSnprintf(buf, sizeof(buf), _T("[%d]"), citeCount);
1149 ref->sectionNumber = copystring(buf);
1150 citeCount ++;
1151 }
1152 else
1153 {
1154 wxSnprintf(buf, sizeof(buf), _T("Warning: bib ref %s not resolved."), citeKey);
1155 OnInform(buf);
1156 }
1157 node = node->GetNext();
1158 }
1159}
1160
1161// Remember we need to resolve this citation
1162void AddCitation(const wxChar *citeKey)
1163{
1164 if (!CitationList.Member(citeKey))
1165 CitationList.Add(citeKey);
1166
1167 if (!TexReferences.Get(citeKey))
1168 {
1169 TexReferences.Put(citeKey, new TexRef(citeKey, _T("??"), NULL));
1170 }
1171}
1172
1173TexRef *FindReference(const wxChar *key)
1174{
1175 return (TexRef *)TexReferences.Get(key);
1176}
1177
1178/*
1179 * Custom macro stuff
1180 *
1181 */
1182
1183bool StringTobool(const wxString& val)
1184{
1185 wxString up(val);
1186 up.MakeUpper();
1187
1188 if (up.IsSameAs(_T("YES")) ||
1189 up.IsSameAs(_T("TRUE")) ||
1190 up.IsSameAs(_T("ON")) ||
1191 up.IsSameAs(_T("OK")) |
1192 up.IsSameAs(_T("1")))
1193 return true;
1194
1195 return false;
1196}
1197
1198void RegisterIntSetting (const wxString& s, int *number)
1199{
1200 if (number)
1201 {
1202 long val;
1203 s.ToLong(&val);
1204 *number = (int)val;
1205 }
1206}
1207
1208// Define a variable value from the .ini file
1209wxChar *RegisterSetting(const wxString& settingName, const wxString& settingValue, bool interactive)
1210{
1211 wxString settingValueStr( settingValue );
1212
1213 static wxChar errorCode[100];
1214 wxStrcpy(errorCode, _T("OK"));
1215 if (StringMatch(settingName, _T("chapterName"), false, true))
1216 {
1217 delete[] ChapterNameString;
1218 ChapterNameString = copystring(settingValue);
1219 }
1220 else if (StringMatch(settingName, _T("sectionName"), false, true))
1221 {
1222 delete[] SectionNameString;
1223 SectionNameString = copystring(settingValue);
1224 }
1225 else if (StringMatch(settingName, _T("subsectionName"), false, true))
1226 {
1227 delete[] SubsectionNameString;
1228 SubsectionNameString = copystring(settingValue);
1229 }
1230 else if (StringMatch(settingName, _T("subsubsectionName"), false, true))
1231 {
1232 delete[] SubsubsectionNameString;
1233 SubsubsectionNameString = copystring(settingValue);
1234 }
1235 else if (StringMatch(settingName, _T("indexName"), false, true))
1236 {
1237 delete[] IndexNameString;
1238 IndexNameString = copystring(settingValue);
1239 }
1240 else if (StringMatch(settingName, _T("contentsName"), false, true))
1241 {
1242 delete[] ContentsNameString;
1243 ContentsNameString = copystring(settingValue);
1244 }
1245 else if (StringMatch(settingName, _T("glossaryName"), false, true))
1246 {
1247 delete[] GlossaryNameString;
1248 GlossaryNameString = copystring(settingValue);
1249 }
1250 else if (StringMatch(settingName, _T("referencesName"), false, true))
1251 {
1252 delete[] ReferencesNameString;
1253 ReferencesNameString = copystring(settingValue);
1254 }
1255 else if (StringMatch(settingName, _T("tablesName"), false, true))
1256 {
1257 delete[] TablesNameString;
1258 TablesNameString = copystring(settingValue);
1259 }
1260 else if (StringMatch(settingName, _T("figuresName"), false, true))
1261 {
1262 delete[] FiguresNameString;
1263 FiguresNameString = copystring(settingValue);
1264 }
1265 else if (StringMatch(settingName, _T("tableName"), false, true))
1266 {
1267 delete[] TableNameString;
1268 TableNameString = copystring(settingValue);
1269 }
1270 else if (StringMatch(settingName, _T("figureName"), false, true))
1271 {
1272 delete[] FigureNameString;
1273 FigureNameString = copystring(settingValue);
1274 }
1275 else if (StringMatch(settingName, _T("abstractName"), false, true))
1276 {
1277 delete[] AbstractNameString;
1278 AbstractNameString = copystring(settingValue);
1279 }
1280 else if (StringMatch(settingName, _T("chapterFontSize"), false, true))
1281 RegisterIntSetting(settingValueStr, &chapterFont);
1282 else if (StringMatch(settingName, _T("sectionFontSize"), false, true))
1283 RegisterIntSetting(settingValueStr, &sectionFont);
1284 else if (StringMatch(settingName, _T("subsectionFontSize"), false, true))
1285 RegisterIntSetting(settingValueStr, &subsectionFont);
1286 else if (StringMatch(settingName, _T("titleFontSize"), false, true))
1287 RegisterIntSetting(settingValueStr, &titleFont);
1288 else if (StringMatch(settingName, _T("authorFontSize"), false, true))
1289 RegisterIntSetting(settingValueStr, &authorFont);
1290 else if (StringMatch(settingName, _T("ignoreInput"), false, true))
1291 IgnorableInputFiles.Add(wxFileNameFromPath(settingValue));
1292 else if (StringMatch(settingName, _T("mirrorMargins"), false, true))
1293 mirrorMargins = StringTobool(settingValue);
1294 else if (StringMatch(settingName, _T("runTwice"), false, true))
1295 runTwice = StringTobool(settingValue);
1296 else if (StringMatch(settingName, _T("isInteractive"), false, true))
1297 isInteractive = StringTobool(settingValue);
1298 else if (StringMatch(settingName, _T("headerRule"), false, true))
1299 headerRule = StringTobool(settingValue);
1300 else if (StringMatch(settingName, _T("footerRule"), false, true))
1301 footerRule = StringTobool(settingValue);
1302 else if (StringMatch(settingName, _T("combineSubSections"), false, true))
1303 combineSubSections = StringTobool(settingValue);
1304 else if (StringMatch(settingName, _T("listLabelIndent"), false, true))
1305 RegisterIntSetting(settingValueStr, &labelIndentTab);
1306 else if (StringMatch(settingName, _T("listItemIndent"), false, true))
1307 RegisterIntSetting(settingValueStr, &itemIndentTab);
1308 else if (StringMatch(settingName, _T("useUpButton"), false, true))
1309 useUpButton = StringTobool(settingValue);
1310 else if (StringMatch(settingName, _T("useHeadingStyles"), false, true))
1311 useHeadingStyles = StringTobool(settingValue);
1312 else if (StringMatch(settingName, _T("useWord"), false, true))
1313 useWord = StringTobool(settingValue);
1314 else if (StringMatch(settingName, _T("contentsDepth"), false, true))
1315 RegisterIntSetting(settingValueStr, &contentsDepth);
1316 else if (StringMatch(settingName, _T("generateHPJ"), false, true))
1317 generateHPJ = StringTobool(settingValue);
1318 else if (StringMatch(settingName, _T("truncateFilenames"), false, true))
1319 truncateFilenames = StringTobool(settingValue);
1320 else if (StringMatch(settingName, _T("winHelpVersion"), false, true))
1321 RegisterIntSetting(settingValueStr, &winHelpVersion);
1322 else if (StringMatch(settingName, _T("winHelpContents"), false, true))
1323 winHelpContents = StringTobool(settingValue);
1324 else if (StringMatch(settingName, _T("htmlIndex"), false, true))
1325 htmlIndex = StringTobool(settingValue);
1326 else if (StringMatch(settingName, _T("htmlWorkshopFiles"), false, true))
1327 htmlWorkshopFiles = StringTobool(settingValue);
1328 else if (StringMatch(settingName, _T("htmlFrameContents"), false, true))
1329 htmlFrameContents = StringTobool(settingValue);
1330 else if (StringMatch(settingName, _T("htmlStylesheet"), false, true))
1331 {
1332 if (htmlStylesheet)
1333 delete[] htmlStylesheet;
1334 htmlStylesheet = copystring(settingValue);
1335 }
1336 else if (StringMatch(settingName, _T("upperCaseNames"), false, true))
1337 upperCaseNames = StringTobool(settingValue);
1338 else if (StringMatch(settingName, _T("ignoreBadRefs"), false, true))
1339 ignoreBadRefs = StringTobool(settingValue);
1340 else if (StringMatch(settingName, _T("htmlFaceName"), false, true))
1341 {
1342 delete[] htmlFaceName;
1343 htmlFaceName = copystring(settingValue);
1344 }
1345 else if (StringMatch(settingName, _T("winHelpTitle"), false, true))
1346 {
1347 if (winHelpTitle)
1348 delete[] winHelpTitle;
1349 winHelpTitle = copystring(settingValue);
1350 }
1351 else if (StringMatch(settingName, _T("indexSubsections"), false, true))
1352 indexSubsections = StringTobool(settingValue);
1353 else if (StringMatch(settingName, _T("compatibility"), false, true))
1354 compatibilityMode = StringTobool(settingValue);
1355 else if (StringMatch(settingName, _T("defaultColumnWidth"), false, true))
1356 {
1357 RegisterIntSetting(settingValueStr, &defaultTableColumnWidth);
1358 defaultTableColumnWidth = 20*defaultTableColumnWidth;
1359 }
1360 else if (StringMatch(settingName, _T("bitmapMethod"), false, true))
1361 {
1362 if ((wxStrcmp(settingValue, _T("includepicture")) != 0) && (wxStrcmp(settingValue, _T("hex")) != 0) &&
1363 (wxStrcmp(settingValue, _T("import")) != 0))
1364 {
1365 if (interactive)
1366 OnError(_T("Unknown bitmapMethod"));
1367 wxStrcpy(errorCode, _T("Unknown bitmapMethod"));
1368 }
1369 else
1370 {
1371 delete[] bitmapMethod;
1372 bitmapMethod = copystring(settingValue);
1373 }
1374 }
1375 else if (StringMatch(settingName, _T("htmlBrowseButtons"), false, true))
1376 {
1377 if (wxStrcmp(settingValue, _T("none")) == 0)
1378 htmlBrowseButtons = HTML_BUTTONS_NONE;
1379 else if (wxStrcmp(settingValue, _T("bitmap")) == 0)
1380 htmlBrowseButtons = HTML_BUTTONS_BITMAP;
1381 else if (wxStrcmp(settingValue, _T("text")) == 0)
1382 htmlBrowseButtons = HTML_BUTTONS_TEXT;
1383 else
1384 {
1385 if (interactive)
1386 OnInform(_T("Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text."));
1387 wxStrcpy(errorCode, _T("Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text."));
1388 }
1389 }
1390 else if (StringMatch(settingName, _T("backgroundImage"), false, true))
1391 {
1392 backgroundImageString = copystring(settingValue);
1393 }
1394 else if (StringMatch(settingName, _T("backgroundColour"), false, true))
1395 {
1396 delete[] backgroundColourString;
1397 backgroundColourString = copystring(settingValue);
1398 }
1399 else if (StringMatch(settingName, _T("textColour"), false, true))
1400 {
1401 textColourString = copystring(settingValue);
1402 }
1403 else if (StringMatch(settingName, _T("linkColour"), false, true))
1404 {
1405 linkColourString = copystring(settingValue);
1406 }
1407 else if (StringMatch(settingName, _T("followedLinkColour"), false, true))
1408 {
1409 followedLinkColourString = copystring(settingValue);
1410 }
1411 else if (StringMatch(settingName, _T("conversionMode"), false, true))
1412 {
1413 if (StringMatch(settingValue, _T("RTF"), false, true))
1414 {
1415 winHelp = false; convertMode = TEX_RTF;
1416 }
1417 else if (StringMatch(settingValue, _T("WinHelp"), false, true))
1418 {
1419 winHelp = true; convertMode = TEX_RTF;
1420 }
1421 else if (StringMatch(settingValue, _T("XLP"), false, true) ||
1422 StringMatch(settingValue, _T("wxHelp"), false, true))
1423 {
1424 convertMode = TEX_XLP;
1425 }
1426 else if (StringMatch(settingValue, _T("HTML"), false, true))
1427 {
1428 convertMode = TEX_HTML;
1429 }
1430 else
1431 {
1432 if (interactive)
1433 OnInform(_T("Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML."));
1434 wxStrcpy(errorCode, _T("Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML."));
1435 }
1436 }
1437 else if (StringMatch(settingName, _T("documentFontSize"), false, true))
1438 {
1439 int n;
1440 RegisterIntSetting(settingValueStr, &n);
1441 if (n == 10 || n == 11 || n == 12)
1442 SetFontSizes(n);
1443 else
1444 {
1445 wxChar buf[200];
1446 wxSnprintf(buf, sizeof(buf), _T("Initialisation file error: nonstandard document font size %d."), n);
1447 if (interactive)
1448 OnInform(buf);
1449 wxStrcpy(errorCode, buf);
1450 }
1451 }
1452 else
1453 {
1454 wxChar buf[200];
1455 wxSnprintf(buf, sizeof(buf), _T("Initialisation file error: unrecognised setting %s."), settingName.c_str());
1456 if (interactive)
1457 OnInform(buf);
1458 wxStrcpy(errorCode, buf);
1459 }
1460 return errorCode;
1461}
1462
1463bool ReadCustomMacros(const wxString& filename)
1464{
1465 if (!wxFileExists(filename))
1466 return false;
1467
1468 wxFileInputStream input( filename );
1469 if(!input.Ok()) return false;
1470 wxTextInputStream ini( input );
1471
1472 CustomMacroList.Clear();
1473
1474 while (!input.Eof())
1475 {
1476 wxString line = ini.ReadLine();
1477 BibEatWhiteSpace(line);
1478 if (line.empty()) continue;
1479
1480 if (line[0] != _T('\\')) // Not a macro definition, so must be NAME=VALUE
1481 {
1482 wxString settingName = BibReadWord(line);
1483 BibEatWhiteSpace(line);
1484 if (line.empty() || line[0] != _T('='))
1485 {
1486 OnError(_T("Expected = following name: malformed tex2rtf.ini file."));
1487 return false;
1488 }
1489 else
1490 {
1491 line = line.substr(1);
1492 BibEatWhiteSpace(line);
1493 wxString settingValue = BibReadToEOL(line);
1494 RegisterSetting(settingName, settingValue);
1495 }
1496 }
1497 else
1498 {
1499 line = line.substr(1);
1500 wxString macroName = BibReadWord(line);
1501 BibEatWhiteSpace(line);
1502 if (line[0] != _T('['))
1503 {
1504 OnError(_T("Expected [ followed by number of arguments: malformed tex2rtf.ini file."));
1505 return false;
1506 }
1507 line = line.substr(1);
1508 wxString noAargStr = line.BeforeFirst(_T(']'));
1509 line = line.AfterFirst(_T(']'));
1510 long noArgs;
1511 if (!noAargStr.ToLong(&noArgs) || line.empty())
1512 {
1513 OnError(_T("Expected ] following number of arguments: malformed tex2rtf.ini file."));
1514 return false;
1515 }
1516 BibEatWhiteSpace(line);
1517 if (line[0] != _T('{'))
1518 {
1519 OnError(_T("Expected { followed by macro body: malformed tex2rtf.ini file."));
1520 return false;
1521 }
1522
1523 CustomMacro *macro = new CustomMacro(macroName.c_str(), noArgs, NULL);
1524 wxString macroBody = BibReadValue(line, false, false); // Don't ignore extra braces
1525 if (!macroBody.empty())
1526 macro->macroBody = copystring(macroBody.c_str());
1527
1528 BibEatWhiteSpace(line);
1529 CustomMacroList.Append(macroName, macro);
1530 AddMacroDef(ltCUSTOM_MACRO, macroName.c_str(), noArgs);
1531 }
1532
1533 }
1534 wxChar mbuf[200];
1535 wxSnprintf(mbuf, sizeof(mbuf), _T("Read initialization file %s."), filename.c_str());
1536 OnInform(mbuf);
1537 return true;
1538}
1539
1540CustomMacro *FindCustomMacro(wxChar *name)
1541{
1542 wxNode *node = CustomMacroList.Find(name);
1543 if (node)
1544 {
1545 CustomMacro *macro = (CustomMacro *)node->GetData();
1546 return macro;
1547 }
1548 return NULL;
1549}
1550
1551// Display custom macros
1552void ShowCustomMacros(void)
1553{
1554 wxNode *node = CustomMacroList.GetFirst();
1555 if (!node)
1556 {
1557 OnInform(_T("No custom macros loaded.\n"));
1558 return;
1559 }
1560
1561 wxChar buf[400];
1562 while (node)
1563 {
1564 CustomMacro *macro = (CustomMacro *)node->GetData();
1565 wxSnprintf(buf, sizeof(buf), _T("\\%s[%d]\n {%s}"), macro->macroName, macro->noArgs,
1566 macro->macroBody ? macro->macroBody : _T(""));
1567 OnInform(buf);
1568 node = node->GetNext();
1569 }
1570}
1571
1572// Parse a string into several comma-separated fields
1573wxChar *ParseMultifieldString(wxChar *allFields, int *pos)
1574{
1575 static wxChar buffer[300];
1576 int i = 0;
1577 int fieldIndex = *pos;
1578 int len = wxStrlen(allFields);
1579 int oldPos = *pos;
1580 bool keepGoing = true;
1581 while ((fieldIndex <= len) && keepGoing)
1582 {
1583 if (allFields[fieldIndex] == _T(' '))
1584 {
1585 // Skip
1586 fieldIndex ++;
1587 }
1588 else if (allFields[fieldIndex] == _T(','))
1589 {
1590 *pos = fieldIndex + 1;
1591 keepGoing = false;
1592 }
1593 else if (allFields[fieldIndex] == 0)
1594 {
1595 *pos = fieldIndex + 1;
1596 keepGoing = false;
1597 }
1598 else
1599 {
1600 buffer[i] = allFields[fieldIndex];
1601 fieldIndex ++;
1602 i++;
1603 }
1604 }
1605 buffer[i] = 0;
1606 if (oldPos == (*pos))
1607 *pos = len + 1;
1608
1609 if (i == 0)
1610 return NULL;
1611 else
1612 return buffer;
1613}
1614
1615/*
1616 * Colour tables
1617 *
1618 */
1619
1620ColourTableEntry::ColourTableEntry(const wxChar *theName, unsigned int r, unsigned int g, unsigned int b)
1621{
1622 name = copystring(theName);
1623 red = r;
1624 green = g;
1625 blue = b;
1626}
1627
1628ColourTableEntry::~ColourTableEntry(void)
1629{
1630 delete[] name;
1631}
1632
1633void AddColour(const wxChar *theName, unsigned int r, unsigned int g, unsigned int b)
1634{
1635 wxNode *node = ColourTable.Find(theName);
1636 if (node)
1637 {
1638 ColourTableEntry *entry = (ColourTableEntry *)node->GetData();
1639 if (entry->red == r || entry->green == g || entry->blue == b)
1640 return;
1641 else
1642 {
1643 delete entry;
1644 delete node;
1645 }
1646 }
1647 ColourTableEntry *entry = new ColourTableEntry(theName, r, g, b);
1648 ColourTable.Append(theName, entry);
1649}
1650
1651int FindColourPosition(wxChar *theName)
1652{
1653 int i = 0;
1654 wxNode *node = ColourTable.GetFirst();
1655 while (node)
1656 {
1657 ColourTableEntry *entry = (ColourTableEntry *)node->GetData();
1658 if (wxStrcmp(theName, entry->name) == 0)
1659 return i;
1660 i ++;
1661 node = node->GetNext();
1662 }
1663 return -1;
1664}
1665
1666// Converts e.g. "red" -> "#FF0000"
1667extern void DecToHex(int, wxChar *);
1668bool FindColourHTMLString(wxChar *theName, wxChar *buf)
1669{
1670 wxNode *node = ColourTable.GetFirst();
1671 while (node)
1672 {
1673 ColourTableEntry *entry = (ColourTableEntry *)node->GetData();
1674 if (wxStrcmp(theName, entry->name) == 0)
1675 {
1676 wxStrcpy(buf, _T("#"));
1677
1678 wxChar buf2[3];
1679 DecToHex(entry->red, buf2);
1680 wxStrcat(buf, buf2);
1681 DecToHex(entry->green, buf2);
1682 wxStrcat(buf, buf2);
1683 DecToHex(entry->blue, buf2);
1684 wxStrcat(buf, buf2);
1685
1686 return true;
1687 }
1688 node = node->GetNext();
1689 }
1690 return false;
1691}
1692
1693
1694void InitialiseColourTable(void)
1695{
1696 // \\red0\\green0\\blue0;
1697 AddColour(_T("black"), 0,0,0);
1698
1699 // \\red0\\green0\\blue255;\\red0\\green255\\blue255;\n");
1700 AddColour(_T("cyan"), 0,255,255);
1701
1702 // \\red0\\green255\\blue0;
1703 AddColour(_T("green"), 0,255,0);
1704
1705 // \\red255\\green0\\blue255;
1706 AddColour(_T("magenta"), 255,0,255);
1707
1708 // \\red255\\green0\\blue0;
1709 AddColour(_T("red"), 255,0,0);
1710
1711 // \\red255\\green255\\blue0;
1712 AddColour(_T("yellow"), 255,255,0);
1713
1714 // \\red255\\green255\\blue255;}");
1715 AddColour(_T("white"), 255,255,255);
1716}
1717
1718/*
1719 * The purpose of this is to reduce the number of times wxYield is
1720 * called, since under Windows this can slow things down.
1721 */
1722
1723void Tex2RTFYield(bool force)
1724{
1725#ifdef __WINDOWS__
1726 static int yieldCount = 0;
1727
1728 if (isSync)
1729 return;
1730
1731 if (force)
1732 yieldCount = 0;
1733 if (yieldCount == 0)
1734 {
1735 if (wxTheApp)
1736 wxYield();
1737 yieldCount = 10;
1738 }
1739 yieldCount --;
1740#else
1741 wxUnusedVar(force);
1742#endif
1743}
1744
1745// In both RTF generation and HTML generation for wxHelp version 2,
1746// we need to associate \indexed keywords with the current filename/topics.
1747
1748// Hash table for lists of keywords for topics (WinHelp).
1749wxHashTable TopicTable(wxKEY_STRING);
1750void AddKeyWordForTopic(wxChar *topic, wxChar *entry, wxChar *filename)
1751{
1752 TexTopic *texTopic = (TexTopic *)TopicTable.Get(topic);
1753 if (!texTopic)
1754 {
1755 texTopic = new TexTopic(filename);
1756 texTopic->keywords = new wxStringList;
1757 TopicTable.Put(topic, texTopic);
1758 }
1759
1760 if (!texTopic->keywords->Member(entry))
1761 texTopic->keywords->Add(entry);
1762}
1763
1764void ClearKeyWordTable(void)
1765{
1766 TopicTable.BeginFind();
1767 wxHashTable::Node *node = TopicTable.Next();
1768 while (node)
1769 {
1770 TexTopic *texTopic = (TexTopic *)node->GetData();
1771 delete texTopic;
1772 node = TopicTable.Next();
1773 }
1774 TopicTable.Clear();
1775}
1776
1777
1778/*
1779 * TexTopic structure
1780 */
1781
1782TexTopic::TexTopic(wxChar *f)
1783{
1784 if (f)
1785 filename = copystring(f);
1786 else
1787 filename = NULL;
1788 hasChildren = false;
1789 keywords = NULL;
1790}
1791
1792TexTopic::~TexTopic(void)
1793{
1794 if (keywords)
1795 delete keywords;
1796 if (filename)
1797 delete[] filename;
1798}
1799
1800// Convert case, according to upperCaseNames setting.
1801wxChar *ConvertCase(wxChar *s)
1802{
1803 static wxChar buf[256];
1804 int len = wxStrlen(s);
1805 int i;
1806 if (upperCaseNames)
1807 for (i = 0; i < len; i ++)
1808 buf[i] = (wxChar)wxToupper(s[i]);
1809 else
1810 for (i = 0; i < len; i ++)
1811 buf[i] = (wxChar)wxTolower(s[i]);
1812 buf[i] = 0;
1813 return buf;
1814}
1815
1816// if substring is true, search for str1 in str2
1817bool StringMatch(const wxChar *str1, const wxChar *str2, bool subString,
1818 bool exact)
1819{
1820 if (subString)
1821 {
1822 wxString Sstr1(str1);
1823 wxString Sstr2(str2);
1824 if (!exact)
1825 {
1826 Sstr1.MakeUpper();
1827 Sstr2.MakeUpper();
1828 }
1829 return Sstr2.Index(Sstr1) != (size_t)wxNOT_FOUND;
1830 }
1831 else
1832 return exact ? wxString(str2).Cmp(str1) == 0 :
1833 wxString(str2).CmpNoCase(str1) == 0;
1834}