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