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