]> git.saurik.com Git - wxWidgets.git/blob - utils/tex2rtf/src/texutils.cpp
Fixed unicode reference file writing under some builds.
[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("ON")) ||
1189 up.IsSameAs(_T("OK")) |
1190 up.IsSameAs(_T("1")))
1191 return true;
1192
1193 return false;
1194 }
1195
1196 void RegisterIntSetting (const wxString& s, int *number)
1197 {
1198 if (number)
1199 {
1200 long val;
1201 s.ToLong(&val);
1202 *number = (int)val;
1203 }
1204 }
1205
1206 // Define a variable value from the .ini file
1207 wxChar *RegisterSetting(const wxString& settingName, const wxString& settingValue, bool interactive)
1208 {
1209 wxString settingValueStr( settingValue );
1210
1211 static wxChar errorCode[100];
1212 wxStrcpy(errorCode, _T("OK"));
1213 if (StringMatch(settingName, _T("chapterName"), false, true))
1214 {
1215 delete[] ChapterNameString;
1216 ChapterNameString = copystring(settingValue);
1217 }
1218 else if (StringMatch(settingName, _T("sectionName"), false, true))
1219 {
1220 delete[] SectionNameString;
1221 SectionNameString = copystring(settingValue);
1222 }
1223 else if (StringMatch(settingName, _T("subsectionName"), false, true))
1224 {
1225 delete[] SubsectionNameString;
1226 SubsectionNameString = copystring(settingValue);
1227 }
1228 else if (StringMatch(settingName, _T("subsubsectionName"), false, true))
1229 {
1230 delete[] SubsubsectionNameString;
1231 SubsubsectionNameString = copystring(settingValue);
1232 }
1233 else if (StringMatch(settingName, _T("indexName"), false, true))
1234 {
1235 delete[] IndexNameString;
1236 IndexNameString = copystring(settingValue);
1237 }
1238 else if (StringMatch(settingName, _T("contentsName"), false, true))
1239 {
1240 delete[] ContentsNameString;
1241 ContentsNameString = copystring(settingValue);
1242 }
1243 else if (StringMatch(settingName, _T("glossaryName"), false, true))
1244 {
1245 delete[] GlossaryNameString;
1246 GlossaryNameString = copystring(settingValue);
1247 }
1248 else if (StringMatch(settingName, _T("referencesName"), false, true))
1249 {
1250 delete[] ReferencesNameString;
1251 ReferencesNameString = copystring(settingValue);
1252 }
1253 else if (StringMatch(settingName, _T("tablesName"), false, true))
1254 {
1255 delete[] TablesNameString;
1256 TablesNameString = copystring(settingValue);
1257 }
1258 else if (StringMatch(settingName, _T("figuresName"), false, true))
1259 {
1260 delete[] FiguresNameString;
1261 FiguresNameString = copystring(settingValue);
1262 }
1263 else if (StringMatch(settingName, _T("tableName"), false, true))
1264 {
1265 delete[] TableNameString;
1266 TableNameString = copystring(settingValue);
1267 }
1268 else if (StringMatch(settingName, _T("figureName"), false, true))
1269 {
1270 delete[] FigureNameString;
1271 FigureNameString = copystring(settingValue);
1272 }
1273 else if (StringMatch(settingName, _T("abstractName"), false, true))
1274 {
1275 delete[] AbstractNameString;
1276 AbstractNameString = copystring(settingValue);
1277 }
1278 else if (StringMatch(settingName, _T("chapterFontSize"), false, true))
1279 RegisterIntSetting(settingValueStr, &chapterFont);
1280 else if (StringMatch(settingName, _T("sectionFontSize"), false, true))
1281 RegisterIntSetting(settingValueStr, &sectionFont);
1282 else if (StringMatch(settingName, _T("subsectionFontSize"), false, true))
1283 RegisterIntSetting(settingValueStr, &subsectionFont);
1284 else if (StringMatch(settingName, _T("titleFontSize"), false, true))
1285 RegisterIntSetting(settingValueStr, &titleFont);
1286 else if (StringMatch(settingName, _T("authorFontSize"), false, true))
1287 RegisterIntSetting(settingValueStr, &authorFont);
1288 else if (StringMatch(settingName, _T("ignoreInput"), false, true))
1289 IgnorableInputFiles.Add(wxFileNameFromPath(settingValue));
1290 else if (StringMatch(settingName, _T("mirrorMargins"), false, true))
1291 mirrorMargins = StringTobool(settingValue);
1292 else if (StringMatch(settingName, _T("runTwice"), false, true))
1293 runTwice = StringTobool(settingValue);
1294 else if (StringMatch(settingName, _T("isInteractive"), false, true))
1295 isInteractive = StringTobool(settingValue);
1296 else if (StringMatch(settingName, _T("headerRule"), false, true))
1297 headerRule = StringTobool(settingValue);
1298 else if (StringMatch(settingName, _T("footerRule"), false, true))
1299 footerRule = StringTobool(settingValue);
1300 else if (StringMatch(settingName, _T("combineSubSections"), false, true))
1301 combineSubSections = StringTobool(settingValue);
1302 else if (StringMatch(settingName, _T("listLabelIndent"), false, true))
1303 RegisterIntSetting(settingValueStr, &labelIndentTab);
1304 else if (StringMatch(settingName, _T("listItemIndent"), false, true))
1305 RegisterIntSetting(settingValueStr, &itemIndentTab);
1306 else if (StringMatch(settingName, _T("useUpButton"), false, true))
1307 useUpButton = StringTobool(settingValue);
1308 else if (StringMatch(settingName, _T("useHeadingStyles"), false, true))
1309 useHeadingStyles = StringTobool(settingValue);
1310 else if (StringMatch(settingName, _T("useWord"), false, true))
1311 useWord = StringTobool(settingValue);
1312 else if (StringMatch(settingName, _T("contentsDepth"), false, true))
1313 RegisterIntSetting(settingValueStr, &contentsDepth);
1314 else if (StringMatch(settingName, _T("generateHPJ"), false, true))
1315 generateHPJ = StringTobool(settingValue);
1316 else if (StringMatch(settingName, _T("truncateFilenames"), false, true))
1317 truncateFilenames = StringTobool(settingValue);
1318 else if (StringMatch(settingName, _T("winHelpVersion"), false, true))
1319 RegisterIntSetting(settingValueStr, &winHelpVersion);
1320 else if (StringMatch(settingName, _T("winHelpContents"), false, true))
1321 winHelpContents = StringTobool(settingValue);
1322 else if (StringMatch(settingName, _T("htmlIndex"), false, true))
1323 htmlIndex = StringTobool(settingValue);
1324 else if (StringMatch(settingName, _T("htmlWorkshopFiles"), false, true))
1325 htmlWorkshopFiles = StringTobool(settingValue);
1326 else if (StringMatch(settingName, _T("htmlFrameContents"), false, true))
1327 htmlFrameContents = StringTobool(settingValue);
1328 else if (StringMatch(settingName, _T("htmlStylesheet"), false, true))
1329 {
1330 if (htmlStylesheet)
1331 delete[] htmlStylesheet;
1332 htmlStylesheet = copystring(settingValue);
1333 }
1334 else if (StringMatch(settingName, _T("upperCaseNames"), false, true))
1335 upperCaseNames = StringTobool(settingValue);
1336 else if (StringMatch(settingName, _T("ignoreBadRefs"), false, true))
1337 ignoreBadRefs = StringTobool(settingValue);
1338 else if (StringMatch(settingName, _T("htmlFaceName"), false, true))
1339 {
1340 delete[] htmlFaceName;
1341 htmlFaceName = copystring(settingValue);
1342 }
1343 else if (StringMatch(settingName, _T("winHelpTitle"), false, true))
1344 {
1345 if (winHelpTitle)
1346 delete[] winHelpTitle;
1347 winHelpTitle = copystring(settingValue);
1348 }
1349 else if (StringMatch(settingName, _T("indexSubsections"), false, true))
1350 indexSubsections = StringTobool(settingValue);
1351 else if (StringMatch(settingName, _T("compatibility"), false, true))
1352 compatibilityMode = StringTobool(settingValue);
1353 else if (StringMatch(settingName, _T("defaultColumnWidth"), false, true))
1354 {
1355 RegisterIntSetting(settingValueStr, &defaultTableColumnWidth);
1356 defaultTableColumnWidth = 20*defaultTableColumnWidth;
1357 }
1358 else if (StringMatch(settingName, _T("bitmapMethod"), false, true))
1359 {
1360 if ((wxStrcmp(settingValue, _T("includepicture")) != 0) && (wxStrcmp(settingValue, _T("hex")) != 0) &&
1361 (wxStrcmp(settingValue, _T("import")) != 0))
1362 {
1363 if (interactive)
1364 OnError(_T("Unknown bitmapMethod"));
1365 wxStrcpy(errorCode, _T("Unknown bitmapMethod"));
1366 }
1367 else
1368 {
1369 delete[] bitmapMethod;
1370 bitmapMethod = copystring(settingValue);
1371 }
1372 }
1373 else if (StringMatch(settingName, _T("htmlBrowseButtons"), false, true))
1374 {
1375 if (wxStrcmp(settingValue, _T("none")) == 0)
1376 htmlBrowseButtons = HTML_BUTTONS_NONE;
1377 else if (wxStrcmp(settingValue, _T("bitmap")) == 0)
1378 htmlBrowseButtons = HTML_BUTTONS_BITMAP;
1379 else if (wxStrcmp(settingValue, _T("text")) == 0)
1380 htmlBrowseButtons = HTML_BUTTONS_TEXT;
1381 else
1382 {
1383 if (interactive)
1384 OnInform(_T("Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text."));
1385 wxStrcpy(errorCode, _T("Initialisation file error: htmlBrowseButtons must be one of none, bitmap, or text."));
1386 }
1387 }
1388 else if (StringMatch(settingName, _T("backgroundImage"), false, true))
1389 {
1390 backgroundImageString = copystring(settingValue);
1391 }
1392 else if (StringMatch(settingName, _T("backgroundColour"), false, true))
1393 {
1394 delete[] backgroundColourString;
1395 backgroundColourString = copystring(settingValue);
1396 }
1397 else if (StringMatch(settingName, _T("textColour"), false, true))
1398 {
1399 textColourString = copystring(settingValue);
1400 }
1401 else if (StringMatch(settingName, _T("linkColour"), false, true))
1402 {
1403 linkColourString = copystring(settingValue);
1404 }
1405 else if (StringMatch(settingName, _T("followedLinkColour"), false, true))
1406 {
1407 followedLinkColourString = copystring(settingValue);
1408 }
1409 else if (StringMatch(settingName, _T("conversionMode"), false, true))
1410 {
1411 if (StringMatch(settingValue, _T("RTF"), false, true))
1412 {
1413 winHelp = false; convertMode = TEX_RTF;
1414 }
1415 else if (StringMatch(settingValue, _T("WinHelp"), false, true))
1416 {
1417 winHelp = true; convertMode = TEX_RTF;
1418 }
1419 else if (StringMatch(settingValue, _T("XLP"), false, true) ||
1420 StringMatch(settingValue, _T("wxHelp"), false, true))
1421 {
1422 convertMode = TEX_XLP;
1423 }
1424 else if (StringMatch(settingValue, _T("HTML"), false, true))
1425 {
1426 convertMode = TEX_HTML;
1427 }
1428 else
1429 {
1430 if (interactive)
1431 OnInform(_T("Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML."));
1432 wxStrcpy(errorCode, _T("Initialisation file error: conversionMode must be one of\nRTF, WinHelp, XLP (or wxHelp), HTML."));
1433 }
1434 }
1435 else if (StringMatch(settingName, _T("documentFontSize"), false, true))
1436 {
1437 int n;
1438 RegisterIntSetting(settingValueStr, &n);
1439 if (n == 10 || n == 11 || n == 12)
1440 SetFontSizes(n);
1441 else
1442 {
1443 wxChar buf[200];
1444 wxSnprintf(buf, sizeof(buf), _T("Initialisation file error: nonstandard document font size %d."), n);
1445 if (interactive)
1446 OnInform(buf);
1447 wxStrcpy(errorCode, buf);
1448 }
1449 }
1450 else
1451 {
1452 wxChar buf[200];
1453 wxSnprintf(buf, sizeof(buf), _T("Initialisation file error: unrecognised setting %s."), settingName.c_str());
1454 if (interactive)
1455 OnInform(buf);
1456 wxStrcpy(errorCode, buf);
1457 }
1458 return errorCode;
1459 }
1460
1461 bool ReadCustomMacros(const wxString& filename)
1462 {
1463 if (!wxFileExists(filename))
1464 return false;
1465
1466 wxFileInputStream input( filename );
1467 if(!input.Ok()) return false;
1468 wxTextInputStream ini( input );
1469
1470 CustomMacroList.Clear();
1471
1472 while (!input.Eof())
1473 {
1474 wxString line = ini.ReadLine();
1475 BibEatWhiteSpace(line);
1476 if (line.empty()) continue;
1477
1478 if (line[0] != _T('\\')) // Not a macro definition, so must be NAME=VALUE
1479 {
1480 wxString settingName = BibReadWord(line);
1481 BibEatWhiteSpace(line);
1482 if (line.empty() || line[0] != _T('='))
1483 {
1484 OnError(_T("Expected = following name: malformed tex2rtf.ini file."));
1485 return false;
1486 }
1487 else
1488 {
1489 line = line.substr(1);
1490 BibEatWhiteSpace(line);
1491 wxString settingValue = BibReadToEOL(line);
1492 RegisterSetting(settingName, settingValue);
1493 }
1494 }
1495 else
1496 {
1497 line = line.substr(1);
1498 wxString macroName = BibReadWord(line);
1499 BibEatWhiteSpace(line);
1500 if (line[0] != _T('['))
1501 {
1502 OnError(_T("Expected [ followed by number of arguments: malformed tex2rtf.ini file."));
1503 return false;
1504 }
1505 line = line.substr(1);
1506 wxString noAargStr = line.BeforeFirst(_T(']'));
1507 line = line.AfterFirst(_T(']'));
1508 long noArgs;
1509 if (!noAargStr.ToLong(&noArgs) || line.empty())
1510 {
1511 OnError(_T("Expected ] following number of arguments: malformed tex2rtf.ini file."));
1512 return false;
1513 }
1514 BibEatWhiteSpace(line);
1515 if (line[0] != _T('{'))
1516 {
1517 OnError(_T("Expected { followed by macro body: malformed tex2rtf.ini file."));
1518 return false;
1519 }
1520
1521 CustomMacro *macro = new CustomMacro(macroName.c_str(), noArgs, NULL);
1522 wxString macroBody = BibReadValue(line, false, false); // Don't ignore extra braces
1523 if (!macroBody.empty())
1524 macro->macroBody = copystring(macroBody.c_str());
1525
1526 BibEatWhiteSpace(line);
1527 CustomMacroList.Append(macroName.c_str(), macro);
1528 AddMacroDef(ltCUSTOM_MACRO, macroName.c_str(), noArgs);
1529 }
1530
1531 }
1532 wxChar mbuf[200];
1533 wxSnprintf(mbuf, sizeof(mbuf), _T("Read initialization file %s."), filename.c_str());
1534 OnInform(mbuf);
1535 return true;
1536 }
1537
1538 CustomMacro *FindCustomMacro(wxChar *name)
1539 {
1540 wxNode *node = CustomMacroList.Find(name);
1541 if (node)
1542 {
1543 CustomMacro *macro = (CustomMacro *)node->GetData();
1544 return macro;
1545 }
1546 return NULL;
1547 }
1548
1549 // Display custom macros
1550 void ShowCustomMacros(void)
1551 {
1552 wxNode *node = CustomMacroList.GetFirst();
1553 if (!node)
1554 {
1555 OnInform(_T("No custom macros loaded.\n"));
1556 return;
1557 }
1558
1559 wxChar buf[400];
1560 while (node)
1561 {
1562 CustomMacro *macro = (CustomMacro *)node->GetData();
1563 wxSnprintf(buf, sizeof(buf), _T("\\%s[%d]\n {%s}"), macro->macroName, macro->noArgs,
1564 macro->macroBody ? macro->macroBody : _T(""));
1565 OnInform(buf);
1566 node = node->GetNext();
1567 }
1568 }
1569
1570 // Parse a string into several comma-separated fields
1571 wxChar *ParseMultifieldString(wxChar *allFields, int *pos)
1572 {
1573 static wxChar buffer[300];
1574 int i = 0;
1575 int fieldIndex = *pos;
1576 int len = wxStrlen(allFields);
1577 int oldPos = *pos;
1578 bool keepGoing = true;
1579 while ((fieldIndex <= len) && keepGoing)
1580 {
1581 if (allFields[fieldIndex] == _T(' '))
1582 {
1583 // Skip
1584 fieldIndex ++;
1585 }
1586 else if (allFields[fieldIndex] == _T(','))
1587 {
1588 *pos = fieldIndex + 1;
1589 keepGoing = false;
1590 }
1591 else if (allFields[fieldIndex] == 0)
1592 {
1593 *pos = fieldIndex + 1;
1594 keepGoing = false;
1595 }
1596 else
1597 {
1598 buffer[i] = allFields[fieldIndex];
1599 fieldIndex ++;
1600 i++;
1601 }
1602 }
1603 buffer[i] = 0;
1604 if (oldPos == (*pos))
1605 *pos = len + 1;
1606
1607 if (i == 0)
1608 return NULL;
1609 else
1610 return buffer;
1611 }
1612
1613 /*
1614 * Colour tables
1615 *
1616 */
1617
1618 ColourTableEntry::ColourTableEntry(const wxChar *theName, unsigned int r, unsigned int g, unsigned int b)
1619 {
1620 name = copystring(theName);
1621 red = r;
1622 green = g;
1623 blue = b;
1624 }
1625
1626 ColourTableEntry::~ColourTableEntry(void)
1627 {
1628 delete[] name;
1629 }
1630
1631 void AddColour(const wxChar *theName, unsigned int r, unsigned int g, unsigned int b)
1632 {
1633 wxNode *node = ColourTable.Find(theName);
1634 if (node)
1635 {
1636 ColourTableEntry *entry = (ColourTableEntry *)node->GetData();
1637 if (entry->red == r || entry->green == g || entry->blue == b)
1638 return;
1639 else
1640 {
1641 delete entry;
1642 delete node;
1643 }
1644 }
1645 ColourTableEntry *entry = new ColourTableEntry(theName, r, g, b);
1646 ColourTable.Append(theName, entry);
1647 }
1648
1649 int FindColourPosition(wxChar *theName)
1650 {
1651 int i = 0;
1652 wxNode *node = ColourTable.GetFirst();
1653 while (node)
1654 {
1655 ColourTableEntry *entry = (ColourTableEntry *)node->GetData();
1656 if (wxStrcmp(theName, entry->name) == 0)
1657 return i;
1658 i ++;
1659 node = node->GetNext();
1660 }
1661 return -1;
1662 }
1663
1664 // Converts e.g. "red" -> "#FF0000"
1665 extern void DecToHex(int, wxChar *);
1666 bool FindColourHTMLString(wxChar *theName, wxChar *buf)
1667 {
1668 wxNode *node = ColourTable.GetFirst();
1669 while (node)
1670 {
1671 ColourTableEntry *entry = (ColourTableEntry *)node->GetData();
1672 if (wxStrcmp(theName, entry->name) == 0)
1673 {
1674 wxStrcpy(buf, _T("#"));
1675
1676 wxChar buf2[3];
1677 DecToHex(entry->red, buf2);
1678 wxStrcat(buf, buf2);
1679 DecToHex(entry->green, buf2);
1680 wxStrcat(buf, buf2);
1681 DecToHex(entry->blue, buf2);
1682 wxStrcat(buf, buf2);
1683
1684 return true;
1685 }
1686 node = node->GetNext();
1687 }
1688 return false;
1689 }
1690
1691
1692 void InitialiseColourTable(void)
1693 {
1694 // \\red0\\green0\\blue0;
1695 AddColour(_T("black"), 0,0,0);
1696
1697 // \\red0\\green0\\blue255;\\red0\\green255\\blue255;\n");
1698 AddColour(_T("cyan"), 0,255,255);
1699
1700 // \\red0\\green255\\blue0;
1701 AddColour(_T("green"), 0,255,0);
1702
1703 // \\red255\\green0\\blue255;
1704 AddColour(_T("magenta"), 255,0,255);
1705
1706 // \\red255\\green0\\blue0;
1707 AddColour(_T("red"), 255,0,0);
1708
1709 // \\red255\\green255\\blue0;
1710 AddColour(_T("yellow"), 255,255,0);
1711
1712 // \\red255\\green255\\blue255;}");
1713 AddColour(_T("white"), 255,255,255);
1714 }
1715
1716 /*
1717 * The purpose of this is to reduce the number of times wxYield is
1718 * called, since under Windows this can slow things down.
1719 */
1720
1721 void Tex2RTFYield(bool force)
1722 {
1723 #ifdef __WINDOWS__
1724 static int yieldCount = 0;
1725
1726 if (isSync)
1727 return;
1728
1729 if (force)
1730 yieldCount = 0;
1731 if (yieldCount == 0)
1732 {
1733 if (wxTheApp)
1734 wxYield();
1735 yieldCount = 10;
1736 }
1737 yieldCount --;
1738 #else
1739 wxUnusedVar(force);
1740 #endif
1741 }
1742
1743 // In both RTF generation and HTML generation for wxHelp version 2,
1744 // we need to associate \indexed keywords with the current filename/topics.
1745
1746 // Hash table for lists of keywords for topics (WinHelp).
1747 wxHashTable TopicTable(wxKEY_STRING);
1748 void AddKeyWordForTopic(wxChar *topic, wxChar *entry, wxChar *filename)
1749 {
1750 TexTopic *texTopic = (TexTopic *)TopicTable.Get(topic);
1751 if (!texTopic)
1752 {
1753 texTopic = new TexTopic(filename);
1754 texTopic->keywords = new wxStringList;
1755 TopicTable.Put(topic, texTopic);
1756 }
1757
1758 if (!texTopic->keywords->Member(entry))
1759 texTopic->keywords->Add(entry);
1760 }
1761
1762 void ClearKeyWordTable(void)
1763 {
1764 TopicTable.BeginFind();
1765 wxHashTable::Node *node = TopicTable.Next();
1766 while (node)
1767 {
1768 TexTopic *texTopic = (TexTopic *)node->GetData();
1769 delete texTopic;
1770 node = TopicTable.Next();
1771 }
1772 TopicTable.Clear();
1773 }
1774
1775
1776 /*
1777 * TexTopic structure
1778 */
1779
1780 TexTopic::TexTopic(wxChar *f)
1781 {
1782 if (f)
1783 filename = copystring(f);
1784 else
1785 filename = NULL;
1786 hasChildren = false;
1787 keywords = NULL;
1788 }
1789
1790 TexTopic::~TexTopic(void)
1791 {
1792 if (keywords)
1793 delete keywords;
1794 if (filename)
1795 delete[] filename;
1796 }
1797
1798 // Convert case, according to upperCaseNames setting.
1799 wxChar *ConvertCase(wxChar *s)
1800 {
1801 static wxChar buf[256];
1802 int len = wxStrlen(s);
1803 int i;
1804 if (upperCaseNames)
1805 for (i = 0; i < len; i ++)
1806 buf[i] = (wxChar)wxToupper(s[i]);
1807 else
1808 for (i = 0; i < len; i ++)
1809 buf[i] = (wxChar)wxTolower(s[i]);
1810 buf[i] = 0;
1811 return buf;
1812 }
1813
1814 // if substring is true, search for str1 in str2
1815 bool StringMatch(const wxChar *str1, const wxChar *str2, bool subString,
1816 bool exact)
1817 {
1818 if (subString)
1819 {
1820 wxString Sstr1(str1);
1821 wxString Sstr2(str2);
1822 if (!exact)
1823 {
1824 Sstr1.MakeUpper();
1825 Sstr2.MakeUpper();
1826 }
1827 return Sstr2.Index(Sstr1) != (size_t)wxNOT_FOUND;
1828 }
1829 else
1830 return exact ? wxString(str2).Cmp(str1) == 0 :
1831 wxString(str2).CmpNoCase(str1) == 0;
1832 }