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