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