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