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