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