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