1/////////////////////////////////////////////////////////////////////////////
2// Name:        htmlutil.cpp
3// Purpose:     Converts Latex to HTML
4// Author:      Julian Smart
5// Modified by: Wlodzimierz ABX Skiba 2003/2004 Unicode support
6//              Ron Lee
7// Created:     7.9.93
8// RCS-ID:      $Id: htmlutil.cpp 59105 2009-02-23 11:51:34Z VZ $
9// Copyright:   (c) Julian Smart
10// Licence:     wxWindows licence
11/////////////////////////////////////////////////////////////////////////////
12
13// For compilers that support precompilation, includes "wx.h".
14#include "wx/wxprec.h"
15
16#ifdef __BORLANDC__
17#pragma hdrstop
18#endif
19
20#ifndef WX_PRECOMP
21#endif
22
23#include "wx/arrstr.h"
24
25#include "tex2any.h"
26#include "tex2rtf.h"
27#include "table.h"
28#include <stdio.h>
29#define HTML_FILENAME_PATTERN _T("%s_%s.html")
30
31#if !WXWIN_COMPATIBILITY_2_4
32static inline wxChar* copystring(const wxChar* s)
33    { return wxStrcpy(new wxChar[wxStrlen(s) + 1], s); }
34#endif
35
36extern wxHashTable TexReferences;
37
38extern int passNumber;
39
40extern void DecToHex(int, wxChar *);
41void GenerateHTMLIndexFile(wxChar *fname);
42
43bool PrimaryAnchorOfTheFile( wxChar *file, wxChar *label );
44
45void GenerateHTMLWorkshopFiles(wxChar *fname);
46void HTMLWorkshopAddToContents(int level, wxChar *s, wxChar *file);
47void HTMLWorkshopStartContents();
48void HTMLWorkshopEndContents();
49
50void OutputContentsFrame(void);
51
52#include "readshg.h" // Segmented hypergraphics parsing
53
54wxChar *ChaptersName = NULL;
55wxChar *SectionsName = NULL;
56wxChar *SubsectionsName = NULL;
57wxChar *SubsubsectionsName = NULL;
58wxChar *TitlepageName = NULL;
59wxChar *lastFileName = NULL;
60wxChar *lastTopic = NULL;
61wxChar *currentFileName = NULL;
62wxChar *contentsFrameName = NULL;
63
64static TexChunk *descriptionItemArg = NULL;
65static TexChunk *helpRefFilename = NULL;
66static TexChunk *helpRefText = NULL;
67static int indentLevel = 0;
68static int citeCount = 1;
69extern FILE *Contents;
70FILE *FrameContents = NULL;
71FILE *Titlepage = NULL;
72// FILE *FrameTitlepage = NULL;
73int fileId = 0;
74bool subsectionStarted = false;
75
76// Which column of a row are we in? (Assumes no nested tables, of course)
77int currentColumn = 0;
78
79// Are we in verbatim mode? If so, format differently.
80static bool inVerbatim = false;
81
82// Need to know whether we're in a table or figure for benefit
83// of listoffigures/listoftables
84static bool inFigure = false;
85static bool inTable = false;
86
87// This is defined in the Tex2Any library.
88extern wxChar *BigBuffer;
89
90// DHS Two-column table dimensions.
91static int TwoColWidthA = -1;
92static int TwoColWidthB = -1;
93
94
95class HyperReference: public wxObject
96{
97 public:
98  wxChar *refName;
99  wxChar *refFile;
100  HyperReference(wxChar *name, wxChar *file)
101  {
102    if (name) refName = copystring(name);
103    if (file) refFile = copystring(file);
104  }
105};
106
107class TexNextPage: public wxObject
108{
109 public:
110  wxChar *label;
111  wxChar *filename;
112  TexNextPage(wxChar *theLabel, wxChar *theFile)
113  {
114    label = copystring(theLabel);
115    filename = copystring(theFile);
116  }
117  virtual ~TexNextPage(void)
118  {
119    delete[] label;
120    delete[] filename;
121  }
122};
123
124wxHashTable TexNextPages(wxKEY_STRING);
125
126static wxChar *CurrentChapterName = NULL;
127static wxChar *CurrentChapterFile = NULL;
128static wxChar *CurrentSectionName = NULL;
129static wxChar *CurrentSectionFile = NULL;
130static wxChar *CurrentSubsectionName = NULL;
131static wxChar *CurrentSubsectionFile = NULL;
132static wxChar *CurrentSubsubsectionName = NULL;
133static wxChar *CurrentSubsubsectionFile = NULL;
134static wxChar *CurrentTopic = NULL;
135
136static void SetCurrentTopic(wxChar *s)
137{
138  if (CurrentTopic) delete[] CurrentTopic;
139  CurrentTopic = copystring(s);
140}
141
142void SetCurrentChapterName(wxChar *s, wxChar *file)
143{
144  if (CurrentChapterName) delete[] CurrentChapterName;
145  CurrentChapterName = copystring(s);
146  if (CurrentChapterFile) delete[] CurrentChapterFile;
147  CurrentChapterFile = copystring(file);
148
149  currentFileName = CurrentChapterFile;
150
151  SetCurrentTopic(s);
152}
153void SetCurrentSectionName(wxChar *s, wxChar *file)
154{
155  if (CurrentSectionName) delete[] CurrentSectionName;
156  CurrentSectionName = copystring(s);
157  if (CurrentSectionFile) delete[] CurrentSectionFile;
158  CurrentSectionFile = copystring(file);
159
160  currentFileName = CurrentSectionFile;
161  SetCurrentTopic(s);
162}
163void SetCurrentSubsectionName(wxChar *s, wxChar *file)
164{
165  if (CurrentSubsectionName) delete[] CurrentSubsectionName;
166  CurrentSubsectionName = copystring(s);
167  if (CurrentSubsectionFile) delete[] CurrentSubsectionFile;
168  CurrentSubsectionFile = copystring(file);
169  currentFileName = CurrentSubsectionFile;
170  SetCurrentTopic(s);
171}
172void SetCurrentSubsubsectionName(wxChar *s, wxChar *file)
173{
174  if (CurrentSubsubsectionName) delete[] CurrentSubsubsectionName;
175  CurrentSubsubsectionName = copystring(s);
176  if (CurrentSubsubsectionFile) delete[] CurrentSubsubsectionFile;
177  CurrentSubsubsectionFile = copystring(file);
178  currentFileName = CurrentSubsubsectionFile;
179  SetCurrentTopic(s);
180}
181
182
183// mapping between fileId and filenames if truncateFilenames=false:
184static wxArrayString gs_filenames;
185
186
187/*
188 * Close former filedescriptor and reopen using another filename.
189 *
190 */
191
192void ReopenFile(FILE **fd, wxChar **fileName, const wxChar *label)
193{
194  if (*fd)
195  {
196    wxFprintf(*fd, _T("\n</FONT></BODY></HTML>\n"));
197    fclose(*fd);
198  }
199  fileId ++;
200  wxChar buf[400];
201  if (truncateFilenames)
202  {
203    wxSnprintf(buf, sizeof(buf), _T("%s%d.htm"), FileRoot, fileId);
204  }
205  else
206  {
207    if (fileId == 1)
208      gs_filenames.Add(wxEmptyString);
209    wxSnprintf(buf, sizeof(buf), HTML_FILENAME_PATTERN, FileRoot, label);
210    gs_filenames.Add(buf);
211  }
212  if (*fileName) delete[] *fileName;
213  *fileName = copystring(wxFileNameFromPath(buf));
214  *fd = wxFopen(buf, _T("w"));
215  wxFprintf(*fd, _T("<HTML>\n"));
216}
217
218/*
219 * Reopen section contents file, i.e. the index appended to each section
220 * in subsectionCombine mode
221 */
222
223static wxChar *SectionContentsFilename = NULL;
224static FILE *SectionContentsFD = NULL;
225
226void ReopenSectionContentsFile(void)
227{
228    if ( SectionContentsFD )
229    {
230        fclose(SectionContentsFD);
231    }
232    if ( SectionContentsFilename )
233        delete[] SectionContentsFilename;
234    SectionContentsFD = NULL;
235    SectionContentsFilename = NULL;
236
237    // Create the name from the current section filename
238    if ( CurrentSectionFile )
239    {
240        wxChar buf[256];
241        wxStrcpy(buf, CurrentSectionFile);
242        wxStripExtension(buf);
243        wxStrcat(buf, _T(".con"));
244        SectionContentsFilename = copystring(buf);
245
246        SectionContentsFD = wxFopen(SectionContentsFilename, _T("w"));
247    }
248}
249
250
251/*
252 * Given a TexChunk with a string value, scans through the string
253 * converting Latex-isms into HTML-isms, such as 2 newlines -> <P>.
254 *
255 */
256
257void ProcessText2HTML(TexChunk *chunk)
258{
259  bool changed = false;
260  int ptr = 0;
261  int i = 0;
262  wxChar ch = 1;
263  int len = wxStrlen(chunk->value);
264  while (ch != 0)
265  {
266    ch = chunk->value[i];
267
268    // 2 newlines means \par
269    if (!inVerbatim && chunk->value[i] == 10 && ((len > i+1 && chunk->value[i+1] == 10) ||
270                        ((len > i+1 && chunk->value[i+1] == 13) &&
271                        (len > i+2 && chunk->value[i+2] == 10))))
272    {
273      BigBuffer[ptr] = 0; wxStrcat(BigBuffer, _T("<P>\n\n")); ptr += 5;
274      i += 2;
275      changed = true;
276    }
277    else if (!inVerbatim && ch == _T('`') && (len >= i+1 && chunk->value[i+1] == '`'))
278    {
279      BigBuffer[ptr] = '"'; ptr ++;
280      i += 2;
281      changed = true;
282    }
283    else if (!inVerbatim && ch == _T('`')) // Change ` to '
284    {
285      BigBuffer[ptr] = 39; ptr ++;
286      i += 1;
287      changed = true;
288    }
289    else if (ch == _T('<')) // Change < to &lt
290    {
291      BigBuffer[ptr] = 0;
292      wxStrcat(BigBuffer, _T("&lt;"));
293      ptr += 4;
294      i += 1;
295      changed = true;
296    }
297    else if (ch == _T('>')) // Change > to &gt
298    {
299      BigBuffer[ptr] = 0;
300      wxStrcat(BigBuffer, _T("&gt;"));
301      ptr += 4;
302      i += 1;
303      changed = true;
304    }
305    else
306    {
307      BigBuffer[ptr] = ch;
308      i ++;
309      ptr ++;
310    }
311  }
312  BigBuffer[ptr] = 0;
313
314  if (changed)
315  {
316    delete chunk->value;
317    chunk->value = copystring(BigBuffer);
318  }
319}
320
321/*
322 * Scan through all chunks starting from the given one,
323 * calling ProcessText2HTML to convert Latex-isms to RTF-isms.
324 * This should be called after Tex2Any has parsed the file,
325 * and before TraverseDocument is called.
326 *
327 */
328
329void Text2HTML(TexChunk *chunk)
330{
331  Tex2RTFYield();
332  if (stopRunning) return;
333
334  switch (chunk->type)
335  {
336    case CHUNK_TYPE_MACRO:
337    {
338      TexMacroDef *def = chunk->def;
339
340      if (def && def->ignore)
341        return;
342
343      if (def && (def->macroId == ltVERBATIM || def->macroId == ltVERB || def->macroId == ltSPECIAL))
344        inVerbatim = true;
345
346      wxNode *node = chunk->children.GetFirst();
347      while (node)
348      {
349        TexChunk *child_chunk = (TexChunk *)node->GetData();
350        Text2HTML(child_chunk);
351        node = node->GetNext();
352      }
353
354      if (def && (def->macroId == ltVERBATIM || def->macroId == ltVERB || def->macroId == ltSPECIAL))
355        inVerbatim = false;
356
357      break;
358    }
359    case CHUNK_TYPE_ARG:
360    {
361      wxNode *node = chunk->children.GetFirst();
362      while (node)
363      {
364        TexChunk *child_chunk = (TexChunk *)node->GetData();
365        Text2HTML(child_chunk);
366        node = node->GetNext();
367      }
368
369      break;
370    }
371    case CHUNK_TYPE_STRING:
372    {
373      if (chunk->value)
374        ProcessText2HTML(chunk);
375      break;
376    }
377  }
378}
379
380/*
381 * Add appropriate browse buttons to this page.
382 *
383 */
384
385void AddBrowseButtons(wxChar *upLabel, wxChar *upFilename,
386  wxChar *previousLabel, wxChar *previousFilename,
387  wxChar *thisLabel, wxChar *thisFilename)
388{
389  wxChar contentsReferenceBuf[80];
390  wxChar upReferenceBuf[80];
391  wxChar backReferenceBuf[80];
392  wxChar forwardReferenceBuf[80];
393  if (htmlBrowseButtons == HTML_BUTTONS_NONE)
394    return;
395
396  wxChar *contentsReference; // no need to initialize because always assigned below
397  if (htmlBrowseButtons == HTML_BUTTONS_TEXT)
398    contentsReference = ContentsNameString;
399  else
400  {
401//    contentsReference = "<img align=center src=\"contents.gif\" BORDER=0 ALT=\"Contents\">";
402    contentsReference = contentsReferenceBuf;
403    wxSnprintf(contentsReference, sizeof(contentsReferenceBuf),
404               _T("<img align=center src=\"%s\" BORDER=0 ALT=\"Contents\">"),
405               ConvertCase(_T("contents.gif")));
406  }
407
408  wxChar *upReference; // no need to initialize because always assigned below
409  if (htmlBrowseButtons == HTML_BUTTONS_TEXT)
410    upReference = UpNameString;
411  else
412  {
413//    upReference = "<img align=center src=\"up.gif\" ALT=\"Up\">";
414    upReference = upReferenceBuf;
415    wxSnprintf(upReference, sizeof(upReferenceBuf),
416               _T("<img align=center src=\"%s\" BORDER=0 ALT=\"Up\">"),
417               ConvertCase(_T("up.gif")));
418  }
419
420  wxChar *backReference; // no need to initialize because always assigned below
421  if (htmlBrowseButtons == HTML_BUTTONS_TEXT)
422    backReference = _T("&lt;&lt;");
423  else
424  {
425//    backReference = "<img align=center src=\"back.gif\" ALT=\"Previous\">";
426    backReference = backReferenceBuf;
427    wxSnprintf(backReference, sizeof(backReferenceBuf),
428               _T("<img align=center src=\"%s\" BORDER=0 ALT=\"Previous\">"),
429               ConvertCase(_T("back.gif")));
430  }
431
432  wxChar *forwardReference; // no need to initialize because always assigned below
433  if (htmlBrowseButtons == HTML_BUTTONS_TEXT)
434    forwardReference = _T("&gt;&gt;");
435  else
436  {
437//    forwardReference = "<img align=center src=\"forward.gif\" ALT=\"Next\">";
438    forwardReference = forwardReferenceBuf;
439    wxSnprintf(forwardReference, sizeof(forwardReferenceBuf),
440               _T("<img align=center src=\"%s\" BORDER=0 ALT=\"Next\">"),
441               ConvertCase(_T("forward.gif")));
442  }
443
444  TexOutput(_T("<CENTER>"));
445
446  wxChar buf[200];
447
448  /*
449   * Contents button
450   *
451   */
452
453  if (truncateFilenames)
454  {
455    wxChar buf1[80];
456    wxStrcpy(buf1, ConvertCase(wxFileNameFromPath(FileRoot)));
457    wxSnprintf(buf, sizeof(buf),
458               _T("\n<A HREF=\"%s.%s\">%s</A> "),
459               buf1, ConvertCase(_T("htm")), contentsReference);
460  }
461  else
462  {
463    wxChar buf1[80];
464    wxStrcpy(buf1, ConvertCase(wxFileNameFromPath(FileRoot)));
465    wxSnprintf(buf, sizeof(buf),
466               _T("\n<A HREF=\"%s%s\">%s</A> "),
467               buf1, ConvertCase(_T("_contents.html")), contentsReference);
468  }
469//  TexOutput(_T("<NOFRAMES>"));
470  TexOutput(buf);
471//  TexOutput(_T("</NOFRAMES>"));
472
473  /*
474   * Up button
475   *
476   */
477
478  if (upLabel && upFilename)
479  {
480    if ( (wxStrlen(upLabel) > 0) && !PrimaryAnchorOfTheFile(upFilename, upLabel) )
481      wxSnprintf(buf, sizeof(buf),
482                 _T("<A HREF=\"%s#%s\">%s</A> "),
483                 ConvertCase(upFilename), upLabel, upReference);
484    else
485      wxSnprintf(buf, sizeof(buf),
486                 _T("<A HREF=\"%s\">%s</A> "),
487                 ConvertCase(upFilename), upReference);
488    if (wxStrcmp(upLabel, _T("contents")) == 0)
489    {
490//      TexOutput(_T("<NOFRAMES>"));
491      TexOutput(buf);
492//      TexOutput(_T("</NOFRAMES>"));
493    }
494    else
495     TexOutput(buf);
496  }
497
498  /*
499   * << button
500   *
501   */
502
503  if (previousLabel && previousFilename)
504  {
505    if (PrimaryAnchorOfTheFile(previousFilename, previousLabel))
506      wxSnprintf(buf, sizeof(buf),
507                 _T("<A HREF=\"%s\">%s</A> "),
508                 ConvertCase(previousFilename), backReference);
509    else
510      wxSnprintf(buf, sizeof(buf),
511                 _T("<A HREF=\"%s#%s\">%s</A> "),
512                 ConvertCase(previousFilename), previousLabel, backReference);
513    if (wxStrcmp(previousLabel, _T("contents")) == 0)
514    {
515//      TexOutput(_T("<NOFRAMES>"));
516      TexOutput(buf);
517//      TexOutput(_T("</NOFRAMES>"));
518    }
519    else
520      TexOutput(buf);
521  }
522  else
523  {
524    // A placeholder so the buttons don't keep moving position
525    wxSnprintf(buf, sizeof(buf), _T("%s "), backReference);
526    TexOutput(buf);
527  }
528
529  wxChar *nextLabel = NULL;
530  wxChar *nextFilename = NULL;
531
532  // Get the next page, and record the previous page's 'next' page
533  // (i.e. this page)
534  TexNextPage *nextPage = (TexNextPage *)TexNextPages.Get(thisLabel);
535  if (nextPage)
536  {
537    nextLabel = nextPage->label;
538    nextFilename = nextPage->filename;
539  }
540  if (previousLabel && previousFilename)
541  {
542    TexNextPage *oldNextPage = (TexNextPage *)TexNextPages.Get(previousLabel);
543    if (oldNextPage)
544    {
545      delete oldNextPage;
546      TexNextPages.Delete(previousLabel);
547    }
548    TexNextPage *newNextPage = new TexNextPage(thisLabel, thisFilename);
549    TexNextPages.Put(previousLabel, newNextPage);
550  }
551
552  /*
553   * >> button
554   *
555   */
556
557  if (nextLabel && nextFilename)
558  {
559    if (PrimaryAnchorOfTheFile(nextFilename, nextLabel))
560      wxSnprintf(buf, sizeof(buf),
561                 _T("<A HREF=\"%s\">%s</A> "),
562                 ConvertCase(nextFilename), forwardReference);
563    else
564      wxSnprintf(buf, sizeof(buf),
565                 _T("<A HREF=\"%s#%s\">%s</A> "),
566                 ConvertCase(nextFilename), nextLabel, forwardReference);
567    TexOutput(buf);
568  }
569  else
570  {
571    // A placeholder so the buttons don't keep moving position
572    wxSnprintf(buf, sizeof(buf), _T("%s "), forwardReference);
573    TexOutput(buf);
574  }
575
576  /*
577   * Horizontal rule to finish it off nicely.
578   *
579   */
580  TexOutput(_T("</CENTER>"));
581  TexOutput(_T("<HR>\n"));
582
583  // Update last topic/filename
584  if (lastFileName)
585    delete[] lastFileName;
586  lastFileName = copystring(thisFilename);
587  if (lastTopic)
588    delete[] lastTopic;
589  lastTopic = copystring(thisLabel);
590}
591
592// A colour string is either 3 numbers separated by semicolons (RGB),
593// or a reference to a GIF. Return the filename or a hex string like #934CE8
594wxChar *ParseColourString(wxChar *bkStr, bool *isPicture)
595{
596  static wxChar resStr[300];
597  wxStrcpy(resStr, bkStr);
598  wxStringTokenizer tok(resStr, _T(";"), wxTOKEN_STRTOK);
599  if (tok.HasMoreTokens())
600  {
601    wxString token1 = tok.GetNextToken();
602    if (!tok.HasMoreTokens())
603    {
604      *isPicture = true;
605      return resStr;
606    }
607    else
608    {
609      wxString token2 = tok.GetNextToken();
610      *isPicture = false;
611      if (tok.HasMoreTokens())
612      {
613        wxString token3 = tok.GetNextToken();
614
615        // Now convert 3 strings into decimal numbers, and then hex numbers.
616        int red = wxAtoi(token1.c_str());
617        int green = wxAtoi(token2.c_str());
618        int blue = wxAtoi(token3.c_str());
619
620        wxStrcpy(resStr, _T("#"));
621
622        wxChar buf[3];
623        DecToHex(red, buf);
624        wxStrcat(resStr, buf);
625        DecToHex(green, buf);
626        wxStrcat(resStr, buf);
627        DecToHex(blue, buf);
628        wxStrcat(resStr, buf);
629        return resStr;
630      }
631      else return NULL;
632    }
633  }
634  else return NULL;
635}
636
637void OutputFont(void)
638{
639  // Only output <font face> if explicitly requested by htmlFaceName= directive in
640  // tex2rtf.ini. Otherwise do NOT set the font because we want to use browser's
641  // default font:
642  if (htmlFaceName)
643  {
644    // Output <FONT FACE=...>
645    TexOutput(_T("<FONT FACE=\""));
646    TexOutput(htmlFaceName);
647    TexOutput(_T("\">\n"));
648  }
649}
650
651// Output start of <BODY> block
652void OutputBodyStart(void)
653{
654  TexOutput(_T("\n<BODY"));
655  if (backgroundImageString)
656  {
657    bool isPicture = false;
658    wxChar *s = ParseColourString(backgroundImageString, &isPicture);
659    if (s)
660    {
661      TexOutput(_T(" BACKGROUND=\""));
662      TexOutput(s);
663      TexOutput(_T("\""));
664    }
665  }
666  if (backgroundColourString)
667  {
668    bool isPicture = false;
669    wxChar *s = ParseColourString(backgroundColourString, &isPicture);
670    if (s)
671    {
672      TexOutput(_T(" BGCOLOR="));
673      TexOutput(s);
674    }
675  }
676
677  // Set foreground text colour, if one is specified
678  if (textColourString)
679  {
680    bool isPicture = false;
681    wxChar *s = ParseColourString(textColourString, &isPicture);
682    if (s)
683    {
684      TexOutput(_T(" TEXT=")); TexOutput(s);
685    }
686  }
687  // Set link text colour, if one is specified
688  if (linkColourString)
689  {
690    bool isPicture = false;
691    wxChar *s = ParseColourString(linkColourString, &isPicture);
692    if (s)
693    {
694      TexOutput(_T(" LINK=")); TexOutput(s);
695    }
696  }
697  // Set followed link text colour, if one is specified
698  if (followedLinkColourString)
699  {
700    bool isPicture = false;
701    wxChar *s = ParseColourString(followedLinkColourString, &isPicture);
702    if (s)
703    {
704      TexOutput(_T(" VLINK=")); TexOutput(s);
705    }
706  }
707  TexOutput(_T(">\n"));
708
709  OutputFont();
710}
711
712void HTMLHead()
713{
714  TexOutput(_T("<head>"));
715  if (htmlStylesheet) {
716    TexOutput(_T("<link rel=stylesheet type=\"text/css\" href=\""));
717    TexOutput(htmlStylesheet);
718    TexOutput(_T("\">"));
719  }
720};
721
722void HTMLHeadTo(FILE* f)
723{
724  if (htmlStylesheet)
725    wxFprintf(f,_T("<head><link rel=stylesheet type=\"text/css\" href=\"%s\">"),htmlStylesheet);
726  else
727    wxFprintf(f,_T("<head>"));
728}
729
730// Called on start/end of macro examination
731void HTMLOnMacro(int macroId, int no_args, bool start)
732{
733  switch (macroId)
734  {
735  case ltCHAPTER:
736  case ltCHAPTERSTAR:
737  case ltCHAPTERHEADING:
738  {
739    if (!start)
740    {
741      sectionNo = 0;
742      figureNo = 0;
743      subsectionNo = 0;
744      subsubsectionNo = 0;
745      if (macroId != ltCHAPTERSTAR)
746        chapterNo ++;
747
748      SetCurrentOutput(NULL);
749      startedSections = true;
750
751      wxChar *topicName = FindTopicName(GetNextChunk());
752      ReopenFile(&Chapters, &ChaptersName, topicName);
753      AddTexRef(topicName, ChaptersName, ChapterNameString);
754
755      SetCurrentChapterName(topicName, ChaptersName);
756      if (htmlWorkshopFiles) HTMLWorkshopAddToContents(0, topicName, ChaptersName);
757
758      SetCurrentOutput(Chapters);
759
760      HTMLHead();
761      TexOutput(_T("<title>"));
762      OutputCurrentSection(); // Repeat section header
763      TexOutput(_T("</title></head>\n"));
764      OutputBodyStart();
765
766      wxChar titleBuf[200];
767      if (truncateFilenames)
768        wxSnprintf(titleBuf, sizeof(titleBuf), _T("%s.htm"), wxFileNameFromPath(FileRoot));
769      else
770        wxSnprintf(titleBuf, sizeof(titleBuf), _T("%s_contents.html"), wxFileNameFromPath(FileRoot));
771
772      wxFprintf(Chapters, _T("<A NAME=\"%s\"></A>"), topicName);
773
774      AddBrowseButtons(_T(""), titleBuf, // Up
775                       lastTopic, lastFileName,  // Last topic
776                       topicName, ChaptersName); // This topic
777
778      if(PrimaryAnchorOfTheFile(ChaptersName, topicName))
779        wxFprintf(Contents, _T("\n<LI><A HREF=\"%s\">"), ConvertCase(ChaptersName));
780      else
781        wxFprintf(Contents, _T("\n<LI><A HREF=\"%s#%s\">"), ConvertCase(ChaptersName), topicName);
782
783      if (htmlFrameContents && FrameContents)
784      {
785        SetCurrentOutput(FrameContents);
786        if(PrimaryAnchorOfTheFile(ChaptersName, topicName))
787          wxFprintf(FrameContents, _T("\n<LI><A HREF=\"%s\" TARGET=\"mainwindow\">"), ConvertCase(ChaptersName));
788        else
789          wxFprintf(FrameContents, _T("\n<LI><A HREF=\"%s#%s\" TARGET=\"mainwindow\">"), ConvertCase(ChaptersName), topicName);
790        OutputCurrentSection();
791        wxFprintf(FrameContents, _T("</A>\n"));
792      }
793
794      SetCurrentOutputs(Contents, Chapters);
795      wxFprintf(Chapters, _T("\n<H2>"));
796      OutputCurrentSection();
797      wxFprintf(Contents, _T("</A>\n"));
798      wxFprintf(Chapters, _T("</H2>\n"));
799
800      SetCurrentOutput(Chapters);
801
802      // Add this section title to the list of keywords
803      if (htmlIndex)
804      {
805        OutputCurrentSectionToString(wxTex2RTFBuffer);
806        AddKeyWordForTopic(topicName, wxTex2RTFBuffer, ConvertCase(currentFileName));
807      }
808    }
809    break;
810  }
811  case ltSECTION:
812  case ltSECTIONSTAR:
813  case ltSECTIONHEADING:
814  case ltGLOSS:
815  {
816    if (!start)
817    {
818      subsectionNo = 0;
819      subsubsectionNo = 0;
820      subsectionStarted = false;
821
822      if (macroId != ltSECTIONSTAR)
823        sectionNo ++;
824
825      SetCurrentOutput(NULL);
826      startedSections = true;
827
828      wxChar *topicName = FindTopicName(GetNextChunk());
829      ReopenFile(&Sections, &SectionsName, topicName);
830      AddTexRef(topicName, SectionsName, SectionNameString);
831
832      SetCurrentSectionName(topicName, SectionsName);
833      if (htmlWorkshopFiles) HTMLWorkshopAddToContents(1, topicName, SectionsName);
834
835      SetCurrentOutput(Sections);
836      HTMLHead();
837      TexOutput(_T("<title>"));
838      OutputCurrentSection();
839      TexOutput(_T("</title></head>\n"));
840      OutputBodyStart();
841
842      wxFprintf(Sections, _T("<A NAME=\"%s\"></A>"), topicName);
843      AddBrowseButtons(CurrentChapterName, CurrentChapterFile, // Up
844                       lastTopic, lastFileName,  // Last topic
845                       topicName, SectionsName); // This topic
846
847      FILE *jumpFrom = ((DocumentStyle == LATEX_ARTICLE) ? Contents : Chapters);
848
849      SetCurrentOutputs(jumpFrom, Sections);
850      if (DocumentStyle == LATEX_ARTICLE)
851      {
852        if(PrimaryAnchorOfTheFile(SectionsName, topicName))
853          wxFprintf(jumpFrom, _T("\n<LI><A HREF=\"%s\">"), ConvertCase(SectionsName));
854        else
855          wxFprintf(jumpFrom, _T("\n<LI><A HREF=\"%s#%s\">"), ConvertCase(SectionsName), topicName);
856      }
857      else
858      {
859        if(PrimaryAnchorOfTheFile(SectionsName, topicName))
860          wxFprintf(jumpFrom, _T("\n<A HREF=\"%s\"><B>"), ConvertCase(SectionsName));
861        else
862          wxFprintf(jumpFrom, _T("\n<A HREF=\"%s#%s\"><B>"), ConvertCase(SectionsName), topicName);
863      }
864
865      wxFprintf(Sections, _T("\n<H2>"));
866      OutputCurrentSection();
867
868      if (DocumentStyle == LATEX_ARTICLE)
869        wxFprintf(jumpFrom, _T("</A>\n"));
870      else
871        wxFprintf(jumpFrom, _T("</B></A><BR>\n"));
872      wxFprintf(Sections, _T("</H2>\n"));
873
874      SetCurrentOutput(Sections);
875      // Add this section title to the list of keywords
876      if (htmlIndex)
877      {
878        OutputCurrentSectionToString(wxTex2RTFBuffer);
879        AddKeyWordForTopic(topicName, wxTex2RTFBuffer, currentFileName);
880      }
881    }
882    break;
883  }
884  case ltSUBSECTION:
885  case ltSUBSECTIONSTAR:
886  case ltMEMBERSECTION:
887  case ltFUNCTIONSECTION:
888  {
889    if (!start)
890    {
891      if (!Sections)
892      {
893        OnError(_T("You cannot have a subsection before a section!"));
894      }
895      else
896      {
897          subsubsectionNo = 0;
898
899          if (macroId != ltSUBSECTIONSTAR)
900            subsectionNo ++;
901
902          if ( combineSubSections && !subsectionStarted )
903          {
904            fflush(Sections);
905
906            // Read old .con file in at this point
907            wxChar buf[256];
908            wxStrcpy(buf, CurrentSectionFile);
909            wxStripExtension(buf);
910            wxStrcat(buf, _T(".con"));
911            FILE *fd = wxFopen(buf, _T("r"));
912            if ( fd )
913            {
914                int ch = getc(fd);
915                while (ch != EOF)
916                {
917                    wxPutc(ch, Sections);
918                    ch = getc(fd);
919                }
920                fclose(fd);
921            }
922            wxFprintf(Sections, _T("<P>\n"));
923
924            // Close old file, create a new file for the sub(sub)section contents entries
925            ReopenSectionContentsFile();
926          }
927
928          startedSections = true;
929          subsectionStarted = true;
930
931          wxChar *topicName = FindTopicName(GetNextChunk());
932
933          if ( !combineSubSections )
934          {
935            SetCurrentOutput(NULL);
936            ReopenFile(&Subsections, &SubsectionsName, topicName);
937            AddTexRef(topicName, SubsectionsName, SubsectionNameString);
938            SetCurrentSubsectionName(topicName, SubsectionsName);
939            if (htmlWorkshopFiles) HTMLWorkshopAddToContents(2, topicName, SubsectionsName);
940            SetCurrentOutput(Subsections);
941
942            HTMLHead();
943            TexOutput(_T("<title>"));
944            OutputCurrentSection();
945            TexOutput(_T("</title></head>\n"));
946            OutputBodyStart();
947
948            wxFprintf(Subsections, _T("<A NAME=\"%s\"></A>"), topicName);
949            AddBrowseButtons(CurrentSectionName, CurrentSectionFile, // Up
950                           lastTopic, lastFileName,  // Last topic
951                           topicName, SubsectionsName); // This topic
952
953            SetCurrentOutputs(Sections, Subsections);
954            if(PrimaryAnchorOfTheFile(SubsectionsName, topicName))
955              wxFprintf(Sections, _T("\n<A HREF=\"%s\"><B>"), ConvertCase(SubsectionsName));
956            else
957              wxFprintf(Sections, _T("\n<A HREF=\"%s#%s\"><B>"), ConvertCase(SubsectionsName), topicName);
958
959            wxFprintf(Subsections, _T("\n<H3>"));
960            OutputCurrentSection();
961            wxFprintf(Sections, _T("</B></A><BR>\n"));
962            wxFprintf(Subsections, _T("</H3>\n"));
963
964            SetCurrentOutput(Subsections);
965          }
966          else
967          {
968            AddTexRef(topicName, SectionsName, SubsectionNameString);
969            SetCurrentSubsectionName(topicName, SectionsName);
970
971//            if ( subsectionNo != 0 )
972            wxFprintf(Sections, _T("\n<HR>\n"));
973
974            // We're putting everything into the section file
975            wxFprintf(Sections, _T("<A NAME=\"%s\"></A>"), topicName);
976            wxFprintf(Sections, _T("\n<H3>"));
977            OutputCurrentSection();
978            wxFprintf(Sections, _T("</H3>\n"));
979
980            SetCurrentOutput(SectionContentsFD);
981            wxFprintf(SectionContentsFD, _T("<A HREF=\"#%s\">"), topicName);
982            OutputCurrentSection();
983            TexOutput(_T("</A><BR>\n"));
984
985            if (htmlWorkshopFiles) HTMLWorkshopAddToContents(2, topicName, SectionsName);
986            SetCurrentOutput(Sections);
987          }
988          // Add this section title to the list of keywords
989          if (htmlIndex)
990          {
991            OutputCurrentSectionToString(wxTex2RTFBuffer);
992            AddKeyWordForTopic(topicName, wxTex2RTFBuffer, currentFileName);
993          }
994
995      }
996    }
997    break;
998  }
999  case ltSUBSUBSECTION:
1000  case ltSUBSUBSECTIONSTAR:
1001  {
1002    if (!start)
1003    {
1004      if (!Subsections && !combineSubSections)
1005      {
1006        OnError(_T("You cannot have a subsubsection before a subsection!"));
1007      }
1008      else
1009      {
1010        if (macroId != ltSUBSUBSECTIONSTAR)
1011          subsubsectionNo ++;
1012
1013        startedSections = true;
1014
1015        wxChar *topicName = FindTopicName(GetNextChunk());
1016
1017        if ( !combineSubSections )
1018        {
1019            SetCurrentOutput(NULL);
1020            ReopenFile(&Subsubsections, &SubsubsectionsName, topicName);
1021            AddTexRef(topicName, SubsubsectionsName, SubsubsectionNameString);
1022            SetCurrentSubsubsectionName(topicName, SubsubsectionsName);
1023            if (htmlWorkshopFiles) HTMLWorkshopAddToContents(3, topicName, SubsubsectionsName);
1024
1025            SetCurrentOutput(Subsubsections);
1026            HTMLHead();
1027            TexOutput(_T("<title>"));
1028            OutputCurrentSection();
1029            TexOutput(_T("</title></head>\n"));
1030            OutputBodyStart();
1031
1032            wxFprintf(Subsubsections, _T("<A NAME=\"%s\"></A>"), topicName);
1033
1034            AddBrowseButtons(CurrentSubsectionName, CurrentSubsectionFile, // Up
1035                         lastTopic, lastFileName,  // Last topic
1036                         topicName, SubsubsectionsName); // This topic
1037
1038            SetCurrentOutputs(Subsections, Subsubsections);
1039            if(PrimaryAnchorOfTheFile(SubsubsectionsName, topicName))
1040              wxFprintf(Subsections, _T("\n<A HREF=\"%s\"><B>"), ConvertCase(SubsubsectionsName));
1041            else
1042              wxFprintf(Subsections, _T("\n<A HREF=\"%s#%s\"><B>"), ConvertCase(SubsubsectionsName), topicName);
1043
1044            wxFprintf(Subsubsections, _T("\n<H3>"));
1045            OutputCurrentSection();
1046            wxFprintf(Subsections, _T("</B></A><BR>\n"));
1047            wxFprintf(Subsubsections, _T("</H3>\n"));
1048        }
1049        else
1050        {
1051            AddTexRef(topicName, SectionsName, SubsubsectionNameString);
1052            SetCurrentSubsectionName(topicName, SectionsName);
1053            wxFprintf(Sections, _T("\n<HR>\n"));
1054
1055            // We're putting everything into the section file
1056            wxFprintf(Sections, _T("<A NAME=\"%s\"></A>"), topicName);
1057            wxFprintf(Sections, _T("\n<H3>"));
1058            OutputCurrentSection();
1059            wxFprintf(Sections, _T("</H3>\n"));
1060/* TODO: where do we put subsubsection contents entry - indented, with subsection entries?
1061            SetCurrentOutput(SectionContentsFD);
1062            wxFprintf(SectionContentsFD, "<A HREF=\"#%s\">", topicName);
1063            OutputCurrentSection();
1064            TexOutput(_T("</A><BR>"));
1065*/
1066            if (htmlWorkshopFiles) HTMLWorkshopAddToContents(2, topicName, SectionsName);
1067            SetCurrentOutput(Sections);
1068        }
1069
1070        // Add this section title to the list of keywords
1071        if (htmlIndex)
1072        {
1073          OutputCurrentSectionToString(wxTex2RTFBuffer);
1074          AddKeyWordForTopic(topicName, wxTex2RTFBuffer, currentFileName);
1075        }
1076      }
1077    }
1078    break;
1079  }
1080  case ltFUNC:
1081  case ltPFUNC:
1082  {
1083    if ( !combineSubSections )
1084        SetCurrentOutput(Subsections);
1085    else
1086        SetCurrentOutput(Sections);
1087    if (start)
1088    {
1089    }
1090    else
1091    {
1092    }
1093    break;
1094  }
1095  case ltCLIPSFUNC:
1096  {
1097    if ( !combineSubSections )
1098        SetCurrentOutput(Subsections);
1099    else
1100        SetCurrentOutput(Sections);
1101    if (start)
1102    {
1103    }
1104    else
1105    {
1106    }
1107    break;
1108  }
1109  case ltMEMBER:
1110  {
1111    if ( !combineSubSections )
1112        SetCurrentOutput(Subsections);
1113    else
1114        SetCurrentOutput(Sections);
1115    if (start)
1116    {
1117    }
1118    else
1119    {
1120    }
1121    break;
1122  }
1123  case ltVOID:
1124//    if (start)
1125//      TexOutput(_T("<B>void</B>"));
1126    break;
1127  case ltHARDY:
1128    if (start)
1129      TexOutput(_T("HARDY"));
1130    break;
1131  case ltWXCLIPS:
1132    if (start)
1133      TexOutput(_T("wxCLIPS"));
1134    break;
1135  case ltAMPERSAND:
1136    if (start)
1137      TexOutput(_T("&amp;"));
1138    break;
1139  case ltSPECIALAMPERSAND:
1140  {
1141    if (start)
1142    {
1143      if (inTabular)
1144      {
1145        // End cell, start cell
1146
1147        TexOutput(_T("</FONT></TD>"));
1148
1149        // Start new row and cell, setting alignment for the first cell.
1150        if (currentColumn < noColumns)
1151          currentColumn ++;
1152
1153        wxChar buf[100];
1154        if (TableData[currentColumn].justification == 'c')
1155          wxSnprintf(buf, sizeof(buf), _T("\n<TD ALIGN=CENTER>"));
1156        else if (TableData[currentColumn].justification == 'r')
1157          wxSnprintf(buf, sizeof(buf), _T("\n<TD ALIGN=RIGHT>"));
1158        else if (TableData[currentColumn].absWidth)
1159        {
1160          // Convert from points * 20 into pixels.
1161          int points = TableData[currentColumn].width / 20;
1162
1163          // Say the display is 100 DPI (dots/pixels per inch).
1164          // There are 72 pts to the inch. So 1pt = 1/72 inch, or 100 * 1/72 dots.
1165          int pixels = (int)(points * 100.0 / 72.0);
1166          wxSnprintf(buf, sizeof(buf), _T("<TD ALIGN=CENTER WIDTH=%d>"), pixels);
1167        }
1168        else
1169          wxSnprintf(buf, sizeof(buf), _T("\n<TD ALIGN=LEFT>"));
1170        TexOutput(buf);
1171        OutputFont();
1172      }
1173      else
1174        TexOutput(_T("&amp;"));
1175    }
1176    break;
1177  }
1178  case ltBACKSLASHCHAR:
1179  {
1180    if (start)
1181    {
1182      if (inTabular)
1183      {
1184        // End row. In fact, tables without use of \row or \ruledrow isn't supported for
1185        // HTML: the syntax is too different (e.g. how do we know where to put the first </TH>
1186        // if we've ended the last row?). So normally you wouldn't use \\ to end a row.
1187        TexOutput(_T("</TR>\n"));
1188      }
1189      else
1190        TexOutput(_T("<BR>\n"));
1191    }
1192    break;
1193  }
1194  case ltROW:
1195  case ltRULEDROW:
1196  {
1197    if (start)
1198    {
1199      currentColumn = 0;
1200
1201      // Start new row and cell, setting alignment for the first cell.
1202      wxChar buf[100];
1203      if (TableData[currentColumn].justification == 'c')
1204        wxSnprintf(buf, sizeof(buf), _T("<TR>\n<TD ALIGN=CENTER>"));
1205      else if (TableData[currentColumn].justification == 'r')
1206        wxSnprintf(buf, sizeof(buf), _T("<TR>\n<TD ALIGN=RIGHT>"));
1207      else if (TableData[currentColumn].absWidth)
1208      {
1209        // Convert from points * 20 into pixels.
1210        int points = TableData[currentColumn].width / 20;
1211
1212        // Say the display is 100 DPI (dots/pixels per inch).
1213        // There are 72 pts to the inch. So 1pt = 1/72 inch, or 100 * 1/72 dots.
1214        int pixels = (int)(points * 100.0 / 72.0);
1215        wxSnprintf(buf, sizeof(buf), _T("<TR>\n<TD ALIGN=CENTER WIDTH=%d>"), pixels);
1216      }
1217      else
1218        wxSnprintf(buf, sizeof(buf), _T("<TR>\n<TD ALIGN=LEFT>"));
1219      TexOutput(buf);
1220      OutputFont();
1221    }
1222    else
1223    {
1224      // End cell and row
1225      // Start new row and cell
1226      TexOutput(_T("</FONT></TD>\n</TR>\n"));
1227    }
1228    break;
1229  }
1230  // HTML-only: break until the end of the picture (both margins are clear).
1231  case ltBRCLEAR:
1232  {
1233    if (start)
1234      TexOutput(_T("<BR CLEAR=ALL>"));
1235    break;
1236  }
1237  case ltRTFSP:  // Explicit space, RTF only
1238    break;
1239  case ltSPECIALTILDE:
1240  {
1241    if (start)
1242    {
1243      #if (1) // if(inVerbatim)
1244        TexOutput(_T("~"));
1245      #else
1246        TexOutput(_T(" "));
1247      #endif
1248    }
1249    break;
1250  }
1251  case ltINDENTED :
1252  {
1253    if ( start )
1254        TexOutput(_T("<UL><UL>\n"));
1255    else
1256        TexOutput(_T("</UL></UL>\n"));
1257    break;
1258  }
1259  case ltITEMIZE:
1260  case ltENUMERATE:
1261  case ltDESCRIPTION:
1262//  case ltTWOCOLLIST:
1263  {
1264    if (start)
1265    {
1266      indentLevel ++;
1267
1268      int listType;
1269      if (macroId == ltENUMERATE)
1270        listType = LATEX_ENUMERATE;
1271      else if (macroId == ltITEMIZE)
1272        listType = LATEX_ITEMIZE;
1273      else
1274        listType = LATEX_DESCRIPTION;
1275
1276      itemizeStack.Insert(new ItemizeStruc(listType));
1277      switch (listType)
1278      {
1279        case LATEX_ITEMIZE:
1280          TexOutput(_T("<UL>\n"));
1281          break;
1282        case LATEX_ENUMERATE:
1283          TexOutput(_T("<OL>\n"));
1284          break;
1285        case LATEX_DESCRIPTION:
1286        default:
1287          TexOutput(_T("<DL>\n"));
1288          break;
1289      }
1290    }
1291    else
1292    {
1293      indentLevel --;
1294      if (itemizeStack.GetFirst())
1295      {
1296        ItemizeStruc *struc = (ItemizeStruc *)itemizeStack.GetFirst()->GetData();
1297        switch (struc->listType)
1298        {
1299          case LATEX_ITEMIZE:
1300            TexOutput(_T("</UL>\n"));
1301            break;
1302          case LATEX_ENUMERATE:
1303            TexOutput(_T("</OL>\n"));
1304            break;
1305          case LATEX_DESCRIPTION:
1306          default:
1307            TexOutput(_T("</DL>\n"));
1308            break;
1309        }
1310
1311        delete struc;
1312        delete itemizeStack.GetFirst();
1313      }
1314    }
1315    break;
1316  }
1317  case ltTWOCOLLIST :
1318  {
1319    if ( start )
1320        TexOutput(_T("\n<TABLE>\n"));
1321    else {
1322        TexOutput(_T("\n</TABLE>\n"));
1323    // DHS
1324        TwoColWidthA = -1;
1325        TwoColWidthB = -1;
1326    }
1327    break;
1328  }
1329  case ltPAR:
1330  {
1331    if (start)
1332      TexOutput(_T("<P>\n"));
1333    break;
1334  }
1335/* For footnotes we need to output the text at the bottom of the page and
1336 * insert a reference to it. Is it worth the trouble...
1337  case ltFOOTNOTE:
1338  case ltFOOTNOTEPOPUP:
1339  {
1340    if (start)
1341    {
1342      TexOutput(_T("<FN>"));
1343    }
1344    else TexOutput(_T("</FN>"));
1345    break;
1346  }
1347*/
1348  case ltVERB:
1349  {
1350    if (start)
1351      TexOutput(_T("<TT>"));
1352    else TexOutput(_T("</TT>"));
1353    break;
1354  }
1355  case ltVERBATIM:
1356  {
1357    if (start)
1358    {
1359      wxChar buf[100];
1360      wxSnprintf(buf, sizeof(buf), _T("<PRE>\n"));
1361      TexOutput(buf);
1362    }
1363    else TexOutput(_T("</PRE>\n"));
1364    break;
1365  }
1366  case ltCENTERLINE:
1367  case ltCENTER:
1368  {
1369    if (start)
1370    {
1371      TexOutput(_T("<CENTER>"));
1372    }
1373    else TexOutput(_T("</CENTER>"));
1374    break;
1375  }
1376  case ltFLUSHLEFT:
1377  {
1378/*
1379    if (start)
1380    {
1381      TexOutput(_T("{\\ql "));
1382    }
1383    else TexOutput(_T("}\\par\\pard\n"));
1384*/
1385    break;
1386  }
1387  case ltFLUSHRIGHT:
1388  {
1389/*
1390    if (start)
1391    {
1392      TexOutput(_T("{\\qr "));
1393    }
1394    else TexOutput(_T("}\\par\\pard\n"));
1395*/
1396    break;
1397  }
1398  case ltSMALL:
1399  {
1400    if (start)
1401    {
1402      // Netscape extension
1403      TexOutput(_T("<FONT SIZE=2>"));
1404    }
1405    else TexOutput(_T("</FONT>"));
1406    break;
1407  }
1408  case ltTINY:
1409  {
1410    if (start)
1411    {
1412      // Netscape extension
1413      TexOutput(_T("<FONT SIZE=1>"));
1414    }
1415    else TexOutput(_T("</FONT>"));
1416    break;
1417  }
1418  case ltNORMALSIZE:
1419  {
1420    if (start)
1421    {
1422      // Netscape extension
1423      TexOutput(_T("<FONT SIZE=3>"));
1424    }
1425    else TexOutput(_T("</FONT>"));
1426    break;
1427  }
1428  case ltlarge:
1429  {
1430    if (start)
1431    {
1432      // Netscape extension
1433      TexOutput(_T("<FONT SIZE=4>"));
1434    }
1435    else TexOutput(_T("</FONT>"));
1436    break;
1437  }
1438  case ltLarge:
1439  {
1440    if (start)
1441    {
1442      // Netscape extension
1443      TexOutput(_T("<FONT SIZE=5>"));
1444    }
1445    else TexOutput(_T("</FONT>"));
1446    break;
1447  }
1448  case ltLARGE:
1449  {
1450    if (start)
1451    {
1452      // Netscape extension
1453      TexOutput(_T("<FONT SIZE=6>"));
1454    }
1455    else TexOutput(_T("</FONT>"));
1456    break;
1457  }
1458  case ltBFSERIES:
1459  case ltTEXTBF:
1460  case ltBF:
1461  {
1462    if (start)
1463    {
1464      TexOutput(_T("<B>"));
1465    }
1466    else TexOutput(_T("</B>"));
1467    break;
1468  }
1469  case ltITSHAPE:
1470  case ltTEXTIT:
1471  case ltIT:
1472  {
1473    if (start)
1474    {
1475      TexOutput(_T("<I>"));
1476    }
1477    else TexOutput(_T("</I>"));
1478    break;
1479  }
1480  case ltEMPH:
1481  case ltEM:
1482  {
1483    if (start)
1484    {
1485      TexOutput(_T("<EM>"));
1486    }
1487    else TexOutput(_T("</EM>"));
1488    break;
1489  }
1490  case ltUNDERLINE:
1491  {
1492    if (start)
1493    {
1494      TexOutput(_T("<UL>"));
1495    }
1496    else TexOutput(_T("</UL>"));
1497    break;
1498  }
1499  case ltTTFAMILY:
1500  case ltTEXTTT:
1501  case ltTT:
1502  {
1503    if (start)
1504    {
1505      TexOutput(_T("<TT>"));
1506    }
1507    else TexOutput(_T("</TT>"));
1508    break;
1509  }
1510  case ltCOPYRIGHT:
1511  {
1512    if (start)
1513      TexOutput(_T("&copy;"), true);
1514    break;
1515  }
1516  case ltREGISTERED:
1517  {
1518    if (start)
1519      TexOutput(_T("&reg;"), true);
1520    break;
1521  }
1522  // Arrows
1523  case ltLEFTARROW:
1524  {
1525    if (start) TexOutput(_T("&lt;--"));
1526    break;
1527  }
1528  case ltLEFTARROW2:
1529  {
1530    if (start) TexOutput(_T("&lt;=="));
1531    break;
1532  }
1533  case ltRIGHTARROW:
1534  {
1535      if (start) TexOutput(_T("--&gt;"));
1536      break;
1537  }
1538  case ltRIGHTARROW2:
1539  {
1540    if (start) TexOutput(_T("==&gt;"));
1541    break;
1542  }
1543  case ltLEFTRIGHTARROW:
1544  {
1545    if (start) TexOutput(_T("&lt;--&gt;"));
1546    break;
1547  }
1548  case ltLEFTRIGHTARROW2:
1549  {
1550    if (start) TexOutput(_T("&lt;==&gt;"));
1551    break;
1552  }
1553/*
1554  case ltSC:
1555  {
1556    break;
1557  }
1558*/
1559  case ltITEM:
1560  {
1561    if (!start)
1562    {
1563      wxNode *node = itemizeStack.GetFirst();
1564      if (node)
1565      {
1566        ItemizeStruc *struc = (ItemizeStruc *)node->GetData();
1567        struc->currentItem += 1;
1568        if (struc->listType == LATEX_DESCRIPTION)
1569        {
1570          if (descriptionItemArg)
1571          {
1572            TexOutput(_T("<DT> "));
1573            TraverseChildrenFromChunk(descriptionItemArg);
1574            TexOutput(_T("\n"));
1575            descriptionItemArg = NULL;
1576          }
1577          TexOutput(_T("<DD>"));
1578        }
1579        else
1580          TexOutput(_T("<LI>"));
1581      }
1582    }
1583    break;
1584  }
1585  case ltMAKETITLE:
1586  {
1587    if (start && DocumentTitle && DocumentAuthor)
1588    {
1589      // Add a special label for the contents page.
1590//      TexOutput(_T("<CENTER>\n"));
1591      TexOutput(_T("<A NAME=\"contents\">"));
1592      TexOutput(_T("<H2 ALIGN=CENTER>\n"));
1593      TraverseChildrenFromChunk(DocumentTitle);
1594      TexOutput(_T("</H2>"));
1595      TexOutput(_T("<P>"));
1596      TexOutput(_T("</A>\n"));
1597      TexOutput(_T("<P>\n\n"));
1598      TexOutput(_T("<H3 ALIGN=CENTER>"));
1599      TraverseChildrenFromChunk(DocumentAuthor);
1600      TexOutput(_T("</H3><P>\n\n"));
1601      if (DocumentDate)
1602      {
1603        TexOutput(_T("<H3 ALIGN=CENTER>"));
1604        TraverseChildrenFromChunk(DocumentDate);
1605        TexOutput(_T("</H3><P>\n\n"));
1606      }
1607//      TexOutput(_T("\n</CENTER>\n"));
1608      TexOutput(_T("\n<P><HR><P>\n"));
1609
1610/*
1611      // Now do optional frame contents page
1612      if (htmlFrameContents && FrameContents)
1613      {
1614        SetCurrentOutput(FrameContents);
1615
1616        // Add a special label for the contents page.
1617        TexOutput(_T("<CENTER>\n"));
1618        TexOutput(_T("<H3>\n"));
1619        TraverseChildrenFromChunk(DocumentTitle);
1620        TexOutput(_T("</H3>"));
1621        TexOutput(_T("<P>"));
1622        TexOutput(_T("</A>\n"));
1623        TexOutput(_T("<P>\n\n"));
1624        TexOutput(_T("<H3>"));
1625        TraverseChildrenFromChunk(DocumentAuthor);
1626        TexOutput(_T("</H3><P>\n\n"));
1627        if (DocumentDate)
1628        {
1629          TexOutput(_T("<H4>"));
1630          TraverseChildrenFromChunk(DocumentDate);
1631          TexOutput(_T("</H4><P>\n\n"));
1632        }
1633        TexOutput(_T("\n</CENTER>\n"));
1634        TexOutput(_T("<P><HR><P>\n"));
1635
1636        SetCurrentOutput(Titlepage);
1637      }
1638*/
1639    }
1640    break;
1641  }
1642  case ltHELPREF:
1643  case ltHELPREFN:
1644  case ltPOPREF:
1645  case ltURLREF:
1646  {
1647    if (start)
1648    {
1649      helpRefFilename = NULL;
1650      helpRefText = NULL;
1651    }
1652    break;
1653  }
1654  case ltBIBLIOGRAPHY:
1655  {
1656    if (start)
1657    {
1658      DefaultOnMacro(macroId, no_args, start);
1659    }
1660    else
1661    {
1662      DefaultOnMacro(macroId, no_args, start);
1663      TexOutput(_T("</DL>\n"));
1664    }
1665    break;
1666  }
1667  case ltHRULE:
1668  {
1669    if (start)
1670    {
1671      TexOutput(_T("<HR>\n"));
1672    }
1673    break;
1674  }
1675  case ltRULE:
1676  {
1677    if (start)
1678    {
1679      TexOutput(_T("<HR>\n"));
1680    }
1681    break;
1682  }
1683  case ltTABLEOFCONTENTS:
1684  {
1685    if (start)
1686    {
1687      // NB: if this is uncommented, the table of contents
1688      // completely disappears. If left commented, it's in the wrong
1689      // place.
1690      //fflush(Titlepage);
1691
1692      FILE *fd = wxFopen(ContentsName, _T("r"));
1693      if (fd)
1694      {
1695        int ch = getc(fd);
1696        while (ch != EOF)
1697        {
1698          wxPutc(ch, Titlepage);
1699          ch = getc(fd);
1700        }
1701        fclose(fd);
1702        fflush(Titlepage);
1703      }
1704      else
1705      {
1706        TexOutput(_T("RUN TEX2RTF AGAIN FOR CONTENTS PAGE\n"));
1707        OnInform(_T("Run Tex2RTF again to include contents page."));
1708      }
1709    }
1710    break;
1711  }
1712  case ltLANGLEBRA:
1713  {
1714    if (start)
1715      TexOutput(_T("&lt;"));
1716    break;
1717  }
1718  case ltRANGLEBRA:
1719  {
1720    if (start)
1721      TexOutput(_T("&gt;"));
1722    break;
1723  }
1724  case ltQUOTE:
1725  case ltQUOTATION:
1726  {
1727    if (start)
1728      TexOutput(_T("<BLOCKQUOTE>"));
1729    else
1730      TexOutput(_T("</BLOCKQUOTE>"));
1731    break;
1732  }
1733  case ltCAPTION:
1734  case ltCAPTIONSTAR:
1735  {
1736    if (start)
1737    {
1738      if (inTabular)
1739        TexOutput(_T("\n<CAPTION>"));
1740
1741      wxChar figBuf[40];
1742
1743      if ( inFigure )
1744      {
1745          figureNo ++;
1746
1747          if (DocumentStyle != LATEX_ARTICLE)
1748            wxSnprintf(figBuf, sizeof(figBuf), _T("%s %d.%d: "), FigureNameString, chapterNo, figureNo);
1749          else
1750            wxSnprintf(figBuf, sizeof(figBuf), _T("%s %d: "), FigureNameString, figureNo);
1751      }
1752      else
1753      {
1754          tableNo ++;
1755
1756          if (DocumentStyle != LATEX_ARTICLE)
1757            wxSnprintf(figBuf, sizeof(figBuf), _T("%s %d.%d: "), TableNameString, chapterNo, tableNo);
1758          else
1759            wxSnprintf(figBuf, sizeof(figBuf), _T("%s %d: "), TableNameString, tableNo);
1760      }
1761
1762      TexOutput(figBuf);
1763    }
1764    else
1765    {
1766      if (inTabular)
1767        TexOutput(_T("\n</CAPTION>\n"));
1768
1769      wxChar *topicName = FindTopicName(GetNextChunk());
1770
1771      int n = inFigure ? figureNo : tableNo;
1772
1773      AddTexRef(topicName, NULL, NULL,
1774           ((DocumentStyle != LATEX_ARTICLE) ? chapterNo : n),
1775            ((DocumentStyle != LATEX_ARTICLE) ? n : 0));
1776    }
1777    break;
1778  }
1779  case ltSS:
1780  {
1781    if (start) TexOutput(_T("&szlig;"));
1782    break;
1783  }
1784  case ltFIGURE:
1785  {
1786    if (start) inFigure = true;
1787    else inFigure = false;
1788    break;
1789  }
1790  case ltTABLE:
1791  {
1792    if (start) inTable = true;
1793    else inTable = false;
1794    break;
1795  }
1796  default:
1797    DefaultOnMacro(macroId, no_args, start);
1798    break;
1799  }
1800}
1801/*     CheckTypeRef()
1802
1803       should be called at of argument which usually is
1804       type declaration which propably contains name of
1805       documented class
1806
1807       examples:
1808               HTMLOnArgument
1809                       - ltFUNC,
1810                       - ltPARAM
1811                       - ltCPARAM
1812
1813       checks: GetArgData() if contains Type Declaration
1814                               and can be referenced to some file
1815       prints:
1816               before<a href="xxx&yyy">type</a>after
1817
1818       returns:
1819               false   - if no reference was found
1820               true    - if reference was found and HREF printed
1821*/
1822static bool CheckTypeRef()
1823{
1824  wxString typeDecl = GetArgData();
1825  if( !typeDecl.empty() ) {
1826    typeDecl.Replace(wxT("\\"),wxT(""));
1827    wxString label = typeDecl;
1828    label.Replace(wxT("const"),wxT(""));
1829    label.Replace(wxT("virtual"),wxT(""));
1830    label.Replace(wxT("static"),wxT(""));
1831    label.Replace(wxT("extern"),wxT(""));
1832    label = label.BeforeFirst('&');
1833    label = label.BeforeFirst(wxT('*'));
1834    label = label.BeforeFirst(wxT('\\'));
1835    label.Trim(true); label.Trim(false);
1836    wxString typeName = label;
1837    label.MakeLower();
1838    TexRef *texRef = FindReference((wxChar*)label.c_str());
1839
1840    if (texRef && texRef->refFile && wxStrcmp(texRef->refFile, _T("??")) != 0) {
1841      int a = typeDecl.Find(typeName);
1842      wxString before = typeDecl.Mid( 0, a );
1843      wxString after = typeDecl.Mid( a+typeName.Length() );
1844      //wxFprintf(stderr,wxT("%s <%s> %s to ... %s#%s !!!!\n"),
1845       //      before.c_str(),
1846       //      typeName.c_str(),
1847       //      after.c_str(),
1848       //      texRef->refFile,label.c_str());
1849      TexOutput(before);
1850      TexOutput(_T("<A HREF=\""));
1851      TexOutput(texRef->refFile);
1852      TexOutput(_T("#"));
1853      TexOutput(label);
1854      TexOutput(wxT("\">"));
1855      TexOutput(typeName);
1856      TexOutput(wxT("</A>"));
1857      TexOutput(after);
1858      return true;
1859    } else {
1860      //wxFprintf(stderr,wxT("'%s' from (%s) -> label %s NOT FOUND\n"),
1861       //      typeName.c_str(),
1862       //      typeDecl.c_str(),
1863       //      label.c_str());
1864      return false;
1865    }
1866  }
1867  return false;
1868}
1869// Called on start/end of argument examination
1870bool HTMLOnArgument(int macroId, int arg_no, bool start)
1871{
1872  switch (macroId)
1873  {
1874  case ltCHAPTER:
1875  case ltCHAPTERSTAR:
1876  case ltCHAPTERHEADING:
1877  case ltSECTION:
1878  case ltSECTIONSTAR:
1879  case ltSECTIONHEADING:
1880  case ltSUBSECTION:
1881  case ltSUBSECTIONSTAR:
1882  case ltSUBSUBSECTION:
1883  case ltSUBSUBSECTIONSTAR:
1884  case ltGLOSS:
1885  case ltMEMBERSECTION:
1886  case ltFUNCTIONSECTION:
1887  {
1888    if (!start && (arg_no == 1))
1889      currentSection = GetArgChunk();
1890    return false;
1891  }
1892  case ltFUNC:
1893  {
1894    if (start && (arg_no == 1)) {
1895      TexOutput(_T("<B>"));
1896      if( CheckTypeRef() ) {
1897       TexOutput(_T("</B> "));
1898       return false;
1899      }
1900    }
1901
1902    if (!start && (arg_no == 1))
1903      TexOutput(_T("</B> "));
1904
1905    if (start && (arg_no == 2))
1906    {
1907      if (!suppressNameDecoration) TexOutput(_T("<B>"));
1908      currentMember = GetArgChunk();
1909    }
1910    if (!start && (arg_no == 2))
1911    {
1912      if (!suppressNameDecoration) TexOutput(_T("</B>"));
1913    }
1914
1915    if (start && (arg_no == 3))
1916      TexOutput(_T("("));
1917    if (!start && (arg_no == 3))
1918     TexOutput(_T(")"));
1919   break;
1920  }
1921  case ltCLIPSFUNC:
1922  {
1923    if (start && (arg_no == 1))
1924      TexOutput(_T("<B>"));
1925    if (!start && (arg_no == 1))
1926      TexOutput(_T("</B> "));
1927
1928    if (start && (arg_no == 2))
1929    {
1930      if (!suppressNameDecoration) TexOutput(_T("( "));
1931      currentMember = GetArgChunk();
1932    }
1933    if (!start && (arg_no == 2))
1934    {
1935    }
1936
1937    if (!start && (arg_no == 3))
1938     TexOutput(_T(")"));
1939    break;
1940  }
1941  case ltPFUNC:
1942  {
1943    if (!start && (arg_no == 1))
1944      TexOutput(_T(" "));
1945
1946    if (start && (arg_no == 2))
1947      TexOutput(_T("(*"));
1948    if (!start && (arg_no == 2))
1949      TexOutput(_T(")"));
1950
1951    if (start && (arg_no == 2))
1952      currentMember = GetArgChunk();
1953
1954    if (start && (arg_no == 3))
1955      TexOutput(_T("("));
1956    if (!start && (arg_no == 3))
1957      TexOutput(_T(")"));
1958    break;
1959  }
1960  case ltPARAM:
1961  case ltCPARAM:
1962  {
1963    const wxChar* pend = macroId == ltCPARAM ?
1964       _T("</B> ") : _T("</B>");
1965    if( arg_no == 1) {
1966      if( start ) {
1967       TexOutput(_T("<B>"));
1968       if( CheckTypeRef() ) {
1969         TexOutput(pend);
1970         return false;
1971       }
1972      } else {
1973       TexOutput(pend);
1974      }
1975    }
1976    if (start && (arg_no == 2))
1977    {
1978      TexOutput(_T("<I>"));
1979    }
1980    if (!start && (arg_no == 2))
1981    {
1982      TexOutput(_T("</I>"));
1983    }
1984    break;
1985  }
1986  case ltMEMBER:
1987  {
1988    if (!start && (arg_no == 1))
1989      TexOutput(_T(" "));
1990
1991    if (start && (arg_no == 2))
1992      currentMember = GetArgChunk();
1993    break;
1994  }
1995  case ltREF:
1996  {
1997    if (start)
1998    {
1999      wxChar *sec = NULL;
2000
2001      wxChar *refName = GetArgData();
2002      if (refName)
2003      {
2004        TexRef *texRef = FindReference(refName);
2005        if (texRef)
2006        {
2007          sec = texRef->sectionNumber;
2008        }
2009      }
2010      if (sec)
2011      {
2012        TexOutput(sec);
2013      }
2014      return false;
2015    }
2016    break;
2017  }
2018  case ltURLREF:
2019  {
2020    if (IsArgOptional())
2021      return false;
2022    else if ((GetNoArgs() - arg_no) == 1)
2023    {
2024      if (start)
2025        helpRefText = GetArgChunk();
2026      return false;
2027    }
2028    else if ((GetNoArgs() - arg_no) == 0) // Arg = 2, or 3 if first is optional
2029    {
2030      if (start)
2031      {
2032        TexChunk *ref = GetArgChunk();
2033        TexOutput(_T("<A HREF=\""));
2034        inVerbatim = true;
2035        TraverseChildrenFromChunk(ref);
2036        inVerbatim = false;
2037        TexOutput(_T("\">"));
2038        if (helpRefText)
2039          TraverseChildrenFromChunk(helpRefText);
2040        TexOutput(_T("</A>"));
2041      }
2042      return false;
2043    }
2044    break;
2045  }
2046
2047  case ltHELPREF:
2048  case ltHELPREFN:
2049  case ltPOPREF:
2050  {
2051    if (IsArgOptional())
2052    {
2053      if (start)
2054        helpRefFilename = GetArgChunk();
2055      return false;
2056    }
2057    if ((GetNoArgs() - arg_no) == 1)
2058    {
2059      if (start)
2060        helpRefText = GetArgChunk();
2061      return false;
2062    }
2063    else if ((GetNoArgs() - arg_no) == 0) // Arg = 2, or 3 if first is optional
2064    {
2065      if (start)
2066      {
2067        wxChar *refName = GetArgData();
2068        wxChar *refFilename = NULL;
2069
2070        if (refName)
2071        {
2072          TexRef *texRef = FindReference(refName);
2073          if (texRef)
2074          {
2075            if (texRef->refFile && wxStrcmp(texRef->refFile, _T("??")) != 0)
2076              refFilename = texRef->refFile;
2077
2078            TexOutput(_T("<A HREF=\""));
2079            // If a filename is supplied, use it, otherwise try to
2080            // use the filename associated with the reference (from this document).
2081            if (helpRefFilename)
2082            {
2083              TraverseChildrenFromChunk(helpRefFilename);
2084              TexOutput(_T("#"));
2085              TexOutput(refName);
2086            }
2087            else if (refFilename)
2088            {
2089              TexOutput(ConvertCase(refFilename));
2090              if(!PrimaryAnchorOfTheFile(texRef->refFile, refName))
2091              {
2092                TexOutput(_T("#"));
2093                TexOutput(refName);
2094              }
2095            }
2096            TexOutput(_T("\">"));
2097            if (helpRefText)
2098              TraverseChildrenFromChunk(helpRefText);
2099            TexOutput(_T("</A>"));
2100          }
2101          else
2102          {
2103            if (helpRefText)
2104              TraverseChildrenFromChunk(helpRefText);
2105            if (!ignoreBadRefs)
2106              TexOutput(_T(" (REF NOT FOUND)"));
2107
2108            // for launching twice do not warn in preparation pass
2109            if ((passNumber == 1 && !runTwice) ||
2110                (passNumber == 2 && runTwice))
2111            {
2112              wxString errBuf;
2113              errBuf.Printf(_T("Warning: unresolved reference '%s'"), refName);
2114              OnInform((wxChar *)errBuf.c_str());
2115            }
2116          }
2117        }
2118        else TexOutput(_T("??"));
2119      }
2120      return false;
2121    }
2122    break;
2123  }
2124  case ltIMAGE:
2125  case ltIMAGEL:
2126  case ltIMAGER:
2127  case ltPSBOXTO:
2128  {
2129    if (arg_no == 2)
2130    {
2131      if (start)
2132      {
2133        wxChar *alignment = _T("");
2134        if (macroId == ltIMAGEL)
2135          alignment = _T(" align=left");
2136        else if  (macroId == ltIMAGER)
2137          alignment = _T(" align=right");
2138
2139        // Try to find an XBM or GIF image first.
2140        wxChar *filename = copystring(GetArgData());
2141        wxChar buf[500];
2142
2143        wxStrcpy(buf, filename);
2144        StripExtension(buf);
2145        wxStrcat(buf, _T(".xbm"));
2146        wxString f = TexPathList.FindValidPath(buf);
2147
2148        if (f == _T("")) // Try for a GIF instead
2149        {
2150          wxStrcpy(buf, filename);
2151          StripExtension(buf);
2152          wxStrcat(buf, _T(".gif"));
2153          f = TexPathList.FindValidPath(buf);
2154        }
2155
2156        if (f == _T("")) // Try for a JPEG instead
2157        {
2158          wxStrcpy(buf, filename);
2159          StripExtension(buf);
2160          wxStrcat(buf, _T(".jpg"));
2161          f = TexPathList.FindValidPath(buf);
2162        }
2163
2164        if (f == _T("")) // Try for a PNG instead
2165        {
2166          wxStrcpy(buf, filename);
2167          StripExtension(buf);
2168          wxStrcat(buf, _T(".png"));
2169          f = TexPathList.FindValidPath(buf);
2170        }
2171
2172        if (f != _T(""))
2173        {
2174          wxChar *inlineFilename = copystring(f);
2175#if 0
2176          wxChar *originalFilename = TexPathList.FindValidPath(filename);
2177          // If we have found the existing filename, make the inline
2178          // image point to the original file (could be PS, for example)
2179          if (originalFilename && (wxStrcmp(inlineFilename, originalFilename) != 0))
2180          {
2181            TexOutput(_T("<A HREF=\""));
2182            TexOutput(ConvertCase(originalFilename));
2183            TexOutput(_T("\">"));
2184            TexOutput(_T("<img src=\""));
2185            TexOutput(ConvertCase(wxFileNameFromPath(inlineFilename)));
2186            TexOutput(_T("\""));
2187            TexOutput(alignment);
2188            TexOutput(_T("></A>"));
2189          }
2190          else
2191#endif
2192          {
2193            TexOutput(_T("<img src=\""));
2194            TexOutput(ConvertCase(wxFileNameFromPath(inlineFilename)));
2195            TexOutput(_T("\""));
2196            TexOutput(alignment);
2197            TexOutput(_T(">"));
2198            delete[] inlineFilename;
2199          }
2200        }
2201        else
2202        {
2203          // Last resort - a link to a PS file.
2204          TexOutput(_T("<A HREF=\""));
2205          TexOutput(ConvertCase(wxFileNameFromPath(filename)));
2206          TexOutput(_T("\">Picture</A>\n"));
2207          wxSnprintf(buf, sizeof(buf), _T("Warning: could not find an inline XBM/GIF for %s."), filename);
2208          OnInform(buf);
2209        }
2210      }
2211    }
2212    return false;
2213  }
2214  // First arg is PSBOX spec (ignored), second is image file, third is map name.
2215  case ltIMAGEMAP:
2216  {
2217    static wxChar *imageFile = NULL;
2218    if (start && (arg_no == 2))
2219    {
2220      // Try to find an XBM or GIF image first.
2221      wxChar *filename = copystring(GetArgData());
2222      wxChar buf[500];
2223
2224      wxStrcpy(buf, filename);
2225      StripExtension(buf);
2226      wxStrcat(buf, _T(".xbm"));
2227      wxString f = TexPathList.FindValidPath(buf);
2228
2229      if (f == _T("")) // Try for a GIF instead
2230      {
2231        wxStrcpy(buf, filename);
2232        StripExtension(buf);
2233        wxStrcat(buf, _T(".gif"));
2234        f = TexPathList.FindValidPath(buf);
2235      }
2236      if (f == _T(""))
2237      {
2238        wxChar buf[300];
2239        wxSnprintf(buf, sizeof(buf), _T("Warning: could not find an inline XBM/GIF for %s."), filename);
2240        OnInform(buf);
2241      }
2242      delete[] filename;
2243      if (imageFile)
2244        delete[] imageFile;
2245      imageFile = NULL;
2246      if (!f.empty())
2247      {
2248        imageFile = copystring(f);
2249      }
2250    }
2251    else if (start && (arg_no == 3))
2252    {
2253      if (imageFile)
2254      {
2255        // First, try to find a .shg (segmented hypergraphics file)
2256        // that we can convert to a map file
2257        wxChar buf[256];
2258        wxStrcpy(buf, imageFile);
2259        StripExtension(buf);
2260        wxStrcat(buf, _T(".shg"));
2261        wxString f = TexPathList.FindValidPath(buf);
2262
2263        if (f != _T(""))
2264        {
2265          // The default HTML file to go to is THIS file (so a no-op)
2266          SHGToMap((wxChar *)f.c_str(), currentFileName);
2267        }
2268
2269        wxChar *mapName = GetArgData();
2270        TexOutput(_T("<A HREF=\"/cgi-bin/imagemap/"));
2271        if (mapName)
2272          TexOutput(mapName);
2273        else
2274          TexOutput(_T("unknown"));
2275        TexOutput(_T("\">"));
2276        TexOutput(_T("<img src=\""));
2277        TexOutput(ConvertCase(wxFileNameFromPath(imageFile)));
2278        TexOutput(_T("\" ISMAP></A><P>"));
2279        delete[] imageFile;
2280        imageFile = NULL;
2281      }
2282    }
2283    return false;
2284  }
2285  case ltINDENTED :
2286  {
2287    if ( arg_no == 1 )
2288        return false;
2289    else
2290    {
2291        return true;
2292    }
2293  }
2294  case ltITEM:
2295  {
2296    if (start)
2297    {
2298      descriptionItemArg = GetArgChunk();
2299      return false;
2300    }
2301    return true;
2302  }
2303  case ltTWOCOLITEM:
2304  case ltTWOCOLITEMRULED:
2305  {
2306/*
2307    if (start && (arg_no == 1))
2308      TexOutput(_T("\n<DT> "));
2309    if (start && (arg_no == 2))
2310      TexOutput(_T("<DD> "));
2311*/
2312    if (arg_no == 1)
2313    {
2314      if ( start ) {
2315        // DHS
2316        if (TwoColWidthA > -1)
2317        {
2318          wxChar buf[100];
2319          wxSnprintf(buf, sizeof(buf), _T("\n<TR><TD VALIGN=TOP WIDTH=%d>\n"),TwoColWidthA);
2320          TexOutput(buf);
2321        }
2322        else
2323        {
2324          TexOutput(_T("\n<TR><TD VALIGN=TOP>\n"));
2325        }
2326        OutputFont();
2327      }  else
2328            TexOutput(_T("\n</FONT></TD>\n"));
2329    }
2330    if (arg_no == 2)
2331    {
2332      // DHS
2333      if ( start )
2334      {
2335        if (TwoColWidthB > -1)
2336        {
2337          wxChar buf[100];
2338          wxSnprintf(buf, sizeof(buf), _T("\n<TD VALIGN=TOP WIDTH=%d>\n"),TwoColWidthB);
2339          TexOutput(buf);
2340        }
2341        else
2342        {
2343          TexOutput(_T("\n<TD VALIGN=TOP>\n"));
2344        }
2345        OutputFont();
2346      }  else
2347           TexOutput(_T("\n</FONT></TD></TR>\n"));
2348    }
2349    return true;
2350  }
2351  case ltNUMBEREDBIBITEM:
2352  {
2353    if (arg_no == 1 && start)
2354    {
2355      TexOutput(_T("\n<DT> "));
2356    }
2357    if (arg_no == 2 && !start)
2358      TexOutput(_T("<P>\n"));
2359    break;
2360  }
2361  case ltBIBITEM:
2362  {
2363    wxChar buf[100];
2364    if (arg_no == 1 && start)
2365    {
2366      wxChar *citeKey = GetArgData();
2367      TexRef *ref = (TexRef *)TexReferences.Get(citeKey);
2368      if (ref)
2369      {
2370        if (ref->sectionNumber) delete[] ref->sectionNumber;
2371        wxSnprintf(buf, sizeof(buf), _T("[%d]"), citeCount);
2372        ref->sectionNumber = copystring(buf);
2373      }
2374
2375      wxSnprintf(buf, sizeof(buf), _T("\n<DT> [%d] "), citeCount);
2376      TexOutput(buf);
2377      citeCount ++;
2378      return false;
2379    }
2380    if (arg_no == 2 && !start)
2381      TexOutput(_T("<P>\n"));
2382    return true;
2383  }
2384  case ltMARGINPAR:
2385  case ltMARGINPARODD:
2386  case ltMARGINPAREVEN:
2387  case ltNORMALBOX:
2388  case ltNORMALBOXD:
2389  {
2390    if (start)
2391    {
2392      TexOutput(_T("<HR>\n"));
2393      return true;
2394    }
2395    else
2396      TexOutput(_T("<HR><P>\n"));
2397    break;
2398  }
2399  // DHS
2400  case ltTWOCOLWIDTHA:
2401  {
2402    if (start)
2403    {
2404      wxChar *val = GetArgData();
2405      float points = ParseUnitArgument(val);
2406      TwoColWidthA = (int)((points * 100.0) / 72.0);
2407    }
2408    return false;
2409  }
2410  // DHS
2411  case ltTWOCOLWIDTHB:
2412  {
2413    if (start)
2414    {
2415      wxChar *val = GetArgData();
2416      float points = ParseUnitArgument(val);
2417      TwoColWidthB = (int)((points * 100.0) / 72.0);
2418    }
2419    return false;
2420  }
2421  /*
2422   * Accents
2423   *
2424   */
2425  case ltACCENT_GRAVE:
2426  {
2427    if (start)
2428    {
2429      wxChar *val = GetArgData();
2430      if (val)
2431      {
2432        switch (val[0])
2433        {
2434          case 'a':
2435           TexOutput(_T("&agrave;"));
2436           break;
2437          case 'e':
2438           TexOutput(_T("&egrave;"));
2439           break;
2440          case 'i':
2441           TexOutput(_T("&igrave;"));
2442           break;
2443          case 'o':
2444           TexOutput(_T("&ograve;"));
2445           break;
2446          case 'u':
2447           TexOutput(_T("&ugrave;"));
2448           break;
2449          case 'A':
2450           TexOutput(_T("&Agrave;"));
2451           break;
2452          case 'E':
2453           TexOutput(_T("&Egrave;"));
2454           break;
2455          case 'I':
2456           TexOutput(_T("&Igrave;"));
2457           break;
2458          case 'O':
2459           TexOutput(_T("&Ograve;"));
2460           break;
2461          case 'U':
2462           TexOutput(_T("&Igrave;"));
2463           break;
2464          default:
2465           break;
2466        }
2467      }
2468    }
2469    return false;
2470  }
2471  case ltACCENT_ACUTE:
2472  {
2473    if (start)
2474    {
2475      wxChar *val = GetArgData();
2476      if (val)
2477      {
2478        switch (val[0])
2479        {
2480          case 'a':
2481           TexOutput(_T("&aacute;"));
2482           break;
2483          case 'e':
2484           TexOutput(_T("&eacute;"));
2485           break;
2486          case 'i':
2487           TexOutput(_T("&iacute;"));
2488           break;
2489          case 'o':
2490           TexOutput(_T("&oacute;"));
2491           break;
2492          case 'u':
2493           TexOutput(_T("&uacute;"));
2494           break;
2495          case 'y':
2496           TexOutput(_T("&yacute;"));
2497           break;
2498          case 'A':
2499           TexOutput(_T("&Aacute;"));
2500           break;
2501          case 'E':
2502           TexOutput(_T("&Eacute;"));
2503           break;
2504          case 'I':
2505           TexOutput(_T("&Iacute;"));
2506           break;
2507          case 'O':
2508           TexOutput(_T("&Oacute;"));
2509           break;
2510          case 'U':
2511           TexOutput(_T("&Uacute;"));
2512           break;
2513          case 'Y':
2514           TexOutput(_T("&Yacute;"));
2515           break;
2516          default:
2517           break;
2518        }
2519      }
2520    }
2521    return false;
2522  }
2523  case ltACCENT_CARET:
2524  {
2525    if (start)
2526    {
2527      wxChar *val = GetArgData();
2528      if (val)
2529      {
2530        switch (val[0])
2531        {
2532          case 'a':
2533           TexOutput(_T("&acirc;"));
2534           break;
2535          case 'e':
2536           TexOutput(_T("&ecirc;"));
2537           break;
2538          case 'i':
2539           TexOutput(_T("&icirc;"));
2540           break;
2541          case 'o':
2542           TexOutput(_T("&ocirc;"));
2543           break;
2544          case 'u':
2545           TexOutput(_T("&ucirc;"));
2546           break;
2547          case 'A':
2548           TexOutput(_T("&Acirc;"));
2549           break;
2550          case 'E':
2551           TexOutput(_T("&Ecirc;"));
2552           break;
2553          case 'I':
2554           TexOutput(_T("&Icirc;"));
2555           break;
2556          case 'O':
2557           TexOutput(_T("&Ocirc;"));
2558           break;
2559          case 'U':
2560           TexOutput(_T("&Icirc;"));
2561           break;
2562          default:
2563           break;
2564        }
2565      }
2566    }
2567    return false;
2568  }
2569  case ltACCENT_TILDE:
2570  {
2571    if (start)
2572    {
2573      wxChar *val = GetArgData();
2574      if (val)
2575      {
2576        switch (val[0])
2577        {
2578          case ' ':
2579           TexOutput(_T("~"));
2580           break;
2581          case 'a':
2582           TexOutput(_T("&atilde;"));
2583           break;
2584          case 'n':
2585           TexOutput(_T("&ntilde;"));
2586           break;
2587          case 'o':
2588           TexOutput(_T("&otilde;"));
2589           break;
2590          case 'A':
2591           TexOutput(_T("&Atilde;"));
2592           break;
2593          case 'N':
2594           TexOutput(_T("&Ntilde;"));
2595           break;
2596          case 'O':
2597           TexOutput(_T("&Otilde;"));
2598           break;
2599          default:
2600           break;
2601        }
2602      }
2603    }
2604    return false;
2605  }
2606  case ltACCENT_UMLAUT:
2607  {
2608    if (start)
2609    {
2610      wxChar *val = GetArgData();
2611      if (val)
2612      {
2613        switch (val[0])
2614        {
2615          case 'a':
2616           TexOutput(_T("&auml;"));
2617           break;
2618          case 'e':
2619           TexOutput(_T("&euml;"));
2620           break;
2621          case 'i':
2622           TexOutput(_T("&iuml;"));
2623           break;
2624          case 'o':
2625           TexOutput(_T("&ouml;"));
2626           break;
2627          case 'u':
2628           TexOutput(_T("&uuml;"));
2629           break;
2630          case 'y':
2631           TexOutput(_T("&yuml;"));
2632           break;
2633          case 'A':
2634           TexOutput(_T("&Auml;"));
2635           break;
2636          case 'E':
2637           TexOutput(_T("&Euml;"));
2638           break;
2639          case 'I':
2640           TexOutput(_T("&Iuml;"));
2641           break;
2642          case 'O':
2643           TexOutput(_T("&Ouml;"));
2644           break;
2645          case 'U':
2646           TexOutput(_T("&Uuml;"));
2647           break;
2648          case 'Y':
2649           TexOutput(_T("&Yuml;"));
2650           break;
2651          default:
2652           break;
2653        }
2654      }
2655    }
2656    return false;
2657  }
2658  case ltACCENT_DOT:
2659  {
2660    if (start)
2661    {
2662      wxChar *val = GetArgData();
2663      if (val)
2664      {
2665        switch (val[0])
2666        {
2667          case 'a':
2668           TexOutput(_T("&aring;"));
2669           break;
2670          case 'A':
2671           TexOutput(_T("&Aring;"));
2672           break;
2673          default:
2674           break;
2675        }
2676      }
2677    }
2678    return false;
2679  }
2680  case ltBACKGROUND:
2681  {
2682    if (start)
2683    {
2684      wxChar *val = GetArgData();
2685      if (val)
2686      {
2687        bool isPicture = false;
2688        ParseColourString(val, &isPicture);
2689        if (isPicture)
2690        {
2691          if (backgroundImageString)
2692            delete[] backgroundImageString;
2693          backgroundImageString = copystring(val);
2694        }
2695        else
2696        {
2697          if (backgroundColourString)
2698            delete[] backgroundColourString;
2699          backgroundColourString = copystring(val);
2700        }
2701      }
2702    }
2703    return false;
2704  }
2705  case ltBACKGROUNDIMAGE:
2706  {
2707    if (start)
2708    {
2709      wxChar *val = GetArgData();
2710      if (val)
2711      {
2712        if (backgroundImageString)
2713          delete[] backgroundImageString;
2714        backgroundImageString = copystring(val);
2715      }
2716    }
2717    return false;
2718  }
2719  case ltBACKGROUNDCOLOUR:
2720  {
2721    if (start)
2722    {
2723      wxChar *val = GetArgData();
2724      if (val)
2725      {
2726        if (backgroundColourString)
2727          delete[] backgroundColourString;
2728        backgroundColourString = copystring(val);
2729      }
2730    }
2731    return false;
2732  }
2733  case ltTEXTCOLOUR:
2734  {
2735    if (start)
2736    {
2737      wxChar *val = GetArgData();
2738      if (val)
2739      {
2740        if (textColourString)
2741          delete[] textColourString;
2742        textColourString = copystring(val);
2743      }
2744    }
2745    return false;
2746  }
2747  case ltLINKCOLOUR:
2748  {
2749    if (start)
2750    {
2751      wxChar *val = GetArgData();
2752      if (val)
2753      {
2754        if (linkColourString)
2755          delete[] linkColourString;
2756        linkColourString = copystring(val);
2757      }
2758    }
2759    return false;
2760  }
2761  case ltFOLLOWEDLINKCOLOUR:
2762  {
2763    if (start)
2764    {
2765      wxChar *val = GetArgData();
2766      if (val)
2767      {
2768        if (followedLinkColourString)
2769          delete[] followedLinkColourString;
2770        followedLinkColourString = copystring(val);
2771      }
2772    }
2773    return false;
2774  }
2775  case ltACCENT_CADILLA:
2776  {
2777    if (start)
2778    {
2779      wxChar *val = GetArgData();
2780      if (val)
2781      {
2782        switch (val[0])
2783        {
2784          case 'c':
2785           TexOutput(_T("&ccedil;"));
2786           break;
2787          case 'C':
2788           TexOutput(_T("&Ccedil;"));
2789           break;
2790          default:
2791           break;
2792        }
2793      }
2794    }
2795    return false;
2796  }
2797/*
2798  case ltFOOTNOTE:
2799  case ltFOOTNOTEPOPUP:
2800  {
2801    if (arg_no == 1)
2802      return true;
2803    else
2804      return false;
2805    break;
2806  }
2807*/
2808  case ltTABULAR:
2809  case ltSUPERTABULAR:
2810  {
2811    if (arg_no == 1)
2812    {
2813      if (start)
2814      {
2815        currentRowNumber = 0;
2816        inTabular = true;
2817        startRows = true;
2818        tableVerticalLineLeft = false;
2819        tableVerticalLineRight = false;
2820
2821        wxChar *alignString = copystring(GetArgData());
2822        ParseTableArgument(alignString);
2823
2824        TexOutput(_T("<TABLE BORDER>\n"));
2825
2826        // Write the first row formatting for compatibility
2827        // with standard Latex
2828        if (compatibilityMode)
2829        {
2830          TexOutput(_T("<TR>\n<TD>"));
2831          OutputFont();
2832/*
2833          for (int i = 0; i < noColumns; i++)
2834          {
2835            currentWidth += TableData[i].width;
2836            wxSnprintf(buf, sizeof(buf), _T("\\cellx%d"), currentWidth);
2837            TexOutput(buf);
2838          }
2839          TexOutput(_T("\\pard\\intbl\n"));
2840*/
2841        }
2842        delete[] alignString;
2843
2844        return false;
2845      }
2846    }
2847    else if (arg_no == 2 && !start)
2848    {
2849      TexOutput(_T("</TABLE>\n"));
2850      inTabular = false;
2851    }
2852    break;
2853  }
2854  case ltTHEBIBLIOGRAPHY:
2855  {
2856    if (start && (arg_no == 1))
2857    {
2858      ReopenFile(&Chapters, &ChaptersName, _T("bibliography"));
2859      AddTexRef(_T("bibliography"), ChaptersName, _T("bibliography"));
2860      SetCurrentSubsectionName(_T("bibliography"), ChaptersName);
2861
2862      citeCount = 1;
2863
2864      SetCurrentOutput(Chapters);
2865
2866      wxChar titleBuf[150];
2867      if (truncateFilenames)
2868        wxSnprintf(titleBuf, sizeof(titleBuf), _T("%s.htm"), wxFileNameFromPath(FileRoot));
2869      else
2870        wxSnprintf(titleBuf, sizeof(titleBuf), _T("%s_contents.html"), wxFileNameFromPath(FileRoot));
2871
2872      HTMLHead();
2873      TexOutput(_T("<title>"));
2874      TexOutput(ReferencesNameString);
2875      TexOutput(_T("</title></head>\n"));
2876      OutputBodyStart();
2877
2878      wxFprintf(Chapters, _T("<A NAME=\"%s\">\n<H2>%s"), _T("bibliography"), ReferencesNameString);
2879      AddBrowseButtons(_T("contents"), titleBuf, // Up
2880                       lastTopic, lastFileName,  // Last topic
2881                       _T("bibliography"), ChaptersName); // This topic
2882
2883      SetCurrentOutputs(Contents, Chapters);
2884      if(PrimaryAnchorOfTheFile(ChaptersName, _T("bibliography")))
2885        wxFprintf(Contents, _T("\n<LI><A HREF=\"%s\">"), ConvertCase(ChaptersName));
2886      else
2887        wxFprintf(Contents, _T("\n<LI><A HREF=\"%s#%s\">"), ConvertCase(ChaptersName), _T("bibliography"));
2888
2889      wxFprintf(Contents, _T("%s</A>\n"), ReferencesNameString);
2890      wxFprintf(Chapters, _T("</H2>\n</A>\n"));
2891
2892      SetCurrentOutput(Chapters);
2893      return false;
2894    }
2895    if (!start && (arg_no == 2))
2896    {
2897    }
2898    return true;
2899  }
2900  case ltINDEX:
2901  {
2902    /* Build up list of keywords associated with topics */
2903    if (start)
2904    {
2905//      wxChar *entry = GetArgData();
2906      wxChar buf[300];
2907      OutputChunkToString(GetArgChunk(), buf);
2908      if (CurrentTopic)
2909      {
2910        AddKeyWordForTopic(CurrentTopic, buf, currentFileName);
2911      }
2912    }
2913    return false;
2914  }
2915  case ltFCOL:
2916//  case ltBCOL:
2917  {
2918    if (start)
2919    {
2920      switch (arg_no)
2921      {
2922        case 1:
2923        {
2924          wxChar *name = GetArgData();
2925          wxChar buf2[10];
2926          if (!FindColourHTMLString(name, buf2))
2927          {
2928            wxStrcpy(buf2, _T("#000000"));
2929            wxChar buf[100];
2930            wxSnprintf(buf, sizeof(buf), _T("Could not find colour name %s"), name);
2931            OnError(buf);
2932          }
2933          TexOutput(_T("<FONT COLOR=\""));
2934          TexOutput(buf2);
2935          TexOutput(_T("\">"));
2936          break;
2937        }
2938        case 2:
2939        {
2940          return true;
2941        }
2942        default:
2943          break;
2944      }
2945    }
2946    else
2947    {
2948      if (arg_no == 2) TexOutput(_T("</FONT>"));
2949    }
2950    return false;
2951  }
2952  case ltINSERTATLEVEL:
2953  {
2954    // This macro allows you to insert text at a different level
2955    // from the current level, e.g. into the Sections from within a subsubsection.
2956    if (useWord)
2957        return false;
2958    static int currentLevelNo = 1;
2959    static FILE* oldLevelFile = Chapters;
2960    if (start)
2961    {
2962      switch (arg_no)
2963      {
2964        case 1:
2965        {
2966          oldLevelFile = CurrentOutput1;
2967
2968          wxChar *str = GetArgData();
2969          currentLevelNo = wxAtoi(str);
2970          FILE* outputFile;
2971          // TODO: cope with article style (no chapters)
2972          switch (currentLevelNo)
2973          {
2974            case 1:
2975            {
2976                outputFile = Chapters;
2977                break;
2978            }
2979            case 2:
2980            {
2981                outputFile = Sections;
2982                break;
2983            }
2984            case 3:
2985            {
2986                outputFile = Subsections;
2987                break;
2988            }
2989            case 4:
2990            {
2991                outputFile = Subsubsections;
2992                break;
2993            }
2994            default:
2995            {
2996                outputFile = NULL;
2997                break;
2998            }
2999          }
3000          if (outputFile)
3001            CurrentOutput1 = outputFile;
3002          return false;
3003        }
3004        case 2:
3005        {
3006          return true;
3007        }
3008        default:
3009          break;
3010      }
3011      return true;
3012    }
3013    else
3014    {
3015        if (arg_no == 2)
3016        {
3017            CurrentOutput1 = oldLevelFile;
3018        }
3019        return true;
3020    }
3021  }
3022  default:
3023    return DefaultOnArgument(macroId, arg_no, start);
3024  }
3025  return true;
3026}
3027
3028bool HTMLGo(void)
3029{
3030    fileId = 0;
3031    inVerbatim = false;
3032    indentLevel = 0;
3033    inTabular = false;
3034    startRows = false;
3035    tableVerticalLineLeft = false;
3036    tableVerticalLineRight = false;
3037    noColumns = 0;
3038
3039    if (!InputFile.empty() && !OutputFile.empty())
3040    {
3041        // Do some HTML-specific transformations on all the strings,
3042        // recursively
3043        Text2HTML(GetTopLevelChunk());
3044
3045        wxChar buf[300];
3046        if (truncateFilenames)
3047            wxSnprintf(buf, WXSIZEOF(buf), _T("%s.htm"), FileRoot);
3048        else
3049            wxSnprintf(buf, WXSIZEOF(buf), _T("%s_contents.html"), FileRoot);
3050        if (TitlepageName) delete[] TitlepageName;
3051        TitlepageName = copystring(buf);
3052        Titlepage = wxFopen(buf, _T("w"));
3053
3054        if (truncateFilenames)
3055            wxSnprintf(buf, WXSIZEOF(buf), _T("%s_fc.htm"), FileRoot);
3056        else
3057            wxSnprintf(buf, WXSIZEOF(buf), _T("%s_fcontents.html"), FileRoot);
3058
3059        contentsFrameName = copystring(buf);
3060
3061        Contents = wxFopen(TmpContentsName, _T("w"));
3062
3063        if (htmlFrameContents)
3064        {
3065//          FrameContents = wxFopen(TmpFrameContentsName, _T("w"));
3066            FrameContents = wxFopen(contentsFrameName, _T("w"));
3067            wxFprintf(FrameContents, _T("<HTML>\n<UL>\n"));
3068        }
3069
3070        if (!Titlepage || !Contents)
3071        {
3072            OnError(_T("Cannot open output file!"));
3073            return false;
3074        }
3075        AddTexRef(_T("contents"), wxFileNameFromPath(TitlepageName), ContentsNameString);
3076
3077        wxFprintf(Contents, _T("<P><P><H2>%s</H2><P><P>\n"), ContentsNameString);
3078
3079        wxFprintf(Contents, _T("<UL>\n"));
3080
3081        SetCurrentOutput(Titlepage);
3082        if (htmlWorkshopFiles) HTMLWorkshopStartContents();
3083        OnInform(_T("Converting..."));
3084
3085        TraverseDocument();
3086        wxFprintf(Contents, _T("</UL>\n\n"));
3087
3088//        SetCurrentOutput(Titlepage);
3089        fclose(Titlepage);
3090
3091        if (Contents)
3092        {
3093//            wxFprintf(Titlepage, _T("\n</BODY></HTML>\n"));
3094            fclose(Contents);
3095            Contents = NULL;
3096        }
3097
3098        if (FrameContents)
3099        {
3100            wxFprintf(FrameContents, _T("\n</UL>\n"));
3101            wxFprintf(FrameContents, _T("</HTML>\n"));
3102            fclose(FrameContents);
3103            FrameContents = NULL;
3104        }
3105
3106        if (Chapters)
3107        {
3108            wxFprintf(Chapters, _T("\n</FONT></BODY></HTML>\n"));
3109            fclose(Chapters);
3110            Chapters = NULL;
3111        }
3112        if (Sections)
3113        {
3114            wxFprintf(Sections, _T("\n</FONT></BODY></HTML>\n"));
3115            fclose(Sections);
3116            Sections = NULL;
3117        }
3118        if (Subsections && !combineSubSections)
3119        {
3120            wxFprintf(Subsections, _T("\n</FONT></BODY></HTML>\n"));
3121            fclose(Subsections);
3122            Subsections = NULL;
3123        }
3124        if (Subsubsections && !combineSubSections)
3125        {
3126            wxFprintf(Subsubsections, _T("\n</FONT></BODY></HTML>\n"));
3127            fclose(Subsubsections);
3128            Subsubsections = NULL;
3129        }
3130        if ( SectionContentsFD )
3131        {
3132            fclose(SectionContentsFD);
3133            SectionContentsFD = NULL;
3134        }
3135
3136        // Create a temporary file for the title page header, add some info,
3137        // and concat the titlepage just generated.
3138        // This is necessary in order to put the title of the document
3139        // at the TOP of the file within <HEAD>, even though we only find out
3140        // what it is later on.
3141        FILE *tmpTitle = wxFopen(_T("title.tmp"), _T("w"));
3142        if (tmpTitle)
3143        {
3144            if (DocumentTitle)
3145            {
3146                SetCurrentOutput(tmpTitle);
3147                HTMLHead();
3148                TexOutput(_T("\n<TITLE>"));
3149                TraverseChildrenFromChunk(DocumentTitle);
3150                TexOutput(_T("</TITLE></HEAD>\n"));
3151            }
3152            else
3153            {
3154                SetCurrentOutput(tmpTitle);
3155                HTMLHeadTo(tmpTitle);
3156                if (contentsString)
3157                    wxFprintf(tmpTitle, _T("<TITLE>%s</TITLE></HEAD>\n\n"), contentsString);
3158                else
3159                    wxFprintf(tmpTitle, _T("<TITLE>%s</TITLE></HEAD>\n\n"), wxFileNameFromPath(FileRoot));
3160            }
3161
3162            // Output frame information
3163            if (htmlFrameContents)
3164            {
3165                wxChar firstFileName[300];
3166                if (truncateFilenames)
3167                    wxSnprintf(firstFileName, sizeof(firstFileName), _T("%s1.htm"), FileRoot);
3168                else
3169                    wxStrcpy(firstFileName, gs_filenames[1].c_str());
3170
3171                wxFprintf(tmpTitle, _T("<FRAMESET COLS=\"30%%,70%%\">\n"));
3172
3173                wxFprintf(tmpTitle, _T("<FRAME SRC=\"%s\">\n"), ConvertCase(wxFileNameFromPath(contentsFrameName)));
3174                wxFprintf(tmpTitle, _T("<FRAME SRC=\"%s\" NAME=\"mainwindow\">\n"), ConvertCase(wxFileNameFromPath(firstFileName)));
3175                wxFprintf(tmpTitle, _T("</FRAMESET>\n"));
3176
3177                wxFprintf(tmpTitle, _T("<NOFRAMES>\n"));
3178            }
3179
3180            // Output <BODY...> to temporary title page
3181            OutputBodyStart();
3182            fflush(tmpTitle);
3183
3184            // Concat titlepage
3185            FILE *fd = wxFopen(TitlepageName, _T("r"));
3186            if (fd)
3187            {
3188                int ch = getc(fd);
3189                while (ch != EOF)
3190                {
3191                    wxPutc(ch, tmpTitle);
3192                    ch = getc(fd);
3193                }
3194                fclose(fd);
3195            }
3196
3197            wxFprintf(tmpTitle, _T("\n</FONT></BODY>\n"));
3198
3199            if (htmlFrameContents)
3200            {
3201                wxFprintf(tmpTitle, _T("\n</NOFRAMES>\n"));
3202            }
3203            wxFprintf(tmpTitle, _T("\n</HTML>\n"));
3204
3205            fclose(tmpTitle);
3206            if (wxFileExists(TitlepageName)) wxRemoveFile(TitlepageName);
3207            if (!wxRenameFile(_T("title.tmp"), TitlepageName))
3208            {
3209                wxCopyFile(_T("title.tmp"), TitlepageName);
3210                wxRemoveFile(_T("title.tmp"));
3211            }
3212        }
3213
3214        if (lastFileName) delete[] lastFileName;
3215        lastFileName = NULL;
3216        if (lastTopic) delete[] lastTopic;
3217        lastTopic = NULL;
3218
3219        if (wxFileExists(ContentsName)) wxRemoveFile(ContentsName);
3220
3221        if (!wxRenameFile(TmpContentsName, ContentsName))
3222        {
3223            wxCopyFile(TmpContentsName, ContentsName);
3224            wxRemoveFile(TmpContentsName);
3225        }
3226
3227        // Generate .htx file if requested
3228        if (htmlIndex)
3229        {
3230            wxChar htmlIndexName[300];
3231            wxSnprintf(htmlIndexName, sizeof(htmlIndexName), _T("%s.htx"), FileRoot);
3232            GenerateHTMLIndexFile(htmlIndexName);
3233        }
3234
3235        // Generate HTML Help Workshop files if requested
3236        if (htmlWorkshopFiles)
3237        {
3238            HTMLWorkshopEndContents();
3239            GenerateHTMLWorkshopFiles(FileRoot);
3240        }
3241
3242        return true;
3243    }
3244
3245    return false;
3246}
3247
3248// Output .htx index file
3249void GenerateHTMLIndexFile(wxChar *fname)
3250{
3251  FILE *fd = wxFopen(fname, _T("w"));
3252  if (!fd)
3253    return;
3254
3255  TopicTable.BeginFind();
3256  wxHashTable::Node *node = TopicTable.Next();
3257  while (node)
3258  {
3259    TexTopic *texTopic = (TexTopic *)node->GetData();
3260    const wxChar *topicName = node->GetKeyString();
3261    if (texTopic->filename && texTopic->keywords)
3262    {
3263      wxStringListNode *node1 = texTopic->keywords->GetFirst();
3264      while (node1)
3265      {
3266        wxChar *s = (wxChar *)node1->GetData();
3267        wxFprintf(fd, _T("%s|%s|%s\n"), topicName, texTopic->filename, s);
3268        node1 = node1->GetNext();
3269      }
3270    }
3271    node = TopicTable.Next();
3272  }
3273  fclose(fd);
3274}
3275
3276
3277
3278
3279
3280
3281
3282// output .hpp, .hhc and .hhk files:
3283
3284
3285void GenerateHTMLWorkshopFiles(wxChar *fname)
3286{
3287  FILE *f;
3288  wxChar buf[300];
3289
3290  /* Generate project file : */
3291
3292  wxSnprintf(buf, sizeof(buf), _T("%s.hhp"), fname);
3293  f = wxFopen(buf, _T("wt"));
3294  wxFprintf(f,
3295      _T("[OPTIONS]\n")
3296      _T("Compatibility=1.1\n")
3297      _T("Full-text search=Yes\n")
3298      _T("Contents file=%s.hhc\n")
3299      _T("Compiled file=%s.chm\n")
3300      _T("Default Window=%sHelp\n")
3301      _T("Default topic=%s\n")
3302      _T("Index file=%s.hhk\n")
3303      _T("Title="),
3304      wxFileNameFromPath(fname),
3305      wxFileNameFromPath(fname),
3306      wxFileNameFromPath(fname),
3307      wxFileNameFromPath(TitlepageName),
3308      wxFileNameFromPath(fname)
3309      );
3310
3311  if (DocumentTitle) {
3312    SetCurrentOutput(f);
3313    TraverseChildrenFromChunk(DocumentTitle);
3314  }
3315  else wxFprintf(f, _T("(unknown)"));
3316
3317  wxFprintf(f, _T("\n\n[WINDOWS]\n")
3318          _T("%sHelp=,\"%s.hhc\",\"%s.hhk\",\"%s\",,,,,,0x2420,,0x380e,,,,,0,,,"),
3319          wxFileNameFromPath(fname),
3320          wxFileNameFromPath(fname),
3321          wxFileNameFromPath(fname),
3322          wxFileNameFromPath(TitlepageName));
3323
3324
3325  wxFprintf(f, _T("\n\n[FILES]\n"));
3326  wxFprintf(f, _T("%s\n"), wxFileNameFromPath(TitlepageName));
3327  for (int i = 1; i <= fileId; i++) {
3328    if (truncateFilenames)
3329      wxSnprintf(buf, sizeof(buf), _T("%s%d.htm"), wxFileNameFromPath(FileRoot), i);
3330    else
3331      wxStrcpy(buf, wxFileNameFromPath(gs_filenames[i].c_str()));
3332    wxFprintf(f, _T("%s\n"), buf);
3333  }
3334  fclose(f);
3335
3336  /* Generate index file : */
3337
3338  wxSnprintf(buf, sizeof(buf), _T("%s.hhk"), fname);
3339  f = wxFopen(buf, _T("wt"));
3340
3341  wxFprintf(f,
3342      _T("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n")
3343      _T("<HTML>\n"));
3344  HTMLHeadTo(f);
3345  wxFprintf(f,
3346      _T("\n")
3347      _T("<meta name=\"GENERATOR\" content=\"tex2rtf\">\n")
3348      _T("<!-- Sitemap 1.0 -->\n")
3349      _T("</HEAD><BODY>\n")
3350      _T("<OBJECT type=\"text/site properties\">\n")
3351      _T(" <param name=\"ImageType\" value=\"Folder\">\n")
3352      _T("</OBJECT>\n")
3353      _T("<UL>\n"));
3354
3355  TopicTable.BeginFind();
3356  wxHashTable::Node *node = TopicTable.Next();
3357  while (node)
3358  {
3359    TexTopic *texTopic = (TexTopic *)node->GetData();
3360    const wxChar *topicName = node->GetKeyString();
3361    if (texTopic->filename && texTopic->keywords)
3362    {
3363      wxStringListNode *node1 = texTopic->keywords->GetFirst();
3364      while (node1)
3365      {
3366        wxChar *s = (wxChar *)node1->GetData();
3367        wxFprintf(f,
3368            _T(" <LI> <OBJECT type=\"text/sitemap\">\n")
3369            _T("  <param name=\"Local\" value=\"%s#%s\">\n")
3370            _T("  <param name=\"Name\" value=\"%s\">\n")
3371            _T("  </OBJECT>\n"),
3372        texTopic->filename, topicName, s);
3373        node1 = node1->GetNext();
3374      }
3375    }
3376    node = TopicTable.Next();
3377  }
3378
3379  wxFprintf(f, _T("</UL>\n"));
3380  fclose(f);
3381}
3382
3383
3384
3385static FILE *HTMLWorkshopContents = NULL;
3386static int HTMLWorkshopLastLevel = 0;
3387
3388void HTMLWorkshopAddToContents(int level, wxChar *s, wxChar *file)
3389{
3390  int i;
3391
3392  if (level > HTMLWorkshopLastLevel)
3393    for (i = HTMLWorkshopLastLevel; i < level; i++)
3394      wxFprintf(HTMLWorkshopContents, _T("<UL>"));
3395  if (level < HTMLWorkshopLastLevel)
3396    for (i = level; i < HTMLWorkshopLastLevel; i++)
3397      wxFprintf(HTMLWorkshopContents, _T("</UL>"));
3398
3399  SetCurrentOutput(HTMLWorkshopContents);
3400  wxFprintf(HTMLWorkshopContents,
3401            _T(" <LI> <OBJECT type=\"text/sitemap\">\n")
3402            _T("  <param name=\"Local\" value=\"%s#%s\">\n")
3403            _T("  <param name=\"Name\" value=\""),
3404            file, s);
3405  OutputCurrentSection();
3406  wxFprintf(HTMLWorkshopContents,
3407            _T("\">\n")
3408            _T("  </OBJECT>\n"));
3409  HTMLWorkshopLastLevel = level;
3410}
3411
3412
3413void HTMLWorkshopStartContents()
3414{
3415  wxChar buf[300];
3416  wxSnprintf(buf, sizeof(buf), _T("%s.hhc"), FileRoot);
3417  HTMLWorkshopContents = wxFopen(buf, _T("wt"));
3418  HTMLWorkshopLastLevel = 0;
3419
3420  wxFprintf(HTMLWorkshopContents,
3421      _T("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n")
3422      _T("<HTML>\n"));
3423  HTMLHeadTo(HTMLWorkshopContents);
3424  wxFprintf(HTMLWorkshopContents,
3425      _T("\n")
3426      _T("<meta name=\"GENERATOR\" content=\"tex2rtf\">\n")
3427      _T("<!-- Sitemap 1.0 -->\n")
3428      _T("</HEAD><BODY>\n")
3429      _T("<OBJECT type=\"text/site properties\">\n")
3430      _T(" <param name=\"ImageType\" value=\"Folder\">\n")
3431      _T("</OBJECT>\n")
3432      _T("<UL>\n")
3433      _T("<LI> <OBJECT type=\"text/sitemap\">\n")
3434      _T("<param name=\"Local\" value=\"%s\">\n")
3435      _T("<param name=\"Name\" value=\"Contents\">\n</OBJECT>\n"),
3436      wxFileNameFromPath(TitlepageName)
3437      );
3438
3439}
3440
3441
3442void HTMLWorkshopEndContents()
3443{
3444    for (int i = HTMLWorkshopLastLevel; i >= 0; i--)
3445        wxFprintf(HTMLWorkshopContents, _T("</UL>\n"));
3446    fclose(HTMLWorkshopContents);
3447}
3448
3449
3450bool PrimaryAnchorOfTheFile( wxChar *file, wxChar *label )
3451{
3452    wxString file_label;
3453    file_label.Printf( HTML_FILENAME_PATTERN, FileRoot, label );
3454    return file_label.IsSameAs( file , false );
3455}
3456